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

use assert_cmd::Command;
use proc_macro2::Span;
use quote::quote;
use std::{fs::File, io::Write, path::Path};
use syn::Token;
use tempdir::TempDir;

static INPUT_H: &str = indoc::indoc! {"
    inline int DoMath(int a) {
        return a * 3;
    }

    struct First {
        First() {}
        int foo;
    };

    struct Second {
        Second(const First& a) {}
        int bar;
    };
"};

#[test]
fn test_reduce_direct() -> Result<(), Box<dyn std::error::Error>> {
    do_reduce(|header, _| Ok(header.into()))
}

#[test]
fn test_reduce_preprocessed() -> Result<(), Box<dyn std::error::Error>> {
    do_reduce(|header, demo_code_dir| {
        let hexathorpe = Token![#](Span::call_site());
        write_to_file(
            &demo_code_dir,
            "main.rs",
            quote! {
                autocxx::include_cpp! {
                    #hexathorpe include #header
                    generate_all!()
                    safety(unsafe_ffi)
                }
            }
            .to_string()
            .as_bytes(),
        );
        let prepro = demo_code_dir.join("autocxx-preprocessed.h");
        let mut cmd = Command::cargo_bin("autocxx-gen")?;
        cmd.arg("--inc")
            .arg(demo_code_dir.to_str().unwrap())
            .arg(demo_code_dir.join("main.rs"))
            .env("AUTOCXX_PREPROCESS", prepro.to_str().unwrap())
            .arg("--outdir")
            .arg(demo_code_dir.to_str().unwrap())
            .arg("--gen-cpp")
            .assert()
            .success();
        Ok("autocxx-preprocessed.h".into())
    })
}

fn do_reduce<F>(get_header_name: F) -> Result<(), Box<dyn std::error::Error>>
where
    F: FnOnce(&str, &Path) -> Result<String, Box<dyn std::error::Error>>,
{
    if creduce_is_broken() {
        return Ok(());
    }
    let tmp_dir = TempDir::new("example")?;
    let demo_code_dir = tmp_dir.path().join("demo");
    std::fs::create_dir(&demo_code_dir).unwrap();
    write_to_file(&demo_code_dir, "input.h", INPUT_H.as_bytes());
    let output_path = tmp_dir.path().join("min.h");
    let header_name = get_header_name("input.h", &demo_code_dir)?;
    let mut cmd = Command::cargo_bin("autocxx-reduce")?;
    cmd.arg("--inc")
        .arg(demo_code_dir.to_str().unwrap())
        .arg("-h")
        .arg(header_name)
        .arg("-o")
        .arg(output_path.to_str().unwrap())
        .arg("-d")
        .arg("generate_all!()")
        .arg("-d")
        .arg("block!(\"First\")")
        .arg("-p")
        .arg("type marked as blocked")
        .arg("-k")
        .assert()
        .success();
    let minimized = std::fs::read_to_string(output_path)?;
    assert!(minimized.contains("First"));
    assert!(!minimized.contains("DoMath"));
    Ok(())
}

fn write_to_file(dir: &Path, filename: &str, content: &[u8]) {
    let path = dir.join(filename);
    let mut f = File::create(&path).expect("Unable to create file");
    f.write_all(content).expect("Unable to write file");
}

fn creduce_is_broken() -> bool {
    // On some machines, creduce immediately segfaults
    Command::new("creduce").arg("--version").ok().is_err()
}
<commit_msg>Ignore new test.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use assert_cmd::Command;
use proc_macro2::Span;
use quote::quote;
use std::{fs::File, io::Write, path::Path};
use syn::Token;
use tempdir::TempDir;

static INPUT_H: &str = indoc::indoc! {"
    inline int DoMath(int a) {
        return a * 3;
    }

    struct First {
        First() {}
        int foo;
    };

    struct Second {
        Second(const First& a) {}
        int bar;
    };
"};

#[test]
fn test_reduce_direct() -> Result<(), Box<dyn std::error::Error>> {
    do_reduce(|header, _| Ok(header.into()))
}

#[test]
#[ignore] // takes absolutely ages but you can run using cargo test -- --ignored
fn test_reduce_preprocessed() -> Result<(), Box<dyn std::error::Error>> {
    do_reduce(|header, demo_code_dir| {
        let hexathorpe = Token![#](Span::call_site());
        write_to_file(
            &demo_code_dir,
            "main.rs",
            quote! {
                autocxx::include_cpp! {
                    #hexathorpe include #header
                    generate_all!()
                    safety(unsafe_ffi)
                }
            }
            .to_string()
            .as_bytes(),
        );
        let prepro = demo_code_dir.join("autocxx-preprocessed.h");
        let mut cmd = Command::cargo_bin("autocxx-gen")?;
        cmd.arg("--inc")
            .arg(demo_code_dir.to_str().unwrap())
            .arg(demo_code_dir.join("main.rs"))
            .env("AUTOCXX_PREPROCESS", prepro.to_str().unwrap())
            .arg("--outdir")
            .arg(demo_code_dir.to_str().unwrap())
            .arg("--gen-cpp")
            .assert()
            .success();
        Ok("autocxx-preprocessed.h".into())
    })
}

fn do_reduce<F>(get_header_name: F) -> Result<(), Box<dyn std::error::Error>>
where
    F: FnOnce(&str, &Path) -> Result<String, Box<dyn std::error::Error>>,
{
    if creduce_is_broken() {
        return Ok(());
    }
    let tmp_dir = TempDir::new("example")?;
    let demo_code_dir = tmp_dir.path().join("demo");
    std::fs::create_dir(&demo_code_dir).unwrap();
    write_to_file(&demo_code_dir, "input.h", INPUT_H.as_bytes());
    let output_path = tmp_dir.path().join("min.h");
    let header_name = get_header_name("input.h", &demo_code_dir)?;
    let mut cmd = Command::cargo_bin("autocxx-reduce")?;
    cmd.arg("--inc")
        .arg(demo_code_dir.to_str().unwrap())
        .arg("-h")
        .arg(header_name)
        .arg("-o")
        .arg(output_path.to_str().unwrap())
        .arg("-d")
        .arg("generate_all!()")
        .arg("-d")
        .arg("block!(\"First\")")
        .arg("-p")
        .arg("type marked as blocked")
        .arg("-k")
        .assert()
        .success();
    let minimized = std::fs::read_to_string(output_path)?;
    assert!(minimized.contains("First"));
    assert!(!minimized.contains("DoMath"));
    Ok(())
}

fn write_to_file(dir: &Path, filename: &str, content: &[u8]) {
    let path = dir.join(filename);
    let mut f = File::create(&path).expect("Unable to create file");
    f.write_all(content).expect("Unable to write file");
}

fn creduce_is_broken() -> bool {
    // On some machines, creduce immediately segfaults
    Command::new("creduce").arg("--version").ok().is_err()
}
<|endoftext|>


<commit_before>
// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! LookupHost result from a resolution with a Resolver

use std::io;
use std::mem;
use std::net::IpAddr;
use std::slice::Iter;

use futures::{Async, future, Future, Poll, task};

use trust_dns::client::ClientHandle;
use trust_dns::error::ClientError;
use trust_dns::op::Message;
use trust_dns::rr::{DNSClass, Name, RData, RecordType};

use config::LookupIpStrategy;

/// Result of a DNS query when querying for A or AAAA records.
#[derive(Debug)]
pub struct LookupIp {
    ips: Vec<IpAddr>,
}

impl LookupIp {
    fn new(ips: Vec<IpAddr>) -> Self {
        LookupIp { ips }
    }

    /// Returns a borrowed iterator of the returned IPs
    pub fn iter(&self) -> LookupIpIter {
        LookupIpIter(self.ips.iter())
    }
}

impl Iterator for LookupIp {
    type Item = IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.ips.pop()
    }
}

/// Borrowed view of set of IPs returned from a LookupIp
pub struct LookupIpIter<'a>(Iter<'a, IpAddr>);

impl<'a> Iterator for LookupIpIter<'a> {
    type Item = &'a IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

/// The Future returned from ResolverFuture when performing an A or AAAA lookup.
pub struct LookupIpFuture {
    future: Box<Future<Item = LookupIp, Error = io::Error>>,
}

impl LookupIpFuture {
    pub(crate) fn lookup<C: ClientHandle>(
        host: &str,
        strategy: LookupIpStrategy,
        client: &mut C,
    ) -> Self {
        let name = match Name::parse(host, None) {
            Ok(name) => name,
            Err(err) => {
                return LookupIpFuture { future: Box::new(future::err(io::Error::from(err))) }
            }
        };

        let query = LookupIpState::lookup(name, strategy, client);
        LookupIpFuture { future: Box::new(query) }
    }
}

impl Future for LookupIpFuture {
    type Item = LookupIp;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.future.poll()
    }
}

// TODO: maximum recursion on CNAME, etc, chains...
// struct LookupStack(Vec<Query>);

// impl LookupStack {
//     // pushes the Query onto the stack, and returns a reference. An error will be returned
//     fn push(&mut self, query: Query) -> io::Result<&Query> {
//         if self.0.contains(&query) {
//             return Err(io::Error::new(io::ErrorKind::Other, "circular CNAME or other recursion"));
//         }

//         self.0.push(query);
//         Ok(self.0.last().unwrap())
//     }
// }

enum LookupIpState {
    Query(Box<Future<Item = Vec<IpAddr>, Error = ClientError>>),
    Fin(Vec<IpAddr>),
}

impl LookupIpState {
    pub fn lookup<C: ClientHandle>(name: Name, strategy: LookupIpStrategy, client: &mut C) -> Self {
        let query_future = lookup(name, strategy, client);

        LookupIpState::Query(query_future)
    }

    fn transition_query(&mut self, ips: Vec<IpAddr>) {
        assert!(if let LookupIpState::Query(_) = *self {
            true
        } else {
            false
        });

        // transition
        mem::replace(self, LookupIpState::Fin(ips));
    }
}

impl Future for LookupIpState {
    type Item = LookupIp;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // first transition any polling that is needed (mutable refs...)
        let poll;
        match *self {
            LookupIpState::Query(ref mut query) => {
                poll = query.poll().map_err(|e| e.into());
                match poll {
                    Ok(Async::NotReady) => {
                        return Ok(Async::NotReady);
                    }
                    Ok(Async::Ready(_)) => (), // handled in next match
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
            LookupIpState::Fin(ref mut ips) => {
                let ips = mem::replace(ips, Vec::<IpAddr>::new());
                let ips = LookupIp::new(ips);
                return Ok(Async::Ready(ips));
            }
        }

        // getting here means there are Aync::Ready available.
        match *self {
            LookupIpState::Query(_) => {
                match poll {
                    Ok(Async::Ready(ips)) => self.transition_query(ips),
                    _ => panic!("should have returned earlier"),
                }
            }
            LookupIpState::Fin(_) => panic!("should have returned earlier"),
        }

        task::current().notify(); // yield
        Ok(Async::NotReady)
    }
}

fn lookup<C: ClientHandle>(
    name: Name,
    strategy: LookupIpStrategy,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    match strategy {
        LookupIpStrategy::Ipv4Only => ipv4_only(name, client),
        LookupIpStrategy::Ipv6Only => ipv6_only(name, client),
        LookupIpStrategy::Ipv4AndIpv6 => ipv4_and_ipv6(name, client),
        LookupIpStrategy::Ipv6thenIpv4 => unimplemented!(),
        LookupIpStrategy::Ipv4thenIpv6 => unimplemented!(),
    }
}

fn map_message_to_ipaddr(mut message: Message) -> Vec<IpAddr> {
    message
        .take_answers()
        .iter()
        .filter_map(|r| match *r.rdata() {
            RData::A(ipaddr) => Some(IpAddr::V4(ipaddr)),
            RData::AAAA(ipaddr) => Some(IpAddr::V6(ipaddr)),
            _ => None,
        })
        .collect()
}

/// queries only for A records
fn ipv4_only<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(client.query(name, DNSClass::IN, RecordType::A).map(
        map_message_to_ipaddr,
    ))
}

fn ipv6_only<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(client.query(name, DNSClass::IN, RecordType::AAAA).map(
        map_message_to_ipaddr,
    ))
}

fn ipv4_and_ipv6<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(
        client
            .query(name.clone(), DNSClass::IN, RecordType::A)
            .map(map_message_to_ipaddr)
            .select(client.query(name, DNSClass::IN, RecordType::AAAA).map(
                map_message_to_ipaddr,
            ))
            .then(|sel_res| {
                match sel_res {
                    // A record returned, get the other record result, or else just return record
                    Ok((mut ips, remaining_query)) => {
                        Box::new(remaining_query.then(move |query_res| match query_res {
                            /// join AAAA and A results
                            Ok(mut rem_ips) => {
                                rem_ips.append(&mut ips);
                                future::ok(rem_ips)
                            }
                            // AAAA failed, just return A
                            Err(_) => future::ok(ips),
                        })) as
                            // This cast is to resolve a comilation error, not sure of it's necessity
                            Box<Future<Item = Vec<IpAddr>, Error = ClientError>>
                    }

                    // A failed, just return the AAAA result
                    Err((_, remaining_query)) => Box::new(remaining_query),
                }
            }),
    )
}

