<commit_before>use crate::math::{EARTH_RADIUS_MAX_M, EARTH_RADIUS_MIN_M};
use crate::read_write::{Encoding, NodeWriter, OpenMode};
use crate::s2_cells::{S2CellMeta, S2Meta};
use crate::{AttributeData, AttributeDataType, PointsBatch};
use cgmath::{EuclideanSpace, InnerSpace, Point3};
use collision::{Aabb, Aabb3};
use fnv::FnvHashMap;
use lru::LruCache;
use s2::cellid::CellID;
use s2::point::Point;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::io::{Error, ErrorKind, Result};
use std::iter::Iterator;
use std::path::PathBuf;

/// The actual number of underlying writers is MAX_NUM_NODE_WRITERS * num_attributes.
const MAX_NUM_NODE_WRITERS: usize = 25;
/// Corresponds to cells of up to about 10m x 10m.
const S2_SPLIT_LEVEL: u64 = 20;

pub struct S2Splitter<W> {
    writers: LruCache<CellID, W>,
    already_opened_writers: HashSet<CellID>,
    cell_stats: FnvHashMap<CellID, S2CellMeta>,
    bounding_box: Option<Aabb3<f64>>,
    attributes_seen: BTreeMap<String, AttributeDataType>,
    encoding: Encoding,
    open_mode: OpenMode,
    stem: PathBuf,
}

impl<W> NodeWriter<PointsBatch> for S2Splitter<W>
where
    W: NodeWriter<PointsBatch>,
{
    fn new(path: impl Into<PathBuf>, encoding: Encoding, open_mode: OpenMode) -> Self {
        let writers = LruCache::new(MAX_NUM_NODE_WRITERS);
        let already_opened_writers = HashSet::new();
        let stem = path.into();
        let cell_stats = FnvHashMap::default();
        let bounding_box = None;
        let attributes_seen = BTreeMap::new();
        S2Splitter {
            writers,
            already_opened_writers,
            cell_stats,
            bounding_box,
            attributes_seen,
            encoding,
            open_mode,
            stem,
        }
    }

    fn write(&mut self, points_batch: &PointsBatch) -> Result<()> {
        self.check_attributes(points_batch)?;
        let mut batches_by_s2_cell = HashMap::new();
        for (i, pos) in points_batch.position.iter().enumerate() {
            let radius = pos.magnitude();
            if radius > EARTH_RADIUS_MAX_M || radius < EARTH_RADIUS_MIN_M {
                let msg = format!(
                    "Point ({}, {}, {}) is not a valid ECEF point",
                    pos.x, pos.y, pos.z
                );
                return Err(Error::new(ErrorKind::InvalidInput, msg));
            }
            let p3 = Point3::from_vec(*pos);
            let b = self.bounding_box.get_or_insert(Aabb3::new(p3, p3));
            *b = b.grow(p3);
            let s2_point = Point::from_coords(pos.x, pos.y, pos.z);
            let s2_cell_id = CellID::from(s2_point).parent(S2_SPLIT_LEVEL);
            self.cell_stats
                .entry(s2_cell_id)
                .or_insert(S2CellMeta { num_points: 0 })
                .num_points += 1;
            let s2_cell_batch = batches_by_s2_cell.entry(s2_cell_id).or_insert(PointsBatch {
                position: Vec::new(),
                attributes: BTreeMap::new(),
            });
            s2_cell_batch.position.push(*pos);
            for (in_key, in_data) in &points_batch.attributes {
                use AttributeData::*;
                let key = in_key.to_string();
                s2_cell_batch
                    .attributes
                    .entry(key)
                    .and_modify(|out_data| match (in_data, out_data) {
                        (U8(in_vec), U8(out_vec)) => out_vec.push(in_vec[i]),
                        (I64(in_vec), I64(out_vec)) => out_vec.push(in_vec[i]),
                        (U64(in_vec), U64(out_vec)) => out_vec.push(in_vec[i]),
                        (F32(in_vec), F32(out_vec)) => out_vec.push(in_vec[i]),
                        (F64(in_vec), F64(out_vec)) => out_vec.push(in_vec[i]),
                        (U8Vec3(in_vec), U8Vec3(out_vec)) => out_vec.push(in_vec[i]),
                        (F64Vec3(in_vec), F64Vec3(out_vec)) => out_vec.push(in_vec[i]),
                        _ => panic!("Input data type unequal output data type."),
                    })
                    .or_insert(match in_data {
                        U8(in_vec) => U8(vec![in_vec[i]]),
                        I64(in_vec) => I64(vec![in_vec[i]]),
                        U64(in_vec) => U64(vec![in_vec[i]]),
                        F32(in_vec) => F32(vec![in_vec[i]]),
                        F64(in_vec) => F64(vec![in_vec[i]]),
                        U8Vec3(in_vec) => U8Vec3(vec![in_vec[i]]),
                        F64Vec3(in_vec) => F64Vec3(vec![in_vec[i]]),
                    });
            }
        }

        for (cell_id, batch) in &batches_by_s2_cell {
            self.writer(cell_id).write(batch)?;
        }
        Ok(())
    }
}

