<commit_before>use std::collections::HashMap;

use core::{
    Dependency,
    PackageId,
    Summary,
    Registry
};

use util::{CargoResult, human, internal};

/* TODO:
 * - The correct input here is not a registry. Resolves should be performable
 * on package summaries vs. the packages themselves.
 */
pub fn resolve<R: Registry>(deps: &[Dependency],
                            registry: &mut R) -> CargoResult<Vec<PackageId>> {
    log!(5, "resolve; deps={}", deps);

    let mut remaining = Vec::from_slice(deps);
    let mut resolve = HashMap::<String, Summary>::new();

    loop {
        let curr = match remaining.pop() {
            Some(curr) => curr,
            None => {
                let ret = resolve.values().map(|summary| {
                    summary.get_package_id().clone()
                }).collect();
                log!(5, "resolve complete; ret={}", ret);
                return Ok(ret);
            }
        };

        let opts = try!(registry.query(&curr));

        if opts.len() == 0 {
            return Err(human(format!("No package named {} found", curr.get_name())));
        }

        if opts.len() > 1 {
            return Err(internal(format!("At the moment, Cargo only supports a\
                single source for a particular package name ({}).", curr.get_name())));
        }

        let pkg = opts.get(0).clone();
        resolve.insert(pkg.get_name().to_str(), pkg.clone());

        for dep in pkg.get_dependencies().iter() {
            if !dep.is_transitive() { continue; }

            if !resolve.contains_key_equiv(&dep.get_name()) {
                remaining.push(dep.clone());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use url;
    use hamcrest::{assert_that, equal_to, contains};

    use core::source::{SourceId, RegistryKind, Location, Remote};
    use core::{Dependency, PackageId, Summary};
    use super::resolve;

    trait ToDep {
        fn to_dep(self) -> Dependency;
    }

    impl ToDep for &'static str {
        fn to_dep(self) -> Dependency {
            let url = url::from_str("http://example.com").unwrap();
            let source_id = SourceId::new(RegistryKind, Remote(url));
            Dependency::parse(self, Some("1.0.0"), &source_id).unwrap()
        }
    }

    impl ToDep for Dependency {
        fn to_dep(self) -> Dependency {
            self
        }
    }

    macro_rules! pkg(
        ($name:expr => $($deps:expr),+) => ({
            let d: Vec<Dependency> = vec!($($deps.to_dep()),+);

            Summary::new(&PackageId::new($name, "1.0.0", &registry_loc()).unwrap(),
                         d.as_slice())
        });

        ($name:expr) => (
            Summary::new(&PackageId::new($name, "1.0.0", &registry_loc()).unwrap(),
                         [])
        )
    )

    fn registry_loc() -> Location {
        Location::parse("http://www.example.com/").unwrap()
    }

    fn pkg(name: &str) -> Summary {
        Summary::new(&PackageId::new(name, "1.0.0", &registry_loc()).unwrap(),
                     &[])
    }

    fn dep(name: &str) -> Dependency {
        let url = url::from_str("http://example.com").unwrap();
        let source_id = SourceId::new(RegistryKind, Remote(url));
        Dependency::parse(name, Some("1.0.0"), &source_id).unwrap()
    }

    fn registry(pkgs: Vec<Summary>) -> Vec<Summary> {
        pkgs
    }

    fn names(names: &[&'static str]) -> Vec<PackageId> {
        names.iter()
            .map(|name| PackageId::new(*name, "1.0.0", &registry_loc()).unwrap())
            .collect()
    }

    #[test]
    pub fn test_resolving_empty_dependency_list() {
        let res = resolve([], &mut registry(vec!())).unwrap();

        assert_that(&res, equal_to(&names([])));
    }

    #[test]
    pub fn test_resolving_only_package() {
        let mut reg = registry(vec!(pkg("foo")));
        let res = resolve([dep("foo")], &mut reg);

        assert_that(&res.unwrap(), equal_to(&names(["foo"])));
    }

    #[test]
    pub fn test_resolving_one_dep() {
        let mut reg = registry(vec!(pkg("foo"), pkg("bar")));
        let res = resolve([dep("foo")], &mut reg);

        assert_that(&res.unwrap(), equal_to(&names(["foo"])));
    }

    #[test]
    pub fn test_resolving_multiple_deps() {
        let mut reg = registry(vec!(pkg!("foo"), pkg!("bar"), pkg!("baz")));
        let res = resolve([dep("foo"), dep("baz")], &mut reg).unwrap();

        assert_that(&res, contains(names(["foo", "baz"])).exactly());
    }

    #[test]
    pub fn test_resolving_transitive_deps() {
        let mut reg = registry(vec!(pkg!("foo"), pkg!("bar" => "foo")));
        let res = resolve([dep("bar")], &mut reg).unwrap();

        assert_that(&res, contains(names(["foo", "bar"])));
    }

    #[test]
    pub fn test_resolving_common_transitive_deps() {
        let mut reg = registry(vec!(pkg!("foo" => "bar"), pkg!("bar")));
        let res = resolve([dep("foo"), dep("bar")], &mut reg).unwrap();

        assert_that(&res, contains(names(["foo", "bar"])));
    }

    #[test]
    pub fn test_resolving_with_dev_deps() {
        let mut reg = registry(vec!(
            pkg!("foo" => "bar", dep("baz").as_dev()),
            pkg!("baz" => "bat", dep("bam").as_dev()),
            pkg!("bar"),
            pkg!("bat")
        ));

        let res = resolve([dep("foo"), dep("baz").as_dev()], &mut reg).unwrap();

        assert_that(&res, contains(names(["foo", "bar", "baz"])));
    }
}
<commit_msg>auto merge of #116 : Indiv0/cargo/typofix, r=alexcrichton<commit_after>use std::collections::HashMap;

use core::{
    Dependency,
    PackageId,
    Summary,
    Registry
};

use util::{CargoResult, human, internal};

/* TODO:
 * - The correct input here is not a registry. Resolves should be performable
 * on package summaries vs. the packages themselves.
 */
pub fn resolve<R: Registry>(deps: &[Dependency],
                            registry: &mut R) -> CargoResult<Vec<PackageId>> {
    log!(5, "resolve; deps={}", deps);

    let mut remaining = Vec::from_slice(deps);
    let mut resolve = HashMap::<String, Summary>::new();

    loop {
        let curr = match remaining.pop() {
            Some(curr) => curr,
            None => {
                let ret = resolve.values().map(|summary| {
                    summary.get_package_id().clone()
                }).collect();
                log!(5, "resolve complete; ret={}", ret);
                return Ok(ret);
            }
        };

        let opts = try!(registry.query(&curr));

        if opts.len() == 0 {
            return Err(human(format!("No package named {} found", curr.get_name())));
        }

        if opts.len() > 1 {
            return Err(internal(format!("At the moment, Cargo only supports a \
                single source for a particular package name ({}).", curr.get_name())));
        }

        let pkg = opts.get(0).clone();
        resolve.insert(pkg.get_name().to_str(), pkg.clone());

        for dep in pkg.get_dependencies().iter() {
            if !dep.is_transitive() { continue; }

            if !resolve.contains_key_equiv(&dep.get_name()) {
                remaining.push(dep.clone());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use url;
    use hamcrest::{assert_that, equal_to, contains};

    use core::source::{SourceId, RegistryKind, Location, Remote};
    use core::{Dependency, PackageId, Summary};
    use super::resolve;

    trait ToDep {
        fn to_dep(self) -> Dependency;
    }

    impl ToDep for &'static str {
        fn to_dep(self) -> Dependency {
            let url = url::from_str("http://example.com").unwrap();
            let source_id = SourceId::new(RegistryKind, Remote(url));
            Dependency::parse(self, Some("1.0.0"), &source_id).unwrap()
        }
    }

    impl ToDep for Dependency {
        fn to_dep(self) -> Dependency {
            self
        }
    }

    macro_rules! pkg(
        ($name:expr => $($deps:expr),+) => ({
            let d: Vec<Dependency> = vec!($($deps.to_dep()),+);

            Summary::new(&PackageId::new($name, "1.0.0", &registry_loc()).unwrap(),
                         d.as_slice())
        });

        ($name:expr) => (
            Summary::new(&PackageId::new($name, "1.0.0", &registry_loc()).unwrap(),
                         [])
        )
    )

    fn registry_loc() -> Location {
        Location::parse("http://www.example.com/").unwrap()
    }

    fn pkg(name: &str) -> Summary {
        Summary::new(&PackageId::new(name, "1.0.0", &registry_loc()).unwrap(),
                     &[])
    }

    fn dep(name: &str) -> Dependency {
        let url = url::from_str("http://example.com").unwrap();
        let source_id = SourceId::new(RegistryKind, Remote(url));
        Dependency::parse(name, Some("1.0.0"), &source_id).unwrap()
    }

    fn registry(pkgs: Vec<Summary>) -> Vec<Summary> {
        pkgs
    }

    fn names(names: &[&'static str]) -> Vec<PackageId> {
        names.iter()
            .map(|name| PackageId::new(*name, "1.0.0", &registry_loc()).unwrap())
            .collect()
    }

    #[test]
    pub fn test_resolving_empty_dependency_list() {
        let res = resolve([], &mut registry(vec!())).unwrap();

        assert_that(&res, equal_to(&names([])));
    }

    #[test]
    pub fn test_resolving_only_package() {
        let mut reg = registry(vec!(pkg("foo")));
        let res = resolve([dep("foo")], &mut reg);

        assert_that(&res.unwrap(), equal_to(&names(["foo"])));
    }

    #[test]
    pub fn test_resolving_one_dep() {
        let mut reg = registry(vec!(pkg("foo"), pkg("bar")));
        let res = resolve([dep("foo")], &mut reg);

        assert_that(&res.unwrap(), equal_to(&names(["foo"])));
    }

    #[test]
    pub fn test_resolving_multiple_deps() {
        let mut reg = registry(vec!(pkg!("foo"), pkg!("bar"), pkg!("baz")));
        let res = resolve([dep("foo"), dep("baz")], &mut reg).unwrap();

        assert_that(&res, contains(names(["foo", "baz"])).exactly());
    }

    #[test]
    pub fn test_resolving_transitive_deps() {
        let mut reg = registry(vec!(pkg!("foo"), pkg!("bar" => "foo")));
        let res = resolve([dep("bar")], &mut reg).unwrap();

        assert_that(&res, contains(names(["foo", "bar"])));
    }

    #[test]
    pub fn test_resolving_common_transitive_deps() {
        let mut reg = registry(vec!(pkg!("foo" => "bar"), pkg!("bar")));
        let res = resolve([dep("foo"), dep("bar")], &mut reg).unwrap();

        assert_that(&res, contains(names(["foo", "bar"])));
    }

    #[test]
    pub fn test_resolving_with_dev_deps() {
        let mut reg = registry(vec!(
            pkg!("foo" => "bar", dep("baz").as_dev()),
            pkg!("baz" => "bat", dep("bam").as_dev()),
            pkg!("bar"),
            pkg!("bat")
        ));

        let res = resolve([dep("foo"), dep("baz").as_dev()], &mut reg).unwrap();

        assert_that(&res, contains(names(["foo", "bar", "baz"])));
    }
}
<|endoftext|>


<commit_before>use dns_parser::Packet as DnsPacket;
use dns_parser::{Opcode, ResponseCode, QueryType, QueryClass};
use serde_json::{Value, Map, Number, to_value};

#[derive(Serialize)]
pub struct DnsQuestion {
	name: String,
	qtype: String,
	qclass: String,
}

pub struct DnsHeader {
	id: Number,
	opcode: String,
	flags: Value,
	rcode: String,
	total_questions: Number,
	total_answer_rrs: Number,
	total_authority_rrs: Number,
	total_additional_rrs: Number,
	questions: Value,
}

impl DnsHeader {
	pub fn new(p: &DnsPacket) -> DnsHeader {
		let opcode_number = p.header.opcode;
		let opcode_string = match opcode_number {
			Opcode::StandardQuery => "QUERY",
			Opcode::InverseQuery => "IQUERY",
			Opcode::ServerStatusRequest => "STATUS",
			_ => "UNKNOWN",
		};

		let mut flags: Vec<&str> = Vec::new();
		if p.header.authoritative {
			flags.push("AA");
		}
		if p.header.truncated {
			flags.push("TC");
		}
		if p.header.recursion_desired {
			flags.push("RD");
		}
		if p.header.recursion_available {
			flags.push("RA");
		}
		if p.header.authenticated_data {
			flags.push("AD");
		}
		if p.header.checking_disabled {
			flags.push("CD");
		}

		let rcode_number = p.header.response_code;
		let rcode_string = match rcode_number {
			ResponseCode::NoError => "NOERROR",
			ResponseCode::FormatError => "FORMERR",
			ResponseCode::ServerFailure => "SERVFAIL",
			ResponseCode::NameError => "NXDOMAIN",
			ResponseCode::NotImplemented => "NOTIMPL",
			ResponseCode::Refused => "REFUSED",
			_ => "UNKNOWN",
		};

		let mut questions: Vec<DnsQuestion> = Vec::new();
		if ! p.questions.is_empty() {
			for q in p.questions.iter() {
				let question = DnsQuestion {
					name: q.qname.to_string(),
					qtype: match q.qtype {
						QueryType::A => String::from("A"),
						QueryType::NS => String::from("NS"),
						QueryType::MF => String::from("MF"),
						QueryType::CNAME => String::from("CNAME"),
						QueryType::SOA => String::from("SOA"),
						QueryType::MB => String::from("MB"),
						QueryType::MG => String::from("MG"),
						QueryType::MR => String::from("MR"),
						QueryType::NULL => String::from("NULL"),
						QueryType::WKS => String::from("WKS"),
						QueryType::PTR => String::from("PTR"),
						QueryType::HINFO => String::from("HINFO"),
						QueryType::MINFO => String::from("MINFO"),
						QueryType::MX => String::from("MX"),
						QueryType::TXT => String::from("TXT"),
						QueryType::AAAA => String::from("AAAA"),
						QueryType::SRV => String::from("SRV"),
						QueryType::AXFR => String::from("AXFR"),
						QueryType::MAILB => String::from("MAILB"),
						QueryType::MAILA => String::from("MAILA"),
						QueryType::All => String::from("ALL"),
					},
					qclass: match q.qclass {
						QueryClass::IN => String::from("IN"),
						QueryClass::CS => String::from("CS"),
						QueryClass::CH => String::from("CH"),
						QueryClass::HS => String::from("HS"),
						QueryClass::Any => String::from("ANY"),
					},
				};
				questions.push(question);
			}
		}

		DnsHeader {
			id: Number::from(p.header.id),
			opcode: opcode_string.to_string(),
			flags: Value::from(flags),
			rcode: rcode_string.to_string(),
			total_questions: Number::from(p.header.questions),
			total_answer_rrs: Number::from(p.header.answers),
			total_authority_rrs: Number::from(p.header.nameservers),
			total_additional_rrs: Number::from(p.header.additional),
			questions: to_value(questions).unwrap(),
		}
	}

	pub fn to_json_map(&self) -> Map<String, Value> {
		let mut header = Map::new();

		header.insert("id".to_string(), Value::Number(self.id.clone()));
		header.insert("opcode".to_string(), Value::String(self.opcode.clone()));
		header.insert("flags".to_string(), self.flags.clone());
		header.insert("rcode".to_string(), Value::String(self.rcode.clone()));
		header.insert("total_questions".to_string(), Value::Number(self.total_questions.clone()));
		header.insert("total_answer_rrs".to_string(), Value::Number(self.total_answer_rrs.clone()));
		header.insert("total_authority_rrs".to_string(), Value::Number(self.total_authority_rrs.clone()));
		header.insert("total_additional_rrs".to_string(), Value::Number(self.total_additional_rrs.clone()));
		header.insert("questions".to_string(), self.questions.clone());

		header
	}
}<commit_msg>Parse DNS resource records<commit_after>use dns_parser::Packet as DnsPacket;
use dns_parser::{Opcode, ResponseCode, QueryType, QueryClass, Class, RRData};
use serde_json::{Value, Map, Number, to_value};

#[derive(Serialize)]
pub struct DnsQuestion {
	name: String,
	qtype: String,
	qclass: String,
}

#[derive(Serialize)]
pub struct DnsResourceRecord {
	name: String,
	class: String,
	ttl: Number,
	rdata: String,
}

pub struct DnsHeader {
	id: Number,
	opcode: String,
	flags: Value,
	rcode: String,
	total_questions: Number,
	total_answer_rrs: Number,
	total_authority_rrs: Number,
	total_additional_rrs: Number,
	questions: Value,
	answer_rrs: Value,
	authority_rrs: Value,
	additional_rrs: Value,
}

impl DnsHeader {
	pub fn new(p: &DnsPacket) -> DnsHeader {
		let opcode_number = p.header.opcode;
		let opcode_string = match opcode_number {
			Opcode::StandardQuery => "QUERY",
			Opcode::InverseQuery => "IQUERY",
			Opcode::ServerStatusRequest => "STATUS",
			_ => "UNKNOWN",
		};

		let mut flags: Vec<&str> = Vec::new();
		if p.header.authoritative {
			flags.push("AA");
		}
		if p.header.truncated {
			flags.push("TC");
		}
		if p.header.recursion_desired {
			flags.push("RD");
		}
		if p.header.recursion_available {
			flags.push("RA");
		}
		if p.header.authenticated_data {
			flags.push("AD");
		}
		if p.header.checking_disabled {
			flags.push("CD");
		}

		let rcode_number = p.header.response_code;
		let rcode_string = match rcode_number {
			ResponseCode::NoError => "NOERROR",
			ResponseCode::FormatError => "FORMERR",
			ResponseCode::ServerFailure => "SERVFAIL",
			ResponseCode::NameError => "NXDOMAIN",
			ResponseCode::NotImplemented => "NOTIMPL",
			ResponseCode::Refused => "REFUSED",
			_ => "UNKNOWN",
		};

		let mut questions: Vec<DnsQuestion> = Vec::new();
		if ! p.questions.is_empty() {
			for q in p.questions.iter() {
				let question = DnsQuestion {
					name: q.qname.to_string(),
					qtype: match q.qtype {
						QueryType::A => String::from("A"),
						QueryType::NS => String::from("NS"),
						QueryType::MF => String::from("MF"),
						QueryType::CNAME => String::from("CNAME"),
						QueryType::SOA => String::from("SOA"),
						QueryType::MB => String::from("MB"),
						QueryType::MG => String::from("MG"),
						QueryType::MR => String::from("MR"),
						QueryType::NULL => String::from("NULL"),
						QueryType::WKS => String::from("WKS"),
						QueryType::PTR => String::from("PTR"),
						QueryType::HINFO => String::from("HINFO"),
						QueryType::MINFO => String::from("MINFO"),
						QueryType::MX => String::from("MX"),
						QueryType::TXT => String::from("TXT"),
						QueryType::AAAA => String::from("AAAA"),
						QueryType::SRV => String::from("SRV"),
						QueryType::AXFR => String::from("AXFR"),
						QueryType::MAILB => String::from("MAILB"),
						QueryType::MAILA => String::from("MAILA"),
						QueryType::All => String::from("ALL"),
					},
					qclass: match q.qclass {
						QueryClass::IN => String::from("IN"),
						QueryClass::CS => String::from("CS"),
						QueryClass::CH => String::from("CH"),
						QueryClass::HS => String::from("HS"),
						QueryClass::Any => String::from("ANY"),
					},
				};
				questions.push(question);
			}
		}

		let mut answers: Vec<DnsResourceRecord> = Vec::new();
		if ! p.answers.is_empty() {
			for a in p.answers.iter() {
				let answer = DnsResourceRecord {
					name: a.name.to_string(),
					class: match a.cls {
						Class::IN => String::from("IN"),
						Class::CS => String::from("CS"),
						Class::CH => String::from("CH"),
						Class::HS => String::from("HS"),
					},
					ttl: Number::from(a.ttl),
					rdata: match a.data {
						RRData::CNAME(cname) => cname.to_string(),
						RRData::NS(ns) => ns.to_string(),
						RRData::PTR(ptr) => ptr.to_string(),
						RRData::TXT(ref txt) => txt.clone(),
						_ => String::from("Unknown"),
					},
				};
				answers.push(answer);
			}
		}

		let mut nameservers: Vec<DnsResourceRecord> = Vec::new();
		if ! p.nameservers.is_empty() {
			for a in p.nameservers.iter() {
				let nameserver = DnsResourceRecord {
					name: a.name.to_string(),
					class: match a.cls {
						Class::IN => String::from("IN"),
						Class::CS => String::from("CS"),
						Class::CH => String::from("CH"),
						Class::HS => String::from("HS"),
					},
					ttl: Number::from(a.ttl),
					rdata: match a.data {
						RRData::CNAME(cname) => cname.to_string(),
						RRData::NS(ns) => ns.to_string(),
						RRData::PTR(ptr) => ptr.to_string(),
						RRData::TXT(ref txt) => txt.clone(),
						_ => String::from("Unknown"),
					},
				};
				nameservers.push(nameserver);
			}
		}

		let mut additionals: Vec<DnsResourceRecord> = Vec::new();
		if ! p.additional.is_empty() {
			for a in p.additional.iter() {
				let additional = DnsResourceRecord {
					name: a.name.to_string(),
					class: match a.cls {
						Class::IN => String::from("IN"),
						Class::CS => String::from("CS"),
						Class::CH => String::from("CH"),
						Class::HS => String::from("HS"),
					},
					ttl: Number::from(a.ttl),
					rdata: match a.data {
						RRData::CNAME(cname) => cname.to_string(),
						RRData::NS(ns) => ns.to_string(),
						RRData::PTR(ptr) => ptr.to_string(),
						RRData::TXT(ref txt) => txt.clone(),
						_ => String::from("Unknown"),
					},
				};
				additionals.push(additional);
			}
		}

		DnsHeader {
			id: Number::from(p.header.id),
			opcode: opcode_string.to_string(),
			flags: Value::from(flags),
			rcode: rcode_string.to_string(),
			total_questions: Number::from(p.header.questions),
			total_answer_rrs: Number::from(p.header.answers),
			total_authority_rrs: Number::from(p.header.nameservers),
			total_additional_rrs: Number::from(p.header.additional),
			questions: to_value(questions).unwrap(),
			answer_rrs: to_value(answers).unwrap(),
			authority_rrs: to_value(nameservers).unwrap(),
			additional_rrs: to_value(additionals).unwrap(),
		}
	}

	pub fn to_json_map(&self) -> Map<String, Value> {
		let mut header = Map::new();

		header.insert("id".to_string(), Value::Number(self.id.clone()));
		header.insert("opcode".to_string(), Value::String(self.opcode.clone()));
		header.insert("flags".to_string(), self.flags.clone());
		header.insert("rcode".to_string(), Value::String(self.rcode.clone()));
		header.insert("total_questions".to_string(), Value::Number(self.total_questions.clone()));
		header.insert("total_answer_rrs".to_string(), Value::Number(self.total_answer_rrs.clone()));
		header.insert("total_authority_rrs".to_string(), Value::Number(self.total_authority_rrs.clone()));
		header.insert("total_additional_rrs".to_string(), Value::Number(self.total_additional_rrs.clone()));
		header.insert("questions".to_string(), self.questions.clone());
		header.insert("answer_rrs".to_string(), self.answer_rrs.clone());
		header.insert("authority_rrs".to_string(), self.authority_rrs.clone());
		header.insert("additional_rrs".to_string(), self.additional_rrs.clone());

		header
	}
}<|endoftext|>


<commit_before>use super::prelude::*;

use crate::middleware::current_user::TrustedUserId;
use crate::models::{ApiToken, User};
use crate::util::errors::{internal, AppError, AppResult, ChainError, Unauthorized};

#[derive(Debug)]
pub struct AuthenticatedUser {
    user_id: i32,
    token_id: Option<i32>,
}

impl AuthenticatedUser {
    pub fn user_id(&self) -> i32 {
        self.user_id
    }

    pub fn api_token_id(&self) -> Option<i32> {
        self.token_id
    }

    pub fn find_user(&self, conn: &PgConnection) -> AppResult<User> {
        User::find(conn, self.user_id())
            .chain_error(|| internal("user_id from cookie or token not found in database"))
    }
}

impl<'a> UserAuthenticationExt for dyn RequestExt + 'a {
    /// Obtain `AuthenticatedUser` for the request or return an `Unauthorized` error
    fn authenticate(&self, conn: &PgConnection) -> AppResult<AuthenticatedUser> {
        if let Some(id) = self.extensions().find::<TrustedUserId>() {
            // A trusted user_id was provided by a signed cookie (or a test `MockCookieUser`)
            Ok(AuthenticatedUser {
                user_id: id.0,
                token_id: None,
            })
        } else {
            // Otherwise, look for an `Authorization` header on the request
            if let Some(headers) = self.headers().get(header::AUTHORIZATION) {
                ApiToken::find_by_api_token(conn, headers.to_str().unwrap_or_default())
                    .map(|token| AuthenticatedUser {
                        user_id: token.user_id,
                        token_id: Some(token.id),
                    })
                    .chain_error(|| internal("invalid token"))
                    .chain_error(|| Box::new(Unauthorized) as Box<dyn AppError>)
            } else {
                // Unable to authenticate the user
                Err(internal("no cookie session or auth header found"))
                    .chain_error(|| Box::new(Unauthorized) as Box<dyn AppError>)
            }
        }
    }
}
<commit_msg>Restrict authentication to same-origin requests.<commit_after>use super::prelude::*;

use crate::middleware::current_user::TrustedUserId;
use crate::models::{ApiToken, User};
use crate::util::errors::{internal, AppError, AppResult, ChainError, Unauthorized};

#[derive(Debug)]
pub struct AuthenticatedUser {
    user_id: i32,
    token_id: Option<i32>,
}

impl AuthenticatedUser {
    pub fn user_id(&self) -> i32 {
        self.user_id
    }

    pub fn api_token_id(&self) -> Option<i32> {
        self.token_id
    }

    pub fn find_user(&self, conn: &PgConnection) -> AppResult<User> {
        User::find(conn, self.user_id())
            .chain_error(|| internal("user_id from cookie or token not found in database"))
    }
}

impl<'a> UserAuthenticationExt for dyn RequestExt + 'a {
    /// Obtain `AuthenticatedUser` for the request or return an `Unauthorized` error
    fn authenticate(&self, conn: &PgConnection) -> AppResult<AuthenticatedUser> {
        let origin_headers = self.headers().get_all(header::ORIGIN);
        let expected_origin = match (self.scheme(), self.host()) {
            (conduit::Scheme::Http, conduit::Host::Name(host)) => format!("http://{}", host),
            (conduit::Scheme::Https, conduit::Host::Name(host)) => format!("https://{}", host),
            _ => "".to_string(),
        };
        if origin_headers
            .iter()
            .any(|h| h.as_bytes() != expected_origin.as_bytes())
        {
            return Err(internal("only same-origin requests can be authenticated"))
                .chain_error(|| Box::new(Unauthorized) as Box<dyn AppError>);
        }
        if let Some(id) = self.extensions().find::<TrustedUserId>() {
            // A trusted user_id was provided by a signed cookie (or a test `MockCookieUser`)
            Ok(AuthenticatedUser {
                user_id: id.0,
                token_id: None,
            })
        } else {
            // Otherwise, look for an `Authorization` header on the request
            if let Some(headers) = self.headers().get(header::AUTHORIZATION) {
                ApiToken::find_by_api_token(conn, headers.to_str().unwrap_or_default())
                    .map(|token| AuthenticatedUser {
                        user_id: token.user_id,
                        token_id: Some(token.id),
                    })
                    .chain_error(|| internal("invalid token"))
                    .chain_error(|| Box::new(Unauthorized) as Box<dyn AppError>)
            } else {
                // Unable to authenticate the user
                Err(internal("no cookie session or auth header found"))
                    .chain_error(|| Box::new(Unauthorized) as Box<dyn AppError>)
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::{Dummy, Fake, Faker};
use crate::faker::boolean::raw::Boolean;
use crate::locales::{EN};
use rand::seq::SliceRandom;
use rand::Rng;

const UNSTABLE_SEMVER: &'static [&'static str] = &[
    "alpha", "beta", "rc"
];

impl Dummy<Faker> for semver::Version {
    fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
        let probability = 10;
        let pre;
        if Boolean(EN, probability).fake_with_rng(rng) {
            pre = vec!(semver::Identifier::AlphaNumeric(format!(
                "{}.{}",
                *UNSTABLE_SEMVER.choose(rng).unwrap(),
                &(0..9).fake_with_rng::<u8, _>(rng).to_string()
            )));
        } else {
            pre = vec!();
        }
        semver::Version {
            major: (0..9).fake_with_rng::<u64, _>(rng),
            minor: (0..20).fake_with_rng::<u64, _>(rng),
            patch: (0..20).fake_with_rng::<u64, _>(rng),
            pre: pre,
            build: vec!(),
        }
    }
}
<commit_msg>fix semver support<commit_after>use crate::{Dummy, Fake, Faker};
use crate::faker::boolean::raw::Boolean;
use crate::locales::{EN};
use rand::seq::SliceRandom;
use rand::Rng;

const UNSTABLE_SEMVER: &'static [&'static str] = &[
    "alpha", "beta", "rc"
];

impl Dummy<Faker> for semver::Version {
    fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
        let probability = 10;
        let pre = if Boolean(EN, probability).fake_with_rng(rng) {
            semver::Prerelease::new(&format!(
                "{}.{}",
                *UNSTABLE_SEMVER.choose(rng).unwrap(),
                &(0..9).fake_with_rng::<u8, _>(rng).to_string()
            )).unwrap()
        } else {
            semver::Prerelease::EMPTY
        };
        semver::Version {
            major: (0..9).fake_with_rng::<u64, _>(rng),
            minor: (0..20).fake_with_rng::<u64, _>(rng),
            patch: (0..20).fake_with_rng::<u64, _>(rng),
            pre: pre,
            build: semver::BuildMetadata::EMPTY,
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2014, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

#![crate_type = "bin"]

extern crate capnp;
pub mod addressbook_capnp;

pub mod addressbook {
    use std::io::{stdin, stdout};
    use addressbook_capnp::{AddressBook, Person};
    use capnp::serialize_packed;
    use capnp::message::{MallocMessageBuilder, MessageBuilder, DefaultReaderOptions, MessageReader};

    pub fn write_address_book() {
        let mut message = MallocMessageBuilder::new_default();
        let address_book = message.init_root::<AddressBook::Builder>();

        let people = address_book.init_people(2);

        let alice = people[0];
        alice.set_id(123);
        alice.set_name("Alice");
        alice.set_email("alice@example.com");

        let alice_phones = alice.init_phones(1);
        alice_phones[0].set_number("555-1212");
        alice_phones[0].set_type(Person::PhoneNumber::Type::Mobile);
        alice.get_employment().set_school("MIT");

        let bob = people[1];
        bob.set_id(456);
        bob.set_name("Bob");
        bob.set_email("bob@example.com");
        let bob_phones = bob.init_phones(2);
        bob_phones[0].set_number("555-4567");
        bob_phones[0].set_type(Person::PhoneNumber::Type::Home);
        bob_phones[1].set_number("555-7654");
        bob_phones[1].set_type(Person::PhoneNumber::Type::Work);
        bob.get_employment().set_unemployed(());

        serialize_packed::write_packed_message_unbuffered(&mut stdout(), & message).unwrap();
    }

    pub fn print_address_book() {

        let message_reader = serialize_packed::new_reader_unbuffered(&mut stdin(), DefaultReaderOptions).unwrap();
        let address_book = message_reader.get_root::<AddressBook::Reader>();
        let people = address_book.get_people();

        for i in range(0, people.size()) {
            let person = people[i];
            println!("{}: {}", person.get_name(), person.get_email());
            let phones = person.get_phones();
            for j in range(0, phones.size()) {
                let phone = phones[j];
                let type_name = match phone.get_type() {
                    Some(Person::PhoneNumber::Type::Mobile) => {"mobile"}
                    Some(Person::PhoneNumber::Type::Home) => {"home"}
                    Some(Person::PhoneNumber::Type::Work) => {"work"}
                    None => {"UNKNOWN"}
                };
                println!("  {} phone: {}", type_name, phone.get_number());
            }
            match person.get_employment().which() {
                Some(Person::Employment::Unemployed(())) => {
                    println!("  unemployed");
                }
                Some(Person::Employment::Employer(employer)) => {
                    println!("  employer: {}", employer);
                }
                Some(Person::Employment::School(school)) => {
                    println!("  student at: {}", school);
                }
                Some(Person::Employment::SelfEmployed(())) => {
                    println!("  self-employed");
                }
                None => { }
            }
        }
    }
}

pub fn main() {

    let args = std::os::args();
    if args.len() < 2 {
        println!("usage: $ {} [write | read]", args[0]);
    } else {
        match args[1].as_slice() {
            "write" => addressbook::write_address_book(),
            "read" => addressbook::print_address_book(),
            _ => {println!("unrecognized argument") }
        }
    }

}
<commit_msg>use IoResult in addressbook example<commit_after>/*
 * Copyright (c) 2013-2014, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

#![crate_type = "bin"]

extern crate capnp;
pub mod addressbook_capnp;

pub mod addressbook {
    use std::io::{stdin, stdout, IoResult};
    use addressbook_capnp::{AddressBook, Person};
    use capnp::serialize_packed;
    use capnp::message::{MallocMessageBuilder, MessageBuilder, DefaultReaderOptions, MessageReader};

    pub fn write_address_book() -> IoResult<()> {
        let mut message = MallocMessageBuilder::new_default();
        let address_book = message.init_root::<AddressBook::Builder>();

        let people = address_book.init_people(2);

        let alice = people[0];
        alice.set_id(123);
        alice.set_name("Alice");
        alice.set_email("alice@example.com");

        let alice_phones = alice.init_phones(1);
        alice_phones[0].set_number("555-1212");
        alice_phones[0].set_type(Person::PhoneNumber::Type::Mobile);
        alice.get_employment().set_school("MIT");

        let bob = people[1];
        bob.set_id(456);
        bob.set_name("Bob");
        bob.set_email("bob@example.com");
        let bob_phones = bob.init_phones(2);
        bob_phones[0].set_number("555-4567");
        bob_phones[0].set_type(Person::PhoneNumber::Type::Home);
        bob_phones[1].set_number("555-7654");
        bob_phones[1].set_type(Person::PhoneNumber::Type::Work);
        bob.get_employment().set_unemployed(());

        serialize_packed::write_packed_message_unbuffered(&mut stdout(), & message)
    }

    pub fn print_address_book() -> IoResult<()> {

        let message_reader = try!(serialize_packed::new_reader_unbuffered(&mut stdin(), DefaultReaderOptions));
        let address_book = message_reader.get_root::<AddressBook::Reader>();
        let people = address_book.get_people();

        for i in range(0, people.size()) {
            let person = people[i];
            println!("{}: {}", person.get_name(), person.get_email());
            let phones = person.get_phones();
            for j in range(0, phones.size()) {
                let phone = phones[j];
                let type_name = match phone.get_type() {
                    Some(Person::PhoneNumber::Type::Mobile) => {"mobile"}
                    Some(Person::PhoneNumber::Type::Home) => {"home"}
                    Some(Person::PhoneNumber::Type::Work) => {"work"}
                    None => {"UNKNOWN"}
                };
                println!("  {} phone: {}", type_name, phone.get_number());
            }
            match person.get_employment().which() {
                Some(Person::Employment::Unemployed(())) => {
                    println!("  unemployed");
                }
                Some(Person::Employment::Employer(employer)) => {
                    println!("  employer: {}", employer);
                }
                Some(Person::Employment::School(school)) => {
                    println!("  student at: {}", school);
                }
                Some(Person::Employment::SelfEmployed(())) => {
                    println!("  self-employed");
                }
                None => { }
            }
        }
        Ok(())
    }
}

pub fn main() {

    let args = std::os::args();
    if args.len() < 2 {
        println!("usage: $ {} [write | read]", args[0]);
    } else {
        match args[1].as_slice() {
            "write" => addressbook::write_address_book().unwrap(),
            "read" => addressbook::print_address_book().unwrap(),
            _ => {println!("unrecognized argument") }
        }
    }

}
<|endoftext|>


<commit_before>#[macro_use]
extern crate apache2;

use apache2::{Request, Status};

apache2_module!(coming_soon_handler, c_coming_soon_handler, coming_soon_module, b"mod_coming_soon\0");

macro_rules! html_template {() => ("<!doctype html>

      <meta charset=\"utf-8\">
      <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">
      <title>PolyDraw – Coming Soon</title>
      <meta name=\"description\" content=\"PolyDraw website is coming soon\">
      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">

      <link href=\"https://fonts.googleapis.com/css?family=Fira+Sans:300,500\" rel=\"stylesheet\" type=\"text/css\">
      <link href=\"https://fonts.googleapis.com/css?family=Roboto+Condensed:400\" rel=\"stylesheet\" type=\"text/css\">
      <link href=\"https://fonts.googleapis.com/css?family=Khand:400\" rel=\"stylesheet\" type=\"text/css\">

PolyDraw

Open source software development

COMING SOON

in

000

days

                  In the meantime, please sign the international petition against

ORGAN HARVESTING

from Falun Gong practitioners in China!

                  JOIN THE PETITION!

")}

fn coming_soon_handler(r: &mut Request) -> Status {
   if r.handler().unwrap() != "coming-soon" || r.uri().unwrap() != "/" {
      return Status::DECLINED
   }

   r.set_content_type("text/html");

   r.write(format!(
      html_template!(),
      STYLESHEET
   ));

   Status::OK
}

const STYLESHEET: &'static str = "
   html, body {
      height: 100%;
      width: 100%;
      margin: 0;
   }

   body {
      display: block;
      font-family: 'Roboto Condensed', sans-serif;
      background-image: url(https://www.polydraw.com/img/mountain-mist.jpg);
      background-size: cover;
      background-repeat: no-repeat;
      background-attachment: fixed;
      background-position: right bottom;
   }

   main {
      display: block;
      position: relative;
      top: 50%;
      margin: 0 auto;
      -webkit-transform: translateY(-50%);
      -ms-transform: translateY(-50%);
      transform: translateY(-50%);
   }

   h1 {
      display: block;
      width: 60%;
      margin: 0 auto;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 500;
      font-size: 3.5em;
      color: white;
      text-align: center;
   }

   h2 {
      display: block;
      width: 70%;
      margin: 0 auto;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 300;
      font-size: 1.2em;
      color: #5b5b5b;
      text-align: center;
   }

   .coming-soon {
      display: block;
      width: 40%;
      margin: 3em auto .1em;
      font-size: 1.5em;
      color: white;
      text-align: center;
   }

   .in {
      display: block;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 300;
      font-size: .8em;
      font-style: italic;
      color: white;
      text-align: center;
   }

   .timer {
      display: block;
      width: 7em;
      text-align: center;
      border-style: solid none solid none;
      border-color: #e6e6e6;
      border-width: 1px;
      margin: 0 auto 1em;
   }

   .timer .number {
      display: block;
      font-family: 'Khand', sans-serif;
      font-size: 4em;
      font-weight: bold;
      color: white;
      text-align: center;
   }

   .timer .days {
      display: block;
      font-family: 'Khand', sans-serif;
      font-size: 1.5em;
      color: white;
      text-align: center;
      margin: -1em auto 0;
   }

   .urgent-call {
      margin: 3% auto 0;
   }

   .urgent-call .description {
      display: block;
      width: 100%;
      line-height: 1.9em;
      background: -webkit-linear-gradient(left, rgba(86,86,107,0), rgba(86,86,107,.25), rgba(86,86,107,0));
      background: linear-gradient(to right,rgba(86,86,107,0),rgba(86,86,107,.25),rgba(86,86,107,0));
   }

   .urgent-call .first, .urgent-call .second, .urgent-call .third {
      margin: 0 auto;
      width: 90%;
      color: white;
      font-size: 1em;
      text-align: center;
   }

   .urgent-call .second {
      width: 100%;
      color: #9c292e;
      font-family: 'Khand', sans-serif;
      font-weight: bold;
      font-size: 1.2em;
   }

   .petition .button {
      display: block;
      width: 120px;
      margin: 1em auto 0;
      padding: 3px 6px;
      background: #829776;
      color: #ffffff;
      font-family: 'Fira Sans', sans-serif;
      font-size: .85em;
      font-weight: 300;
      text-align: center;
      text-decoration: none;
      border: solid #ffffff 1px;
      border-radius: 3px;
   }

   .petition .button:hover {
      background: #4d6b3c;
   }

   footer {
      display: table;
      position: fixed;
      width: 96%;
      bottom: 0;
      padding-left: 2%;
      padding-right: 2%;
   }

   .social {
      display: block;
      vertical-align: middle;
      float: right;
   }

   .social a {
      display: inline-block;
      width: 28px;
      height: 28px;
      background-repeat: no-repeat;
      opacity: .5;
      margin-left: .5em;
   }

   .social a:hover {
      opacity: .9;
   }

   .social a.facebook {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAG1BMVEUAAADY2NjY2NjY2NjY2NhGRkZqamqFhYWtra1jMrL/AAAACXRSTlMAPGaw//////9HdVBWAAAAp0lEQVQoz42TQRLDIAwDVyb/f3GxegAGmJC0PhkWge0RYoYQxuvGSGKkTu9wohW3vQj2yAQoR4Zwh3fWaYAODEJwQWNltqAKEJXShSV71dVWGJCJLuy6+MxFEKwN8uGSPGraml+uaG9s9RuqvVX8FLvSgqJ5PPysdPASP5SP1AS5O2IuEkHRcfCuCFSOt1Y3J5wGkW5O8IFmDg/daTPYH9Z8N/X5O3wBpdI+PxtA6DIAAAAASUVORK5CYII=);
   }

   .social a.twitter {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAJFBMVEUAAADY2NjV1dXY2NjY2NjY2NjY2NhHR0empqaQkJBtbW3Dw8PQfCyMAAAADHRSTlMAPPVmwKD////////J66Z0AAAA5UlEQVQoz32T0ZKFIAxDT1qc/f+/3VFo9wFQXL23D+oQGpJQxVXCCHJdmB+lFQCq17yDclsoonXYx9NZ+dPy7PQbBEBro/MFw0gwUPJSKRAUewOJiqEbZu5QAUyITQBbVgAPwHUA5OHQO6N4zOMsAFpKW89lAw8FgLW+6XB1Hz9KcuY6XuEjt12XqBKn2bGwgMcpfe7a/XFRYQ+uUzRY9wdE7/DfCdX0cZp5l2jt5FI46QC5F5M4Fl31e/AOmW9oDbB+c89S9klI7POYkIvf4aJd05do5Y6IZTQhYjqsqvE/yLff4Q+6BFspw2Tr1AAAAABJRU5ErkJggg==);
   }

   .social a.github {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAJFBMVEUAAADY2NjY2NjY2NjY2NjY2NhHR0ebm5u3t7dYWFh3d3dqampwrbVmAAAADHRSTlMAPGbxsP////////80TrKnAAAA4UlEQVQoz32TwW7DMAxDH+ns/z94tbhDpDRBi+lkSCBN0bR4lxAh98YcVgxAaec51NKNIj1eANjmyR+AA8CLZxmqkR8zwAQMEl9KAsExQy+RXaPqxXEBl9gidnZDowGu0olxvBvqcUTSOgmGKlhudeU6JJWLbmmWXwXs04Ga1UaqVK/z9LsuT9+2/XxxovWkFwB2pjfI7ZaB8L6Q53aFdw44UqZb8dyek0R4WMUa5iybIEvNuv83XqBnDLqqgiH59p7JmYTwCd0TE3KLaHPWO315ZiV1jyZUFLUdl2D99x3+AND/ZE+Y11fiAAAAAElFTkSuQmCC);
   }

   @media all and (max-width: 319px) {
      main {
         margin: auto 0;
      }

      h1 {
         margin: -7% auto 0;
         font-size: 1.6em;
      }

      h2 {
         margin: 0 auto;
         font-size: .8em;
      }

      .coming-soon {
         margin: .7em auto 0;
         font-size: .8em;
      }

      .in {
         font-size: .7em;
      }

      .timer {
         width: 3em;
         margin: 0 auto .2em;
      }

      .timer .number {
         font-size: 2em;
      }

      .timer .days {
         font-size: .75em;
      }

      .urgent-call {
         margin: 0 auto;
      }

      .urgent-call .description {
         font-size: 0.7em;
         line-height: 140%;
      }

      .petition .button {
         width: 120px;
         margin: 1em auto 0;
         padding: 3px;
         font-size: .6em;
      }
   }

   @media all and (min-width: 320px) and (max-width: 460px) {
      h1 {
         margin: 0 auto;
         font-size: 2.5em;
      }

      h2 {
         margin: 0 auto 2em;
         font-size: .9em;
      }

      .coming-soon {
         margin: 0 auto;
         font-size: 1.3em;
      }

      .timer {
         width: 5em;
         margin: 0 auto 1em;
      }

      .timer .number {
         font-size: 2.8em;
      }

      .timer .days {
         font-size: 1.1em;
      }

      .urgent-call .description {
         font-size: .85em;
         line-height: 140%;
      }

      .petition .button {
         width: 100px;
         margin: 1em auto 0;
         font-size: .6em;
      }
   }

   @media all and (min-width: 1600px) {
      h1 {
         font-size: 5.25em;
      }

      h2 {
         font-size: 1.8em;
      }

      .coming-soon {
         font-size: 2.25em;
      }

      .in {
         font-size: 1.2em;
      }

      .timer {
         width: 10em;
         margin: 0.5em auto 2em;
      }

      .timer .number {
         font-size: 6em;
      }

      .timer .days {
         font-size: 2.25em;
      }

      .urgent-call .description {
         line-height: 3em;
      }

      .urgent-call .first, .urgent-call .third {
         font-size: 1.5em;
      }

      .urgent-call .second {
         font-size: 1.8em;
      }

      .petition .button {
         width: 180px;
         margin: .8em auto 0;
         padding: 5px;
         font-size: 1.2em;
      }
   }
";
<commit_msg>More margin adjustments on the coming soon page.<commit_after>#[macro_use]
extern crate apache2;

use apache2::{Request, Status};

apache2_module!(coming_soon_handler, c_coming_soon_handler, coming_soon_module, b"mod_coming_soon\0");

macro_rules! html_template {() => ("<!doctype html>

      <meta charset=\"utf-8\">
      <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">
      <title>PolyDraw – Coming Soon</title>
      <meta name=\"description\" content=\"PolyDraw website is coming soon\">
      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">

      <link href=\"https://fonts.googleapis.com/css?family=Fira+Sans:300,500\" rel=\"stylesheet\" type=\"text/css\">
      <link href=\"https://fonts.googleapis.com/css?family=Roboto+Condensed:400\" rel=\"stylesheet\" type=\"text/css\">
      <link href=\"https://fonts.googleapis.com/css?family=Khand:400\" rel=\"stylesheet\" type=\"text/css\">

PolyDraw

Open source software development

COMING SOON

in

000

days

                  In the meantime, please sign the international petition against

ORGAN HARVESTING

from Falun Gong practitioners in China!

                  JOIN THE PETITION!

")}

fn coming_soon_handler(r: &mut Request) -> Status {
   if r.handler().unwrap() != "coming-soon" || r.uri().unwrap() != "/" {
      return Status::DECLINED
   }

   r.set_content_type("text/html");

   r.write(format!(
      html_template!(),
      STYLESHEET
   ));

   Status::OK
}

const STYLESHEET: &'static str = "
   html, body {
      height: 100%;
      width: 100%;
      margin: 0;
   }

   body {
      display: block;
      font-family: 'Roboto Condensed', sans-serif;
      background-image: url(https://www.polydraw.com/img/mountain-mist.jpg);
      background-size: cover;
      background-repeat: no-repeat;
      background-attachment: fixed;
      background-position: right bottom;
   }

   main {
      display: block;
      position: relative;
      top: 50%;
      margin: 0 auto;
      -webkit-transform: translateY(-50%);
      -ms-transform: translateY(-50%);
      transform: translateY(-50%);
   }

   h1 {
      display: block;
      width: 60%;
      margin: 0 auto;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 500;
      font-size: 3.5em;
      color: white;
      text-align: center;
   }

   h2 {
      display: block;
      width: 70%;
      margin: -0.2em auto 0;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 300;
      font-size: 1.2em;
      color: #5b5b5b;
      text-align: center;
   }

   .coming-soon {
      display: block;
      width: 40%;
      margin: 2.5em auto .1em;
      font-size: 1.5em;
      color: white;
      text-align: center;
   }

   .in {
      display: block;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 300;
      font-size: .8em;
      font-style: italic;
      color: white;
      text-align: center;
   }

   .timer {
      display: block;
      width: 7em;
      text-align: center;
      border-style: solid none solid none;
      border-color: #e6e6e6;
      border-width: 1px;
      margin: 0 auto 1em;
   }

   .timer .number {
      display: block;
      font-family: 'Khand', sans-serif;
      font-size: 4em;
      font-weight: bold;
      color: white;
      text-align: center;
   }

   .timer .days {
      display: block;
      font-family: 'Khand', sans-serif;
      font-size: 1.5em;
      color: white;
      text-align: center;
      margin: -1em auto 0;
   }

   .urgent-call {
      margin: 3% auto 0;
   }

   .urgent-call .description {
      display: block;
      width: 100%;
      padding-top: 1em;
      padding-bottom: 1em;
      background: -webkit-linear-gradient(left, rgba(86,86,107,0), rgba(86,86,107,.25), rgba(86,86,107,0));
      background: linear-gradient(to right,rgba(86,86,107,0),rgba(86,86,107,.25),rgba(86,86,107,0));
   }

   .urgent-call .first, .urgent-call .second, .urgent-call .third {
      margin: 0 auto;
      width: 90%;
      color: white;
      font-size: 1em;
      text-align: center;
   }

   .urgent-call .first {
      margin-bottom: 0.25em;
   }

   .urgent-call .second {
      width: 100%;
      color: #9c292e;
      font-family: 'Khand', sans-serif;
      font-weight: bold;
      font-size: 1.2em;
   }

   .petition .button {
      display: block;
      width: 120px;
      margin: 1em auto 0;
      padding: 3px 6px;
      background: #829776;
      color: #ffffff;
      font-family: 'Fira Sans', sans-serif;
      font-size: .85em;
      font-weight: 300;
      text-align: center;
      text-decoration: none;
      border: solid #ffffff 1px;
      border-radius: 3px;
   }

   .petition .button:hover {
      background: #4d6b3c;
   }

   footer {
      display: table;
      position: fixed;
      width: 96%;
      bottom: 0;
      padding-left: 2%;
      padding-right: 2%;
   }

   .social {
      display: block;
      vertical-align: middle;
      float: right;
   }

   .social a {
      display: inline-block;
      width: 28px;
      height: 28px;
      background-repeat: no-repeat;
      opacity: .5;
      margin-left: .5em;
   }

   .social a:hover {
      opacity: .9;
   }

   .social a.facebook {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAG1BMVEUAAADY2NjY2NjY2NjY2NhGRkZqamqFhYWtra1jMrL/AAAACXRSTlMAPGaw//////9HdVBWAAAAp0lEQVQoz42TQRLDIAwDVyb/f3GxegAGmJC0PhkWge0RYoYQxuvGSGKkTu9wohW3vQj2yAQoR4Zwh3fWaYAODEJwQWNltqAKEJXShSV71dVWGJCJLuy6+MxFEKwN8uGSPGraml+uaG9s9RuqvVX8FLvSgqJ5PPysdPASP5SP1AS5O2IuEkHRcfCuCFSOt1Y3J5wGkW5O8IFmDg/daTPYH9Z8N/X5O3wBpdI+PxtA6DIAAAAASUVORK5CYII=);
   }

   .social a.twitter {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAJFBMVEUAAADY2NjV1dXY2NjY2NjY2NjY2NhHR0empqaQkJBtbW3Dw8PQfCyMAAAADHRSTlMAPPVmwKD////////J66Z0AAAA5UlEQVQoz32T0ZKFIAxDT1qc/f+/3VFo9wFQXL23D+oQGpJQxVXCCHJdmB+lFQCq17yDclsoonXYx9NZ+dPy7PQbBEBro/MFw0gwUPJSKRAUewOJiqEbZu5QAUyITQBbVgAPwHUA5OHQO6N4zOMsAFpKW89lAw8FgLW+6XB1Hz9KcuY6XuEjt12XqBKn2bGwgMcpfe7a/XFRYQ+uUzRY9wdE7/DfCdX0cZp5l2jt5FI46QC5F5M4Fl31e/AOmW9oDbB+c89S9klI7POYkIvf4aJd05do5Y6IZTQhYjqsqvE/yLff4Q+6BFspw2Tr1AAAAABJRU5ErkJggg==);
   }

   .social a.github {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAJFBMVEUAAADY2NjY2NjY2NjY2NjY2NhHR0ebm5u3t7dYWFh3d3dqampwrbVmAAAADHRSTlMAPGbxsP////////80TrKnAAAA4UlEQVQoz32TwW7DMAxDH+ns/z94tbhDpDRBi+lkSCBN0bR4lxAh98YcVgxAaec51NKNIj1eANjmyR+AA8CLZxmqkR8zwAQMEl9KAsExQy+RXaPqxXEBl9gidnZDowGu0olxvBvqcUTSOgmGKlhudeU6JJWLbmmWXwXs04Ga1UaqVK/z9LsuT9+2/XxxovWkFwB2pjfI7ZaB8L6Q53aFdw44UqZb8dyek0R4WMUa5iybIEvNuv83XqBnDLqqgiH59p7JmYTwCd0TE3KLaHPWO315ZiV1jyZUFLUdl2D99x3+AND/ZE+Y11fiAAAAAElFTkSuQmCC);
   }

   @media all and (max-width: 319px) {
      main {
         margin: auto 0;
      }

      h1 {
         margin: -7% auto 0;
         font-size: 1.6em;
      }

      h2 {
         margin: 0 auto;
         font-size: .8em;
      }

      .coming-soon {
         margin: .7em auto 0;
         font-size: .8em;
      }

      .in {
         font-size: .7em;
      }

      .timer {
         width: 3em;
         margin: 0 auto .2em;
      }

      .timer .number {
         font-size: 2em;
      }

      .timer .days {
         font-size: .75em;
      }

      .urgent-call {
         margin: 0 auto;
      }

      .urgent-call .description {
         font-size: 0.7em;
      }

      .petition .button {
         width: 120px;
         margin: 1em auto 0;
         padding: 3px;
         font-size: .6em;
      }
   }

   @media all and (min-width: 320px) and (max-width: 460px) {
      h1 {
         margin: 0 auto;
         font-size: 2.5em;
      }

      h2 {
         margin: 0 auto 2em;
         font-size: .9em;
      }

      .coming-soon {
         margin: 0 auto;
         font-size: 1.3em;
      }

      .timer {
         width: 5em;
         margin: 0 auto 1em;
      }

      .timer .number {
         font-size: 2.8em;
      }

      .timer .days {
         font-size: 1.1em;
      }

      .urgent-call .description {
         font-size: .85em;
      }

      .petition .button {
         width: 100px;
         margin: 1em auto 0;
         font-size: .6em;
      }
   }

   @media all and (min-width: 1600px) {
      h1 {
         font-size: 5.25em;
      }

      h2 {
         font-size: 1.8em;
      }

      .coming-soon {
         font-size: 2.25em;
      }

      .in {
         font-size: 1.2em;
      }

      .timer {
         width: 10em;
         margin: 0.5em auto 2em;
      }

      .timer .number {
         font-size: 6em;
      }

      .timer .days {
         font-size: 2.25em;
      }

      .urgent-call .description {
      }

      .urgent-call .first, .urgent-call .third {
         font-size: 1.5em;
      }

      .urgent-call .second {
         font-size: 1.8em;
      }

      .petition .button {
         width: 180px;
         margin: .8em auto 0;
         padding: 5px;
         font-size: 1.2em;
      }
   }
";
<|endoftext|>


<commit_before>//! Contains high-level interface for a pull-based (StAX-like) FBX parser.

use std::io::Read;
use self::error::Result;

pub use self::error::{Error, ErrorKind};

mod error;
mod parser;

/// Format of FBX data
#[derive(Debug, Clone, Copy)]
pub enum FbxFormatType {
    /// Binary FBX, with version (for example, 7400 for FBX 7.4).
    Binary(u32),
    /// ASCII FBX.
    Text,
}

/// A node of an FBX input stream.
///
/// Items of this enum are emitted by `reader::EventReader`.
#[derive(Debug, Clone)]
pub enum FbxEvent {
    /// Denotes start of FBX data.
    ///
    /// For Binary FBX, this item corresponds to magic binary.
    StartFbx(FbxFormatType),
    /// Denotes end of FBX data.
    ///
    /// NOTE: Current implementation of `reader::parser::BinaryParser` does not read to end of the
    ///       FBX stream.
    EndFbx,
    /// Denotes beginning of a node.
    StartNode {
        /// Node name.
        name: String,
        /// Node properties.
        properties: Vec<PropertyValue>,
    },
    /// Denotes end of a node.
    EndNode,
    /// Comment.
    ///
    /// Comment only appears in ASCII FBX.
    Comment(String),
}

/// A wrapper around an `std::io::Read` instance which provides pull-based FBX parsing.
pub struct EventReader<R: Read> {
    source: R,
    parser: parser::Parser,
}

impl<R: Read> EventReader<R> {
    /// Creates a new reader, consuming the given stream.
    pub fn new(source: R) -> Self {
        EventReader {
            source: source,
            parser: parser::Parser::new(),
        }
    }

    /// Pulls and returns next FBX event from the stream.
    pub fn next(&mut self) -> Result<FbxEvent> {
        self.parser.next(&mut self.source)
    }
}

impl <R: Read> IntoIterator for EventReader<R> {
    type Item = Result<FbxEvent>;
    type IntoIter = Events<R>;

    /// Consumes `EventReader` and returns an iterator (`Events`) over it.
    fn into_iter(self) -> Events<R> {
        Events {
            reader: self,
            finished: false,
        }
    }
}

/// An iterator over FBX events created from some type implementing `Read`.
///
/// When the next event is `reader::error::Error` or `reader::FbxEvent::EndFbx`, then it will be
/// returned by the iterator once, and then it will stop producing events.
pub struct Events<R: Read> {
    reader: EventReader<R>,
    finished: bool,
}

impl<R: Read> Iterator for Events<R> {
    type Item = Result<FbxEvent>;

    fn next(&mut self) -> Option<Result<FbxEvent>> {
        if self.finished {
            None
        } else {
            let ev = self.reader.next();
            match ev {
                Ok(FbxEvent::EndFbx) | Err(_) => self.finished = true,
                _ => {}
            }
            Some(ev)
        }
    }
}

/// A property type of the FBX node.
#[derive(Debug, Clone, PartialEq)]
pub enum PropertyValue {
    /// Boolean.
    Bool(bool),
    /// 2 byte signed integer.
    I16(i16),
    /// 4 byte signed integer.
    I32(i32),
    /// 8 byte signed integer.
    I64(i64),
    /// 4 byte single-precision IEEE 754 floating-point number.
    F32(f32),
    /// 8 byte double-precision IEEE 754 floating-point number.
    F64(f64),
    /// Array of boolean.
    VecBool(Vec<bool>),
    /// Array of 4 byte signed integer.
    VecI32(Vec<i32>),
    /// Array of 8 byte signed integer.
    VecI64(Vec<i64>),
    /// Array of 4 byte single-precision IEEE 754 number.
    VecF32(Vec<f32>),
    /// Array of 8 byte double-precision IEEE 754 number.
    VecF64(Vec<f64>),
    /// String.
    ///
    /// Note that the string can contain special character like `\u{0}`.
    String(String),
    /// Raw binary data.
    Binary(Vec<u8>),
}
<commit_msg>Add `reader::Events::into_inner()` to get internal reader<commit_after>//! Contains high-level interface for a pull-based (StAX-like) FBX parser.

use std::io::Read;
use self::error::Result;

pub use self::error::{Error, ErrorKind};

mod error;
mod parser;

/// Format of FBX data
#[derive(Debug, Clone, Copy)]
pub enum FbxFormatType {
    /// Binary FBX, with version (for example, 7400 for FBX 7.4).
    Binary(u32),
    /// ASCII FBX.
    Text,
}

/// A node of an FBX input stream.
///
/// Items of this enum are emitted by `reader::EventReader`.
#[derive(Debug, Clone)]
pub enum FbxEvent {
    /// Denotes start of FBX data.
    ///
    /// For Binary FBX, this item corresponds to magic binary.
    StartFbx(FbxFormatType),
    /// Denotes end of FBX data.
    ///
    /// NOTE: Current implementation of `reader::parser::BinaryParser` does not read to end of the
    ///       FBX stream.
    EndFbx,
    /// Denotes beginning of a node.
    StartNode {
        /// Node name.
        name: String,
        /// Node properties.
        properties: Vec<PropertyValue>,
    },
    /// Denotes end of a node.
    EndNode,
    /// Comment.
    ///
    /// Comment only appears in ASCII FBX.
    Comment(String),
}

/// A wrapper around an `std::io::Read` instance which provides pull-based FBX parsing.
pub struct EventReader<R: Read> {
    source: R,
    parser: parser::Parser,
}

impl<R: Read> EventReader<R> {
    /// Creates a new reader, consuming the given stream.
    pub fn new(source: R) -> Self {
        EventReader {
            source: source,
            parser: parser::Parser::new(),
        }
    }

    /// Pulls and returns next FBX event from the stream.
    pub fn next(&mut self) -> Result<FbxEvent> {
        self.parser.next(&mut self.source)
    }
}

impl <R: Read> IntoIterator for EventReader<R> {
    type Item = Result<FbxEvent>;
    type IntoIter = Events<R>;

    /// Consumes `EventReader` and returns an iterator (`Events`) over it.
    fn into_iter(self) -> Events<R> {
        Events {
            reader: self,
            finished: false,
        }
    }
}

/// An iterator over FBX events created from some type implementing `Read`.
///
/// When the next event is `reader::error::Error` or `reader::FbxEvent::EndFbx`, then it will be
/// returned by the iterator once, and then it will stop producing events.
pub struct Events<R: Read> {
    reader: EventReader<R>,
    finished: bool,
}

impl<R: Read> Events<R> {
    /// Returns internal `EventReader`.
    #[allow(dead_code)]
    fn into_inner(self) -> EventReader<R> {
        self.reader
    }
}

impl<R: Read> Iterator for Events<R> {
    type Item = Result<FbxEvent>;

    fn next(&mut self) -> Option<Result<FbxEvent>> {
        if self.finished {
            None
        } else {
            let ev = self.reader.next();
            match ev {
                Ok(FbxEvent::EndFbx) | Err(_) => self.finished = true,
                _ => {}
            }
            Some(ev)
        }
    }
}

/// A property type of the FBX node.
#[derive(Debug, Clone, PartialEq)]
pub enum PropertyValue {
    /// Boolean.
    Bool(bool),
    /// 2 byte signed integer.
    I16(i16),
    /// 4 byte signed integer.
    I32(i32),
    /// 8 byte signed integer.
    I64(i64),
    /// 4 byte single-precision IEEE 754 floating-point number.
    F32(f32),
    /// 8 byte double-precision IEEE 754 floating-point number.
    F64(f64),
    /// Array of boolean.
    VecBool(Vec<bool>),
    /// Array of 4 byte signed integer.
    VecI32(Vec<i32>),
    /// Array of 8 byte signed integer.
    VecI64(Vec<i64>),
    /// Array of 4 byte single-precision IEEE 754 number.
    VecF32(Vec<f32>),
    /// Array of 8 byte double-precision IEEE 754 number.
    VecF64(Vec<f64>),
    /// String.
    ///
    /// Note that the string can contain special character like `\u{0}`.
    String(String),
    /// Raw binary data.
    Binary(Vec<u8>),
}
<|endoftext|>


<commit_before>use std::Option;

struct Tree<T> {
    root: Option<~Node<T>>
}
pub struct Node<T> {
    left_child: Option<~Node<T>>,
    right_child: Option<~Node<T>>,
    key: T
}

impl<T:Ord> Node<T> {
    pub fn new (nodeKey: T) -> Node<T> {
        Node {
            left_child: None,
            right_child: None,
            key: nodeKey
        }
    }

    pub fn add_child_node(&mut self, new_node: ~Node<T>) {
        if new_node.key > self.key {
            self.add_right_child(new_node);
        }
        else {
            self.add_left_child(new_node);
        }
    }

    fn add_right_child(&mut self, new_node: ~Node<T>) {
        match self.right_child {
            None => {
                self.right_child = Some(new_node);
            },
            Some(ref mut right_child) => {
                right_child.add_child_node(new_node);
            }
        }
    }

    fn add_left_child(&mut self, new_node: ~Node<T>) {
        match self.left_child {
            None => {
                self.left_child = Some(new_node);
            },
            Some(ref mut left_child) => {
                left_child.add_child_node(new_node);
            }
        }
    }

    pub fn has_children(node: &Node<T>) -> bool {
        match node.left_child {
            Some(_) => true,
            _ => {
                match node.right_child {
                    Some(_) => true,
                    _ => false
                }
            }
        }
    }
}

pub impl<T:Ord> Tree<T> {
    pub fn new () -> Tree<T> {
        Tree {
            root: None
        }
    }

    fn insert_value (&mut self, value: T) {
        let new_node = ~Node::new(value);
        self.insert_node(new_node);
    }

    fn insert_node (&mut self, new_node: ~Node<T>) {
        match self.root {
            None => {
                self.root = Some(new_node);
            },
            Some(ref mut n) => {
                n.add_child_node(new_node);
            }
        }
    }
}

fn main () {
    let mut myTree: Tree<int> = Tree::new();

    myTree.insert_value(3);
    myTree.insert_value(2);
    myTree.insert_value(4);
}
<commit_msg>Add visit_in_order implementation for the tree.<commit_after>use std::Option;

struct Tree<T> {
    root: Option<~Node<T>>
}
pub struct Node<T> {
    left_child: Option<~Node<T>>,
    right_child: Option<~Node<T>>,
    key: T
}

impl<T:Ord> Node<T> {
    pub fn new (nodeKey: T) -> Node<T> {
        Node {
            left_child: None,
            right_child: None,
            key: nodeKey
        }
    }

    pub fn add_child_node(&mut self, new_node: ~Node<T>) {
        if new_node.key > self.key {
            self.add_right_child(new_node);
        }
        else {
            self.add_left_child(new_node);
        }
    }

    fn add_right_child(&mut self, new_node: ~Node<T>) {
        match self.right_child {
            None => {
                self.right_child = Some(new_node);
            },
            Some(ref mut right_child) => {
                right_child.add_child_node(new_node);
            }
        }
    }

    fn add_left_child(&mut self, new_node: ~Node<T>) {
        match self.left_child {
            None => {
                self.left_child = Some(new_node);
            },
            Some(ref mut left_child) => {
                left_child.add_child_node(new_node);
            }
        }
    }

    pub fn has_children(node: &Node<T>) -> bool {
        match node.left_child {
            Some(_) => true,
            _ => {
                match node.right_child {
                    Some(_) => true,
                    _ => false
                }
            }
        }
    }

    pub fn visit_in_order(&self, visitor: &fn(&Node<T>)) {
        match self.left_child {
            Some (ref n) => {
                n.visit_in_order(visitor);
            },
            _ => {}
        }

        visitor(self);

        match self.right_child {
            Some (ref n) => {
                n.visit_in_order(visitor);
            },
            _ => {}
        }
    }
}

pub impl<T:Ord> Tree<T> {
    pub fn new () -> Tree<T> {
        Tree {
            root: None
        }
    }

    fn insert_value (&mut self, value: T) {
        let new_node = ~Node::new(value);
        self.insert_node(new_node);
    }

    fn insert_node (&mut self, new_node: ~Node<T>) {
        match self.root {
            None => {
                self.root = Some(new_node);
            },
            Some(ref mut n) => {
                n.add_child_node(new_node);
            }
        }
    }

    fn visit_in_order (&self, visitor: &fn(&Node<T>)) {
        match self.root {
            Some(ref n) => {
                n.visit_in_order(visitor);
            },
            _ => {
            }
        }
    }
}

fn main () {
    let mut myTree: Tree<int> = Tree::new();

    myTree.insert_value(3);
    myTree.insert_value(2);
    myTree.insert_value(4);
    myTree.insert_value(0);

    myTree.visit_in_order(|n| {
                          std::io::println(fmt!("%d", n.key));
                          });
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use crate::controllers::frontend_prelude::*;

use crate::controllers::helpers::*;

use crate::controllers::helpers::pagination::{Paginated, PaginationOptions};
use crate::models::{
    CrateOwner, Email, Follow, NewEmail, OwnerKind, User, Version, VersionOwnerAction,
};
use crate::schema::{crate_owners, crates, emails, follows, users, versions};
use crate::views::{EncodableMe, EncodablePrivateUser, EncodableVersion, OwnedCrate};

/// Handles the `GET /me` route.
pub fn me(req: &mut dyn RequestExt) -> EndpointResult {
    let user_id = req.authenticate()?.forbid_api_token_auth()?.user_id();
    let conn = req.db_conn()?;

    let (user, verified, email, verification_sent): (User, Option<bool>, Option<String>, bool) =
        users::table
            .find(user_id)
            .left_join(emails::table)
            .select((
                users::all_columns,
                emails::verified.nullable(),
                emails::email.nullable(),
                emails::token_generated_at.nullable().is_not_null(),
            ))
            .first(&*conn)?;

    let owned_crates = CrateOwner::by_owner_kind(OwnerKind::User)
        .inner_join(crates::table)
        .filter(crate_owners::owner_id.eq(user_id))
        .select((crates::id, crates::name, crate_owners::email_notifications))
        .order(crates::name.asc())
        .load(&*conn)?
        .into_iter()
        .map(|(id, name, email_notifications)| OwnedCrate {
            id,
            name,
            email_notifications,
        })
        .collect();

    let verified = verified.unwrap_or(false);
    let verification_sent = verified || verification_sent;
    Ok(req.json(&EncodableMe {
        user: EncodablePrivateUser::from(user, email, verified, verification_sent),
        owned_crates,
    }))
}

/// Handles the `GET /me/updates` route.
pub fn updates(req: &mut dyn RequestExt) -> EndpointResult {
    use diesel::dsl::any;

    let authenticated_user = req.authenticate()?.forbid_api_token_auth()?;
    let user = authenticated_user.user();

    let followed_crates = Follow::belonging_to(&user).select(follows::crate_id);
    let query = versions::table
        .inner_join(crates::table)
        .left_outer_join(users::table)
        .filter(crates::id.eq(any(followed_crates)))
        .order(versions::created_at.desc())
        .select((
            versions::all_columns,
            crates::name,
            users::all_columns.nullable(),
        ))
        .pages_pagination(PaginationOptions::builder().gather(req)?);
    let conn = req.db_conn()?;
    let data: Paginated<(Version, String, Option<User>)> = query.load(&*conn)?;
    let more = data.next_page_params().is_some();
    let versions = data.iter().map(|(v, _, _)| v).cloned().collect::<Vec<_>>();
    let data = data
        .into_iter()
        .zip(VersionOwnerAction::for_versions(&conn, &versions)?.into_iter())
        .map(|((v, cn, pb), voas)| (v, cn, pb, voas))
        .collect::<Vec<_>>();

    let versions = data
        .into_iter()
        .map(|(version, crate_name, published_by, actions)| {
            EncodableVersion::from(version, &crate_name, published_by, actions)
        })
        .collect();

    #[derive(Serialize)]
    struct R {
        versions: Vec<EncodableVersion>,
        meta: Meta,
    }
    #[derive(Serialize)]
    struct Meta {
        more: bool,
    }
    Ok(req.json(&R {
        versions,
        meta: Meta { more },
    }))
}

/// Handles the `PUT /users/:user_id` route.
pub fn update_user(req: &mut dyn RequestExt) -> EndpointResult {
    use self::emails::user_id;
    use diesel::insert_into;

    let authenticated_user = req.authenticate()?;

    let mut body = String::new();
    req.body().read_to_string(&mut body)?;

    let param_user_id = &req.params()["user_id"];
    let conn = req.db_conn()?;
    let user = authenticated_user.user();

    // need to check if current user matches user to be updated
    if &user.id.to_string() != param_user_id {
        return Err(bad_request("current user does not match requested user"));
    }

    #[derive(Deserialize)]
    struct UserUpdate {
        user: User,
    }

    #[derive(Deserialize)]
    struct User {
        email: Option<String>,
    }

    let user_update: UserUpdate =
        serde_json::from_str(&body).map_err(|_| bad_request("invalid json request"))?;

    let user_email = match &user_update.user.email {
        Some(email) => email.trim(),
        None => return Err(bad_request("empty email rejected")),
    };

    if user_email.is_empty() {
        return Err(bad_request("empty email rejected"));
    }

    conn.transaction::<_, Box<dyn AppError>, _>(|| {
        let new_email = NewEmail {
            user_id: user.id,
            email: user_email,
        };

        let token: String = insert_into(emails::table)
            .values(&new_email)
            .on_conflict(user_id)
            .do_update()
            .set(&new_email)
            .returning(emails::token)
            .get_result(&*conn)
            .map_err(|_| server_error("Error in creating token"))?;

        // This swallows any errors that occur while attempting to send the email. Some users have
        // an invalid email set in their GitHub profile, and we should let them sign in even though
        // we're trying to silently use their invalid address during signup and can't send them an
        // email. They'll then have to provide a valid email address.
        let _ = req
            .app()
            .emails
            .send_user_confirm(user_email, &user.gh_login, &token);

        Ok(())
    })?;

    ok_true()
}

/// Handles the `PUT /confirm/:email_token` route
pub fn confirm_user_email(req: &mut dyn RequestExt) -> EndpointResult {
    use diesel::update;

    let conn = req.db_conn()?;
    let req_token = &req.params()["email_token"];

    let updated_rows = update(emails::table.filter(emails::token.eq(req_token)))
        .set(emails::verified.eq(true))
        .execute(&*conn)?;

    if updated_rows == 0 {
        return Err(bad_request("Email belonging to token not found."));
    }

    ok_true()
}

/// Handles `PUT /user/:user_id/resend` route
pub fn regenerate_token_and_send(req: &mut dyn RequestExt) -> EndpointResult {
    use diesel::dsl::sql;
    use diesel::update;

    let param_user_id = req.params()["user_id"]
        .parse::<i32>()
        .chain_error(|| bad_request("invalid user_id"))?;
    let authenticated_user = req.authenticate()?;
    let conn = req.db_conn()?;
    let user = authenticated_user.user();

    // need to check if current user matches user to be updated
    if user.id != param_user_id {
        return Err(bad_request("current user does not match requested user"));
    }

    conn.transaction(|| {
        let email: Email = update(Email::belonging_to(&user))
            .set(emails::token.eq(sql("DEFAULT")))
            .get_result(&*conn)
            .map_err(|_| bad_request("Email could not be found"))?;

        req.app()
            .emails
            .send_user_confirm(&email.email, &user.gh_login, &email.token)
    })?;

    ok_true()
}

/// Handles `PUT /me/email_notifications` route
pub fn update_email_notifications(req: &mut dyn RequestExt) -> EndpointResult {
    use self::crate_owners::dsl::*;
    use diesel::pg::upsert::excluded;

    #[derive(Deserialize)]
    struct CrateEmailNotifications {
        id: i32,
        email_notifications: bool,
    }

    let mut body = String::new();
    req.body().read_to_string(&mut body)?;
    let updates: HashMap<i32, bool> = serde_json::from_str::<Vec<CrateEmailNotifications>>(&body)
        .map_err(|_| bad_request("invalid json request"))?
        .iter()
        .map(|c| (c.id, c.email_notifications))
        .collect();

    let user_id = req.authenticate()?.user_id();
    let conn = req.db_conn()?;

    // Build inserts from existing crates belonging to the current user
    let to_insert = CrateOwner::by_owner_kind(OwnerKind::User)
        .filter(owner_id.eq(user_id))
        .select((crate_id, owner_id, owner_kind, email_notifications))
        .load(&*conn)?
        .into_iter()
        // Remove records whose `email_notifications` will not change from their current value
        .map(
            |(c_id, o_id, o_kind, e_notifications): (i32, i32, i32, bool)| {
                let current_e_notifications = *updates.get(&c_id).unwrap_or(&e_notifications);
                (
                    crate_id.eq(c_id),
                    owner_id.eq(o_id),
                    owner_kind.eq(o_kind),
                    email_notifications.eq(current_e_notifications),
                )
            },
        )
        .collect::<Vec<_>>();

    // Upsert crate owners; this should only actually exectute updates
    diesel::insert_into(crate_owners)
        .values(&to_insert)
        .on_conflict((crate_id, owner_id, owner_kind))
        .do_update()
        .set(email_notifications.eq(excluded(email_notifications)))
        .execute(&*conn)?;

    ok_true()
}
<commit_msg>Fix clippy warning<commit_after>use std::collections::HashMap;

use crate::controllers::frontend_prelude::*;

use crate::controllers::helpers::*;

use crate::controllers::helpers::pagination::{Paginated, PaginationOptions};
use crate::models::{
    CrateOwner, Email, Follow, NewEmail, OwnerKind, User, Version, VersionOwnerAction,
};
use crate::schema::{crate_owners, crates, emails, follows, users, versions};
use crate::views::{EncodableMe, EncodablePrivateUser, EncodableVersion, OwnedCrate};

/// Handles the `GET /me` route.
pub fn me(req: &mut dyn RequestExt) -> EndpointResult {
    let user_id = req.authenticate()?.forbid_api_token_auth()?.user_id();
    let conn = req.db_conn()?;

    let (user, verified, email, verification_sent): (User, Option<bool>, Option<String>, bool) =
        users::table
            .find(user_id)
            .left_join(emails::table)
            .select((
                users::all_columns,
                emails::verified.nullable(),
                emails::email.nullable(),
                emails::token_generated_at.nullable().is_not_null(),
            ))
            .first(&*conn)?;

    let owned_crates = CrateOwner::by_owner_kind(OwnerKind::User)
        .inner_join(crates::table)
        .filter(crate_owners::owner_id.eq(user_id))
        .select((crates::id, crates::name, crate_owners::email_notifications))
        .order(crates::name.asc())
        .load(&*conn)?
        .into_iter()
        .map(|(id, name, email_notifications)| OwnedCrate {
            id,
            name,
            email_notifications,
        })
        .collect();

    let verified = verified.unwrap_or(false);
    let verification_sent = verified || verification_sent;
    Ok(req.json(&EncodableMe {
        user: EncodablePrivateUser::from(user, email, verified, verification_sent),
        owned_crates,
    }))
}

/// Handles the `GET /me/updates` route.
pub fn updates(req: &mut dyn RequestExt) -> EndpointResult {
    use diesel::dsl::any;

    let authenticated_user = req.authenticate()?.forbid_api_token_auth()?;
    let user = authenticated_user.user();

    let followed_crates = Follow::belonging_to(&user).select(follows::crate_id);
    let query = versions::table
        .inner_join(crates::table)
        .left_outer_join(users::table)
        .filter(crates::id.eq(any(followed_crates)))
        .order(versions::created_at.desc())
        .select((
            versions::all_columns,
            crates::name,
            users::all_columns.nullable(),
        ))
        .pages_pagination(PaginationOptions::builder().gather(req)?);
    let conn = req.db_conn()?;
    let data: Paginated<(Version, String, Option<User>)> = query.load(&*conn)?;
    let more = data.next_page_params().is_some();
    let versions = data.iter().map(|(v, _, _)| v).cloned().collect::<Vec<_>>();
    let data = data
        .into_iter()
        .zip(VersionOwnerAction::for_versions(&conn, &versions)?.into_iter())
        .map(|((v, cn, pb), voas)| (v, cn, pb, voas));

    let versions = data
        .into_iter()
        .map(|(version, crate_name, published_by, actions)| {
            EncodableVersion::from(version, &crate_name, published_by, actions)
        })
        .collect();

    #[derive(Serialize)]
    struct R {
        versions: Vec<EncodableVersion>,
        meta: Meta,
    }
    #[derive(Serialize)]
    struct Meta {
        more: bool,
    }
    Ok(req.json(&R {
        versions,
        meta: Meta { more },
    }))
}

/// Handles the `PUT /users/:user_id` route.
pub fn update_user(req: &mut dyn RequestExt) -> EndpointResult {
    use self::emails::user_id;
    use diesel::insert_into;

    let authenticated_user = req.authenticate()?;

    let mut body = String::new();
    req.body().read_to_string(&mut body)?;

    let param_user_id = &req.params()["user_id"];
    let conn = req.db_conn()?;
    let user = authenticated_user.user();

    // need to check if current user matches user to be updated
    if &user.id.to_string() != param_user_id {
        return Err(bad_request("current user does not match requested user"));
    }

    #[derive(Deserialize)]
    struct UserUpdate {
        user: User,
    }

    #[derive(Deserialize)]
    struct User {
        email: Option<String>,
    }

    let user_update: UserUpdate =
        serde_json::from_str(&body).map_err(|_| bad_request("invalid json request"))?;

    let user_email = match &user_update.user.email {
        Some(email) => email.trim(),
        None => return Err(bad_request("empty email rejected")),
    };

    if user_email.is_empty() {
        return Err(bad_request("empty email rejected"));
    }

    conn.transaction::<_, Box<dyn AppError>, _>(|| {
        let new_email = NewEmail {
            user_id: user.id,
            email: user_email,
        };

        let token: String = insert_into(emails::table)
            .values(&new_email)
            .on_conflict(user_id)
            .do_update()
            .set(&new_email)
            .returning(emails::token)
            .get_result(&*conn)
            .map_err(|_| server_error("Error in creating token"))?;

        // This swallows any errors that occur while attempting to send the email. Some users have
        // an invalid email set in their GitHub profile, and we should let them sign in even though
        // we're trying to silently use their invalid address during signup and can't send them an
        // email. They'll then have to provide a valid email address.
        let _ = req
            .app()
            .emails
            .send_user_confirm(user_email, &user.gh_login, &token);

        Ok(())
    })?;

    ok_true()
}

/// Handles the `PUT /confirm/:email_token` route
pub fn confirm_user_email(req: &mut dyn RequestExt) -> EndpointResult {
    use diesel::update;

    let conn = req.db_conn()?;
    let req_token = &req.params()["email_token"];

    let updated_rows = update(emails::table.filter(emails::token.eq(req_token)))
        .set(emails::verified.eq(true))
        .execute(&*conn)?;

    if updated_rows == 0 {
        return Err(bad_request("Email belonging to token not found."));
    }

    ok_true()
}

/// Handles `PUT /user/:user_id/resend` route
pub fn regenerate_token_and_send(req: &mut dyn RequestExt) -> EndpointResult {
    use diesel::dsl::sql;
    use diesel::update;

    let param_user_id = req.params()["user_id"]
        .parse::<i32>()
        .chain_error(|| bad_request("invalid user_id"))?;
    let authenticated_user = req.authenticate()?;
    let conn = req.db_conn()?;
    let user = authenticated_user.user();

    // need to check if current user matches user to be updated
    if user.id != param_user_id {
        return Err(bad_request("current user does not match requested user"));
    }

    conn.transaction(|| {
        let email: Email = update(Email::belonging_to(&user))
            .set(emails::token.eq(sql("DEFAULT")))
            .get_result(&*conn)
            .map_err(|_| bad_request("Email could not be found"))?;

        req.app()
            .emails
            .send_user_confirm(&email.email, &user.gh_login, &email.token)
    })?;

    ok_true()
}

/// Handles `PUT /me/email_notifications` route
pub fn update_email_notifications(req: &mut dyn RequestExt) -> EndpointResult {
    use self::crate_owners::dsl::*;
    use diesel::pg::upsert::excluded;

    #[derive(Deserialize)]
    struct CrateEmailNotifications {
        id: i32,
        email_notifications: bool,
    }

    let mut body = String::new();
    req.body().read_to_string(&mut body)?;
    let updates: HashMap<i32, bool> = serde_json::from_str::<Vec<CrateEmailNotifications>>(&body)
        .map_err(|_| bad_request("invalid json request"))?
        .iter()
        .map(|c| (c.id, c.email_notifications))
        .collect();

    let user_id = req.authenticate()?.user_id();
    let conn = req.db_conn()?;

    // Build inserts from existing crates belonging to the current user
    let to_insert = CrateOwner::by_owner_kind(OwnerKind::User)
        .filter(owner_id.eq(user_id))
        .select((crate_id, owner_id, owner_kind, email_notifications))
        .load(&*conn)?
        .into_iter()
        // Remove records whose `email_notifications` will not change from their current value
        .map(
            |(c_id, o_id, o_kind, e_notifications): (i32, i32, i32, bool)| {
                let current_e_notifications = *updates.get(&c_id).unwrap_or(&e_notifications);
                (
                    crate_id.eq(c_id),
                    owner_id.eq(o_id),
                    owner_kind.eq(o_kind),
                    email_notifications.eq(current_e_notifications),
                )
            },
        )
        .collect::<Vec<_>>();

    // Upsert crate owners; this should only actually exectute updates
    diesel::insert_into(crate_owners)
        .values(&to_insert)
        .on_conflict((crate_id, owner_id, owner_kind))
        .do_update()
        .set(email_notifications.eq(excluded(email_notifications)))
        .execute(&*conn)?;

    ok_true()
}
<|endoftext|>


<commit_before>//! Models for JSONI (JSON Interface)

#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct XtensisObject {
    version: String,
    direction: String,
    comm_type: String,
}

#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct BufferObject {
    uuid: String,
    active: bool,
    temporary: bool,
    major_mode: String,
    minor_modes: Vec<String>,
    read_only: bool,
    dirty: bool,
}

#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct BufferResponse {
    xtensis: XtensisObject,
    buffer: BufferObject,
}
<commit_msg>Add `file_path` field<commit_after>//! Models for JSONI (JSON Interface)

#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct XtensisObject {
    version: String,
    direction: String,
    comm_type: String,
}

#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct BufferObject {
    uuid: String,
    file_path: String,
    active: bool,
    temporary: bool,
    major_mode: String,
    minor_modes: Vec<String>,
    read_only: bool,
    dirty: bool,
}

#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct BufferResponse {
    xtensis: XtensisObject,
    buffer: BufferObject,
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

#[forbid(deprecated_mode)];
//! Additional general-purpose comparison functionality.

use core::f32;
use core::f64;
use core::float;

const fuzzy_epsilon: float = 1.0e-6;

pub trait FuzzyEq {
    pure fn fuzzy_eq(&self, other: &self) -> bool;
}

impl float: FuzzyEq {
    pure fn fuzzy_eq(&self, other: &float) -> bool {
        float::abs(*self - *other) < fuzzy_epsilon
    }
}

impl f32: FuzzyEq {
    pure fn fuzzy_eq(&self, other: &f32) -> bool {
        f32::abs(*self - *other) < (fuzzy_epsilon as f32)
    }
}

impl f64: FuzzyEq {
    pure fn fuzzy_eq(&self, other: &f64) -> bool {
        f64::abs(*self - *other) < (fuzzy_epsilon as f64)
    }
}

#[test]
fn test_fuzzy_equals() {
    assert (&1.0).fuzzy_eq(&1.0);
    assert (&1.0f32).fuzzy_eq(&1.0f32);
    assert (&1.0f64).fuzzy_eq(&1.0f64);
}
<commit_msg>add a FuzzyEq method that accepts an epsilon value<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[forbid(deprecated_mode)];
//! Additional general-purpose comparison functionality.

use core::f32;
use core::f64;
use core::float;

const fuzzy_epsilon: float = 1.0e-6;

pub trait FuzzyEq {
    pure fn fuzzy_eq(&self, other: &self) -> bool;
    pure fn fuzzy_eq_eps(&self, other: &self, epsilon: &self) -> bool;
}

impl float: FuzzyEq {
    pure fn fuzzy_eq(&self, other: &float) -> bool {
        float::abs(*self - *other) < fuzzy_epsilon
    }

    pure fn fuzzy_eq_eps(&self, other: &float, epsilon: &float) -> bool {
        float::abs(*self - *other) < *epsilon
    }
}

impl f32: FuzzyEq {
    pure fn fuzzy_eq(&self, other: &f32) -> bool {
        f32::abs(*self - *other) < (fuzzy_epsilon as f32)
    }

    pure fn fuzzy_eq_eps(&self, other: &f32, epsilon: &f32) -> bool {
        f32::abs(*self - *other) < *epsilon
    }
}

impl f64: FuzzyEq {
    pure fn fuzzy_eq(&self, other: &f64) -> bool {
        f64::abs(*self - *other) < (fuzzy_epsilon as f64)
    }

    pure fn fuzzy_eq_eps(&self, other: &f64, epsilon: &f64) -> bool {
        f64::abs(*self - *other) < *epsilon
    }
}

#[test]
fn test_fuzzy_equals() {
    assert (&1.0).fuzzy_eq(&1.0);
    assert (&1.0f32).fuzzy_eq(&1.0f32);
    assert (&1.0f64).fuzzy_eq(&1.0f64);
}

#[test]
fn test_fuzzy_eq_eps() {
    assert (&1.2).fuzzy_eq_eps(&0.9, &0.5);
    assert !(&1.5).fuzzy_eq_eps(&0.9, &0.5);
}
<|endoftext|>


<commit_before>import future_spawn = future::spawn;

export map, mapi, alli, any, mapi_factory;

/**
 * The maximum number of tasks this module will spawn for a single
 * operation.
 */
const max_tasks : uint = 32u;

/// The minimum number of elements each task will process.
const min_granularity : uint = 1024u;

/**
 * An internal helper to map a function over a large vector and
 * return the intermediate results.
 *
 * This is used to build most of the other parallel vector functions,
 * like map or alli.
 */
fn map_slices<A: copy send, B: copy send>(
    xs: ~[A],
    f: fn() -> fn~(uint, v: &[A]) -> B)
    -> ~[B] {

    let len = xs.len();
    if len < min_granularity {
        log(info, ~"small slice");
        // This is a small vector, fall back on the normal map.
        ~[f()(0u, xs)]
    }
    else {
        let num_tasks = uint::min(max_tasks, len / min_granularity);

        let items_per_task = len / num_tasks;

        let mut futures = ~[];
        let mut base = 0u;
        log(info, ~"spawning tasks");
        while base < len {
            let end = uint::min(len, base + items_per_task);
            // FIXME: why is the ::<A, ()> annotation required here? (#2617)
            do vec::as_buf::<A, ()>(xs) |p, _len| {
                let f = f();
                let f = do future_spawn() |copy base| {
                    unsafe {
                        let len = end - base;
                        let slice = (ptr::offset(p, base),
                                     len * sys::size_of::<A>());
                        log(info, fmt!("pre-slice: %?", (base, slice)));
                        let slice : &[A] =
                            unsafe::reinterpret_cast(slice);
                        log(info, fmt!("slice: %?",
                                       (base, vec::len(slice), end - base)));
                        assert(vec::len(slice) == end - base);
                        f(base, slice)
                    }
                };
                vec::push(futures, f);
            };
            base += items_per_task;
        }
        log(info, ~"tasks spawned");

        log(info, fmt!("num_tasks: %?", (num_tasks, futures.len())));
        assert(num_tasks == futures.len());

        let r = do futures.map() |ys| {
            ys.get()
        };
        assert(r.len() == futures.len());
        r
    }
}

/// A parallel version of map.
fn map<A: copy send, B: copy send>(xs: ~[A], f: fn~(A) -> B) -> ~[B] {
    vec::concat(map_slices(xs, || {
        fn~(_base: uint, slice : &[A], copy f) -> ~[B] {
            vec::map(slice, |x| f(x))
        }
    }))
}

/// A parallel version of mapi.
fn mapi<A: copy send, B: copy send>(xs: ~[A],
                                    f: fn~(uint, A) -> B) -> ~[B] {
    let slices = map_slices(xs, || {
        fn~(base: uint, slice : &[A], copy f) -> ~[B] {
            vec::mapi(slice, |i, x| {
                f(i + base, x)
            })
        }
    });
    let r = vec::concat(slices);
    log(info, (r.len(), xs.len()));
    assert(r.len() == xs.len());
    r
}

/**
 * A parallel version of mapi.
 *
 * In this case, f is a function that creates functions to run over the
 * inner elements. This is to skirt the need for copy constructors.
 */
fn mapi_factory<A: copy send, B: copy send>(
    xs: ~[A], f: fn() -> fn~(uint, A) -> B) -> ~[B] {
    let slices = map_slices(xs, || {
        let f = f();
        fn~(base: uint, slice : &[A], move f) -> ~[B] {
            vec::mapi(slice, |i, x| {
                f(i + base, x)
            })
        }
    });
    let r = vec::concat(slices);
    log(info, (r.len(), xs.len()));
    assert(r.len() == xs.len());
    r
}

/// Returns true if the function holds for all elements in the vector.
fn alli<A: copy send>(xs: ~[A], f: fn~(uint, A) -> bool) -> bool {
    do vec::all(map_slices(xs, || {
        fn~(base: uint, slice : &[A], copy f) -> bool {
            vec::alli(slice, |i, x| {
                f(i + base, x)
            })
        }
    })) |x| { x }
}

/// Returns true if the function holds for any elements in the vector.
fn any<A: copy send>(xs: ~[A], f: fn~(A) -> bool) -> bool {
    do vec::any(map_slices(xs, || {
        fn~(_base : uint, slice: &[A], copy f) -> bool {
            vec::any(slice, |x| f(x))
        }
    })) |x| { x }
}
<commit_msg>Remove type annotation that is no longer necessary<commit_after>import future_spawn = future::spawn;

export map, mapi, alli, any, mapi_factory;

/**
 * The maximum number of tasks this module will spawn for a single
 * operation.
 */
const max_tasks : uint = 32u;

/// The minimum number of elements each task will process.
const min_granularity : uint = 1024u;

/**
 * An internal helper to map a function over a large vector and
 * return the intermediate results.
 *
 * This is used to build most of the other parallel vector functions,
 * like map or alli.
 */
fn map_slices<A: copy send, B: copy send>(
    xs: ~[A],
    f: fn() -> fn~(uint, v: &[A]) -> B)
    -> ~[B] {

    let len = xs.len();
    if len < min_granularity {
        log(info, ~"small slice");
        // This is a small vector, fall back on the normal map.
        ~[f()(0u, xs)]
    }
    else {
        let num_tasks = uint::min(max_tasks, len / min_granularity);

        let items_per_task = len / num_tasks;

        let mut futures = ~[];
        let mut base = 0u;
        log(info, ~"spawning tasks");
        while base < len {
            let end = uint::min(len, base + items_per_task);
            do vec::as_buf(xs) |p, _len| {
                let f = f();
                let f = do future_spawn() |copy base| {
                    unsafe {
                        let len = end - base;
                        let slice = (ptr::offset(p, base),
                                     len * sys::size_of::<A>());
                        log(info, fmt!("pre-slice: %?", (base, slice)));
                        let slice : &[A] =
                            unsafe::reinterpret_cast(slice);
                        log(info, fmt!("slice: %?",
                                       (base, vec::len(slice), end - base)));
                        assert(vec::len(slice) == end - base);
                        f(base, slice)
                    }
                };
                vec::push(futures, f);
            };
            base += items_per_task;
        }
        log(info, ~"tasks spawned");

        log(info, fmt!("num_tasks: %?", (num_tasks, futures.len())));
        assert(num_tasks == futures.len());

        let r = do futures.map() |ys| {
            ys.get()
        };
        assert(r.len() == futures.len());
        r
    }
}

/// A parallel version of map.
fn map<A: copy send, B: copy send>(xs: ~[A], f: fn~(A) -> B) -> ~[B] {
    vec::concat(map_slices(xs, || {
        fn~(_base: uint, slice : &[A], copy f) -> ~[B] {
            vec::map(slice, |x| f(x))
        }
    }))
}

/// A parallel version of mapi.
fn mapi<A: copy send, B: copy send>(xs: ~[A],
                                    f: fn~(uint, A) -> B) -> ~[B] {
    let slices = map_slices(xs, || {
        fn~(base: uint, slice : &[A], copy f) -> ~[B] {
            vec::mapi(slice, |i, x| {
                f(i + base, x)
            })
        }
    });
    let r = vec::concat(slices);
    log(info, (r.len(), xs.len()));
    assert(r.len() == xs.len());
    r
}

/**
 * A parallel version of mapi.
 *
 * In this case, f is a function that creates functions to run over the
 * inner elements. This is to skirt the need for copy constructors.
 */
fn mapi_factory<A: copy send, B: copy send>(
    xs: ~[A], f: fn() -> fn~(uint, A) -> B) -> ~[B] {
    let slices = map_slices(xs, || {
        let f = f();
        fn~(base: uint, slice : &[A], move f) -> ~[B] {
            vec::mapi(slice, |i, x| {
                f(i + base, x)
            })
        }
    });
    let r = vec::concat(slices);
    log(info, (r.len(), xs.len()));
    assert(r.len() == xs.len());
    r
}

/// Returns true if the function holds for all elements in the vector.
fn alli<A: copy send>(xs: ~[A], f: fn~(uint, A) -> bool) -> bool {
    do vec::all(map_slices(xs, || {
        fn~(base: uint, slice : &[A], copy f) -> bool {
            vec::alli(slice, |i, x| {
                f(i + base, x)
            })
        }
    })) |x| { x }
}

/// Returns true if the function holds for any elements in the vector.
fn any<A: copy send>(xs: ~[A], f: fn~(A) -> bool) -> bool {
    do vec::any(map_slices(xs, || {
        fn~(_base : uint, slice: &[A], copy f) -> bool {
            vec::any(slice, |x| f(x))
        }
    })) |x| { x }
}
<|endoftext|>