// TODO: build some non-network tests which test all variants of the Strategies...<commit_msg>cleanup some comments<commit_after>
// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! LookupHost result from a resolution with a Resolver

use std::io;
use std::mem;
use std::net::IpAddr;
use std::slice::Iter;

use futures::{Async, future, Future, Poll, task};

use trust_dns::client::ClientHandle;
use trust_dns::error::ClientError;
use trust_dns::op::Message;
use trust_dns::rr::{DNSClass, Name, RData, RecordType};

use config::LookupIpStrategy;

/// Result of a DNS query when querying for A or AAAA records.
#[derive(Debug)]
pub struct LookupIp {
    ips: Vec<IpAddr>,
}

impl LookupIp {
    fn new(ips: Vec<IpAddr>) -> Self {
        LookupIp { ips }
    }

    /// Returns a borrowed iterator of the returned IPs
    pub fn iter(&self) -> LookupIpIter {
        LookupIpIter(self.ips.iter())
    }
}

impl Iterator for LookupIp {
    type Item = IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.ips.pop()
    }
}

/// Borrowed view of set of IPs returned from a LookupIp
pub struct LookupIpIter<'a>(Iter<'a, IpAddr>);

impl<'a> Iterator for LookupIpIter<'a> {
    type Item = &'a IpAddr;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

/// The Future returned from ResolverFuture when performing an A or AAAA lookup.
pub struct LookupIpFuture {
    future: Box<Future<Item = LookupIp, Error = io::Error>>,
}

impl LookupIpFuture {
    pub(crate) fn lookup<C: ClientHandle>(
        host: &str,
        strategy: LookupIpStrategy,
        client: &mut C,
    ) -> Self {
        let name = match Name::parse(host, None) {
            Ok(name) => name,
            Err(err) => {
                return LookupIpFuture { future: Box::new(future::err(io::Error::from(err))) }
            }
        };

        let query = LookupIpState::lookup(name, strategy, client);
        LookupIpFuture { future: Box::new(query) }
    }
}

impl Future for LookupIpFuture {
    type Item = LookupIp;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.future.poll()
    }
}

// TODO: maximum recursion on CNAME, etc, chains...
// struct LookupStack(Vec<Query>);

// impl LookupStack {
//     // pushes the Query onto the stack, and returns a reference. An error will be returned
//     fn push(&mut self, query: Query) -> io::Result<&Query> {
//         if self.0.contains(&query) {
//             return Err(io::Error::new(io::ErrorKind::Other, "circular CNAME or other recursion"));
//         }

//         self.0.push(query);
//         Ok(self.0.last().unwrap())
//     }
// }

enum LookupIpState {
    Query(Box<Future<Item = Vec<IpAddr>, Error = ClientError>>),
    Fin(Vec<IpAddr>),
}

impl LookupIpState {
    pub fn lookup<C: ClientHandle>(name: Name, strategy: LookupIpStrategy, client: &mut C) -> Self {
        let query_future = lookup(name, strategy, client);

        LookupIpState::Query(query_future)
    }

    fn transition_query(&mut self, ips: Vec<IpAddr>) {
        assert!(if let LookupIpState::Query(_) = *self {
            true
        } else {
            false
        });

        // transition
        mem::replace(self, LookupIpState::Fin(ips));
    }
}

impl Future for LookupIpState {
    type Item = LookupIp;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // first transition any polling that is needed (mutable refs...)
        let poll;
        match *self {
            LookupIpState::Query(ref mut query) => {
                poll = query.poll().map_err(|e| e.into());
                match poll {
                    Ok(Async::NotReady) => {
                        return Ok(Async::NotReady);
                    }
                    Ok(Async::Ready(_)) => (), // handled in next match
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
            LookupIpState::Fin(ref mut ips) => {
                let ips = mem::replace(ips, Vec::<IpAddr>::new());
                let ips = LookupIp::new(ips);
                return Ok(Async::Ready(ips));
            }
        }

        // getting here means there are Aync::Ready available.
        match *self {
            LookupIpState::Query(_) => {
                match poll {
                    Ok(Async::Ready(ips)) => self.transition_query(ips),
                    _ => panic!("should have returned earlier"),
                }
            }
            LookupIpState::Fin(_) => panic!("should have returned earlier"),
        }

        task::current().notify(); // yield
        Ok(Async::NotReady)
    }
}

fn lookup<C: ClientHandle>(
    name: Name,
    strategy: LookupIpStrategy,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    match strategy {
        LookupIpStrategy::Ipv4Only => ipv4_only(name, client),
        LookupIpStrategy::Ipv6Only => ipv6_only(name, client),
        LookupIpStrategy::Ipv4AndIpv6 => ipv4_and_ipv6(name, client),
        LookupIpStrategy::Ipv6thenIpv4 => unimplemented!(),
        LookupIpStrategy::Ipv4thenIpv6 => unimplemented!(),
    }
}

fn map_message_to_ipaddr(mut message: Message) -> Vec<IpAddr> {
    message
        .take_answers()
        .iter()
        .filter_map(|r| match *r.rdata() {
            RData::A(ipaddr) => Some(IpAddr::V4(ipaddr)),
            RData::AAAA(ipaddr) => Some(IpAddr::V6(ipaddr)),
            _ => None,
        })
        .collect()
}

/// queries only for A records
fn ipv4_only<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(client.query(name, DNSClass::IN, RecordType::A).map(
        map_message_to_ipaddr,
    ))
}

fn ipv6_only<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(client.query(name, DNSClass::IN, RecordType::AAAA).map(
        map_message_to_ipaddr,
    ))
}

fn ipv4_and_ipv6<C: ClientHandle>(
    name: Name,
    client: &mut C,
) -> Box<Future<Item = Vec<IpAddr>, Error = ClientError>> {
    Box::new(
        client
            .query(name.clone(), DNSClass::IN, RecordType::A)
            .map(map_message_to_ipaddr)
            .select(client.query(name, DNSClass::IN, RecordType::AAAA).map(
                map_message_to_ipaddr,
            ))
            .then(|sel_res| {
                match sel_res {
                    // Some ips returned, get the other record result, or else just return record
                    Ok((mut ips, remaining_query)) => {
                        Box::new(remaining_query.then(move |query_res| match query_res {
                            /// join AAAA and A results
                            Ok(mut rem_ips) => {
                                rem_ips.append(&mut ips);
                                future::ok(rem_ips)
                            }
                            // One failed, just return the other
                            Err(_) => future::ok(ips),
                        })) as
                            // This cast is to resolve a comilation error, not sure of it's necessity
                            Box<Future<Item = Vec<IpAddr>, Error = ClientError>>
                    }

                    // One failed, just return the other
                    Err((_, remaining_query)) => Box::new(remaining_query),
                }
            }),
    )
}

// TODO: build some non-network tests which test all variants of the Strategies...<|endoftext|>


<commit_before>#![no_main]

use arbitrary::Arbitrary;
use libfuzzer_sys::fuzz_target;

#[derive(Arbitrary, Debug)]
enum IntegerInput {
    I8(i8),
    U8(u8),
    I16(i16),
    U16(u16),
    I32(i32),
    U32(u32),
    I64(i64),
    U64(u64),
    I128(i128),
    U128(u128),
    Isize(isize),
    Usize(usize),
}

fuzz_target!(|input: IntegerInput| {
    let mut buffer = itoa::Buffer::new();
    match input {
        IntegerInput::I8(val) => buffer.format(val),
        IntegerInput::U8(val) => buffer.format(val),
        IntegerInput::I16(val) => buffer.format(val),
        IntegerInput::U16(val) => buffer.format(val),
        IntegerInput::I32(val) => buffer.format(val),
        IntegerInput::U32(val) => buffer.format(val),
        IntegerInput::I64(val) => buffer.format(val),
        IntegerInput::U64(val) => buffer.format(val),
        IntegerInput::I128(val) => buffer.format(val),
        IntegerInput::U128(val) => buffer.format(val),
        IntegerInput::Isize(val) => buffer.format(val),
        IntegerInput::Usize(val) => buffer.format(val),
    };
});
<commit_msg>Assert size of string in fuzz target<commit_after>#![no_main]