impl<W> S2Splitter<W>
where
    W: NodeWriter<PointsBatch>,
{
    fn writer(&mut self, cell_id: &CellID) -> &mut W {
        let path = self.stem.join(cell_id.to_token());
        if !self.writers.contains(cell_id) {
            let open_mode = if self.open_mode == OpenMode::Append
                || self.already_opened_writers.contains(cell_id)
            {
                OpenMode::Append
            } else {
                self.already_opened_writers.insert(*cell_id);
                OpenMode::Truncate
            };
            self.writers
                .put(*cell_id, W::new(path, self.encoding.clone(), open_mode));
        }
        self.writers.get_mut(cell_id).unwrap()
    }

    /// Records the list of attributes seen in the first batch, and checks
    /// that the following batches contain the same attributes.
    fn check_attributes(&mut self, batch: &PointsBatch) -> Result<()> {
        let mut attr_iter = batch
            .attributes
            .iter()
            .map(|(name, data)| (name, data.data_type()));
        if self.attributes_seen.is_empty() {
            self.attributes_seen
                .extend(attr_iter.map(|(key, val)| (key.to_owned(), val)));
            Ok(())
        } else {
            attr_iter.try_for_each(|(name, dtype)| {
                self.attributes_seen
                    .get(name)
                    .filter(|seen_dtype| **seen_dtype == dtype)
                    .ok_or_else(|| {
                        let msg = format!(
                            "S2Splitter received incompatible data types for attribute {}",
                            name
                        );
                        Error::new(ErrorKind::InvalidInput, msg)
                    })?;
                Ok(())
            })
        }
    }

    pub fn get_meta(self) -> S2Meta {
        S2Meta::new(
            self.cell_stats,
            self.attributes_seen.into_iter().collect(),
            self.bounding_box.unwrap_or_else(Aabb3::zero),
        )
    }
}
<commit_msg>Set S2 cell level to 16 (#376)<commit_after>use crate::math::{EARTH_RADIUS_MAX_M, EARTH_RADIUS_MIN_M};
use crate::read_write::{Encoding, NodeWriter, OpenMode};
use crate::s2_cells::{S2CellMeta, S2Meta};
use crate::{AttributeData, AttributeDataType, PointsBatch};
use cgmath::{EuclideanSpace, InnerSpace, Point3};
use collision::{Aabb, Aabb3};
use fnv::FnvHashMap;
use lru::LruCache;
use s2::cellid::CellID;
use s2::point::Point;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::io::{Error, ErrorKind, Result};
use std::iter::Iterator;
use std::path::PathBuf;

/// The actual number of underlying writers is MAX_NUM_NODE_WRITERS * num_attributes.
const MAX_NUM_NODE_WRITERS: usize = 25;
/// Corresponds to cells of up to about 160m x 160m.
const S2_SPLIT_LEVEL: u64 = 16;

pub struct S2Splitter<W> {
    writers: LruCache<CellID, W>,
    already_opened_writers: HashSet<CellID>,
    cell_stats: FnvHashMap<CellID, S2CellMeta>,
    bounding_box: Option<Aabb3<f64>>,
    attributes_seen: BTreeMap<String, AttributeDataType>,
    encoding: Encoding,
    open_mode: OpenMode,
    stem: PathBuf,
}

impl<W> NodeWriter<PointsBatch> for S2Splitter<W>
where
    W: NodeWriter<PointsBatch>,
{
    fn new(path: impl Into<PathBuf>, encoding: Encoding, open_mode: OpenMode) -> Self {
        let writers = LruCache::new(MAX_NUM_NODE_WRITERS);
        let already_opened_writers = HashSet::new();
        let stem = path.into();
        let cell_stats = FnvHashMap::default();
        let bounding_box = None;
        let attributes_seen = BTreeMap::new();
        S2Splitter {
            writers,
            already_opened_writers,
            cell_stats,
            bounding_box,
            attributes_seen,
            encoding,
            open_mode,
            stem,
        }
    }

    fn write(&mut self, points_batch: &PointsBatch) -> Result<()> {
        self.check_attributes(points_batch)?;
        let mut batches_by_s2_cell = HashMap::new();
        for (i, pos) in points_batch.position.iter().enumerate() {
            let radius = pos.magnitude();
            if radius > EARTH_RADIUS_MAX_M || radius < EARTH_RADIUS_MIN_M {
                let msg = format!(
                    "Point ({}, {}, {}) is not a valid ECEF point",
                    pos.x, pos.y, pos.z
                );
                return Err(Error::new(ErrorKind::InvalidInput, msg));
            }
            let p3 = Point3::from_vec(*pos);
            let b = self.bounding_box.get_or_insert(Aabb3::new(p3, p3));
            *b = b.grow(p3);
            let s2_point = Point::from_coords(pos.x, pos.y, pos.z);
            let s2_cell_id = CellID::from(s2_point).parent(S2_SPLIT_LEVEL);
            self.cell_stats
                .entry(s2_cell_id)
                .or_insert(S2CellMeta { num_points: 0 })
                .num_points += 1;
            let s2_cell_batch = batches_by_s2_cell.entry(s2_cell_id).or_insert(PointsBatch {
                position: Vec::new(),
                attributes: BTreeMap::new(),
            });
            s2_cell_batch.position.push(*pos);
            for (in_key, in_data) in &points_batch.attributes {
                use AttributeData::*;
                let key = in_key.to_string();
                s2_cell_batch
                    .attributes
                    .entry(key)
                    .and_modify(|out_data| match (in_data, out_data) {
                        (U8(in_vec), U8(out_vec)) => out_vec.push(in_vec[i]),
                        (I64(in_vec), I64(out_vec)) => out_vec.push(in_vec[i]),
                        (U64(in_vec), U64(out_vec)) => out_vec.push(in_vec[i]),
                        (F32(in_vec), F32(out_vec)) => out_vec.push(in_vec[i]),
                        (F64(in_vec), F64(out_vec)) => out_vec.push(in_vec[i]),
                        (U8Vec3(in_vec), U8Vec3(out_vec)) => out_vec.push(in_vec[i]),
                        (F64Vec3(in_vec), F64Vec3(out_vec)) => out_vec.push(in_vec[i]),
                        _ => panic!("Input data type unequal output data type."),
                    })
                    .or_insert(match in_data {
                        U8(in_vec) => U8(vec![in_vec[i]]),
                        I64(in_vec) => I64(vec![in_vec[i]]),
                        U64(in_vec) => U64(vec![in_vec[i]]),
                        F32(in_vec) => F32(vec![in_vec[i]]),
                        F64(in_vec) => F64(vec![in_vec[i]]),
                        U8Vec3(in_vec) => U8Vec3(vec![in_vec[i]]),
                        F64Vec3(in_vec) => F64Vec3(vec![in_vec[i]]),
                    });
            }
        }

        for (cell_id, batch) in &batches_by_s2_cell {
            self.writer(cell_id).write(batch)?;
        }
        Ok(())
    }
}

impl<W> S2Splitter<W>
where
    W: NodeWriter<PointsBatch>,
{
    fn writer(&mut self, cell_id: &CellID) -> &mut W {
        let path = self.stem.join(cell_id.to_token());
        if !self.writers.contains(cell_id) {
            let open_mode = if self.open_mode == OpenMode::Append
                || self.already_opened_writers.contains(cell_id)
            {
                OpenMode::Append
            } else {
                self.already_opened_writers.insert(*cell_id);
                OpenMode::Truncate
            };
            self.writers
                .put(*cell_id, W::new(path, self.encoding.clone(), open_mode));
        }
        self.writers.get_mut(cell_id).unwrap()
    }

    /// Records the list of attributes seen in the first batch, and checks
    /// that the following batches contain the same attributes.
    fn check_attributes(&mut self, batch: &PointsBatch) -> Result<()> {
        let mut attr_iter = batch
            .attributes
            .iter()
            .map(|(name, data)| (name, data.data_type()));
        if self.attributes_seen.is_empty() {
            self.attributes_seen
                .extend(attr_iter.map(|(key, val)| (key.to_owned(), val)));
            Ok(())
        } else {
            attr_iter.try_for_each(|(name, dtype)| {
                self.attributes_seen
                    .get(name)
                    .filter(|seen_dtype| **seen_dtype == dtype)
                    .ok_or_else(|| {
                        let msg = format!(
                            "S2Splitter received incompatible data types for attribute {}",
                            name
                        );
                        Error::new(ErrorKind::InvalidInput, msg)
                    })?;
                Ok(())
            })
        }
    }

    pub fn get_meta(self) -> S2Meta {
        S2Meta::new(
            self.cell_stats,
            self.attributes_seen.into_iter().collect(),
            self.bounding_box.unwrap_or_else(Aabb3::zero),
        )
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate rusqlite;
#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;
extern crate rustc_serialize;
extern crate serde_yaml;
extern crate uuid;
#[cfg(test)]
#[macro_use]
extern crate proptest;

mod actions_process;
mod actions_process_list_provides;
mod autoconf;
mod clap_actions;
mod clap_fern;
mod cli_clap;
mod db;
mod db_enviroment;
mod db_fs_dir;
mod db_fs_dir_type;
mod db_fs_file;
mod db_job;
mod db_job_depend;
mod db_job_provide;
mod db_job_require_variable;
mod db_job_require_variable_pair;
mod db_provider;
mod db_session;
mod db_variable_name;
mod db_variable_pair;
mod elephant;
mod jobs_load;
mod json_loader_elephant;
mod loader;
use uuid::Uuid;

fn main() {
    let some_value = 10;
    let clap_matches = cli_clap::cli_clap(&some_value);
    let actions = clap_actions::actions_get(&clap_matches);
    clap_fern::log_setup(&clap_matches);
    let session_uuid = Uuid::new_v4();
    let session_uuid_string = session_uuid.hyphenated().to_string();
    trace!("session_uuid_string:{}", session_uuid_string);
    let conn = db::connect_deligate(&clap_matches);
    db::create_tables(&conn);
    loader::deligate(&conn, &actions, &clap_matches);
    let pk_session = elephant::elephant_session(&conn, &session_uuid_string);
    loader::enviroment(&conn, pk_session, &clap_matches);
    jobs_load::load(&conn);
    actions_process::process(&conn, &actions)
}
<commit_msg>Moved db into its own submodule<commit_after>extern crate clap;
extern crate rusqlite;
#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;
extern crate rustc_serialize;
extern crate serde_yaml;
extern crate uuid;
#[cfg(test)]
#[macro_use]
extern crate proptest;

mod actions_process;
mod actions_process_list_provides;
mod autoconf;
mod clap_actions;
mod clap_fern;
mod cli_clap;
mod db;
mod db_enviroment;
mod db_fs_dir;
mod db_fs_dir_type;
mod db_fs_file;
mod db_job;
mod db_job_depend;
mod db_job_provide;
mod db_job_require_variable;
mod db_job_require_variable_pair;
mod db_provider;
use db::db_session;
mod db_variable_name;
mod db_variable_pair;
mod elephant;
mod jobs_load;
mod json_loader_elephant;
mod loader;
use uuid::Uuid;

fn main() {
    let some_value = 10;
    let clap_matches = cli_clap::cli_clap(&some_value);
    let actions = clap_actions::actions_get(&clap_matches);
    clap_fern::log_setup(&clap_matches);
    let session_uuid = Uuid::new_v4();
    let session_uuid_string = session_uuid.hyphenated().to_string();
    trace!("session_uuid_string:{}", session_uuid_string);
    let conn = db::connect_deligate(&clap_matches);
    db::create_tables(&conn);
    loader::deligate(&conn, &actions, &clap_matches);
    let pk_session = elephant::elephant_session(&conn, &session_uuid_string);
    loader::enviroment(&conn, pk_session, &clap_matches);
    jobs_load::load(&conn);
    actions_process::process(&conn, &actions)
}
<|endoftext|>


<commit_before>#![crate_id="sdl_image#0.3.2"]
#![comment = "SDL_image binding"]
#![license = "MIT"]
#![crate_type = "lib"]

extern crate libc;
extern crate sdl = "sdl#0.3.2";

use libc::c_int;
use std::ptr;

use sdl::get_error;
use sdl::video::Surface;

// Setup linking for all targets.
#[cfg(not(target_os = "macos"))]
#[cfg(not(mac_framework))]
#[link(name = "SDL_image")]
extern {}

#[cfg(target_os = "macos", mac_framework)]
#[link(name = "SDL_image", kind = "framework")]
extern {}

pub mod ll {
    #![allow(non_camel_case_types)]

    use sdl::video::ll::SDL_Surface;

    use libc::{c_int, c_uint, c_schar};

    pub type IMG_InitFlags = c_uint;

    pub static IMG_INIT_JPG: IMG_InitFlags = 1;
    pub static IMG_INIT_PNG: IMG_InitFlags = 2;
    pub static IMG_INIT_TIF: IMG_InitFlags = 4;
    pub static IMG_INIT_WEBP: IMG_InitFlags = 8;

    extern "C" {
        pub fn IMG_Init(flags: c_int) -> c_int;
        pub fn IMG_Quit();
        pub fn IMG_Load(file: *c_schar) -> *SDL_Surface;
    }
}

#[deriving(Eq, TotalEq)]
pub enum InitFlag {
    InitJPG = ll::IMG_INIT_JPG as int,
    InitPNG = ll::IMG_INIT_PNG as int,
    InitTIF = ll::IMG_INIT_TIF as int
}

pub fn init(flags: &[InitFlag]) -> Vec<InitFlag> {
    let bitflags = unsafe {
        ll::IMG_Init(flags.iter().fold(0i32, |flags, &flag| {
            flags | flag as c_int
        }))
    };

    let flags = [InitJPG,
        InitPNG,
        InitTIF];

    flags.iter().filter_map(|&flag| {
        if bitflags & (flag as c_int) != 0 { Some(flag) }
        else { None }
    }).collect()
}

pub fn load(file: &Path) -> Result<~Surface, ~str> {
    file.to_c_str().with_ref(|file| {
        unsafe {
            let raw = ll::IMG_Load(file);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    })
}

pub fn quit() {
    unsafe { ll::IMG_Quit(); }
}
<commit_msg>Forgot one c_schar in sdl_image<commit_after>#![crate_id="sdl_image#0.3.2"]
#![comment = "SDL_image binding"]
#![license = "MIT"]
#![crate_type = "lib"]

extern crate libc;
extern crate sdl = "sdl#0.3.2";

use libc::c_int;
use std::ptr;

use sdl::get_error;
use sdl::video::Surface;

// Setup linking for all targets.
#[cfg(not(target_os = "macos"))]
#[cfg(not(mac_framework))]
#[link(name = "SDL_image")]
extern {}

#[cfg(target_os = "macos", mac_framework)]
#[link(name = "SDL_image", kind = "framework")]
extern {}

pub mod ll {
    #![allow(non_camel_case_types)]

    use sdl::video::ll::SDL_Surface;

    use libc::{c_int, c_uint};
    use libc::types::os::arch::c95::c_schar;

    pub type IMG_InitFlags = c_uint;

    pub static IMG_INIT_JPG: IMG_InitFlags = 1;
    pub static IMG_INIT_PNG: IMG_InitFlags = 2;
    pub static IMG_INIT_TIF: IMG_InitFlags = 4;
    pub static IMG_INIT_WEBP: IMG_InitFlags = 8;

    extern "C" {
        pub fn IMG_Init(flags: c_int) -> c_int;
        pub fn IMG_Quit();
        pub fn IMG_Load(file: *c_schar) -> *SDL_Surface;
    }
}

#[deriving(Eq, TotalEq)]
pub enum InitFlag {
    InitJPG = ll::IMG_INIT_JPG as int,
    InitPNG = ll::IMG_INIT_PNG as int,
    InitTIF = ll::IMG_INIT_TIF as int
}

pub fn init(flags: &[InitFlag]) -> Vec<InitFlag> {
    let bitflags = unsafe {
        ll::IMG_Init(flags.iter().fold(0i32, |flags, &flag| {
            flags | flag as c_int
        }))
    };

    let flags = [InitJPG,
        InitPNG,
        InitTIF];

    flags.iter().filter_map(|&flag| {
        if bitflags & (flag as c_int) != 0 { Some(flag) }
        else { None }
    }).collect()
}

pub fn load(file: &Path) -> Result<~Surface, ~str> {
    file.to_c_str().with_ref(|file| {
        unsafe {
            let raw = ll::IMG_Load(file);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    })
}

pub fn quit() {
    unsafe { ll::IMG_Quit(); }
}
<|endoftext|>


<commit_before>use {Poll, Async, Future, AsyncSink};
use stream::{Stream, Fuse};
use sink::Sink;

/// Future for the `Sink::send_all` combinator, which sends a stream of values
/// to a sink and then waits until the sink has fully flushed those values.
#[must_use = "futures do nothing unless polled"]
pub struct SendAll<T, U: Stream> {
    sink: Option<T>,
    stream: Fuse<U>,
    buffered: Option<U::Item>,
}

pub fn new<T, U>(sink: T, stream: U) -> SendAll<T, U>
    where T: Sink,
          U: Stream<Item = T::SinkItem>,
          T::SinkError: From<U::Error>,
{
    SendAll {
        sink: Some(sink),
        stream: stream.fuse(),
        buffered: None,
    }
}

impl<T, U> SendAll<T, U>
    where T: Sink,
          U: Stream<Item = T::SinkItem>,
          T::SinkError: From<U::Error>,
{
    fn sink_mut(&mut self) -> &mut T {
        self.sink.as_mut().take().expect("Attempted to poll SendAll after completion")
    }

    fn take_sink(&mut self) -> T {
        self.sink.take().expect("Attempted to poll SendAll after completion")
    }

    fn try_start_send(&mut self, item: U::Item) -> Poll<(), T::SinkError> {
        debug_assert!(self.buffered.is_none());
        if let AsyncSink::NotReady(item) = try!(self.sink_mut().start_send(item)) {
            self.buffered = Some(item);
            return Ok(Async::NotReady)
        }
        Ok(Async::Ready(()))
    }
}

impl<T, U> Future for SendAll<T, U>
    where T: Sink,
          U: Stream<Item = T::SinkItem>,
          T::SinkError: From<U::Error>,
{
    type Item = T;
    type Error = T::SinkError;

    fn poll(&mut self) -> Poll<T, T::SinkError> {
        try!(self.sink_mut().poll_complete());

        // If we've got an item buffered already, we need to write it to the
        // sink before we can do anything else
        if let Some(item) = self.buffered.take() {
            try_ready!(self.try_start_send(item))
        }

        loop {
            if let Some(item) = try_ready!(self.stream.poll()) {
                try_ready!(self.try_start_send(item))
            } else {
                // we're done pushing the stream, but want to block on flushing the
                // sink
                try_ready!(self.sink_mut().poll_complete());

                // now everything's emptied, so return the sink for further use
                return Ok(Async::Ready(self.take_sink()))
            }
        }
    }
}
<commit_msg>Fix bug where send_all doesn't call poll_complete after starting a send<commit_after>use {Poll, Async, Future, AsyncSink};
use stream::{Stream, Fuse};
use sink::Sink;

/// Future for the `Sink::send_all` combinator, which sends a stream of values
/// to a sink and then waits until the sink has fully flushed those values.
#[must_use = "futures do nothing unless polled"]
pub struct SendAll<T, U: Stream> {
    sink: Option<T>,
    stream: Fuse<U>,
    buffered: Option<U::Item>,
}

pub fn new<T, U>(sink: T, stream: U) -> SendAll<T, U>
    where T: Sink,
          U: Stream<Item = T::SinkItem>,
          T::SinkError: From<U::Error>,
{
    SendAll {
        sink: Some(sink),
        stream: stream.fuse(),
        buffered: None,
    }
}

impl<T, U> SendAll<T, U>
    where T: Sink,
          U: Stream<Item = T::SinkItem>,
          T::SinkError: From<U::Error>,
{
    fn sink_mut(&mut self) -> &mut T {
        self.sink.as_mut().take().expect("Attempted to poll SendAll after completion")
    }

    fn take_sink(&mut self) -> T {
        self.sink.take().expect("Attempted to poll SendAll after completion")
    }

    fn try_start_send(&mut self, item: U::Item) -> Poll<(), T::SinkError> {
        debug_assert!(self.buffered.is_none());
        if let AsyncSink::NotReady(item) = try!(self.sink_mut().start_send(item)) {
            self.buffered = Some(item);
            return Ok(Async::NotReady)
        }
        Ok(Async::Ready(()))
    }
}

impl<T, U> Future for SendAll<T, U>
    where T: Sink,
          U: Stream<Item = T::SinkItem>,
          T::SinkError: From<U::Error>,
{
    type Item = T;
    type Error = T::SinkError;

    fn poll(&mut self) -> Poll<T, T::SinkError> {
        // If we've got an item buffered already, we need to write it to the
        // sink before we can do anything else
        if let Some(item) = self.buffered.take() {
            try_ready!(self.try_start_send(item))
        }

        loop {
            try!(self.sink_mut().poll_complete());

            if let Some(item) = try_ready!(self.stream.poll()) {
                try_ready!(self.try_start_send(item))
            } else {
                // we're done pushing the stream, but want to block on flushing the
                // sink
                try_ready!(self.sink_mut().poll_complete());

                // now everything's emptied, so return the sink for further use
                return Ok(Async::Ready(self.take_sink()))
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate pkg_config;
#[cfg(target_env = "msvc")]
extern crate vcpkg;
extern crate cc;

use std::env;
use std::fs;
use std::path::{PathBuf, Path};
use std::process::Command;

fn main() {
    let target = env::var("TARGET").unwrap();
    let windows = target.contains("windows");

    // OSX and Haiku ships libcurl by default, so we just use that version
    // unconditionally.
    if target.contains("apple") || target.contains("haiku") {
        return println!("cargo:rustc-flags=-l curl");
    }

    // Next, fall back and try to use pkg-config if its available.
    if windows {
        if try_vcpkg() {
            return
        }
    } else {
        if try_pkg_config() {
            return
        }
    }

    if !Path::new("curl/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let include = dst.join("include");
    let build = dst.join("build");
    println!("cargo:root={}", dst.display());
    println!("cargo:include={}", include.display());
    fs::create_dir_all(include.join("curl")).unwrap();
    fs::copy("curl/include/curl/curl.h", include.join("curl/curl.h")).unwrap();
    fs::copy("curl/include/curl/curlver.h", include.join("curl/curlver.h")).unwrap();
    fs::copy("curl/include/curl/easy.h", include.join("curl/easy.h")).unwrap();
    fs::copy("curl/include/curl/mprintf.h", include.join("curl/mprintf.h")).unwrap();
    fs::copy("curl/include/curl/multi.h", include.join("curl/multi.h")).unwrap();
    fs::copy("curl/include/curl/stdcheaders.h", include.join("curl/stdcheaders.h")).unwrap();
    fs::copy("curl/include/curl/system.h", include.join("curl/system.h")).unwrap();
    fs::copy("curl/include/curl/typecheck-gcc.h", include.join("curl/typecheck-gcc.h")).unwrap();

    let pkgconfig = dst.join("lib/pkgconfig");
    fs::create_dir_all(&pkgconfig).unwrap();
    let contents = fs::read_to_string("curl/libcurl.pc.in").unwrap();
    fs::write(
        pkgconfig.join("libcurl.pc"),
        contents
            .replace("@prefix@", dst.to_str().unwrap())
            .replace("@exec_prefix@", "")
            .replace("@libdir@", dst.join("lib").to_str().unwrap())
            .replace("@includedir@", include.to_str().unwrap())
            .replace("@CPPFLAG_CURL_STATICLIB@", "-DCURL_STATICLIB")
            .replace("@LIBCURL_LIBS@", "")
            .replace("@SUPPORT_FEATURES@", "")
            .replace("@SUPPORT_PROTOCOLS@", "")
            .replace("@CURLVERSION@", "7.61.1"),
    ).unwrap();

    let mut cfg = cc::Build::new();
    cfg.out_dir(&build)
        .include("curl/lib")
        .include("curl/include")
        .define("BUILDING_LIBCURL", None)
        .define("CURL_DISABLE_CRYPTO_AUTH", None)
        .define("CURL_DISABLE_DICT", None)
        .define("CURL_DISABLE_FTP", None)
        .define("CURL_DISABLE_GOPHER", None)
        .define("CURL_DISABLE_IMAP", None)
        .define("CURL_DISABLE_LDAP", None)
        .define("CURL_DISABLE_LDAPS", None)
        .define("CURL_DISABLE_NTLM", None)
        .define("CURL_DISABLE_POP3", None)
        .define("CURL_DISABLE_RTSP", None)
        .define("CURL_DISABLE_SMB", None)
        .define("CURL_DISABLE_SMTP", None)
        .define("CURL_DISABLE_TELNET", None)
        .define("CURL_DISABLE_TFTP", None)
        .define("CURL_STATICLIB", None)
        .define("ENABLE_IPV6", None)
        .define("HAVE_ASSERT_H", None)
        .define("OS", "\"unknown\"") // TODO
        .define("HAVE_ZLIB_H", None)
        .define("HAVE_LIBZ", None)

        .file("curl/lib/asyn-thread.c")
        .file("curl/lib/base64.c")
        .file("curl/lib/conncache.c")
        .file("curl/lib/connect.c")
        .file("curl/lib/content_encoding.c")
        .file("curl/lib/cookie.c")
        .file("curl/lib/curl_addrinfo.c")
        .file("curl/lib/curl_ctype.c")
        .file("curl/lib/curl_memrchr.c")
        .file("curl/lib/curl_range.c")
        .file("curl/lib/curl_threads.c")
        .file("curl/lib/dotdot.c")
        .file("curl/lib/easy.c")
        .file("curl/lib/escape.c")
        .file("curl/lib/file.c")
        .file("curl/lib/fileinfo.c")
        .file("curl/lib/formdata.c")
        .file("curl/lib/getenv.c")
        .file("curl/lib/getinfo.c")
        .file("curl/lib/hash.c")
        .file("curl/lib/hostasyn.c")
        .file("curl/lib/hostcheck.c")
        .file("curl/lib/hostip.c")
        .file("curl/lib/hostip6.c")
        .file("curl/lib/http.c")
        .file("curl/lib/http2.c")
        .file("curl/lib/http_chunks.c")
        .file("curl/lib/http_proxy.c")
        .file("curl/lib/if2ip.c")
        .file("curl/lib/inet_ntop.c")
        .file("curl/lib/inet_pton.c")
        .file("curl/lib/llist.c")
        .file("curl/lib/mime.c")
        .file("curl/lib/mprintf.c")
        .file("curl/lib/multi.c")
        .file("curl/lib/netrc.c")
        .file("curl/lib/nonblock.c")
        .file("curl/lib/parsedate.c")
        .file("curl/lib/pipeline.c")
        .file("curl/lib/progress.c")
        .file("curl/lib/rand.c")
        .file("curl/lib/select.c")
        .file("curl/lib/sendf.c")
        .file("curl/lib/setopt.c")
        .file("curl/lib/share.c")
        .file("curl/lib/slist.c")
        .file("curl/lib/socks.c")
        .file("curl/lib/speedcheck.c")
        .file("curl/lib/splay.c")
        .file("curl/lib/strcase.c")
        .file("curl/lib/strdup.c")
        .file("curl/lib/strerror.c")
        .file("curl/lib/strtok.c")
        .file("curl/lib/strtoofft.c")
        .file("curl/lib/timeval.c")
        .file("curl/lib/transfer.c")
        .file("curl/lib/url.c")
        .file("curl/lib/version.c")
        .file("curl/lib/vtls/vtls.c")
        .file("curl/lib/warnless.c")
        .file("curl/lib/wildcard.c")

        .define("HAVE_GETADDRINFO", None)

        .warnings(false);

    if cfg!(feature = "http2") {
        cfg.define("USE_NGHTTP2", None)
            .define("NGHTTP2_STATICLIB", None);

        if let Some(path) = env::var_os("DEP_NGHTTP2_ROOT") {
            let path = PathBuf::from(path);
            cfg.include(path.join("include"));
        }
    }

    if let Some(path) = env::var_os("DEP_Z_INCLUDE") {
        cfg.include(path);
    }

    if windows {
        cfg.define("USE_THREADS_WIN32", None)
            .define("HAVE_IOCTLSOCKET_FIONBIO", None)
            .define("USE_WINSOCK", None)
            .define("USE_WINDOWS_SSPI", None)
            .define("USE_SCHANNEL", None)
            .file("curl/lib/x509asn1.c")
            .file("curl/lib/curl_sspi.c")
            .file("curl/lib/socks_sspi.c")
            .file("curl/lib/system_win32.c")
            .file("curl/lib/vtls/schannel.c")
            .file("curl/lib/vtls/schannel_verify.c");
    } else {
        cfg.define("RECV_TYPE_ARG1", "int")
            .define("HAVE_PTHREAD_H", None)
            .define("HAVE_ARPA_INET_H", None)
            .define("HAVE_ERRNO_H", None)
            .define("HAVE_FCNTL_H", None)
            .define("HAVE_NETDB_H", None)
            .define("HAVE_NETINET_IN_H", None)
            .define("HAVE_POLL_FINE", None)
            .define("HAVE_POLL_H", None)
            .define("HAVE_FCNTL_O_NONBLOCK", None)
            .define("HAVE_SYS_SELECT_H", None)
            .define("HAVE_SYS_STAT_H", None)
            .define("HAVE_UNISTD_H", None)
            .define("HAVE_RECV", None)
            .define("HAVE_SELECT", None)
            .define("HAVE_SEND", None)
            .define("HAVE_SOCKET", None)
            .define("HAVE_STERRROR_R", None)
            .define("HAVE_STRUCT_TIMEVAL", None)
            .define("USE_THREADS_POSIX", None)
            .define("USE_OPENSSL", None)
            .define("RECV_TYPE_ARG2", "void*")
            .define("RECV_TYPE_ARG3", "size_t")
            .define("RECV_TYPE_ARG4", "int")
            .define("RECV_TYPE_RETV", "ssize_t")
            .define("SEND_QUAL_ARG2", "const")
            .define("SEND_TYPE_ARG1", "int")
            .define("SEND_TYPE_ARG2", "void*")
            .define("SEND_TYPE_ARG3", "size_t")
            .define("SEND_TYPE_ARG4", "int")
            .define("SEND_TYPE_RETV", "ssize_t")
            .define("SIZEOF_CURL_OFF_T", "8")
            .define("SIZEOF_INT", "4")
            .define("SIZEOF_SHORT", "2")
            .file("curl/lib/vtls/openssl.c");

        let width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH")
            .unwrap()
            .parse::<usize>()
            .unwrap();
        cfg.define("SIZEOF_SSIZE_T", Some(&(width / 8).to_string()[..]));
        cfg.define("SIZEOF_SIZE_T", Some(&(width / 8).to_string()[..]));
        cfg.define("SIZEOF_LONG", Some(&(width / 8).to_string()[..]));

        if let Some(path) = env::var_os("DEP_OPENSSL_INCLUDE") {
            cfg.include(path);
        }

        cfg.flag("-fvisibility=hidden");
    }

    cfg.compile("curl");

    if windows {
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=crypt32");
    }

    // Illumos/Solaris requires explicit linking with libnsl
    if target.contains("solaris") {
        println!("cargo:rustc-link-lib=nsl");
    }
}

#[cfg(not(target_env = "msvc"))]
fn try_vcpkg() -> bool {
    false
}

#[cfg(target_env = "msvc")]
fn try_vcpkg() -> bool {

    // the import library for the dll is called libcurl_imp
    let mut successful_probe_details =
        match vcpkg::Config::new().lib_names("libcurl_imp", "libcurl")
                .emit_includes(true).probe("curl") {
            Ok(details) => Some(details),
            Err(e) => {
                println!("first run of vcpkg did not find libcurl: {}", e);
                None
            }
        };

    if successful_probe_details.is_none() {
        match vcpkg::Config::new().lib_name("libcurl")
                .emit_includes(true).probe("curl") {
            Ok(details) => successful_probe_details = Some(details),
            Err(e) => println!("second run of vcpkg did not find libcurl: {}", e),
        }
    }

    if successful_probe_details.is_some() {
        // Found libcurl which depends on openssl, libssh2 and zlib
        // in the a default vcpkg installation. Probe for them
        // but do not fail if they are not present as we may be working
        // with a customized vcpkg installation.
        vcpkg::Config::new()
            .lib_name("libeay32")
            .lib_name("ssleay32")
            .probe("openssl").ok();

        vcpkg::probe_package("libssh2").ok();

        vcpkg::Config::new()
            .lib_names("zlib", "zlib1")
            .probe("zlib").ok();

        println!("cargo:rustc-link-lib=crypt32");
        println!("cargo:rustc-link-lib=gdi32");
        println!("cargo:rustc-link-lib=user32");
        println!("cargo:rustc-link-lib=wldap32");
        return true;
    }
    false
}

fn try_pkg_config() -> bool {
    let mut cfg = pkg_config::Config::new();
    cfg.cargo_metadata(false);
    let lib = match cfg.probe("libcurl") {
        Ok(lib) => lib,
        Err(e) => {
            println!("Couldn't find libcurl from pkgconfig ({:?}), \
                      compiling it from source...", e);
            return false
        }
    };

    // Not all system builds of libcurl have http2 features enabled, so if we've
    // got a http2-requested build then we may fall back to a build from source.
    if cfg!(feature = "http2") {
        let output = Command::new("curl-config")
            .arg("--features")
            .output();
        let output = match output {
            Ok(out) => out,
            Err(e) => {
                println!("failed to run curl-config ({}), building from source", e);
                return false
            }
        };
        if !output.status.success() {
            println!("curl-config failed: {}", output.status);
            return false
        }
        let stdout = String::from_utf8_lossy(&output.stdout);
        if !stdout.contains("HTTP2") {
            println!("failed to find http-2 feature enabled in pkg-config-found \
                      libcurl, building from source");
            return false
        }
    }

    // Re-find the library to print cargo's metadata, then print some extra
    // metadata as well.
    cfg.cargo_metadata(true)
        .probe("libcurl")
        .unwrap();
    for path in lib.include_paths.iter() {
        println!("cargo:include={}", path.display());
    }
    return true
}
<commit_msg>Print out whether curl is a static build or not<commit_after>extern crate pkg_config;
#[cfg(target_env = "msvc")]
extern crate vcpkg;
extern crate cc;

use std::env;
use std::fs;
use std::path::{PathBuf, Path};
use std::process::Command;

fn main() {
    let target = env::var("TARGET").unwrap();
    let windows = target.contains("windows");

    // OSX and Haiku ships libcurl by default, so we just use that version
    // unconditionally.
    if target.contains("apple") || target.contains("haiku") {
        return println!("cargo:rustc-flags=-l curl");
    }

    // Next, fall back and try to use pkg-config if its available.
    if windows {
        if try_vcpkg() {
            return
        }
    } else {
        if try_pkg_config() {
            return
        }
    }

    if !Path::new("curl/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let include = dst.join("include");
    let build = dst.join("build");
    println!("cargo:root={}", dst.display());
    println!("cargo:include={}", include.display());
    println!("cargo:static=1");
    fs::create_dir_all(include.join("curl")).unwrap();
    fs::copy("curl/include/curl/curl.h", include.join("curl/curl.h")).unwrap();
    fs::copy("curl/include/curl/curlver.h", include.join("curl/curlver.h")).unwrap();
    fs::copy("curl/include/curl/easy.h", include.join("curl/easy.h")).unwrap();
    fs::copy("curl/include/curl/mprintf.h", include.join("curl/mprintf.h")).unwrap();
    fs::copy("curl/include/curl/multi.h", include.join("curl/multi.h")).unwrap();
    fs::copy("curl/include/curl/stdcheaders.h", include.join("curl/stdcheaders.h")).unwrap();
    fs::copy("curl/include/curl/system.h", include.join("curl/system.h")).unwrap();
    fs::copy("curl/include/curl/typecheck-gcc.h", include.join("curl/typecheck-gcc.h")).unwrap();

    let pkgconfig = dst.join("lib/pkgconfig");
    fs::create_dir_all(&pkgconfig).unwrap();
    let contents = fs::read_to_string("curl/libcurl.pc.in").unwrap();
    fs::write(
        pkgconfig.join("libcurl.pc"),
        contents
            .replace("@prefix@", dst.to_str().unwrap())
            .replace("@exec_prefix@", "")
            .replace("@libdir@", dst.join("lib").to_str().unwrap())
            .replace("@includedir@", include.to_str().unwrap())
            .replace("@CPPFLAG_CURL_STATICLIB@", "-DCURL_STATICLIB")
            .replace("@LIBCURL_LIBS@", "")
            .replace("@SUPPORT_FEATURES@", "")
            .replace("@SUPPORT_PROTOCOLS@", "")
            .replace("@CURLVERSION@", "7.61.1"),
    ).unwrap();

    let mut cfg = cc::Build::new();
    cfg.out_dir(&build)
        .include("curl/lib")
        .include("curl/include")
        .define("BUILDING_LIBCURL", None)
        .define("CURL_DISABLE_CRYPTO_AUTH", None)
        .define("CURL_DISABLE_DICT", None)
        .define("CURL_DISABLE_FTP", None)
        .define("CURL_DISABLE_GOPHER", None)
        .define("CURL_DISABLE_IMAP", None)
        .define("CURL_DISABLE_LDAP", None)
        .define("CURL_DISABLE_LDAPS", None)
        .define("CURL_DISABLE_NTLM", None)
        .define("CURL_DISABLE_POP3", None)
        .define("CURL_DISABLE_RTSP", None)
        .define("CURL_DISABLE_SMB", None)
        .define("CURL_DISABLE_SMTP", None)
        .define("CURL_DISABLE_TELNET", None)
        .define("CURL_DISABLE_TFTP", None)
        .define("CURL_STATICLIB", None)
        .define("ENABLE_IPV6", None)
        .define("HAVE_ASSERT_H", None)
        .define("OS", "\"unknown\"") // TODO
        .define("HAVE_ZLIB_H", None)
        .define("HAVE_LIBZ", None)

        .file("curl/lib/asyn-thread.c")
        .file("curl/lib/base64.c")
        .file("curl/lib/conncache.c")
        .file("curl/lib/connect.c")
        .file("curl/lib/content_encoding.c")
        .file("curl/lib/cookie.c")
        .file("curl/lib/curl_addrinfo.c")
        .file("curl/lib/curl_ctype.c")
        .file("curl/lib/curl_memrchr.c")
        .file("curl/lib/curl_range.c")
        .file("curl/lib/curl_threads.c")
        .file("curl/lib/dotdot.c")
        .file("curl/lib/easy.c")
        .file("curl/lib/escape.c")
        .file("curl/lib/file.c")
        .file("curl/lib/fileinfo.c")
        .file("curl/lib/formdata.c")
        .file("curl/lib/getenv.c")
        .file("curl/lib/getinfo.c")
        .file("curl/lib/hash.c")
        .file("curl/lib/hostasyn.c")
        .file("curl/lib/hostcheck.c")
        .file("curl/lib/hostip.c")
        .file("curl/lib/hostip6.c")
        .file("curl/lib/http.c")
        .file("curl/lib/http2.c")
        .file("curl/lib/http_chunks.c")
        .file("curl/lib/http_proxy.c")
        .file("curl/lib/if2ip.c")
        .file("curl/lib/inet_ntop.c")
        .file("curl/lib/inet_pton.c")
        .file("curl/lib/llist.c")
        .file("curl/lib/mime.c")
        .file("curl/lib/mprintf.c")
        .file("curl/lib/multi.c")
        .file("curl/lib/netrc.c")
        .file("curl/lib/nonblock.c")
        .file("curl/lib/parsedate.c")
        .file("curl/lib/pipeline.c")
        .file("curl/lib/progress.c")
        .file("curl/lib/rand.c")
        .file("curl/lib/select.c")
        .file("curl/lib/sendf.c")
        .file("curl/lib/setopt.c")
        .file("curl/lib/share.c")
        .file("curl/lib/slist.c")
        .file("curl/lib/socks.c")
        .file("curl/lib/speedcheck.c")
        .file("curl/lib/splay.c")
        .file("curl/lib/strcase.c")
        .file("curl/lib/strdup.c")
        .file("curl/lib/strerror.c")
        .file("curl/lib/strtok.c")
        .file("curl/lib/strtoofft.c")
        .file("curl/lib/timeval.c")
        .file("curl/lib/transfer.c")
        .file("curl/lib/url.c")
        .file("curl/lib/version.c")
        .file("curl/lib/vtls/vtls.c")
        .file("curl/lib/warnless.c")
        .file("curl/lib/wildcard.c")

        .define("HAVE_GETADDRINFO", None)

        .warnings(false);

    if cfg!(feature = "http2") {
        cfg.define("USE_NGHTTP2", None)
            .define("NGHTTP2_STATICLIB", None);

        if let Some(path) = env::var_os("DEP_NGHTTP2_ROOT") {
            let path = PathBuf::from(path);
            cfg.include(path.join("include"));
        }
    }

    if let Some(path) = env::var_os("DEP_Z_INCLUDE") {
        cfg.include(path);
    }

    if windows {
        cfg.define("USE_THREADS_WIN32", None)
            .define("HAVE_IOCTLSOCKET_FIONBIO", None)
            .define("USE_WINSOCK", None)
            .define("USE_WINDOWS_SSPI", None)
            .define("USE_SCHANNEL", None)
            .file("curl/lib/x509asn1.c")
            .file("curl/lib/curl_sspi.c")
            .file("curl/lib/socks_sspi.c")
            .file("curl/lib/system_win32.c")
            .file("curl/lib/vtls/schannel.c")
            .file("curl/lib/vtls/schannel_verify.c");
    } else {
        cfg.define("RECV_TYPE_ARG1", "int")
            .define("HAVE_PTHREAD_H", None)
            .define("HAVE_ARPA_INET_H", None)
            .define("HAVE_ERRNO_H", None)
            .define("HAVE_FCNTL_H", None)
            .define("HAVE_NETDB_H", None)
            .define("HAVE_NETINET_IN_H", None)
            .define("HAVE_POLL_FINE", None)
            .define("HAVE_POLL_H", None)
            .define("HAVE_FCNTL_O_NONBLOCK", None)
            .define("HAVE_SYS_SELECT_H", None)
            .define("HAVE_SYS_STAT_H", None)
            .define("HAVE_UNISTD_H", None)
            .define("HAVE_RECV", None)
            .define("HAVE_SELECT", None)
            .define("HAVE_SEND", None)
            .define("HAVE_SOCKET", None)
            .define("HAVE_STERRROR_R", None)
            .define("HAVE_STRUCT_TIMEVAL", None)
            .define("USE_THREADS_POSIX", None)
            .define("USE_OPENSSL", None)
            .define("RECV_TYPE_ARG2", "void*")
            .define("RECV_TYPE_ARG3", "size_t")
            .define("RECV_TYPE_ARG4", "int")
            .define("RECV_TYPE_RETV", "ssize_t")
            .define("SEND_QUAL_ARG2", "const")
            .define("SEND_TYPE_ARG1", "int")
            .define("SEND_TYPE_ARG2", "void*")
            .define("SEND_TYPE_ARG3", "size_t")
            .define("SEND_TYPE_ARG4", "int")
            .define("SEND_TYPE_RETV", "ssize_t")
            .define("SIZEOF_CURL_OFF_T", "8")
            .define("SIZEOF_INT", "4")
            .define("SIZEOF_SHORT", "2")
            .file("curl/lib/vtls/openssl.c");

        let width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH")
            .unwrap()
            .parse::<usize>()
            .unwrap();
        cfg.define("SIZEOF_SSIZE_T", Some(&(width / 8).to_string()[..]));
        cfg.define("SIZEOF_SIZE_T", Some(&(width / 8).to_string()[..]));
        cfg.define("SIZEOF_LONG", Some(&(width / 8).to_string()[..]));

        if let Some(path) = env::var_os("DEP_OPENSSL_INCLUDE") {
            cfg.include(path);
        }

        cfg.flag("-fvisibility=hidden");
    }

    cfg.compile("curl");

    if windows {
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=crypt32");
    }

    // Illumos/Solaris requires explicit linking with libnsl
    if target.contains("solaris") {
        println!("cargo:rustc-link-lib=nsl");
    }
}

#[cfg(not(target_env = "msvc"))]
fn try_vcpkg() -> bool {
    false
}

#[cfg(target_env = "msvc")]
fn try_vcpkg() -> bool {

    // the import library for the dll is called libcurl_imp
    let mut successful_probe_details =
        match vcpkg::Config::new().lib_names("libcurl_imp", "libcurl")
                .emit_includes(true).probe("curl") {
            Ok(details) => Some(details),
            Err(e) => {
                println!("first run of vcpkg did not find libcurl: {}", e);
                None
            }
        };

    if successful_probe_details.is_none() {
        match vcpkg::Config::new().lib_name("libcurl")
                .emit_includes(true).probe("curl") {
            Ok(details) => successful_probe_details = Some(details),
            Err(e) => println!("second run of vcpkg did not find libcurl: {}", e),
        }
    }

    if successful_probe_details.is_some() {
        // Found libcurl which depends on openssl, libssh2 and zlib
        // in the a default vcpkg installation. Probe for them
        // but do not fail if they are not present as we may be working
        // with a customized vcpkg installation.
        vcpkg::Config::new()
            .lib_name("libeay32")
            .lib_name("ssleay32")
            .probe("openssl").ok();

        vcpkg::probe_package("libssh2").ok();

        vcpkg::Config::new()
            .lib_names("zlib", "zlib1")
            .probe("zlib").ok();

        println!("cargo:rustc-link-lib=crypt32");
        println!("cargo:rustc-link-lib=gdi32");
        println!("cargo:rustc-link-lib=user32");
        println!("cargo:rustc-link-lib=wldap32");
        return true;
    }
    false
}

fn try_pkg_config() -> bool {
    let mut cfg = pkg_config::Config::new();
    cfg.cargo_metadata(false);
    let lib = match cfg.probe("libcurl") {
        Ok(lib) => lib,
        Err(e) => {
            println!("Couldn't find libcurl from pkgconfig ({:?}), \
                      compiling it from source...", e);
            return false
        }
    };

    // Not all system builds of libcurl have http2 features enabled, so if we've
    // got a http2-requested build then we may fall back to a build from source.
    if cfg!(feature = "http2") {
        let output = Command::new("curl-config")
            .arg("--features")
            .output();
        let output = match output {
            Ok(out) => out,
            Err(e) => {
                println!("failed to run curl-config ({}), building from source", e);
                return false
            }
        };
        if !output.status.success() {
            println!("curl-config failed: {}", output.status);
            return false
        }
        let stdout = String::from_utf8_lossy(&output.stdout);
        if !stdout.contains("HTTP2") {
            println!("failed to find http-2 feature enabled in pkg-config-found \
                      libcurl, building from source");
            return false
        }
    }

    // Re-find the library to print cargo's metadata, then print some extra
    // metadata as well.
    cfg.cargo_metadata(true)
        .probe("libcurl")
        .unwrap();
    for path in lib.include_paths.iter() {
        println!("cargo:include={}", path.display());
    }
    return true
}
<|endoftext|>


<commit_before>use Prefab;
use calx::{Dijkstra, hex_neighbors, SRgba};
use euclid::{vec2, Size2D};
use form::{self, Form};
use image::{self, GenericImage, Pixel};
use location::{Location, Portal, Sector};
use mapgen::{self, DigCavesGen};
use rand::{self, Rand, Rng, SeedableRng};
use serde;
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::slice;
use terrain::Terrain;
use world::Loadout;

/// Static generated world.
pub struct Worldgen {
    seed: u32,
    terrain: HashMap<Location, Terrain>,
    portals: HashMap<Location, Portal>,
    spawns: Vec<(Location, Loadout)>,
    player_entry: Location,
}

impl Worldgen {
    pub fn new(seed: u32) -> Worldgen {
        let mut ret = Worldgen {
            seed: seed,
            terrain: HashMap::new(),
            portals: HashMap::new(),
            spawns: Vec::new(),
            player_entry: Location::new(0, 0, 0),
        };

        let mut rng: ::Rng = SeedableRng::from_seed([seed, seed, seed, seed]);

        let mut cave_entrance = Location::new(9, 0, 0);
        ret.cave_entrance(cave_entrance);
        ret.terrain.insert(
            cave_entrance + vec2(1, 1),
            Terrain::Gate,
        );

        for depth in 1..11 {
            let up_stairs;
            let down_stairs;
            let mut spawns = Vec::new();

            {
                let mut digger = SectorDigger::new(&mut ret, Sector::new(0, 0, depth as i16));
                let gen = DigCavesGen::new(digger.domain());
                gen.dig(&mut rng, &mut digger);

                up_stairs = digger.up_portal.expect("Mapgen didn't create stairs up");
                down_stairs = digger.down_portal.expect(
                    "Mapgen didn't create stairs down",
                );

                // Spawn
                digger.clear_spawns_near_entrance(12);

                let mut spawn_locs = rand::sample(&mut rng, digger.spawn_region.iter(), 20);
                let n_spawns = spawn_locs.len();

                let items = Form::filter(|f| f.is_item() && f.at_depth(depth));
                for &loc in spawn_locs.drain(0..n_spawns / 2) {
                    spawns.push((
                        loc,
                        form::rand(&mut rng, &items)
                            .expect("No item spawn")
                            .loadout
                            .clone(),
                    ))
                }

                let mobs = Form::filter(|f| f.is_mob() && f.at_depth(depth));
                for &loc in spawn_locs {
                    spawns.push((
                        loc,
                        form::rand(&mut rng, &mobs)
                            .expect("No mob spawn")
                            .loadout
                            .clone(),
                    ))
                }
            }

            ret.spawns.extend(spawns.into_iter());
            ret.portal(cave_entrance, up_stairs + vec2(1, 1));
            ret.portal(up_stairs, cave_entrance - vec2(1, 1));
            cave_entrance = down_stairs;

            // TODO: Generator needs an option to not generate stairs down on bottom level
        }

        ret
    }

    fn load_prefab(&mut self, origin: Location, prefab: &Prefab) {
        for (p, &(ref terrain, ref entities)) in prefab.iter() {
            let loc = origin + p;

            self.terrain.insert(loc, *terrain);

            for spawn in entities.iter() {
                if spawn == "player" {
                    self.player_entry = loc;
                } else {
                    let form = Form::named(spawn).expect(&format!(
                        "Bad prefab: Form '{}' not found!",
                        spawn
                    ));
                    self.spawns.push((loc, form.loadout.clone()));
                }
            }
        }
    }

    fn load_map_bitmap(&mut self, origin: Location, path: &str) {
        let image = image::open(path).unwrap();

        // Skip the bottom horizontal line, it's used to store metadata pixels.
        // (Currently using it to store palette pixels for the terrains to force image palette)
        for y in 0..(image.height() - 1) {
            for x in 0..image.width() {
                let loc = origin + vec2(x as i32, y as i32);
                let (r, g, b, _) = image.get_pixel(x, y).channels4();

                if let Some(terrain) = Terrain::from_color(SRgba::new(r, g, b, 0xff)) {
                    self.terrain.insert(loc, terrain);
                }
            }
        }
    }

    pub fn seed(&self) -> u32 { self.seed }

    pub fn get_terrain(&self, loc: Location) -> Terrain {
        if let Some(&t) = self.terrain.get(&loc) {
            t
        } else {
            self.default_terrain(loc)
        }
    }

    fn default_terrain(&self, loc: Location) -> Terrain {
        use Terrain::*;
        if loc.z == 0 {
            match loc.noise() {
                n if n > 0.8 => Tree,
                n if n > -0.8 => Grass,
                _ => Water,
            }
        } else {
            Terrain::Rock
        }
    }

    pub fn get_portal(&self, loc: Location) -> Option<Location> {
        self.portals.get(&loc).map(|&p| loc + p)
    }

    pub fn spawns(&self) -> slice::Iter<(Location, Loadout)> { self.spawns.iter() }

    pub fn player_entry(&self) -> Location { self.player_entry }

    /// Make a cave entrance going down.
    fn cave_entrance(&mut self, loc: Location) {
        const DOWNBOUND_ENCLOSURE: [(i32, i32); 5] = [(1, 0), (0, 1), (2, 1), (1, 2), (2, 2)];

        for &v in &DOWNBOUND_ENCLOSURE {
            let loc = loc + vec2(v.0, v.1);
            self.terrain.insert(loc, Terrain::Rock);
        }

        self.terrain.insert(loc, Terrain::Ground);
        self.terrain.insert(loc + vec2(1, 1), Terrain::Ground);
    }

    /// Punch a (one-way) portal between two points.
    fn portal(&mut self, origin: Location, destination: Location) {
        self.portals.insert(
            origin,
            Portal::new(origin, destination),
        );
    }
}

impl serde::Serialize for Worldgen {
    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        self.seed.serialize(s)
    }
}

impl<'a> serde::Deserialize<'a> for Worldgen {
    fn deserialize<D: serde::Deserializer<'a>>(d: D) -> Result<Self, D::Error> {
        Ok(Worldgen::new(serde::Deserialize::deserialize(d)?))
    }
}

struct SectorDigger<'a> {
    worldgen: &'a mut Worldgen,
    sector: Sector,
    up_portal: Option<Location>,
    down_portal: Option<Location>,
    spawn_region: BTreeSet<Location>,
}

impl<'a> SectorDigger<'a> {
    fn new(worldgen: &'a mut Worldgen, sector: Sector) -> SectorDigger<'a> {
        SectorDigger {
            worldgen,
            sector,
            up_portal: None,
            down_portal: None,
            spawn_region: BTreeSet::new(),
        }
    }

    // TODO return impl
    fn domain(&self) -> Vec<mapgen::Point2D> {
        let mut ret = Vec::new();

        let sector_origin = self.sector.origin();
        let mapgen_origin = mapgen::Point2D::zero();

        for loc in self.sector.iter() {
            let pos = mapgen_origin +
                sector_origin.v2_at(loc).expect(
                    "Sector points are not Euclidean",
                );

            // Okay, this part is a bit hairy, hang on.
            // Sectors are arranged in a rectangular grid, so there are some cells where you can
            // step diagonally across two sector boundaries. However, we want to pretend that
            // sectors are only connected in the four cardinal directions, so we omit these cells
            // from the domain to prevent surprise holes between two diagonally adjacent shafts.
            if Self::is_next_to_diagonal_sector(loc) {
                continue;
            }

            ret.push(pos);
        }

        ret
    }

    fn loc(&self, pos: mapgen::Point2D) -> Location { self.sector.origin() + pos.to_vector() }

    fn set(&mut self, loc: Location, terrain: Terrain) {
        if terrain != Terrain::Gate {
            debug_assert_ne!(self.up_portal, Some(loc), "mapgen overwriting exit");
            debug_assert_ne!(self.down_portal, Some(loc), "mapgen overwriting exit");
        }

        // FIXME: Mapgen currently trips this with exit placement
        // debug_assert!(
        //     !Self::is_next_to_diagonal_sector(loc) &&
        //     self.sector.iter().find(|x| x == &loc).is_some(),
        //     "Setting a location outsides sector area");

        self.worldgen.terrain.insert(loc, terrain);
    }

    fn clear_spawns_near_entrance(&mut self, range: u32) {
        for loc in Dijkstra::new(
            vec![self.up_portal.expect("No entrance generated")],
            |loc| {
                self.worldgen
                    .terrain
                    .get(loc)
                    .cloned()
                    .unwrap_or(Terrain::Empty)
                    .is_open()
            },
            10_000,
        ).weights
            .iter()
            .filter_map(|(loc, &w)| if w <= range { Some(loc) } else { None })
        {
            self.spawn_region.remove(loc);
        }
    }

    fn is_next_to_diagonal_sector(loc: Location) -> bool {
        hex_neighbors(loc)
            .map(|x| x.sector().taxicab_distance(loc.sector()))
            .any(|d| d > 1)
    }
}

impl<'a> mapgen::Dungeon for SectorDigger<'a> {
    type Prefab = Room;

    /// Return a random prefab room.
    fn sample_prefab<R: Rng>(&mut self, rng: &mut R) -> Self::Prefab { rng.gen() }

    /// Add a large open continuous region to dungeon.
    fn dig_chamber<I: IntoIterator<Item = mapgen::Point2D>>(&mut self, area: I) {
        for pos in area {
            let loc = self.loc(pos);
            self.spawn_region.insert(loc);
            self.set(loc, Terrain::Ground);
        }
    }

    /// Add a narrow corridor to dungeon.
    fn dig_corridor<I: IntoIterator<Item = mapgen::Point2D>>(&mut self, path: I) {
        for pos in path {
            let loc = self.loc(pos);
            // Do not spawn things in corridors.
            self.spawn_region.remove(&loc);
            self.set(loc, Terrain::Ground);
        }
    }

    fn add_prefab(&mut self, prefab: &Self::Prefab, pos: mapgen::Point2D) {
        // TODO
        unimplemented!();
    }

    fn add_door(&mut self, pos: mapgen::Point2D) {
        let loc = self.loc(pos);
        self.spawn_region.remove(&loc);
        self.set(loc, Terrain::Door);
    }

    fn add_up_stairs(&mut self, pos: mapgen::Point2D) {
        let loc = self.loc(pos);
        self.up_portal = Some(loc);
        self.spawn_region.remove(&loc);
        // TODO: Add debug assertion that up-stairs are dug in the upper wall of a room
        self.set(loc, Terrain::Gate);
    }

    fn add_down_stairs(&mut self, pos: mapgen::Point2D) {
        let loc = self.loc(pos);
        self.down_portal = Some(loc);
        self.spawn_region.remove(&loc);
        self.set(loc, Terrain::Gate);

        // Visual hack to make the down-stairs show up better, carve out the rock blob that would
        // be drawn partially in front of it on screen.
        self.set(loc + vec2(1, 1), Terrain::Empty);
        // TODO: Add a debug assertion here to check that the exit location has proper enclosure to
        // begin with, both it and the rock cell in front of it need to be surrounded by undug
        // front tiles.
        self.spawn_region.remove(&(loc + vec2(1, 1))); // Just in case
    }
}

struct Room {
    size: Size2D<i32>,
}

impl mapgen::Prefab for Room {
    fn contains(&self, pos: mapgen::Point2D) -> bool {
        pos.x >= 0 && pos.y >= 0 && pos.x < self.size.width && pos.y < self.size.height
    }

    fn can_make_door(&self, pos: mapgen::Point2D) -> bool {
        let on_x_wall = pos.x == 0 || pos.x == self.size.width - 1;
        let on_y_wall = pos.y == 0 || pos.y == self.size.height - 1;

        // Must touch one wall, but touching both makes it a corner and we don't want rooms there.
        on_x_wall ^ on_y_wall
    }

    fn size(&self) -> mapgen::Size2D { self.size }
}

impl Rand for Room {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Room { size: Size2D::new(rng.gen_range(3, 10), rng.gen_range(3, 10)) }
    }
}
<commit_msg>Worldgen determinism test<commit_after>use Prefab;
use calx::{Dijkstra, hex_neighbors, SRgba};
use euclid::{vec2, Size2D};
use form::{self, Form};
use image::{self, GenericImage, Pixel};
use location::{Location, Portal, Sector};
use mapgen::{self, DigCavesGen};
use rand::{self, Rand, Rng, SeedableRng};
use serde;
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::slice;
use terrain::Terrain;
use world::Loadout;

/// Static generated world.
pub struct Worldgen {
    seed: u32,
    terrain: HashMap<Location, Terrain>,
    portals: HashMap<Location, Portal>,
    spawns: Vec<(Location, Loadout)>,
    player_entry: Location,
}

impl Worldgen {
    pub fn new(seed: u32) -> Worldgen {
        let mut ret = Worldgen {
            seed: seed,
            terrain: HashMap::new(),
            portals: HashMap::new(),
            spawns: Vec::new(),
            player_entry: Location::new(0, 0, 0),
        };

        let mut rng: ::Rng = SeedableRng::from_seed([seed, seed, seed, seed]);

        let mut cave_entrance = Location::new(9, 0, 0);
        ret.cave_entrance(cave_entrance);
        ret.terrain.insert(
            cave_entrance + vec2(1, 1),
            Terrain::Gate,
        );

        for depth in 1..11 {
            let up_stairs;
            let down_stairs;
            let mut spawns = Vec::new();

            {
                let mut digger = SectorDigger::new(&mut ret, Sector::new(0, 0, depth as i16));
                let gen = DigCavesGen::new(digger.domain());
                gen.dig(&mut rng, &mut digger);

                up_stairs = digger.up_portal.expect("Mapgen didn't create stairs up");
                down_stairs = digger.down_portal.expect(
                    "Mapgen didn't create stairs down",
                );

                // Spawn
                digger.clear_spawns_near_entrance(12);

                let mut spawn_locs = rand::sample(&mut rng, digger.spawn_region.iter(), 20);
                let n_spawns = spawn_locs.len();

                let items = Form::filter(|f| f.is_item() && f.at_depth(depth));
                for &loc in spawn_locs.drain(0..n_spawns / 2) {
                    spawns.push((
                        loc,
                        form::rand(&mut rng, &items)
                            .expect("No item spawn")
                            .loadout
                            .clone(),
                    ))
                }

                let mobs = Form::filter(|f| f.is_mob() && f.at_depth(depth));
                for &loc in spawn_locs {
                    spawns.push((
                        loc,
                        form::rand(&mut rng, &mobs)
                            .expect("No mob spawn")
                            .loadout
                            .clone(),
                    ))
                }
            }

            ret.spawns.extend(spawns.into_iter());
            ret.portal(cave_entrance, up_stairs + vec2(1, 1));
            ret.portal(up_stairs, cave_entrance - vec2(1, 1));
            cave_entrance = down_stairs;

            // TODO: Generator needs an option to not generate stairs down on bottom level
        }

        ret
    }

    fn load_prefab(&mut self, origin: Location, prefab: &Prefab) {
        for (p, &(ref terrain, ref entities)) in prefab.iter() {
            let loc = origin + p;

            self.terrain.insert(loc, *terrain);

            for spawn in entities.iter() {
                if spawn == "player" {
                    self.player_entry = loc;
                } else {
                    let form = Form::named(spawn).expect(&format!(
                        "Bad prefab: Form '{}' not found!",
                        spawn
                    ));
                    self.spawns.push((loc, form.loadout.clone()));
                }
            }
        }
    }

    fn load_map_bitmap(&mut self, origin: Location, path: &str) {
        let image = image::open(path).unwrap();

        // Skip the bottom horizontal line, it's used to store metadata pixels.
        // (Currently using it to store palette pixels for the terrains to force image palette)
        for y in 0..(image.height() - 1) {
            for x in 0..image.width() {
                let loc = origin + vec2(x as i32, y as i32);
                let (r, g, b, _) = image.get_pixel(x, y).channels4();

                if let Some(terrain) = Terrain::from_color(SRgba::new(r, g, b, 0xff)) {
                    self.terrain.insert(loc, terrain);
                }
            }
        }
    }

    pub fn seed(&self) -> u32 { self.seed }

    pub fn get_terrain(&self, loc: Location) -> Terrain {
        if let Some(&t) = self.terrain.get(&loc) {
            t
        } else {
            self.default_terrain(loc)
        }
    }

    fn default_terrain(&self, loc: Location) -> Terrain {
        use Terrain::*;
        if loc.z == 0 {
            match loc.noise() {
                n if n > 0.8 => Tree,
                n if n > -0.8 => Grass,
                _ => Water,
            }
        } else {
            Terrain::Rock
        }
    }

    pub fn get_portal(&self, loc: Location) -> Option<Location> {
        self.portals.get(&loc).map(|&p| loc + p)
    }

    pub fn spawns(&self) -> slice::Iter<(Location, Loadout)> { self.spawns.iter() }

    pub fn player_entry(&self) -> Location { self.player_entry }

    /// Make a cave entrance going down.
    fn cave_entrance(&mut self, loc: Location) {
        const DOWNBOUND_ENCLOSURE: [(i32, i32); 5] = [(1, 0), (0, 1), (2, 1), (1, 2), (2, 2)];

        for &v in &DOWNBOUND_ENCLOSURE {
            let loc = loc + vec2(v.0, v.1);
            self.terrain.insert(loc, Terrain::Rock);
        }

        self.terrain.insert(loc, Terrain::Ground);
        self.terrain.insert(loc + vec2(1, 1), Terrain::Ground);
    }

    /// Punch a (one-way) portal between two points.
    fn portal(&mut self, origin: Location, destination: Location) {
        self.portals.insert(
            origin,
            Portal::new(origin, destination),
        );
    }
}

impl serde::Serialize for Worldgen {
    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        self.seed.serialize(s)
    }
}

impl<'a> serde::Deserialize<'a> for Worldgen {
    fn deserialize<D: serde::Deserializer<'a>>(d: D) -> Result<Self, D::Error> {
        Ok(Worldgen::new(serde::Deserialize::deserialize(d)?))
    }
}

struct SectorDigger<'a> {
    worldgen: &'a mut Worldgen,
    sector: Sector,
    up_portal: Option<Location>,
    down_portal: Option<Location>,
    spawn_region: BTreeSet<Location>,
}

impl<'a> SectorDigger<'a> {
    fn new(worldgen: &'a mut Worldgen, sector: Sector) -> SectorDigger<'a> {
        SectorDigger {
            worldgen,
            sector,
            up_portal: None,
            down_portal: None,
            spawn_region: BTreeSet::new(),
        }
    }

    // TODO return impl
    fn domain(&self) -> Vec<mapgen::Point2D> {
        let mut ret = Vec::new();

        let sector_origin = self.sector.origin();
        let mapgen_origin = mapgen::Point2D::zero();

        for loc in self.sector.iter() {
            let pos = mapgen_origin +
                sector_origin.v2_at(loc).expect(
                    "Sector points are not Euclidean",
                );

            // Okay, this part is a bit hairy, hang on.
            // Sectors are arranged in a rectangular grid, so there are some cells where you can
            // step diagonally across two sector boundaries. However, we want to pretend that
            // sectors are only connected in the four cardinal directions, so we omit these cells
            // from the domain to prevent surprise holes between two diagonally adjacent shafts.
            if Self::is_next_to_diagonal_sector(loc) {
                continue;
            }

            ret.push(pos);
        }

        ret
    }

    fn loc(&self, pos: mapgen::Point2D) -> Location { self.sector.origin() + pos.to_vector() }

    fn set(&mut self, loc: Location, terrain: Terrain) {
        if terrain != Terrain::Gate {
            debug_assert_ne!(self.up_portal, Some(loc), "mapgen overwriting exit");
            debug_assert_ne!(self.down_portal, Some(loc), "mapgen overwriting exit");
        }

        // FIXME: Mapgen currently trips this with exit placement
        // debug_assert!(
        //     !Self::is_next_to_diagonal_sector(loc) &&
        //     self.sector.iter().find(|x| x == &loc).is_some(),
        //     "Setting a location outsides sector area");

        self.worldgen.terrain.insert(loc, terrain);
    }

    fn clear_spawns_near_entrance(&mut self, range: u32) {
        for loc in Dijkstra::new(
            vec![self.up_portal.expect("No entrance generated")],
            |loc| {
                self.worldgen
                    .terrain
                    .get(loc)
                    .cloned()
                    .unwrap_or(Terrain::Empty)
                    .is_open()
            },
            10_000,
        ).weights
            .iter()
            .filter_map(|(loc, &w)| if w <= range { Some(loc) } else { None })
        {
            self.spawn_region.remove(loc);
        }
    }

    fn is_next_to_diagonal_sector(loc: Location) -> bool {
        hex_neighbors(loc)
            .map(|x| x.sector().taxicab_distance(loc.sector()))
            .any(|d| d > 1)
    }
}

impl<'a> mapgen::Dungeon for SectorDigger<'a> {
    type Prefab = Room;

    /// Return a random prefab room.
    fn sample_prefab<R: Rng>(&mut self, rng: &mut R) -> Self::Prefab { rng.gen() }

    /// Add a large open continuous region to dungeon.
    fn dig_chamber<I: IntoIterator<Item = mapgen::Point2D>>(&mut self, area: I) {
        for pos in area {
            let loc = self.loc(pos);
            self.spawn_region.insert(loc);
            self.set(loc, Terrain::Ground);
        }
    }

    /// Add a narrow corridor to dungeon.
    fn dig_corridor<I: IntoIterator<Item = mapgen::Point2D>>(&mut self, path: I) {
        for pos in path {
            let loc = self.loc(pos);
            // Do not spawn things in corridors.
            self.spawn_region.remove(&loc);
            self.set(loc, Terrain::Ground);
        }
    }

    fn add_prefab(&mut self, prefab: &Self::Prefab, pos: mapgen::Point2D) {
        // TODO
        unimplemented!();
    }

    fn add_door(&mut self, pos: mapgen::Point2D) {
        let loc = self.loc(pos);
        self.spawn_region.remove(&loc);
        self.set(loc, Terrain::Door);
    }

    fn add_up_stairs(&mut self, pos: mapgen::Point2D) {
        let loc = self.loc(pos);
        self.up_portal = Some(loc);
        self.spawn_region.remove(&loc);
        // TODO: Add debug assertion that up-stairs are dug in the upper wall of a room
        self.set(loc, Terrain::Gate);
    }

    fn add_down_stairs(&mut self, pos: mapgen::Point2D) {
        let loc = self.loc(pos);
        self.down_portal = Some(loc);
        self.spawn_region.remove(&loc);
        self.set(loc, Terrain::Gate);

        // Visual hack to make the down-stairs show up better, carve out the rock blob that would
        // be drawn partially in front of it on screen.
        self.set(loc + vec2(1, 1), Terrain::Empty);
        // TODO: Add a debug assertion here to check that the exit location has proper enclosure to
        // begin with, both it and the rock cell in front of it need to be surrounded by undug
        // front tiles.
        self.spawn_region.remove(&(loc + vec2(1, 1))); // Just in case
    }
}

struct Room {
    size: Size2D<i32>,
}

impl mapgen::Prefab for Room {
    fn contains(&self, pos: mapgen::Point2D) -> bool {
        pos.x >= 0 && pos.y >= 0 && pos.x < self.size.width && pos.y < self.size.height
    }

    fn can_make_door(&self, pos: mapgen::Point2D) -> bool {
        let on_x_wall = pos.x == 0 || pos.x == self.size.width - 1;
        let on_y_wall = pos.y == 0 || pos.y == self.size.height - 1;

        // Must touch one wall, but touching both makes it a corner and we don't want rooms there.
        on_x_wall ^ on_y_wall
    }

    fn size(&self) -> mapgen::Size2D { self.size }
}

impl Rand for Room {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Room { size: Size2D::new(rng.gen_range(3, 10), rng.gen_range(3, 10)) }
    }
}

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

    #[test]
    fn test_determinism() {
        use rand::{self, Rand};

        let mut rng = rand::thread_rng();

        let seed = u32::rand(&mut rng);
        let mut gen = Worldgen::new(seed);

        // Build the value repeatedly using the same seed and see that they are all equal.
        for _ in 1..4 {
            let second = Worldgen::new(seed);

            assert_eq!(gen.seed, second.seed);
            // These can make huge printouts so don't use assert_eq that would try to print them to
            // stdout
            assert!(gen.terrain == second.terrain);
            assert!(gen.portals == second.portals);
            assert_eq!(gen.player_entry, second.player_entry);

            gen = second;
        }
    }
}
<|endoftext|>


<commit_before>#![feature(core)]

extern crate iron;
extern crate postgres;
extern crate "iron-postgres-middleware" as pg_middleware;

use iron::prelude::*;
use iron::status;
use pg_middleware::{PostgresMiddleware, PostgresReqExt};

fn main() {
    let mut chain = Chain::new(name_list);

    let pg_middleware = PostgresMiddleware::new("postgres://postgres@localhost/example");

    {
        let conn = pg_middleware.pool.get().unwrap();
        conn.execute(
            "CREATE TABLE IF NOT EXISTS names (
                id SERIAL PRIMARY KEY,
                name VARCHAR(255) NOT NULL
            )",
        &[]).unwrap();
        conn.execute("INSERT INTO names(name) VALUES ($1)", &[&"Joe Smith".to_string()]).unwrap();
    }

    chain.link_before(pg_middleware);

    Iron::new(chain).listen("localhost:3000").unwrap();
}

fn name_list(req: &mut Request) -> IronResult<Response> {
    let conn = req.db_conn();
    let stmt = conn.prepare("SELECT id, name FROM names").unwrap();
    let rows = stmt.query(&[]).unwrap();

    let mut resp_str = "Names:\n".to_string();

    for row in rows {
        let id: i32 = row.get(0);
        let name: String = row.get(1);
        let name_format = format!("{}: {}\n", id, name);
        resp_str.push_str(name_format.as_slice());
    }

    Ok(Response::with((status::Ok, resp_str)))
}
<commit_msg>Fix basic example<commit_after>extern crate iron;
extern crate postgres;
extern crate iron_postgres_middleware as pg_middleware;

use iron::prelude::*;
use iron::status;
use pg_middleware::{PostgresMiddleware, PostgresReqExt};

fn main() {
    let mut chain = Chain::new(name_list);

    let pg_middleware = PostgresMiddleware::new("postgres://postgres@localhost/example");

    {
        let conn = pg_middleware.pool.get().unwrap();
        conn.execute(
            "CREATE TABLE IF NOT EXISTS names (
                id SERIAL PRIMARY KEY,
                name VARCHAR(255) NOT NULL
            )",
        &[]).unwrap();
        conn.execute("INSERT INTO names(name) VALUES ($1)", &[&"Joe Smith".to_string()]).unwrap();
    }

    chain.link_before(pg_middleware);

    Iron::new(chain).http("localhost:3000").unwrap();
}

fn name_list(req: &mut Request) -> IronResult<Response> {
    let conn = req.db_conn();
    let stmt = conn.prepare("SELECT id, name FROM names").unwrap();
    let rows = stmt.query(&[]).unwrap();

    let mut resp_str = "Names:\n".to_string();

    for row in rows {
        let id: i32 = row.get(0);
        let name: String = row.get(1);
        let name_format = format!("{}: {}\n", id, name);
        resp_str.push_str(&name_format);
    }

    Ok(Response::with((status::Ok, resp_str)))
}
<|endoftext|>


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

use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    let mut base = super::linux_musl_base::opts();

    // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
    // target.
    base.features = "+v7,+vfp3,+neon".to_string();
    base.cpu = "cortex-a8".to_string();
    base.max_atomic_width = Some(64);
    Ok(Target {
        // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
        // uses it to determine the calling convention and float ABI, and LLVM
        // doesn't support the "musleabihf" value.
        llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
        arch: "arm".to_string(),
        target_os: "linux".to_string(),
        target_env: "musl".to_string(),
        target_vendor: "unknown".to_string(),
        linker_flavor: LinkerFlavor::Gcc,
        options: TargetOptions {
            abi_blacklist: super::arm_base::abi_blacklist(),
            .. base
        },
    })
}
<commit_msg>Disable NEON on musl ARMv7<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    let base = super::linux_musl_base::opts();
    Ok(Target {
        // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
        // uses it to determine the calling convention and float ABI, and LLVM
        // doesn't support the "musleabihf" value.
        llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
        arch: "arm".to_string(),
        target_os: "linux".to_string(),
        target_env: "musl".to_string(),
        target_vendor: "unknown".to_string(),
        linker_flavor: LinkerFlavor::Gcc,

        // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
        // target.
        options: TargetOptions {
            features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
            cpu: "generic".to_string(),
            max_atomic_width: Some(64),
            abi_blacklist: super::arm_base::abi_blacklist(),
            .. base
        }
    })
}
<|endoftext|>