use arbitrary::Arbitrary;
use libfuzzer_sys::fuzz_target;
use std::mem;

#[derive(Arbitrary, Debug)]
enum IntegerInput {
    I8(i8),
    U8(u8),
    I16(i16),
    U16(u16),
    I32(i32),
    U32(u32),
    I64(i64),
    U64(u64),
    I128(i128),
    U128(u128),
    Isize(isize),
    Usize(usize),
}

fuzz_target!(|input: IntegerInput| {
    let mut buffer = itoa::Buffer::new();
    let string = match input {
        IntegerInput::I8(val) => buffer.format(val),
        IntegerInput::U8(val) => buffer.format(val),
        IntegerInput::I16(val) => buffer.format(val),
        IntegerInput::U16(val) => buffer.format(val),
        IntegerInput::I32(val) => buffer.format(val),
        IntegerInput::U32(val) => buffer.format(val),
        IntegerInput::I64(val) => buffer.format(val),
        IntegerInput::U64(val) => buffer.format(val),
        IntegerInput::I128(val) => buffer.format(val),
        IntegerInput::U128(val) => buffer.format(val),
        IntegerInput::Isize(val) => buffer.format(val),
        IntegerInput::Usize(val) => buffer.format(val),
    };
    assert!(string.len() <= mem::size_of::<itoa::Buffer>());
});
<|endoftext|>


<commit_before>use futures::stream::Stream;
use futures::Poll;
use futures::Async;

pub enum ResultOrEof<T, E> {
    Item(T),
    Error(E),
    Eof,
}

impl<T, E> ResultOrEof<T, E> {
    pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> ResultOrEof<U, E> {
        match self {
            ResultOrEof::Item(t) => match op(t) {
                Ok(r) => ResultOrEof::Item(r),
                Err(e) => ResultOrEof::Error(e),
            },
            ResultOrEof::Error(e) => ResultOrEof::Error(e),
            ResultOrEof::Eof => ResultOrEof::Eof,
        }
    }
}

impl<T, E> From<Result<T, E>> for ResultOrEof<T, E> {
    fn from(result: Result<T, E>) -> Self {
        match result {
            Ok(r) => ResultOrEof::Item(r),
            Err(e) => ResultOrEof::Error(e),
        }
    }
}

pub fn stream_with_eof_and_error<T, E, S, F>(s: S, missed_eof: F) -> StreamWithEofAndError<S, F>
    where
        S : Stream<Item=ResultOrEof<T, E>, Error=E>,
        F : FnOnce() -> E,
{
    StreamWithEofAndError {
        stream: s,
        seen_eof: false,
        missed_eof: Some(missed_eof),
    }
}

pub struct StreamWithEofAndError<S, F> {
    stream: S,
    seen_eof: bool,
    missed_eof: Option<F>,
}

impl<T, E, S, F> Stream for StreamWithEofAndError<S, F>
    where
        S : Stream<Item=ResultOrEof<T, E>, Error=E>,
        F : FnOnce() -> E,
{
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            if self.seen_eof {
                match try_ready!(self.stream.poll()) {
                    None => return Ok(Async::Ready(None)),
                    Some(ResultOrEof::Error(e)) => return Err(e),
                    Some(ResultOrEof::Eof) => panic!("eof after eof"),
                    Some(ResultOrEof::Item(_)) => panic!("item after eof"),
                }
            } else {
                match try_ready!(self.stream.poll()) {
                    None => {
                        return Err(self.missed_eof.take().expect("poll after eof")());
                    },
                    Some(ResultOrEof::Eof) => {
                        self.seen_eof = true;
                        continue;
                    }
                    Some(ResultOrEof::Error(e)) => return Err(e),
                    Some(ResultOrEof::Item(item)) => return Ok(Async::Ready(Some(item))),
                }
            }
        }
    }
}
<commit_msg>Fix stream_with_eof_and_error EOF logic error<commit_after>use futures::stream::Stream;
use futures::Poll;
use futures::Async;

pub enum ResultOrEof<T, E> {
    Item(T),
    Error(E),
    Eof,
}

impl<T, E> ResultOrEof<T, E> {
    pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> ResultOrEof<U, E> {
        match self {
            ResultOrEof::Item(t) => match op(t) {
                Ok(r) => ResultOrEof::Item(r),
                Err(e) => ResultOrEof::Error(e),
            },
            ResultOrEof::Error(e) => ResultOrEof::Error(e),
            ResultOrEof::Eof => ResultOrEof::Eof,
        }
    }
}

impl<T, E> From<Result<T, E>> for ResultOrEof<T, E> {
    fn from(result: Result<T, E>) -> Self {
        match result {
            Ok(r) => ResultOrEof::Item(r),
            Err(e) => ResultOrEof::Error(e),
        }
    }
}

pub fn stream_with_eof_and_error<T, E, S, F>(s: S, missed_eof: F) -> StreamWithEofAndError<S, F>
    where
        S : Stream<Item=ResultOrEof<T, E>, Error=E>,
        F : FnOnce() -> E,
{
    StreamWithEofAndError {
        stream: s,
        seen_eof: false,
        missed_eof: Some(missed_eof),
    }
}

pub struct StreamWithEofAndError<S, F> {
    stream: S,
    seen_eof: bool,
    missed_eof: Option<F>,
}

impl<T, E, S, F> Stream for StreamWithEofAndError<S, F>
    where
        S : Stream<Item=ResultOrEof<T, E>, Error=E>,
        F : FnOnce() -> E,
{
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        // must return stream eof after missed eof error
        if let None = self.missed_eof {
            return Ok(Async::Ready(None));
        }

        loop {
            if self.seen_eof {
                match try_ready!(self.stream.poll()) {
                    None => return Ok(Async::Ready(None)),
                    Some(ResultOrEof::Error(e)) => return Err(e),
                    Some(ResultOrEof::Eof) => panic!("eof after eof"),
                    Some(ResultOrEof::Item(_)) => panic!("item after eof"),
                }
            } else {
                match try_ready!(self.stream.poll()) {
                    None => {
                        return Err(self.missed_eof.take().expect("unreachable")());
                    },
                    Some(ResultOrEof::Eof) => {
                        self.seen_eof = true;
                        continue;
                    }
                    Some(ResultOrEof::Error(e)) => return Err(e),
                    Some(ResultOrEof::Item(item)) => return Ok(Async::Ready(Some(item))),
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! A (WIP) C API allowing use of gluon in other langauges than Rust.

extern crate gluon;

use std::str;
use std::slice;

use gluon::vm::api::generic::A;
use gluon::vm::api::{Getable, Pushable, Generic, CPrimitive};
use gluon::vm::types::{VMIndex, VMInt};
use gluon::vm::thread::{RootedThread, Thread, ThreadInternal, Status};

use gluon::Compiler;

pub type Function = extern "C" fn (&Thread) -> Status;

// TODO What should the c api return as errors
// TODO How should error messages be returned
#[repr(C)]
#[derive(Debug, PartialEq)]
pub enum Error {
    Ok,
    Unknown,
}

pub extern "C" fn new_vm() -> *const Thread {
    let vm = RootedThread::new();
    vm.into_raw()
}

pub unsafe extern "C" fn free_vm(vm: &Thread) {
    RootedThread::from_raw(vm);
}

pub unsafe extern "C" fn run_expr(vm: &Thread,
                                  module: &u8,
                                  module_len: usize,
                                  expr: &u8,
                                  expr_len: usize)
                                  -> Error {
    let module = match str::from_utf8(slice::from_raw_parts(module, module_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let expr = match str::from_utf8(slice::from_raw_parts(expr, expr_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let result: Result<Generic<A>, _> = Compiler::new().run_expr(&vm, module, expr);
    match result {
        Ok(_) => Error::Ok,
        Err(_) => Error::Unknown,
    }
}

pub unsafe extern "C" fn load_script(vm: &Thread,
                                     module: &u8,
                                     module_len: usize,
                                     expr: &u8,
                                     expr_len: usize)
                                     -> Error {
    let module = match str::from_utf8(slice::from_raw_parts(module, module_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let expr = match str::from_utf8(slice::from_raw_parts(expr, expr_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let result = Compiler::new().load_script(vm, module, expr);
    match result {
        Ok(_) => Error::Ok,
        Err(_) => Error::Unknown,
    }
}

pub extern "C" fn call_function(thread: &Thread, arguments: VMIndex) -> Error {
    let stack = thread.current_frame();
    match thread.call_function(stack, arguments) {
        Ok(_) => Error::Ok,
        Err(_) => Error::Unknown,
    }
}

pub extern "C" fn len(vm: &Thread) -> usize {
    vm.current_frame().len() as usize
}

pub extern "C" fn pop(vm: &Thread, n: usize) {
    let mut stack = vm.current_frame();
    for _ in 0..n {
        stack.pop();
    }
}

pub extern "C" fn push_int(vm: &Thread, int: VMInt) {
    Thread::push(vm, int);
}

pub extern "C" fn push_float(vm: &Thread, float: f64) {
    Thread::push(vm, float);
}

pub unsafe extern "C" fn push_function(vm: &Thread, name: &u8, len: usize, function: Function, arguments: VMIndex) -> Error {
    let s = match str::from_utf8(slice::from_raw_parts(name, len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    Thread::push(vm, CPrimitive::new(function, arguments, s));
    Error::Ok
}

/// Push a string to the stack. The string must be valid utf-8 or an error will be returned
pub unsafe extern "C" fn push_string(vm: &Thread, s: &u8, len: usize) -> Error {
    let s = match str::from_utf8(slice::from_raw_parts(s, len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    s.push(vm, &mut vm.get_stack());
    Error::Ok
}

/// Push a string to the stack. If the string is not utf-8 this function will trigger undefined
/// behaviour.
pub unsafe extern "C" fn push_string_unchecked(vm: &Thread, s: &u8, len: usize) {
    let s = str::from_utf8_unchecked(slice::from_raw_parts(s, len));
    s.push(vm, &mut vm.get_stack());
}

pub extern "C" fn get_int(vm: &Thread, index: VMIndex, out: &mut VMInt) -> Error {
    get_value(vm, index, out)
}

pub extern "C" fn get_float(vm: &Thread, index: VMIndex, out: &mut f64) -> Error {
    get_value(vm, index, out)
}

/// The returned string is garbage collected and may not be valid after the string is removed from
/// its slot in the stack
pub unsafe extern "C" fn get_string(vm: &Thread,
                                    index: VMIndex,
                                    out: &mut *const u8,
                                    out_len: &mut usize)
                                    -> Error {
    let stack = vm.current_frame();
    match stack.get_variants(index).and_then(|value| <&str>::from_value(vm, value)) {
        Some(value) => {
            *out = &*value.as_ptr();
            *out_len = value.len();
            Error::Ok
        }
        None => Error::Unknown,
    }
}

fn get_value<T>(vm: &Thread, index: VMIndex, out: &mut T) -> Error
    where T: for<'vm> Getable<'vm>
{
    let stack = vm.current_frame();
    match stack.get_variants(index).and_then(|value| T::from_value(vm, value)) {
        Some(value) => {
            *out = value;
            Error::Ok
        }
        None => Error::Unknown,
    }
}
<commit_msg>test(c-api): Add tests for the c-api<commit_after>//! A (WIP) C API allowing use of gluon in other langauges than Rust.

extern crate gluon;

use std::str;
use std::slice;

use gluon::vm::api::generic::A;
use gluon::vm::api::{Getable, Pushable, Generic, CPrimitive};
use gluon::vm::types::{VMIndex, VMInt};
use gluon::vm::thread::{RootedThread, Thread, ThreadInternal, Status};

use gluon::Compiler;

pub type Function = extern "C" fn (&Thread) -> Status;

// TODO What should the c api return as errors
// TODO How should error messages be returned
#[repr(C)]
#[derive(Debug, PartialEq)]
pub enum Error {
    Ok,
    Unknown,
}

pub extern "C" fn new_vm() -> *const Thread {
    let vm = RootedThread::new();
    vm.into_raw()
}

pub unsafe extern "C" fn free_vm(vm: &Thread) {
    RootedThread::from_raw(vm);
}

pub unsafe extern "C" fn run_expr(vm: &Thread,
                                  module: &u8,
                                  module_len: usize,
                                  expr: &u8,
                                  expr_len: usize)
                                  -> Error {
    let module = match str::from_utf8(slice::from_raw_parts(module, module_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let expr = match str::from_utf8(slice::from_raw_parts(expr, expr_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let result: Result<Generic<A>, _> = Compiler::new().run_expr(&vm, module, expr);
    match result {
        Ok(_) => Error::Ok,
        Err(_) => Error::Unknown,
    }
}

pub unsafe extern "C" fn load_script(vm: &Thread,
                                     module: &u8,
                                     module_len: usize,
                                     expr: &u8,
                                     expr_len: usize)
                                     -> Error {
    let module = match str::from_utf8(slice::from_raw_parts(module, module_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let expr = match str::from_utf8(slice::from_raw_parts(expr, expr_len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    let result = Compiler::new().load_script(vm, module, expr);
    match result {
        Ok(_) => Error::Ok,
        Err(_) => Error::Unknown,
    }
}

pub extern "C" fn call_function(thread: &Thread, arguments: VMIndex) -> Error {
    let stack = thread.current_frame();
    match thread.call_function(stack, arguments) {
        Ok(_) => Error::Ok,
        Err(_) => Error::Unknown,
    }
}

pub extern "C" fn len(vm: &Thread) -> usize {
    vm.current_frame().len() as usize
}

pub extern "C" fn pop(vm: &Thread, n: usize) {
    let mut stack = vm.current_frame();
    for _ in 0..n {
        stack.pop();
    }
}

pub extern "C" fn push_int(vm: &Thread, int: VMInt) {
    Thread::push(vm, int);
}

pub extern "C" fn push_float(vm: &Thread, float: f64) {
    Thread::push(vm, float);
}

pub unsafe extern "C" fn push_function(vm: &Thread, name: &u8, len: usize, function: Function, arguments: VMIndex) -> Error {
    let s = match str::from_utf8(slice::from_raw_parts(name, len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    Thread::push(vm, CPrimitive::new(function, arguments, s));
    Error::Ok
}

/// Push a string to the stack. The string must be valid utf-8 or an error will be returned
pub unsafe extern "C" fn push_string(vm: &Thread, s: &u8, len: usize) -> Error {
    let s = match str::from_utf8(slice::from_raw_parts(s, len)) {
        Ok(s) => s,
        Err(_) => return Error::Unknown,
    };
    s.push(vm, &mut vm.get_stack());
    Error::Ok
}

/// Push a string to the stack. If the string is not utf-8 this function will trigger undefined
/// behaviour.
pub unsafe extern "C" fn push_string_unchecked(vm: &Thread, s: &u8, len: usize) {
    let s = str::from_utf8_unchecked(slice::from_raw_parts(s, len));
    s.push(vm, &mut vm.get_stack());
}

pub extern "C" fn get_int(vm: &Thread, index: VMIndex, out: &mut VMInt) -> Error {
    get_value(vm, index, out)
}

pub extern "C" fn get_float(vm: &Thread, index: VMIndex, out: &mut f64) -> Error {
    get_value(vm, index, out)
}

/// The returned string is garbage collected and may not be valid after the string is removed from
/// its slot in the stack
pub unsafe extern "C" fn get_string(vm: &Thread,
                                    index: VMIndex,
                                    out: &mut *const u8,
                                    out_len: &mut usize)
                                    -> Error {
    let stack = vm.current_frame();
    match stack.get_variants(index).and_then(|value| <&str>::from_value(vm, value)) {
        Some(value) => {
            *out = &*value.as_ptr();
            *out_len = value.len();
            Error::Ok
        }
        None => Error::Unknown,
    }
}

fn get_value<T>(vm: &Thread, index: VMIndex, out: &mut T) -> Error
    where T: for<'vm> Getable<'vm>
{
    let stack = vm.current_frame();
    match stack.get_variants(index).and_then(|value| T::from_value(vm, value)) {
        Some(value) => {
            *out = value;
            Error::Ok
        }
        None => Error::Unknown,
    }
}

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

    use gluon::vm::thread::{Status, Thread};

    use std::ptr;
    use std::str;
    use std::slice;

    #[test]
    fn push_pop() {
        unsafe {
            let vm = &*new_vm();

            push_int(vm, 123);
            push_float(vm, 3.14);
            let s = "test";
            push_string(vm, &s.as_bytes()[0], s.len());

            let mut int = 0;
            assert_eq!(get_int(vm, 0, &mut int), Error::Ok);
            assert_eq!(int, 123);

            let mut float = 0.0;
            assert_eq!(get_float(vm, 1, &mut float), Error::Ok);
            assert_eq!(float, 3.14);

            let mut string_ptr = ptr::null();
            let mut string_len = 0;
            assert_eq!(get_string(vm, 2, &mut string_ptr, &mut string_len), Error::Ok);
            assert_eq!(str::from_utf8(slice::from_raw_parts(string_ptr, string_len)), Ok("test"));

            assert_eq!(len(vm), 3);

            pop(vm, 3);

            free_vm(vm);
        }
    }

    #[test]
    fn call_function_test() {
        extern "C" fn mult(vm: &Thread) -> Status {
            let mut l = 0.0;
            assert_eq!(get_float(vm, 0, &mut l), Error::Ok);
            let mut r = 0.0;
            assert_eq!(get_float(vm, 1, &mut r), Error::Ok);
            push_float(vm, l * r);
            Status::Ok
        }

        unsafe {
            let vm = &*new_vm();
            let name = "mult";
            push_function(vm, &name.as_bytes()[0], name.len(), mult, 2);
            push_float(vm, 12.0);
            push_float(vm, 3.0);

            assert_eq!(call_function(vm, 2), Error::Ok);
            let mut result = 0.0;
            assert_eq!(get_float(vm, 0, &mut result), Error::Ok);
            assert_eq!(result, 36.0);

            free_vm(vm);
        }
    }
}
<|endoftext|>


<commit_before>extern crate fern;
extern crate chrono;
extern crate log;

use std;

use cli::{CliOptions};

use self::log::{LevelFilter};
use self::fern::colors::{ColoredLevelConfig};

pub fn setup_logger(cli: &CliOptions) -> Result<(), fern::InitError> {
    let logging_level = match cli.log_level.parse::<LevelFilter>() {
        Ok(level) => level,
        Err(_) => {
            println!("Logging level with value={} is invalid. INFO level was set by default instead.", cli.log_level);
            println!("Use one of available logging levels: {:?}", vec![
                LevelFilter::Off, LevelFilter::Error, LevelFilter::Warn,
                LevelFilter::Info, LevelFilter::Debug, LevelFilter::Trace
            ]);
            LevelFilter::Info
        },
    };

    let colors = ColoredLevelConfig::new();
    fern::Dispatch::new()
        .format(move |out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                colors.color(record.level()),
                message
            ))
        })
        .level(logging_level)
        .chain(std::io::stdout())
        .apply()?;
    Ok(())
}
<commit_msg>Added documentation for logging.rs<commit_after>//! Logging module
//!
//! This module provides a logging opportunities for the pathfinder application
//! so that all output in console will be handled by fern logging tool.
//!
//! # Useful links
//! * [log crate documentation](https://docs.rs/log)
//! * [fern crate documentation](https://docs.rs/fern/*/fern/)
//!

extern crate fern;
extern crate chrono;
extern crate log;

use std;

use cli::{CliOptions};

use self::log::{LevelFilter};
use self::fern::colors::{ColoredLevelConfig};

/// Initialize a logger from the fern crate.
pub fn setup_logger(cli: &CliOptions) -> Result<(), fern::InitError> {
    let logging_level = match cli.log_level.parse::<LevelFilter>() {
        Ok(level) => level,
        Err(_) => {
            println!("Logging level with value={} is invalid. INFO level was set by default instead.", cli.log_level);
            println!("Use one of available logging levels: {:?}", vec![
                LevelFilter::Off, LevelFilter::Error, LevelFilter::Warn,
                LevelFilter::Info, LevelFilter::Debug, LevelFilter::Trace
            ]);
            LevelFilter::Info
        },
    };

    let colors = ColoredLevelConfig::new();
    fern::Dispatch::new()
        .format(move |out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                colors.color(record.level()),
                message
            ))
        })
        .level(logging_level)
        .chain(std::io::stdout())
        .apply()?;
    Ok(())
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(box_syntax)]
#![feature(fnbox)]
#![feature(mpsc_select)]
#![feature(plugin)]
#![feature(proc_macro)]
#![plugin(plugins)]

#![deny(unsafe_code)]

#[macro_use]
extern crate bitflags;
extern crate brotli;
extern crate content_blocker as content_blocker_parser;
extern crate cookie as cookie_rs;
extern crate devtools_traits;
extern crate flate2;
extern crate hyper;
extern crate hyper_serde;
extern crate immeta;
extern crate ipc_channel;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate log;
#[macro_use] #[no_link] extern crate matches;
#[macro_use]
extern crate mime;
extern crate mime_guess;
extern crate msg;
extern crate net_traits;
extern crate openssl;
extern crate openssl_verify;
extern crate profile_traits;
extern crate rustc_serialize;
#[macro_use]
extern crate serde_derive;
extern crate threadpool;
extern crate time;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
extern crate tinyfiledialogs;
extern crate unicase;
extern crate url;
extern crate util;
extern crate uuid;
extern crate webrender_traits;
extern crate websocket;

pub mod about_loader;
pub mod blob_loader;
pub mod chrome_loader;
pub mod connector;
pub mod content_blocker;
pub mod cookie;
pub mod cookie_storage;
mod data_loader;
pub mod file_loader;
pub mod filemanager_thread;
pub mod hsts;
pub mod http_loader;
pub mod image_cache_thread;
pub mod mime_classifier;
pub mod resource_thread;
pub mod storage_thread;
pub mod websocket_loader;

/// An implementation of the [Fetch specification](https://fetch.spec.whatwg.org/)
pub mod fetch {
    pub mod cors_cache;
    pub mod methods;
}
<commit_msg>Privatize some net modules.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(box_syntax)]
#![feature(fnbox)]
#![feature(mpsc_select)]
#![feature(plugin)]
#![feature(proc_macro)]
#![plugin(plugins)]

#![deny(unsafe_code)]

#[macro_use]
extern crate bitflags;
extern crate brotli;
extern crate content_blocker as content_blocker_parser;
extern crate cookie as cookie_rs;
extern crate devtools_traits;
extern crate flate2;
extern crate hyper;
extern crate hyper_serde;
extern crate immeta;
extern crate ipc_channel;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate log;
#[macro_use] #[no_link] extern crate matches;
#[macro_use]
extern crate mime;
extern crate mime_guess;
extern crate msg;
extern crate net_traits;
extern crate openssl;
extern crate openssl_verify;
extern crate profile_traits;
extern crate rustc_serialize;
#[macro_use]
extern crate serde_derive;
extern crate threadpool;
extern crate time;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
extern crate tinyfiledialogs;
extern crate unicase;
extern crate url;
extern crate util;
extern crate uuid;
extern crate webrender_traits;
extern crate websocket;

mod about_loader;
mod blob_loader;
pub mod chrome_loader;
mod connector;
mod content_blocker;
pub mod cookie;
pub mod cookie_storage;
mod data_loader;
mod file_loader;
pub mod filemanager_thread;
pub mod hsts;
pub mod http_loader;
pub mod image_cache_thread;
pub mod mime_classifier;
pub mod resource_thread;
mod storage_thread;
mod websocket_loader;

/// An implementation of the [Fetch specification](https://fetch.spec.whatwg.org/)
pub mod fetch {
    pub mod cors_cache;
    pub mod methods;
}
<|endoftext|>


<commit_before>extern crate combine;
extern crate combine_language;
extern crate mnemosyne as core;

use combine::*;
use combine_language::{ LanguageEnv
                      , LanguageDef
                      , Identifier
                      };
use combine::primitives::{ Stream
                         , Positioner
                         , SourcePosition
                         };

use core::semantic::*;
use core::semantic::annotations::{ Annotated
                                 , UnscopedState
                                 , Unscoped
                                 };
use core::semantic::types::*;
use core::semantic::ast::*;
use core::position::*;

use std::rc::Rc;

type ParseFn<'a, I, T> = fn (&MnEnv<'a, I>, State<I>) -> ParseResult<T, I>;

type U = UnscopedState;

/// Unicode code point for the lambda character
const LAMBDA: &'static str      = "\u{03bb}";
const ARROW: &'static str       = "\u{8594}";
const FAT_ARROW: &'static str   = "\u{8685}";

mod tests;

/// Wraps a parsing function with a language definition environment.
///
/// TODO: this could probably push identifiers to the symbol table here?
#[derive(Copy)]
struct MnParser<'a: 'b, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b {
        env: &'b MnEnv<'a, I>
      , parser: ParseFn<'a, I, T>
}

impl<'a, 'b, I, T> Clone for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    fn clone(&self) -> Self {
        MnParser { env: self.env , parser: self.parser }
    }
}

impl<'a, 'b, I, T> Parser for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    type Input = I;
    type Output = T;

    fn parse_state(&mut self, input: State<I>) -> ParseResult<T, I> {
        (self.parser)(self.env, input)
    }

}

struct MnEnv<'a, I>
where I: Stream<Item = char>
    , I::Item: Positioner<Position = SourcePosition> {
    env: LanguageEnv<'a, I>
}

impl <'a, I> std::ops::Deref for MnEnv<'a, I>
where I: Stream<Item=char> {
    type Target = LanguageEnv<'a, I>;
    fn deref(&self) -> &LanguageEnv<'a, I> { &self.env }
}

impl<'a, 'b, I> MnEnv<'a, I>
where I: Stream<Item=char>
    , I::Item: Positioner<Position = SourcePosition>
    , I::Range: 'b {

    /// Wrap a function into a MnParser with this environment
    fn parser<T>(&'b self, parser: ParseFn<'a, I, T>)
                -> MnParser<'a, 'b, I, T> {
        MnParser { env: self, parser: parser }
    }

    #[allow(dead_code)]
    fn parse_def(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        let function_form
            = self.name()
                  .and(self.function())
                  .map(|(name, fun)| DefForm::Function { name: name
                                                       , fun: fun });
        let top_level
            = self.name()
                  .and(self.type_annotation())
                  .and(self.expr())
                  .map(|((name, ty), body)|
                    DefForm::TopLevel { name: name
                                      , annot: ty
                                      , value: Rc::new(body) });

        self.reserved("defn").or(self.reserved("define"))
            .with(function_form.or(top_level))
            .map(Form::Define)
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_if(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.reserved("if")
            .with(self.expr())
            .and(self.expr())
            .and(optional(self.expr()))
            .map(|((cond, if_clause), else_clause)|
                Form::If { condition: Rc::new(cond)
                         , if_clause: Rc::new(if_clause)
                         , else_clause: else_clause.map(Rc::new)
                         })
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_lambda(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.reserved("lambda")
            .or(self.reserved(LAMBDA))
            .with(self.function())
            .map(Form::Lambda)
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_function(&self, input: State<I>) -> ParseResult<Function<'a, U>, I> {
        unimplemented!()
    }

    #[allow(dead_code)]
    fn parse_primitive_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        choice([ self.reserved("int")
                     .with(value(Primitive::IntSize))
               , self.reserved("uint")
                     .with(value(Primitive::IntSize))
               , self.reserved("float")
                     .with(value(Primitive::Float))
               , self.reserved("double")
                     .with(value(Primitive::Double))
               , self.reserved("bool")
                     .with(value(Primitive::Bool))
               , self.reserved("i8")
                     .with(value(Primitive::Int(Int::Int8)))
               , self.reserved("i16")
                     .with(value(Primitive::Int(Int::Int16)))
               , self.reserved("i32")
                    .with(value(Primitive::Int(Int::Int32)))
               , self.reserved("i64")
                     .with(value(Primitive::Int(Int::Int64)))
              , self.reserved("u8")
                    .with(value(Primitive::Uint(Int::Int8)))
              , self.reserved("u16")
                    .with(value(Primitive::Uint(Int::Int16)))
              , self.reserved("u32")
                    .with(value(Primitive::Uint(Int::Int32)))
              , self.reserved("u64")
                    .with(value(Primitive::Uint(Int::Int64)))
               ])
               .map(|primitive| Type::Prim(primitive))
               .parse_state(input)
    }

    fn raw_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('*').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Raw(Rc::new(t))))
                 .parse_state(input)
    }

    fn unique_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('@').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Unique(Rc::new(t))))
                 .parse_state(input)
    }

    fn borrow_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('&').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Borrowed(Rc::new(t))))
                 .parse_state(input)
    }
    fn parse_type(&self, input: State<I>) -> ParseResult<Type, I> {
        choice([ self.parser(MnEnv::parse_primitive_ty)
               , self.parser(MnEnv::raw_ptr_ty)
               , self.parser(MnEnv::unique_ptr_ty)
               , self.parser(MnEnv::borrow_ptr_ty)
               ])
            .parse_state(input)
    }

    fn parse_binding(&self, input: State<I>)
                    -> ParseResult<Unscoped<'a, Binding<'a, U>>, I> {
        let pos = input.position.clone();
        self.parser(MnEnv::parse_name)
            .and(self.type_annotation())
            .and(self.expr())
            .map(|((name, typ), value)|
                Annotated::new( Binding { name: name
                                        , typ: typ
                                        , value: Rc::new(value)
                                        }
                               , Position::from(pos)
                           ))
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_logical(&self, input: State<I>)
                    -> ParseResult<Logical<'a, U>, I> {
        let and = self.reserved("and")
                      .with(self.expr())
                      .and(self.expr())
                      .map(|(a, b)| Logical::And { a: Rc::new(a)
                                                 , b: Rc::new(b)
                                                 });

         let or = self.reserved("or")
                      .with(self.expr())
                      .and(self.expr())
                      .map(|(a, b)| Logical::And { a: Rc::new(a)
                                                 , b: Rc::new(b)
                                                 });

        and.or(or)
           .parse_state(input)
    }

    fn int_const(&'b self) -> MnParser<'a, 'b, I, Const> {
        self.parser(MnEnv::parse_int_const)
    }

    #[allow(dead_code)]
    fn parse_int_const(&self, input: State<I>) -> ParseResult<Const, I> {
        self.integer()
            .map(Const::IntConst)
            .parse_state(input)
    }

    fn parse_let(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {

        let binding_form =
            self.reserved("let")
                .with(many(self.parens(self.binding())))
                .and(many(self.expr()))
                .map(|(bindings, body)| LetForm::Let { bindings: bindings
                                                     , body: body });

        choice([ binding_form ])
            .map(Form::Let)
            .parse_state(input)
    }

    fn parse_name (&self, input: State<I>) -> ParseResult<Ident, I> {
        let position = input.position.clone();
        self.env.identifier::<'b>()
            .map(|name| Positional { pos: Position::from(position)
                                   , value: name })
            .parse_state(input)
    }

    fn parse_call(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.name()
            .and(many(self.expr()))
            .map(|(name, args)| Form::Call { fun: name, body: args })
            .parse_state(input)
    }

    fn parse_expr(&self, input: State<I>) -> ParseResult<Expr<'a, U>, I> {
        let pos = Position::from(input.position.clone());
        self.env
            .parens(choice([ self.def()
                           , self.if_form()
                           , self.lambda()
                           , self.let_form()
                           , self.call()
                           ]))
            .or(self.int_const()
                    .map(Form::Constant))
            .map(|f| Annotated::new(f, pos) )
            .parse_state(input)
    }

    fn expr(&'b self) -> MnParser<'a, 'b, I, Expr<'a, U>> {
        self.parser(MnEnv::parse_expr)
    }

    fn def(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_def)
    }

    fn if_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_if)
    }

    fn let_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_let)
    }

    fn lambda(&'b self)-> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_lambda)
    }

    fn call(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_call)
    }

    fn name(&'b self) -> MnParser<'a, 'b, I, Ident> {
        self.parser(MnEnv::parse_name)
    }

    fn binding(&'b self)
              -> MnParser< 'a, 'b, I, Unscoped<'a, Binding<'a, U>>> {
        self.parser(MnEnv::parse_binding)
    }

    fn type_annotation(&'b self) -> MnParser<'a, 'b, I, types::Type> {
        self.parser(MnEnv::parse_type)
    }

    fn function(&'b self) -> MnParser<'a, 'b, I, Function<'a, U>> {
        self.parser(MnEnv::parse_function)
    }

}
pub fn parse_module<'a>(code: &'a str)
                        -> Result< Vec<Expr<'a, UnscopedState>>
                                 , ParseError<&str>>
 {
    let alpha_ext = "+-*/<=>!:$%_~^";
    let ops = "+-*/|=<>";
    let env = LanguageEnv::new(LanguageDef {
        ident: Identifier {
            start: letter().or(satisfy(move |c| alpha_ext.contains(c)))
          , rest: alpha_num().or(satisfy(move |c| alpha_ext.contains(c)))
          , reserved: [ // a number of these reserved words have no meaning yet
                        "and"               , "begin"
                      , "case"              , "cond"        , "class"
                      , "data"
                      , "define"            , "defn"        , "def"
                      , "delay"             , "fn"
                      , "do"                , "else"
                      , "if"                , "lambda"      , LAMBDA
                      , "let"               , "let*"        , "letrec"
                      , "or"
                      , "quasiquote"        , "quote"       , "unquote"
                      , "set!"              , "unquote-splicing"
                      , "struct"            , "union"
                      , "i8"                , "u8"
                      , "i16"               , "u16"
                      , "i32"               , "u32"         , "f32"
                      , "i64"               , "u64"         , "f64"
                      , "int"               , "uint"        , "float"
                      , "bool"                              , "double"
                      , "ref"               , "move"        , "borrow"
                      , "trait"             , "typeclass"
                      , "instance"          , "impl"
                      ].iter().map(|x| (*x).into())
                       .collect()
        }
      , op: Identifier {
            start: satisfy(move |c| ops.contains(c))
          , rest:  satisfy(move |c| ops.contains(c))
          , reserved: [ "=>", "->", "\\", "|", ARROW, FAT_ARROW]
                .iter().map(|x| (*x).into()).collect()
        }
      , comment_line: string(";").map(|_| ())
      , comment_start: string("#|").map(|_| ())
      , comment_end: string("|#").map(|_| ())
    });
    let env = MnEnv { env: env };

    env.white_space()
       .with(many1::<Vec<Expr<'a, U>>, _>(env.expr()))
       .parse(code)
       .map(|(e, _)| e)
}
<commit_msg>You can't start names with `~` since it MIGHT be the lazy sigil<commit_after>extern crate combine;
extern crate combine_language;
extern crate mnemosyne as core;

use combine::*;
use combine_language::{ LanguageEnv
                      , LanguageDef
                      , Identifier
                      };
use combine::primitives::{ Stream
                         , Positioner
                         , SourcePosition
                         };

use core::semantic::*;
use core::semantic::annotations::{ Annotated
                                 , UnscopedState
                                 , Unscoped
                                 };
use core::semantic::types::*;
use core::semantic::ast::*;
use core::position::*;

use std::rc::Rc;

type ParseFn<'a, I, T> = fn (&MnEnv<'a, I>, State<I>) -> ParseResult<T, I>;

type U = UnscopedState;

/// Unicode code point for the lambda character
const LAMBDA: &'static str      = "\u{03bb}";
const ARROW: &'static str       = "\u{8594}";
const FAT_ARROW: &'static str   = "\u{8685}";

mod tests;

/// Wraps a parsing function with a language definition environment.
///
/// TODO: this could probably push identifiers to the symbol table here?
#[derive(Copy)]
struct MnParser<'a: 'b, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b {
        env: &'b MnEnv<'a, I>
      , parser: ParseFn<'a, I, T>
}

impl<'a, 'b, I, T> Clone for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    fn clone(&self) -> Self {
        MnParser { env: self.env , parser: self.parser }
    }
}

impl<'a, 'b, I, T> Parser for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    type Input = I;
    type Output = T;

    fn parse_state(&mut self, input: State<I>) -> ParseResult<T, I> {
        (self.parser)(self.env, input)
    }

}