<commit_before>extern crate avro;
extern crate serde_json;

use avro::Codec;
use avro::reader::Reader;
use avro::schema::Schema;
use avro::types::{Record, ToAvro, Value};
use avro::writer::Writer;

struct Test<'a> {
    a: i64,
    b: &'a str,
}

impl<'a> ToAvro for Test<'a> {
    fn avro(self) -> Value {
        let mut record = Record::new();
        record.put("a", self.a);
        record.put("b", self.b);
        record.avro()
    }
}

fn main() {
    let raw_schema = r#"
        {
            "type": "record",
            "name": "test",
            "fields": [
                {"name": "a", "type": "long"},
                {"name": "b", "type": "string"}
            ]
        }
    "#;

    let schema = Schema::parse_str(raw_schema).unwrap();

    println!("{:?}", schema);

    let mut record = Record::with_schema(&schema).unwrap();
    record.put("a", 27);
    record.put("b", "foo");

    let mut writer = Writer::with_codec(&schema, Vec::new(), Codec::Deflate);
    writer.append(record).unwrap();

    let test = Test {
        a: 27,
        b: "foo",
    };

    writer.append(test.avro()).unwrap();

    let input = writer.into_inner();
    let reader = Reader::new(&input[..]);

    for record in reader {
        println!("{:?}", record);
    }
}
<commit_msg>Remove serde_json from example<commit_after>extern crate avro;