struct MnEnv<'a, I>
where I: Stream<Item = char>
    , I::Item: Positioner<Position = SourcePosition> {
    env: LanguageEnv<'a, I>
}

impl <'a, I> std::ops::Deref for MnEnv<'a, I>
where I: Stream<Item=char> {
    type Target = LanguageEnv<'a, I>;
    fn deref(&self) -> &LanguageEnv<'a, I> { &self.env }
}

impl<'a, 'b, I> MnEnv<'a, I>
where I: Stream<Item=char>
    , I::Item: Positioner<Position = SourcePosition>
    , I::Range: 'b {

    /// Wrap a function into a MnParser with this environment
    fn parser<T>(&'b self, parser: ParseFn<'a, I, T>)
                -> MnParser<'a, 'b, I, T> {
        MnParser { env: self, parser: parser }
    }

    #[allow(dead_code)]
    fn parse_def(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        let function_form
            = self.name()
                  .and(self.function())
                  .map(|(name, fun)| DefForm::Function { name: name
                                                       , fun: fun });
        let top_level
            = self.name()
                  .and(self.type_annotation())
                  .and(self.expr())
                  .map(|((name, ty), body)|
                    DefForm::TopLevel { name: name
                                      , annot: ty
                                      , value: Rc::new(body) });

        self.reserved("defn").or(self.reserved("define"))
            .with(function_form.or(top_level))
            .map(Form::Define)
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_if(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.reserved("if")
            .with(self.expr())
            .and(self.expr())
            .and(optional(self.expr()))
            .map(|((cond, if_clause), else_clause)|
                Form::If { condition: Rc::new(cond)
                         , if_clause: Rc::new(if_clause)
                         , else_clause: else_clause.map(Rc::new)
                         })
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_lambda(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.reserved("lambda")
            .or(self.reserved(LAMBDA))
            .with(self.function())
            .map(Form::Lambda)
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_function(&self, input: State<I>) -> ParseResult<Function<'a, U>, I> {
        unimplemented!()
    }

    #[allow(dead_code)]
    fn parse_primitive_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        choice([ self.reserved("int")
                     .with(value(Primitive::IntSize))
               , self.reserved("uint")
                     .with(value(Primitive::IntSize))
               , self.reserved("float")
                     .with(value(Primitive::Float))
               , self.reserved("double")
                     .with(value(Primitive::Double))
               , self.reserved("bool")
                     .with(value(Primitive::Bool))
               , self.reserved("i8")
                     .with(value(Primitive::Int(Int::Int8)))
               , self.reserved("i16")
                     .with(value(Primitive::Int(Int::Int16)))
               , self.reserved("i32")
                    .with(value(Primitive::Int(Int::Int32)))
               , self.reserved("i64")
                     .with(value(Primitive::Int(Int::Int64)))
              , self.reserved("u8")
                    .with(value(Primitive::Uint(Int::Int8)))
              , self.reserved("u16")
                    .with(value(Primitive::Uint(Int::Int16)))
              , self.reserved("u32")
                    .with(value(Primitive::Uint(Int::Int32)))
              , self.reserved("u64")
                    .with(value(Primitive::Uint(Int::Int64)))
               ])
               .map(|primitive| Type::Prim(primitive))
               .parse_state(input)
    }

    fn raw_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('*').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Raw(Rc::new(t))))
                 .parse_state(input)
    }

    fn unique_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('@').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Unique(Rc::new(t))))
                 .parse_state(input)
    }

    fn borrow_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('&').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Borrowed(Rc::new(t))))
                 .parse_state(input)
    }
    fn parse_type(&self, input: State<I>) -> ParseResult<Type, I> {
        choice([ self.parser(MnEnv::parse_primitive_ty)
               , self.parser(MnEnv::raw_ptr_ty)
               , self.parser(MnEnv::unique_ptr_ty)
               , self.parser(MnEnv::borrow_ptr_ty)
               ])
            .parse_state(input)
    }

    fn parse_binding(&self, input: State<I>)
                    -> ParseResult<Unscoped<'a, Binding<'a, U>>, I> {
        let pos = input.position.clone();
        self.parser(MnEnv::parse_name)
            .and(self.type_annotation())
            .and(self.expr())
            .map(|((name, typ), value)|
                Annotated::new( Binding { name: name
                                        , typ: typ
                                        , value: Rc::new(value)
                                        }
                               , Position::from(pos)
                           ))
            .parse_state(input)
    }

    #[allow(dead_code)]
    fn parse_logical(&self, input: State<I>)
                    -> ParseResult<Logical<'a, U>, I> {
        let and = self.reserved("and")
                      .with(self.expr())
                      .and(self.expr())
                      .map(|(a, b)| Logical::And { a: Rc::new(a)
                                                 , b: Rc::new(b)
                                                 });

         let or = self.reserved("or")
                      .with(self.expr())
                      .and(self.expr())
                      .map(|(a, b)| Logical::And { a: Rc::new(a)
                                                 , b: Rc::new(b)
                                                 });

        and.or(or)
           .parse_state(input)
    }

    fn int_const(&'b self) -> MnParser<'a, 'b, I, Const> {
        self.parser(MnEnv::parse_int_const)
    }

    #[allow(dead_code)]
    fn parse_int_const(&self, input: State<I>) -> ParseResult<Const, I> {
        self.integer()
            .map(Const::IntConst)
            .parse_state(input)
    }

    fn parse_let(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {

        let binding_form =
            self.reserved("let")
                .with(many(self.parens(self.binding())))
                .and(many(self.expr()))
                .map(|(bindings, body)| LetForm::Let { bindings: bindings
                                                     , body: body });

        choice([ binding_form ])
            .map(Form::Let)
            .parse_state(input)
    }

    fn parse_name (&self, input: State<I>) -> ParseResult<Ident, I> {
        let position = input.position.clone();
        self.env.identifier::<'b>()
            .map(|name| Positional { pos: Position::from(position)
                                   , value: name })
            .parse_state(input)
    }

    fn parse_call(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.name()
            .and(many(self.expr()))
            .map(|(name, args)| Form::Call { fun: name, body: args })
            .parse_state(input)
    }

    fn parse_expr(&self, input: State<I>) -> ParseResult<Expr<'a, U>, I> {
        let pos = Position::from(input.position.clone());
        self.env
            .parens(choice([ self.def()
                           , self.if_form()
                           , self.lambda()
                           , self.let_form()
                           , self.call()
                           ]))
            .or(self.int_const()
                    .map(Form::Constant))
            .map(|f| Annotated::new(f, pos) )
            .parse_state(input)
    }

    fn expr(&'b self) -> MnParser<'a, 'b, I, Expr<'a, U>> {
        self.parser(MnEnv::parse_expr)
    }

    fn def(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_def)
    }

    fn if_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_if)
    }

    fn let_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_let)
    }

    fn lambda(&'b self)-> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_lambda)
    }

    fn call(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_call)
    }

    fn name(&'b self) -> MnParser<'a, 'b, I, Ident> {
        self.parser(MnEnv::parse_name)
    }

    fn binding(&'b self)
              -> MnParser< 'a, 'b, I, Unscoped<'a, Binding<'a, U>>> {
        self.parser(MnEnv::parse_binding)
    }

    fn type_annotation(&'b self) -> MnParser<'a, 'b, I, types::Type> {
        self.parser(MnEnv::parse_type)
    }

    fn function(&'b self) -> MnParser<'a, 'b, I, Function<'a, U>> {
        self.parser(MnEnv::parse_function)
    }

}
pub fn parse_module<'a>(code: &'a str)
                        -> Result< Vec<Expr<'a, UnscopedState>>
                                 , ParseError<&str>>
 {
    let alpha_ext = "+-*/<=>!:$%_^";
    let ops = "+-*/|=<>";
    let env = LanguageEnv::new(LanguageDef {
        ident: Identifier {
            start: letter().or(satisfy(move |c| alpha_ext.contains(c)))
          , rest: alpha_num().or(satisfy(move |c| alpha_ext.contains(c)))
          , reserved: [ // a number of these reserved words have no meaning yet
                        "and"               , "begin"
                      , "case"              , "cond"        , "class"
                      , "data"
                      , "define"            , "defn"        , "def"
                      , "delay"             , "fn"
                      , "do"                , "else"
                      , "if"                , "lambda"      , LAMBDA
                      , "let"               , "let*"        , "letrec"
                      , "or"
                      , "quasiquote"        , "quote"       , "unquote"
                      , "set!"              , "unquote-splicing"
                      , "struct"            , "union"
                      , "i8"                , "u8"
                      , "i16"               , "u16"
                      , "i32"               , "u32"         , "f32"
                      , "i64"               , "u64"         , "f64"
                      , "int"               , "uint"        , "float"
                      , "bool"                              , "double"
                      , "ref"               , "move"        , "borrow"
                      , "trait"             , "typeclass"
                      , "instance"          , "impl"
                      ].iter().map(|x| (*x).into())
                       .collect()
        }
      , op: Identifier {
            start: satisfy(move |c| ops.contains(c))
          , rest:  satisfy(move |c| ops.contains(c))
          , reserved: [ "=>", "->", "\\", "|", ARROW, FAT_ARROW]
                .iter().map(|x| (*x).into()).collect()
        }
      , comment_line: string(";").map(|_| ())
      , comment_start: string("#|").map(|_| ())
      , comment_end: string("|#").map(|_| ())
    });
    let env = MnEnv { env: env };

    env.white_space()
       .with(many1::<Vec<Expr<'a, U>>, _>(env.expr()))
       .parse(code)
       .map(|(e, _)| e)
}
<|endoftext|>


<commit_before> #![feature(core)]
 #![feature(path_ext)]
extern crate eve;
extern crate getopts;
extern crate url;
extern crate core;

use std::thread;
use std::env;
use std::fs::PathExt;
use getopts::Options;
use std::net::SocketAddr;
use core::str::FromStr;

use eve::server;
use eve::login;

#[allow(dead_code)]
fn main() {

	// handle command line arguments
	let args: Vec<String> = env::args().collect();

	// define the command line arguments
	let mut opts = Options::new();
    opts.optopt("f", "faddress", "specify a socket address for the static file server. Defaults to 0.0.0.0:8080","SOCKET ADDRESS");
    opts.optopt("s", "saves", "specify the location of the saves directory","PATH");
    opts.optflag("h", "help", "prints all options and usage");

    // parse raw input arguments into options
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    // print the help menu
    if matches.opt_present("h") {
        print!("{}", opts.usage(""));
        return;
    }

    // parse static file server address
    let default_addr = SocketAddr::from_str("0.0.0.0:8080").unwrap();
    let addr = match matches.opt_str("f") {
		Some(ip) => {
			match SocketAddr::from_str(&*ip) {
				Ok(addr) => addr,
				Err(_) => {
					println!("WARNING: Could not parse static file server address.\nDefaulting to {:?}",default_addr);
					default_addr
				}
			}
		},
		None => default_addr,
	};

	// parse the autosave file location
    let default_saves_dir = "../saves/".to_owned();
    let saves_dir = match matches.opt_str("s") {
		Some(saves_dir) => saves_dir,
		None => default_saves_dir,
	};
    let absolute_saves_dir = env::current_dir().unwrap().join(saves_dir).canonicalize().unwrap();

	thread::spawn(move || login::run(addr.clone()));
    server::run(absolute_saves_dir.as_path());
}<commit_msg>rename command line option<commit_after> #![feature(core)]
 #![feature(path_ext)]
extern crate eve;
extern crate getopts;
extern crate url;
extern crate core;

use std::thread;
use std::env;
use std::fs::PathExt;
use getopts::Options;
use std::net::SocketAddr;
use core::str::FromStr;

use eve::server;
use eve::login;

#[allow(dead_code)]
fn main() {

	// handle command line arguments
	let args: Vec<String> = env::args().collect();

	// define the command line arguments
	let mut opts = Options::new();
    opts.optopt("f", "file-server-address", "specify a socket address for the static file server. Defaults to 0.0.0.0:8080","SOCKET ADDRESS");
    opts.optopt("s", "saves", "specify the location of the saves directory","PATH");
    opts.optflag("h", "help", "prints all options and usage");

    // parse raw input arguments into options
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    // print the help menu
    if matches.opt_present("h") {
        print!("{}", opts.usage(""));
        return;
    }

    // parse static file server address
    let default_addr = SocketAddr::from_str("0.0.0.0:8080").unwrap();
    let addr = match matches.opt_str("f") {
		Some(ip) => {
			match SocketAddr::from_str(&*ip) {
				Ok(addr) => addr,
				Err(_) => {
					println!("WARNING: Could not parse static file server address.\nDefaulting to {:?}",default_addr);
					default_addr
				}
			}
		},
		None => default_addr,
	};

	// parse the autosave file location
    let default_saves_dir = "../saves/".to_owned();
    let saves_dir = match matches.opt_str("s") {
		Some(saves_dir) => saves_dir,
		None => default_saves_dir,
	};
    let absolute_saves_dir = env::current_dir().unwrap().join(saves_dir).canonicalize().unwrap();

	thread::spawn(move || login::run(addr.clone()));
    server::run(absolute_saves_dir.as_path());
}<|endoftext|>


<commit_before>#![allow(dead_code)]
use std::collections::{BTreeMap, HashMap};
use std::iter::FromIterator;

type DocId = i32;
const MIN_DOC_ID: DocId = std::i32::MIN;
const MAX_DOC_ID: DocId = std::i32::MAX;

#[derive(Clone, Debug, PartialEq)]
struct ScoredDoc {
    id: DocId,
    score: f32,
}

struct Term<'a> {
    field: &'a str,
    token: &'a str,
    weight: f32,
}

// used to populate an index in a simple way
type IndexEntry<'a> = (&'a str, &'a str, DocId, f32);

type DensePostingList = Vec<ScoredDoc>;

#[derive(Debug)]
struct InvertedIndexNaive<'a> {
    posting_lists: HashMap<&'a str, HashMap<&'a str, DensePostingList>>,
}

impl<'a> FromIterator<IndexEntry<'a>> for InvertedIndexNaive<'a> {
    fn from_iter<T: IntoIterator<Item = IndexEntry<'a>>>(iter: T) -> Self {
        // insert field -> (token -> (doc id -> score))
        let mut nested_maps = HashMap::new();
        for (field, token, doc_id, payload) in iter {
            let field_entry = nested_maps.entry(field).or_insert_with(HashMap::new);
            let token_entry = field_entry.entry(token).or_insert_with(BTreeMap::new);
            token_entry.insert(doc_id, payload);
        }
        let mut posting_lists = HashMap::new();
        // turn BTreeMaps into DesnPostingLists
        for (field, token_map) in nested_maps {
            let field_entry = posting_lists.entry(field).or_insert_with(HashMap::new);
            for (token, score_map) in token_map {
                let posting_list = score_map
                    .iter()
                    .map(|x| ScoredDoc {
                        id: *x.0,
                        score: *x.1,
                    })
                    .collect();
                field_entry.insert(token, posting_list);
            }
        }
        InvertedIndexNaive { posting_lists }
    }
}