use avro::Codec;
use avro::reader::Reader;
use avro::schema::Schema;
use avro::types::{Record, ToAvro, Value};
use avro::writer::Writer;

struct Test<'a> {
    a: i64,
    b: &'a str,
}

impl<'a> ToAvro for Test<'a> {
    fn avro(self) -> Value {
        let mut record = Record::new();
        record.put("a", self.a);
        record.put("b", self.b);
        record.avro()
    }
}

fn main() {
    let raw_schema = r#"
        {
            "type": "record",
            "name": "test",
            "fields": [
                {"name": "a", "type": "long"},
                {"name": "b", "type": "string"}
            ]
        }
    "#;

    let schema = Schema::parse_str(raw_schema).unwrap();

    println!("{:?}", schema);

    let mut record = Record::with_schema(&schema).unwrap();
    record.put("a", 27);
    record.put("b", "foo");

    let mut writer = Writer::with_codec(&schema, Vec::new(), Codec::Deflate);
    writer.append(record).unwrap();

    let test = Test {
        a: 27,
        b: "foo",
    };

    writer.append(test.avro()).unwrap();

    let input = writer.into_inner();
    let reader = Reader::new(&input[..]);

    for record in reader {
        println!("{:?}", record);
    }
}
<|endoftext|>


<commit_before>fn main() {
	println!("Hello!");
}