enum AndState {
    Searching,
    HitEmptyList(usize),
    Done,
}

struct And<'a> {
    state: AndState,
    frontier: Vec<std::slice::Iter<'a, ScoredDoc>>,
    weights: Vec<f32>,
    last_viable_id: i32,
}

impl<'a> And<'a> {
    fn new(index: &'a InvertedIndexNaive, terms: &[Term]) -> Self {
        let mut frontier = Vec::with_capacity(terms.len());
        let mut weights = Vec::with_capacity(terms.len());
        // check to see if we can even find posing lists for all the terms
        for term in terms.iter() {
            let lookup = index
                .posting_lists
                .get(term.field)
                .and_then(|field_result| field_result.get(term.token));

            match lookup {
                None => {
                    return And {
                        state: AndState::Done,
                        frontier: Vec::new(),
                        weights: Vec::new(),
                        last_viable_id: MAX_DOC_ID,
                    }
                }
                Some(list) => {
                    frontier.push(list.iter());
                    weights.push(term.weight);
                }
            }
        }
        And {
            state: AndState::Searching,
            frontier,
            weights,
            last_viable_id: MIN_DOC_ID,
        }
    }
}

impl Iterator for And<'_> {
    type Item = ScoredDoc;

    fn next(&mut self) -> Option<ScoredDoc> {
        let mut matched_doc_count = 0;
        let mut score = 0.0;

        for posting_list_number in (0..self.frontier.len()).cycle() {
            let mut last_viable_id = self.last_viable_id;
            let list_iter = self.frontier.get_mut(posting_list_number).unwrap();
            let mut list_iter = list_iter.skip_while(|doc| doc.id < last_viable_id);
            match list_iter.next() {
                None => match self.state {
                    AndState::Searching => self.state = AndState::HitEmptyList(posting_list_number),
                    AndState::HitEmptyList(i) => {
                        if posting_list_number == i {
                            self.state = AndState::Done;
                        }
                    }
                    AndState::Done => break,
                },
                Some(doc) => {
                    if doc.id == last_viable_id {
                        score += self.weights[posting_list_number] * doc.score;
                        matched_doc_count += 1;
                    } else {
                        matched_doc_count = 0;
                        score = self.weights[posting_list_number] * doc.score;
                        last_viable_id = doc.id;
                    }
                }
            }
            if matched_doc_count == self.frontier.len() - 1 {
                return Some(ScoredDoc {
                    id: last_viable_id,
                    score,
                });
            }
            self.last_viable_id = last_viable_id;
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn empty_and() {
        let inverted_index = &InvertedIndexNaive {
            posting_lists: HashMap::new(),
        };
        let term = &vec![Term {
            field: "your",
            token: "mom",
            weight: 9000.1,
        }];
        let and = And::new(inverted_index, term);
        assert_eq!(and.count(), 0);
    }

    #[test]
    fn nonempty_and() {
        let inverted_index: InvertedIndexNaive = [
            ("description", "very", 1, 1.0),
            ("description", "very", 5, 1.0),
            ("description", "human", 2, 1.0),
            ("description", "human", 5, 2.0),
            ("description", "like", 3, 1.0),
            ("description", "like", 5, 3.0),
            ("description", "eyes", 4, 1.0),
            ("description", "eyes", 5, 4.0),
            ("title", "manul", 1, 1.0),
            ("title", "manul", 5, 5.0),
            ("title", "cat", 2, 1.0),
            ("title", "cat", 5, 6.0),
            ("title", "facial", 3, 1.0),
            ("title", "facial", 5, 7.0),
            ("title", "expression", 4, 1.0),
            ("title", "expression", 5, 8.0),
        ]
        .iter()
        .cloned()
        .collect();

        let terms = [
            Term {
                field: "description",
                token: "very",
                weight: 1.0,
            },
            Term {
                field: "description",
                token: "human",
                weight: 10.0,
            },
            Term {
                field: "description",
                token: "like",
                weight: 100.0,
            },
            Term {
                field: "description",
                token: "eyes",
                weight: 1_000.0,
            },
            Term {
                field: "title",
                token: "manul",
                weight: 10_000.0,
            },
            Term {
                field: "title",
                token: "cat",
                weight: 100_000.0,
            },
            Term {
                field: "title",
                token: "facial",
                weight: 1_000_000.0,
            },
            Term {
                field: "title",
                token: "expression",
                weight: 10_000_000.0,
            },
        ];

        let and = And::new(&inverted_index, &terms);
        let actual: Vec<ScoredDoc> = and.collect();
        assert_eq!(
            actual,
            vec![ScoredDoc {
                id: 5,
                score: 87_654_321.0
            }]
        )
    }
}
<commit_msg>And ergonomics<commit_after>#![allow(dead_code)]
use std::collections::{BTreeMap, HashMap};
use std::iter::FromIterator;

type DocId = i32;
const MIN_DOC_ID: DocId = std::i32::MIN;
const MAX_DOC_ID: DocId = std::i32::MAX;

#[derive(Clone, Debug, PartialEq)]
struct ScoredDoc {
    id: DocId,
    score: f32,
}

struct Term<'a> {
    field: &'a str,
    token: &'a str,
    weight: f32,
}

// used to populate an index in a simple way
type IndexEntry<'a> = (&'a str, &'a str, DocId, f32);

type DensePostingList = Vec<ScoredDoc>;

type WeightedPostingListIterator<'a> = (f32, std::slice::Iter<'a, ScoredDoc>);

#[derive(Debug)]
struct InvertedIndexNaive<'a> {
    // TODO: dictionaries and IDF's, etc as well
    posting_lists: HashMap<&'a str, HashMap<&'a str, DensePostingList>>,
}

impl<'a> InvertedIndexNaive<'a> {
    // TODO: figure out the lifetime stuff to make this return an iterator and can early terminate on
    fn get_lists_for_terms(&self, terms: &[Term<'a>]) -> Vec<Option<(f32, &DensePostingList)>> {
        terms
            .iter()
            .map(|term| {
                self.posting_lists.get(term.field).and_then(|field_result| {
                    field_result.get(term.token).map(|list| (term.weight, list))
                })
            })
            .collect()
    }
}

impl<'a> FromIterator<IndexEntry<'a>> for InvertedIndexNaive<'a> {
    fn from_iter<T: IntoIterator<Item = IndexEntry<'a>>>(iter: T) -> Self {
        // insert field -> (token -> (doc id -> score))
        let mut nested_maps = HashMap::new();
        for (field, token, doc_id, payload) in iter {
            let field_entry = nested_maps.entry(field).or_insert_with(HashMap::new);
            let token_entry = field_entry.entry(token).or_insert_with(BTreeMap::new);
            token_entry.insert(doc_id, payload);
        }
        let mut posting_lists = HashMap::new();
        // turn BTreeMaps into DesnPostingLists
        for (field, token_map) in nested_maps {
            let field_entry = posting_lists.entry(field).or_insert_with(HashMap::new);
            for (token, score_map) in token_map {
                let posting_list = score_map
                    .iter()
                    .map(|x| ScoredDoc {
                        id: *x.0,
                        score: *x.1,
                    })
                    .collect();
                field_entry.insert(token, posting_list);
            }
        }
        InvertedIndexNaive { posting_lists }
    }
}

#[derive(Clone, Copy, Debug, PartialEq)]
enum AndState {
    Searching,
    IterationsAfterEmptyList(usize),
    Done,
}

impl AndState {
    fn next_state(&self, frontier_length: usize) -> Self {
        match self {
            AndState::Searching => AndState::IterationsAfterEmptyList(0),
            AndState::IterationsAfterEmptyList(i) => {
                if *i == frontier_length - 1 {
                    AndState::Done
                } else {
                    AndState::IterationsAfterEmptyList(i + 1)
                }
            }
            AndState::Done => AndState::Done,
        }
    }
}

impl Default for AndState {
    fn default() -> Self {
        AndState::Done
    }
}

#[derive(Default)]
struct And<'a> {
    state: AndState,
    frontier: Vec<WeightedPostingListIterator<'a>>,
    last_viable_id: i32,
}

// TODO: ctor that takes in existing iterators
impl<'a> And<'a> {
    fn new(index: &'a InvertedIndexNaive, terms: &[Term<'a>]) -> Self {
        let mut frontier = Vec::with_capacity(terms.len());
        for lookup in index.get_lists_for_terms(terms) {
            match lookup {
                None => return And::default(),
                Some((weight, list)) => frontier.push((weight, list.iter())),
            }
        }
        And {
            state: AndState::Searching,
            frontier,
            last_viable_id: MIN_DOC_ID,
        }
    }
}

impl Iterator for And<'_> {
    type Item = ScoredDoc;

    fn next(&mut self) -> Option<ScoredDoc> {
        let frontier_length = self.frontier.len();
        let mut matched_doc_count = 0;
        let mut score = 0.0;

        while self.state != AndState::Done {
            for (weight, posting_list) in self.frontier.iter_mut() {
                let mut current_state = self.state;
                let mut last_viable_id = self.last_viable_id;
                let mut list_iter = posting_list.skip_while(|doc| doc.id < last_viable_id);
                match list_iter.next() {
                    None => current_state = current_state.next_state(frontier_length),
                    Some(doc) => {
                        let score_contribution = *weight * doc.score;
                        if doc.id == last_viable_id {
                            score += score_contribution;
                            matched_doc_count += 1;
                        } else {
                            score = score_contribution;
                            matched_doc_count = 0;
                            last_viable_id = doc.id;
                        }
                    }
                }
                if matched_doc_count == frontier_length - 1 {
                    return Some(ScoredDoc {
                        id: last_viable_id,
                        score,
                    });
                }
                self.last_viable_id = last_viable_id;
                self.state = current_state;
                if self.state == AndState::Done {
                    break;
                }
            }
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn empty_and() {
        let inverted_index = &InvertedIndexNaive {
            posting_lists: HashMap::new(),
        };
        let term = &vec![Term {
            field: "your",
            token: "mom",
            weight: 9000.1,
        }];
        let and = And::new(inverted_index, term);
        assert_eq!(and.count(), 0);
    }

    #[test]
    fn nonempty_and() {
        let inverted_index: InvertedIndexNaive = [
            ("description", "very", 1, 1.0),
            ("description", "very", 5, 1.0),
            ("description", "very", 6, 1.0),
            ("description", "human", 2, 1.0),
            ("description", "human", 5, 2.0),
            ("description", "human", 6, 1.0),
            ("description", "like", 3, 1.0),
            ("description", "like", 5, 3.0),
            ("description", "eyes", 4, 1.0),
            ("description", "eyes", 5, 4.0),
            ("description", "eyes", 6, 1.0),
            ("title", "manul", 1, 1.0),
            ("title", "manul", 5, 5.0),
            ("title", "manul", 6, 1.0),
            ("title", "cat", 2, 1.0),
            ("title", "cat", 5, 6.0),
            ("title", "cat", 6, 1.0),
            ("title", "facial", 3, 1.0),
            ("title", "facial", 5, 7.0),
            ("title", "facial", 6, 1.0),
            ("title", "expression", 4, 1.0),
            ("title", "expression", 5, 8.0),
            ("title", "expression", 6, 1.0),
        ]
        .iter()
        .cloned()
        .collect();

        let terms = [
            Term {
                field: "description",
                token: "very",
                weight: 1.0,
            },
            Term {
                field: "description",
                token: "human",
                weight: 10.0,
            },
            Term {
                field: "description",
                token: "like",
                weight: 100.0,
            },
            Term {
                field: "description",
                token: "eyes",
                weight: 1_000.0,
            },
            Term {
                field: "title",
                token: "manul",
                weight: 10_000.0,
            },
            Term {
                field: "title",
                token: "cat",
                weight: 100_000.0,
            },
            Term {
                field: "title",
                token: "facial",
                weight: 1_000_000.0,
            },
            Term {
                field: "title",
                token: "expression",
                weight: 10_000_000.0,
            },
        ];

        let and = And::new(&inverted_index, &terms);
        let actual: Vec<ScoredDoc> = and.collect();
        assert_eq!(
            actual,
            vec![ScoredDoc {
                id: 5,
                score: 87_654_321.0
            }]
        )
    }
}
<|endoftext|>