<commit_msg>Created Hello, World! example<commit_after>extern crate time;
extern crate http;
extern crate oauth;

use oauth::server::{Gate, Listener};
use std::io::net::ip::Ipv4Addr;
use http::server::{Request, ResponseWriter};
use http::headers::content_type::MediaType;

fn main() {
  fn handler(_req: &Request, res: &mut ResponseWriter) {
      res.headers.date = Some(time::now_utc());
      res.headers.content_length = Some(14);
      res.headers.content_type = Some(MediaType {
        type_: String::from_str("text"),
        subtype: String::from_str("plain"),
        parameters: vec!((String::from_str("charset"), String::from_str("UTF-8")))
      });
      res.headers.server = Some(String::from_str("Example"));

      res.write(bytes!("Hello, World!\n")).unwrap();
    }

  let server = Gate{
    ip: Ipv4Addr(127, 0, 0, 1),
    port: 8001,
    handler: handler
  };

  server.listen();
}

<|endoftext|>


<commit_before>use fftw::plan::*;
use fftw::types::*;
use num_traits::Zero;

/// Check successive forward and backward transform equals to the identity
#[test]
fn r2r2r_identity() {
    let n = 32;
    let mut a = vec![0.0f64; n];
    let mut b = vec![0.0f64; n];

    // http://www.fftw.org/fftw3_doc/Real_002dto_002dReal-Transform-Kinds.html,
    // contains the normalization rules for each R2R transform. Given
    // normalization `N`, we can test `inverse_dct(dct(x / N)) == x`.
    // If you want to apply the normalization symmetrically in the transform
    // and inverse, then simply divide all elements of the output (or input)
    // vector by `sqrt(N)`, both on the forward and inverse passes. We
    // demonstrate this here.

    // Here we use a type-2 DCT, whose inverse is a type-3 DCT, and whose
    // normalization is `N=2*n`.
    let mut fwd: R2RPlan64 =
        R2RPlan::new(&[n], &mut a, &mut b, R2RKind::FFTW_REDFT10, Flag::Measure).unwrap();
    let mut bwd: R2RPlan64 =
        R2RPlan::new(&[n], &mut b, &mut a, R2RKind::FFTW_REDFT01, Flag::Measure).unwrap();
    let N = 2. * n as f64;

    // Vector of ones.
    a = vec![1.0f64; n];

    // Forward pass.
    fwd.r2r(&mut a, &mut b).unwrap();
    // Renormalize
    for mut i in &mut b {
        *i /= N.sqrt();
    }

    // Inverse.
    bwd.r2r(&mut b, &mut a).unwrap();
    // Renormalize.
    for mut i in &mut a {
        *i /= N.sqrt();
    }

    // Ensure we have the original vector of ones.
    for v in a.iter() {
        let dif = (v - 1.).abs();
        if dif > 1e-7 {
            panic!("Large difference: v={}, dif={}", v, dif);
        }
    }
}
<commit_msg>Rename `N` to `factor`<commit_after>use fftw::plan::*;
use fftw::types::*;

/// Check successive forward and backward transform equals to the identity
#[test]
fn r2r2r_identity() {
    let n = 32;
    let mut a = vec![0.0f64; n];
    let mut b = vec![0.0f64; n];

    // http://www.fftw.org/fftw3_doc/Real_002dto_002dReal-Transform-Kinds.html,
    // contains the normalization rules for each R2R transform. Given
    // normalization `factor`, we can test `inverse_dct(dct(x / factor)) == x`.
    // If you want to apply the normalization symmetrically in the transform
    // and inverse, then simply divide all elements of the output (or input)
    // vector by `sqrt(factor)`, both on the forward and inverse passes. We
    // demonstrate this here.

    // Here we use a type-2 DCT, whose inverse is a type-3 DCT, and whose
    // normalization is `factor=2*n`.
    let mut fwd: R2RPlan64 =
        R2RPlan::new(&[n], &mut a, &mut b, R2RKind::FFTW_REDFT10, Flag::Measure).unwrap();
    let mut bwd: R2RPlan64 =
        R2RPlan::new(&[n], &mut b, &mut a, R2RKind::FFTW_REDFT01, Flag::Measure).unwrap();
    let factor = 2. * n as f64;

    // Vector of ones.
    a = vec![1.0f64; n];

    // Forward pass.
    fwd.r2r(&mut a, &mut b).unwrap();
    // Renormalize
    for i in &mut b {
        *i /= factor.sqrt();
    }

    // Inverse.
    bwd.r2r(&mut b, &mut a).unwrap();
    // Renormalize.
    for i in &mut a {
        *i /= factor.sqrt();
    }

    // Ensure we have the original vector of ones.
    for v in a.iter() {
        let dif = (v - 1.).abs();
        if dif > 1e-7 {
            panic!("Large difference: v={}, dif={}", v, dif);
        }
    }
}
<|endoftext|>