<commit_before>extern crate teleborg;
extern crate reqwest;

#[cfg(test)]
mod tests {
    use teleborg::{Bot, ParseMode, ChatAction, NO_MARKUP};
    use teleborg::objects::{Contact, InlineKeyboardButton, InlineKeyboardMarkup, ForceReply};
    use reqwest::Client;

    use std::env;

    const BASE_URL: &'static str = "https://api.telegram.org/bot";

    fn get_token() -> String {
        env::var("TELEGRAM_BOT_TOKEN")
            .ok()
            .expect("Can't find TELEGRAM_BOT_TOKEN env variable")
    }

    fn setup() -> (Bot, i64) {
        let token = get_token();
        let bot_url = [BASE_URL, &token].concat();
        let bot = Bot::new(bot_url).unwrap();
        let chat_id = env::var("TELEGRAM_CHAT_ID")
            .ok()
            .expect("Can't find TELEGRAM_CHAT_ID env variable")
            .parse::<i64>()
            .unwrap();
        (bot, chat_id)
    }

    #[test]
    fn test_get_me() {
        let token = get_token();
        let bot_url = [BASE_URL, &token].concat();
        let client = Client::new().unwrap();
        let json = Bot::get_me(&client, &bot_url);
        assert!(json.is_ok());
    }

    #[test]
    fn test_send_message() {
        let (bot, chat_id) = setup();
        let message = bot.send_message(&chat_id, "test send_message", None, None, None, None, NO_MARKUP);
        assert!(message.is_ok());
    }

    #[test]
    fn test_send_text_message() {
        let (bot, chat_id) = setup();
        let message = bot.send_message(&chat_id,
                                       "test send text message",
                                       Some(&ParseMode::Text),
                                       None,
                                       None,
                                       None,
                                       NO_MARKUP);
        assert!(message.is_ok());
    }

    #[test]
    fn test_send_markdown_message() {
        let (bot, chat_id) = setup();
        let message = bot.send_message(&chat_id,
                                       "*test send bold message*",
                                       Some(&ParseMode::Markdown),
                                       None,
                                       None,
                                       None,
                                       NO_MARKUP);
        assert!(message.is_ok());
    }

    #[test]
    fn test_send_html_message() {
        let (bot, chat_id) = setup();
        let message = bot.send_message(&chat_id,
                                       "test send HTML message",
                                       Some(&ParseMode::Html),
                                       None,
                                       None,
                                       None,
                                       NO_MARKUP);
        assert!(message.is_ok());
    }

    #[test]
    fn test_url_chat_actions() {
        let (bot, chat_id) = setup();
        let success = bot.send_chat_action(&chat_id, &ChatAction::FindLocation);
        assert!(success.is_ok());
    }

    #[test]
    fn test_url_inline_keyboard() {
        let (bot, chat_id) = setup();
        let mut buttons = Vec::<Vec<InlineKeyboardButton>>::new();
        let mut row = Vec::<InlineKeyboardButton>::new();
        row.push(InlineKeyboardButton::new("TestButton".to_string(),
                                           Some("http://github.com/voider1/teleborg".to_string()),
                                           None,
                                           None,
                                           None));
        buttons.push(row);
        let markup = InlineKeyboardMarkup::new(buttons);
        let message = bot.send_message(&chat_id, "test inline keyboard", None, None, None, None, Some(markup));
        assert!(message.is_ok());
    }

    #[test]
    fn test_force_reply() {
        let (bot, chat_id) = setup();
        let force_reply = ForceReply::new(true, None);
        println!("{:?}", force_reply);
        let message = bot.send_message(&chat_id, "test force reply", None, None, None, None, Some(force_reply));
        println!("{:?}", message);
        assert!(message.is_ok());
    }

    #[test]
    fn test_send_contact() {
        let (bot, chat_id) = setup();

        let contact = Contact {
            phone_number: "0612345678".to_string(),
            first_name: "Voider".to_string(),
            last_name: Some("1".to_string()),
            user_id: Some(666),
        };
        let message = bot.send_contact(&chat_id, &contact, None, None, None);
        assert!(message.is_ok());
    }
}
<commit_msg>Removing debug print statements<commit_after>extern crate teleborg;
extern crate reqwest;

#[cfg(test)]
mod tests {
    use teleborg::{Bot, ParseMode, ChatAction, NO_MARKUP};
    use teleborg::objects::{Contact, InlineKeyboardButton, InlineKeyboardMarkup, ForceReply};
    use reqwest::Client;

    use std::env;

    const BASE_URL: &'static str = "https://api.telegram.org/bot";

    fn get_token() -> String {
        env::var("TELEGRAM_BOT_TOKEN")
            .ok()
            .expect("Can't find TELEGRAM_BOT_TOKEN env variable")
    }

    fn setup() -> (Bot, i64) {
        let token = get_token();
        let bot_url = [BASE_URL, &token].concat();
        let bot = Bot::new(bot_url).unwrap();
        let chat_id = env::var("TELEGRAM_CHAT_ID")
            .ok()
            .expect("Can't find TELEGRAM_CHAT_ID env variable")
            .parse::<i64>()
            .unwrap();
        (bot, chat_id)
    }

    #[test]
    fn test_get_me() {
        let token = get_token();
        let bot_url = [BASE_URL, &token].concat();
        let client = Client::new().unwrap();
        let json = Bot::get_me(&client, &bot_url);
        assert!(json.is_ok());
    }

    #[test]
    fn test_send_message() {
        let (bot, chat_id) = setup();
        let message = bot.send_message(&chat_id, "test send_message", None, None, None, None, NO_MARKUP);
        assert!(message.is_ok());
    }

    #[test]
    fn test_send_text_message() {
        let (bot, chat_id) = setup();
        let message = bot.send_message(&chat_id,
                                       "test send text message",
                                       Some(&ParseMode::Text),
                                       None,
                                       None,
                                       None,
                                       NO_MARKUP);
        assert!(message.is_ok());
    }

    #[test]
    fn test_send_markdown_message() {
        let (bot, chat_id) = setup();
        let message = bot.send_message(&chat_id,
                                       "*test send bold message*",
                                       Some(&ParseMode::Markdown),
                                       None,
                                       None,
                                       None,
                                       NO_MARKUP);
        assert!(message.is_ok());
    }

    #[test]
    fn test_send_html_message() {
        let (bot, chat_id) = setup();
        let message = bot.send_message(&chat_id,
                                       "test send HTML message",
                                       Some(&ParseMode::Html),
                                       None,
                                       None,
                                       None,
                                       NO_MARKUP);
        assert!(message.is_ok());
    }

    #[test]
    fn test_url_chat_actions() {
        let (bot, chat_id) = setup();
        let success = bot.send_chat_action(&chat_id, &ChatAction::FindLocation);
        assert!(success.is_ok());
    }

    #[test]
    fn test_url_inline_keyboard() {
        let (bot, chat_id) = setup();
        let mut buttons = Vec::<Vec<InlineKeyboardButton>>::new();
        let mut row = Vec::<InlineKeyboardButton>::new();
        row.push(InlineKeyboardButton::new("TestButton".to_string(),
                                           Some("http://github.com/voider1/teleborg".to_string()),
                                           None,
                                           None,
                                           None));
        buttons.push(row);
        let markup = InlineKeyboardMarkup::new(buttons);
        let message = bot.send_message(&chat_id, "test inline keyboard", None, None, None, None, Some(markup));
        assert!(message.is_ok());
    }

    #[test]
    fn test_force_reply() {
        let (bot, chat_id) = setup();
        let force_reply = ForceReply::new(true, None);
        let message = bot.send_message(&chat_id, "test force reply", None, None, None, None, Some(force_reply));
        assert!(message.is_ok());
    }

    #[test]
    fn test_send_contact() {
        let (bot, chat_id) = setup();

        let contact = Contact {
            phone_number: "0612345678".to_string(),
            first_name: "Voider".to_string(),
            last_name: Some("1".to_string()),
            user_id: Some(666),
        };
        let message = bot.send_contact(&chat_id, &contact, None, None, None);
        assert!(message.is_ok());
    }
}
<|endoftext|>


<commit_before>macro_rules! try_drop {
    ($e:expr, $msg:expr) => { match $e {
        Ok(x) => x,
        Err(e) => {
            use ::std::io::{Write, stderr};
            if ::std::thread::panicking() {
                write!(stderr(), "{}: {:?}", $msg, e).unwrap();
                return;
            } else {
                panic!("{}: {:?}", $msg, e);
            }
        }
    }}
}

mod command;
mod project_builder;

#[cfg_attr(feature="sqlite", path="sqlite_database.rs")]
#[cfg_attr(feature="postgres", path="postgres_database.rs")]
#[cfg_attr(feature="mysql", path="mysql_database.rs")]
pub mod database;

pub use self::project_builder::project;

pub fn database(url: &str) -> database::Database {
    database::Database::new(url)
}
<commit_msg>add #[allow(unused)] for a macro that is not used in sqlite build<commit_after>#[allow(unused)]
macro_rules! try_drop {
    ($e:expr, $msg:expr) => { match $e {
        Ok(x) => x,
        Err(e) => {
            use ::std::io::{Write, stderr};
            if ::std::thread::panicking() {
                write!(stderr(), "{}: {:?}", $msg, e).unwrap();
                return;
            } else {
                panic!("{}: {:?}", $msg, e);
            }
        }
    }}
}

mod command;
mod project_builder;

#[cfg_attr(feature="sqlite", path="sqlite_database.rs")]
#[cfg_attr(feature="postgres", path="postgres_database.rs")]
#[cfg_attr(feature="mysql", path="mysql_database.rs")]
pub mod database;

pub use self::project_builder::project;

pub fn database(url: &str) -> database::Database {
    database::Database::new(url)
}
<|endoftext|>


<commit_before>use kay::{World, Fate, ActorSystem};
use compact::CVec;
use descartes::{N, P2, V2, Area, WithUniqueOrthogonal, ClosedLinePath, LinePath,
AreaError, AreaEmbedding, AreaFilter};
use ordered_float::OrderedFloat;

use land_use::zone_planning::{Lot, BuildingIntent};
use land_use::buildings::BuildingStyle;
use land_use::buildings::architecture::ideal_lot_shape;
use economy::immigration_and_development::DevelopmentManagerID;
use itertools::Itertools;

use cb_planning::construction::{Constructable, ConstructableID};
use cb_planning::{Prototype, PrototypeID};
use planning::{CBConstructionID, CBPrototypeKind};
use cb_util::log::{debug, error};
const LOG_T: &str = "Vacant Lots";

#[derive(Compact, Clone)]
pub struct VacantLot {
    pub id: VacantLotID,
    pub lot: Lot,
    based_on: PrototypeID,
}

impl Lot {
    pub fn width_depth_per_road_connection(&self) -> Vec<(P2, V2, f32, f32)> {
        let midpoints = self
            .area
            .primitives
            .iter()
            .flat_map(|primitive| {
                primitive
                    .boundary
                    .path()
                    .segments()
                    .map(|segment| segment.midpoint())
            })
            .collect::<Vec<_>>();

        self.all_road_connections()
            .into_iter()
            .map(|(point, direction)| {
                let depth_direction = direction;
                let width_direction = depth_direction.orthogonal_right();

                let depth = midpoints
                    .iter()
                    .map(|midpoint| OrderedFloat((*midpoint - point).dot(&depth_direction)))
                    .minmax()
                    .into_option()
	                .map_or(0.0, |(front, back)| *back - *front);

                let width = midpoints
                    .iter()
                    .map(|midpoint| OrderedFloat((*midpoint - point).dot(&width_direction)))
                    .minmax()
                    .into_option()
                    .map_or(0.0, |(left, right)| *right - *left);

                (point, direction, width, depth)
            })
            .collect()
    }

    #[allow(clippy::too_many_arguments)]
    pub fn split_for(
        &self,
        building_style: BuildingStyle,
        allow_left_split: bool,
        allow_right_split: bool,
        max_width_after_splitting: N,
        recursion_depth: usize,
        log_as: VacantLotID,
        log_in: &mut World,
    ) -> Result<Option<Lot>, AreaError> {
        let (needed_width, needed_depth, needed_compactness) = ideal_lot_shape(building_style);

        let debug_padding: String = ::std::iter::repeat(" ").take(recursion_depth).collect();
        debug(
            LOG_T,
            format!(
                "{}Trying to suggest lot for {:?}. Road Boundaries {:?}",
                debug_padding,
                building_style,
                self.road_boundaries
                    .iter()
                    .map(LinePath::length)
                    .collect::<Vec<_>>(),
            ),
            log_as,
            log_in,
        );

        // TODO: fix fucked up orientation of areas compared to descartes!!
        let compactness = -self.area.primitives[0].area() * 4.0 * ::std::f32::consts::PI
            / self.area.primitives[0].boundary.path().length().powi(2);

        for (point, direction, width, depth) in self.width_depth_per_road_connection() {
            debug(
                LOG_T,
                format!(
                    "{}Is: {:?} Needed: {:?}",
                    debug_padding,
                    (width, depth, compactness),
                    (needed_width, needed_depth, needed_compactness)
                ),
                log_as,
                log_in,
            );

            // make sure that we're making progress after recursing
            if width < max_width_after_splitting {
                let width_ratio = width / needed_width;
                let depth_ratio = depth / needed_depth;

                if width_ratio > 0.5 && width_ratio < 2.0 && depth_ratio > 0.5 && depth_ratio < 2.0
                {
                    if compactness >= needed_compactness {
                        return Ok(Some(self.clone()));
                    } else {
                        return Ok(None);
                    }
                } else if width_ratio > 2.0 && depth_ratio > 0.5 {
                    let orthogonal = direction.orthogonal_right();

                    let corners = vec![
                        point + needed_depth * direction,
                        point + needed_depth * direction + 1_000.0 * orthogonal,
                        point - 500.0 * direction + 1_000.0 * orthogonal,
                        point - 500.0 * direction,
                        point + needed_depth * direction,
                    ];

                    let splitter_area = Area::new_simple(
                        ClosedLinePath::new(LinePath::new(corners.into()).unwrap()).unwrap(),
                    );

                    debug(
                        LOG_T,
                        format!("{}Attempting width split", debug_padding),
                        log_as,
                        log_in,
                    );

                    #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
                    enum SplittingLabel {
                        Lot,
                        Splitter,
                    };

                    let mut embedding = AreaEmbedding::new(width / 10.0);

                    embedding.insert(self.area.clone(), SplittingLabel::Lot);
                    embedding.insert(splitter_area, SplittingLabel::Splitter);

                    if allow_right_split {
                        if let Ok(right_splits) = embedding
                            .view(
                                AreaFilter::has(SplittingLabel::Lot)
                                    .and(AreaFilter::has(SplittingLabel::Splitter)),
                            )
                            .get_areas_with_pieces()
                        {
                            for (right_split, _) in right_splits {
                                let road_boundaries = new_road_boundaries(
                                    &self.road_boundaries,
                                    right_split.primitives[0].boundary.path(),
                                );

                                if !road_boundaries.is_empty() {
                                    let split_lot = Lot {
                                        road_boundaries,
                                        area: right_split.clone(),
                                        original_area: right_split,
                                        ..self.clone()
                                    };

                                    // recurse!
                                    debug(
                                        LOG_T,
                                        format!(
                                            "{}Got right split lot, checking suitability",
                                            debug_padding,
                                        ),
                                        log_as,
                                        log_in,
                                    );
                                    if let Some(ok_split_lot) = split_lot.split_for(
                                        building_style,
                                        true, //false,
                                        true,
                                        width * 0.66,
                                        recursion_depth + 1,
                                        log_as,
                                        log_in,
                                    )? {
                                        return Ok(Some(ok_split_lot));
                                    }
                                }
                            }
                        }
                    }
                    if allow_left_split {
                        if let Ok(left_splits) = embedding
                            .view(
                                AreaFilter::has(SplittingLabel::Lot)
                                    .and(AreaFilter::has(SplittingLabel::Splitter).not()),
                            )
                            .get_areas_with_pieces()
                        {
                            for (left_split, _) in left_splits {
                                let road_boundaries = new_road_boundaries(
                                    &self.road_boundaries,
                                    left_split.primitives[0].boundary.path(),
                                );

                                if !road_boundaries.is_empty() {
                                    let split_lot = Lot {
                                        road_boundaries,
                                        original_area: left_split.clone(),
                                        area: left_split,
                                        ..self.clone()
                                    };

                                    // recurse!
                                    debug(
                                        LOG_T,
                                        format!(
                                            "{}Got right split lot, checking suitability",
                                            debug_padding,
                                        ),
                                        log_as,
                                        log_in,
                                    );
                                    if let Some(ok_split_lot) = split_lot.split_for(
                                        building_style,
                                        true,
                                        true, //false,
                                        width * 0.66,
                                        recursion_depth + 1,
                                        log_as,
                                        log_in,
                                    )? {
                                        return Ok(Some(ok_split_lot));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        Ok(None)
    }
}

fn new_road_boundaries(old_road_bundaries: &[LinePath], new_boundary: &LinePath) -> CVec<LinePath> {
    new_boundary
        .points
        .iter()
        .batching(|points_it| {
            let mut consecutive_points = CVec::new();

            loop {
                if let Some(point) = points_it.next() {
                    if old_road_bundaries
                        .iter()
                        .any(|old_boundary| old_boundary.includes(*point))
                    {
                        consecutive_points.push(*point);
                    } else {
                        break;
                    }
                } else if consecutive_points.is_empty() {
                    return None;
                } else {
                    break;
                }
            }

            Some(LinePath::new(consecutive_points))
        })
        .filter_map(|maybe_new_boundary| maybe_new_boundary)
        .collect()
}

impl VacantLot {
    pub fn spawn(
        id: VacantLotID,
        lot: &Lot,
        based_on: PrototypeID,
        _world: &mut World,
    ) -> VacantLot {
        VacantLot {
            id,
            based_on,
            lot: lot.clone(),
        }
    }

    pub fn suggest_lot(
        &mut self,
        building_style: BuildingStyle,
        requester: DevelopmentManagerID,
        world: &mut World,
    ) {
        if self
            .lot
            .land_uses
            .iter()
            .any(|land_use| building_style.can_appear_in(*land_use))
        {
            debug(LOG_T, "Trying suggest", self.id, world);
            match self.lot.split_for(
                building_style,
                true,
                true,
                ::std::f32::INFINITY,
                0,
                self.id,
                world,
            ) {
                Ok(Some(suitable_lot)) => requester.on_suggested_lot(
                    BuildingIntent {
                        lot: suitable_lot,
                        building_style,
                    },
                    self.based_on,
                    world,
                ),
                Ok(None) => {}
                Err(_err) => error(LOG_T, "Geometry", self.id, world),
            }
        }
    }
}

impl Constructable<CBPrototypeKind> for VacantLot {
    fn morph(
        &mut self,
        _: &Prototype<CBPrototypeKind>,
        _report_to: CBConstructionID,
        _world: &mut World,
    ) {
        unreachable!()
    }

    fn destruct(&mut self, report_to: CBConstructionID, world: &mut World) -> Fate {
        report_to.action_done(self.id.into(), world);
        Fate::Die
    }
}

pub fn setup(system: &mut ActorSystem) {
    system.register::<VacantLot>();
    auto_setup(system);
}

mod kay_auto;
pub use self::kay_auto::*;
<commit_msg>lint: rustfmt<commit_after>use kay::{World, Fate, ActorSystem};
use compact::CVec;
use descartes::{N, P2, V2, Area, WithUniqueOrthogonal, ClosedLinePath, LinePath,
AreaError, AreaEmbedding, AreaFilter};
use ordered_float::OrderedFloat;

use land_use::zone_planning::{Lot, BuildingIntent};
use land_use::buildings::BuildingStyle;
use land_use::buildings::architecture::ideal_lot_shape;
use economy::immigration_and_development::DevelopmentManagerID;
use itertools::Itertools;

use cb_planning::construction::{Constructable, ConstructableID};
use cb_planning::{Prototype, PrototypeID};
use planning::{CBConstructionID, CBPrototypeKind};
use cb_util::log::{debug, error};
const LOG_T: &str = "Vacant Lots";

#[derive(Compact, Clone)]
pub struct VacantLot {
    pub id: VacantLotID,
    pub lot: Lot,
    based_on: PrototypeID,
}

impl Lot {
    pub fn width_depth_per_road_connection(&self) -> Vec<(P2, V2, f32, f32)> {
        let midpoints = self
            .area
            .primitives
            .iter()
            .flat_map(|primitive| {
                primitive
                    .boundary
                    .path()
                    .segments()
                    .map(|segment| segment.midpoint())
            })
            .collect::<Vec<_>>();

        self.all_road_connections()
            .into_iter()
            .map(|(point, direction)| {
                let depth_direction = direction;
                let width_direction = depth_direction.orthogonal_right();

                let depth = midpoints
                    .iter()
                    .map(|midpoint| OrderedFloat((*midpoint - point).dot(&depth_direction)))
                    .minmax()
                    .into_option()
                    .map_or(0.0, |(front, back)| *back - *front);

                let width = midpoints
                    .iter()
                    .map(|midpoint| OrderedFloat((*midpoint - point).dot(&width_direction)))
                    .minmax()
                    .into_option()
                    .map_or(0.0, |(left, right)| *right - *left);

                (point, direction, width, depth)
            })
            .collect()
    }

    #[allow(clippy::too_many_arguments)]
    pub fn split_for(
        &self,
        building_style: BuildingStyle,
        allow_left_split: bool,
        allow_right_split: bool,
        max_width_after_splitting: N,
        recursion_depth: usize,
        log_as: VacantLotID,
        log_in: &mut World,
    ) -> Result<Option<Lot>, AreaError> {
        let (needed_width, needed_depth, needed_compactness) = ideal_lot_shape(building_style);

        let debug_padding: String = ::std::iter::repeat(" ").take(recursion_depth).collect();
        debug(
            LOG_T,
            format!(
                "{}Trying to suggest lot for {:?}. Road Boundaries {:?}",
                debug_padding,
                building_style,
                self.road_boundaries
                    .iter()
                    .map(LinePath::length)
                    .collect::<Vec<_>>(),
            ),
            log_as,
            log_in,
        );

        // TODO: fix fucked up orientation of areas compared to descartes!!
        let compactness = -self.area.primitives[0].area() * 4.0 * ::std::f32::consts::PI
            / self.area.primitives[0].boundary.path().length().powi(2);

        for (point, direction, width, depth) in self.width_depth_per_road_connection() {
            debug(
                LOG_T,
                format!(
                    "{}Is: {:?} Needed: {:?}",
                    debug_padding,
                    (width, depth, compactness),
                    (needed_width, needed_depth, needed_compactness)
                ),
                log_as,
                log_in,
            );

            // make sure that we're making progress after recursing
            if width < max_width_after_splitting {
                let width_ratio = width / needed_width;
                let depth_ratio = depth / needed_depth;

                if width_ratio > 0.5 && width_ratio < 2.0 && depth_ratio > 0.5 && depth_ratio < 2.0
                {
                    if compactness >= needed_compactness {
                        return Ok(Some(self.clone()));
                    } else {
                        return Ok(None);
                    }
                } else if width_ratio > 2.0 && depth_ratio > 0.5 {
                    let orthogonal = direction.orthogonal_right();

                    let corners = vec![
                        point + needed_depth * direction,
                        point + needed_depth * direction + 1_000.0 * orthogonal,
                        point - 500.0 * direction + 1_000.0 * orthogonal,
                        point - 500.0 * direction,
                        point + needed_depth * direction,
                    ];

                    let splitter_area = Area::new_simple(
                        ClosedLinePath::new(LinePath::new(corners.into()).unwrap()).unwrap(),
                    );

                    debug(
                        LOG_T,
                        format!("{}Attempting width split", debug_padding),
                        log_as,
                        log_in,
                    );

                    #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
                    enum SplittingLabel {
                        Lot,
                        Splitter,
                    };

                    let mut embedding = AreaEmbedding::new(width / 10.0);

                    embedding.insert(self.area.clone(), SplittingLabel::Lot);
                    embedding.insert(splitter_area, SplittingLabel::Splitter);

                    if allow_right_split {
                        if let Ok(right_splits) = embedding
                            .view(
                                AreaFilter::has(SplittingLabel::Lot)
                                    .and(AreaFilter::has(SplittingLabel::Splitter)),
                            )
                            .get_areas_with_pieces()
                        {
                            for (right_split, _) in right_splits {
                                let road_boundaries = new_road_boundaries(
                                    &self.road_boundaries,
                                    right_split.primitives[0].boundary.path(),
                                );

                                if !road_boundaries.is_empty() {
                                    let split_lot = Lot {
                                        road_boundaries,
                                        area: right_split.clone(),
                                        original_area: right_split,
                                        ..self.clone()
                                    };

                                    // recurse!
                                    debug(
                                        LOG_T,
                                        format!(
                                            "{}Got right split lot, checking suitability",
                                            debug_padding,
                                        ),
                                        log_as,
                                        log_in,
                                    );
                                    if let Some(ok_split_lot) = split_lot.split_for(
                                        building_style,
                                        true, //false,
                                        true,
                                        width * 0.66,
                                        recursion_depth + 1,
                                        log_as,
                                        log_in,
                                    )? {
                                        return Ok(Some(ok_split_lot));
                                    }
                                }
                            }
                        }
                    }
                    if allow_left_split {
                        if let Ok(left_splits) = embedding
                            .view(
                                AreaFilter::has(SplittingLabel::Lot)
                                    .and(AreaFilter::has(SplittingLabel::Splitter).not()),
                            )
                            .get_areas_with_pieces()
                        {
                            for (left_split, _) in left_splits {
                                let road_boundaries = new_road_boundaries(
                                    &self.road_boundaries,
                                    left_split.primitives[0].boundary.path(),
                                );

                                if !road_boundaries.is_empty() {
                                    let split_lot = Lot {
                                        road_boundaries,
                                        original_area: left_split.clone(),
                                        area: left_split,
                                        ..self.clone()
                                    };

                                    // recurse!
                                    debug(
                                        LOG_T,
                                        format!(
                                            "{}Got right split lot, checking suitability",
                                            debug_padding,
                                        ),
                                        log_as,
                                        log_in,
                                    );
                                    if let Some(ok_split_lot) = split_lot.split_for(
                                        building_style,
                                        true,
                                        true, //false,
                                        width * 0.66,
                                        recursion_depth + 1,
                                        log_as,
                                        log_in,
                                    )? {
                                        return Ok(Some(ok_split_lot));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        Ok(None)
    }
}

fn new_road_boundaries(old_road_bundaries: &[LinePath], new_boundary: &LinePath) -> CVec<LinePath> {
    new_boundary
        .points
        .iter()
        .batching(|points_it| {
            let mut consecutive_points = CVec::new();

            loop {
                if let Some(point) = points_it.next() {
                    if old_road_bundaries
                        .iter()
                        .any(|old_boundary| old_boundary.includes(*point))
                    {
                        consecutive_points.push(*point);
                    } else {
                        break;
                    }
                } else if consecutive_points.is_empty() {
                    return None;
                } else {
                    break;
                }
            }

            Some(LinePath::new(consecutive_points))
        })
        .filter_map(|maybe_new_boundary| maybe_new_boundary)
        .collect()
}

impl VacantLot {
    pub fn spawn(
        id: VacantLotID,
        lot: &Lot,
        based_on: PrototypeID,
        _world: &mut World,
    ) -> VacantLot {
        VacantLot {
            id,
            based_on,
            lot: lot.clone(),
        }
    }

    pub fn suggest_lot(
        &mut self,
        building_style: BuildingStyle,
        requester: DevelopmentManagerID,
        world: &mut World,
    ) {
        if self
            .lot
            .land_uses
            .iter()
            .any(|land_use| building_style.can_appear_in(*land_use))
        {
            debug(LOG_T, "Trying suggest", self.id, world);
            match self.lot.split_for(
                building_style,
                true,
                true,
                ::std::f32::INFINITY,
                0,
                self.id,
                world,
            ) {
                Ok(Some(suitable_lot)) => requester.on_suggested_lot(
                    BuildingIntent {
                        lot: suitable_lot,
                        building_style,
                    },
                    self.based_on,
                    world,
                ),
                Ok(None) => {}
                Err(_err) => error(LOG_T, "Geometry", self.id, world),
            }
        }
    }
}

impl Constructable<CBPrototypeKind> for VacantLot {
    fn morph(
        &mut self,
        _: &Prototype<CBPrototypeKind>,
        _report_to: CBConstructionID,
        _world: &mut World,
    ) {
        unreachable!()
    }

    fn destruct(&mut self, report_to: CBConstructionID, world: &mut World) -> Fate {
        report_to.action_done(self.id.into(), world);
        Fate::Die
    }
}

pub fn setup(system: &mut ActorSystem) {
    system.register::<VacantLot>();
    auto_setup(system);
}

mod kay_auto;
pub use self::kay_auto::*;
<|endoftext|>


<commit_before>extern crate kernel32;
extern crate gdi32;
extern crate user32;
extern crate winapi;
extern crate cgmath;

#[macro_use]
extern crate vulkano;

#[path = "support/teapot.rs"]
mod teapot;

use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::mem;
use std::ptr;

fn main() {
    // The start of this example is exactly the same as `triangle`. You should read the
    // `triangle` example if you haven't done so yet.

    // TODO: for the moment the AMD driver crashes if you don't pass an ApplicationInfo, but in theory it's optional
    let app = vulkano::instance::ApplicationInfo { application_name: "test", application_version: 1, engine_name: "test", engine_version: 1 };
    let instance = vulkano::instance::Instance::new(Some(&app), &[]).expect("failed to create instance");

    let physical = vulkano::instance::PhysicalDevice::enumerate(&instance)
                            .next().expect("no device available");
    println!("Using device: {} (type: {:?})", physical.name(), physical.ty());

    let window = unsafe { create_window() };
    let surface = unsafe { vulkano::swapchain::Surface::from_hwnd(&instance, kernel32::GetModuleHandleW(ptr::null()), window).unwrap() };

    let queue = physical.queue_families().find(|q| q.supports_graphics() &&
                                                   surface.is_supported(q).unwrap_or(false))
                                                .expect("couldn't find a graphical queue family");

    let (device, queues) = vulkano::device::Device::new(&physical, physical.supported_features(),
                                                        [(queue, 0.5)].iter().cloned(), &[])
                                                                .expect("failed to create device");
    let queue = queues.into_iter().next().unwrap();

    let (swapchain, images) = {
        let caps = surface.get_capabilities(&physical).expect("failed to get surface capabilities");

        let dimensions = caps.current_extent.unwrap_or([1280, 1024]);
        let present = caps.present_modes[0];
        let usage = caps.supported_usage_flags;

        vulkano::swapchain::Swapchain::new(&device, &surface, 3,
                                           vulkano::formats::B8G8R8A8Srgb, dimensions, 1,
                                           &usage, &queue, vulkano::swapchain::SurfaceTransform::Identity,
                                           vulkano::swapchain::CompositeAlpha::Opaque,
                                           present, true).expect("failed to create swapchain")
    };

    let vertex_buffer = vulkano::buffer::Buffer::<[teapot::Vertex], _>
                               ::array(&device, teapot::VERTICES.len(),
                                       &vulkano::buffer::Usage::all(),
                                       vulkano::memory::HostVisible, &queue)
                                       .expect("failed to create buffer");

    {
        let mut mapping = vertex_buffer.try_write().unwrap();
        for (o, i) in mapping.iter_mut().zip(teapot::VERTICES.iter()) {
            *o = *i;
        }
    }

    let normals_buffer = vulkano::buffer::Buffer::<[teapot::Normal], _>
                               ::array(&device, teapot::NORMALS.len(),
                                       &vulkano::buffer::Usage::all(),
                                       vulkano::memory::HostVisible, &queue)
                                       .expect("failed to create buffer");

    {
        let mut mapping = normals_buffer.try_write().unwrap();
        for (o, i) in mapping.iter_mut().zip(teapot::NORMALS.iter()) {
            *o = *i;
        }
    }

    let index_buffer = vulkano::buffer::Buffer::<[u16], _>
                               ::array(&device, teapot::INDICES.len(),
                                       &vulkano::buffer::Usage::all(),
                                       vulkano::memory::HostVisible, &queue)
                                       .expect("failed to create buffer");

    {
        let mut mapping = index_buffer.try_write().unwrap();
        for (o, i) in mapping.iter_mut().zip(teapot::INDICES.iter()) {
            *o = *i;
        }
    }

    // note: this teapot was meant for OpenGL where the origin is at the lower left
    //       instead the origin is at the upper left in vulkan, so we reverse the Y axis
    let proj = cgmath::perspective(cgmath::rad(3.141592 / 2.0), { let d = images[0].dimensions(); d[1] as f32 / d[0] as f32 }, 0.01, 100.0);
    let view = cgmath::Matrix4::look_at(cgmath::Point3::new(-2.0, 0.0, 0.4), cgmath::Point3::new(0.0, 0.0, 0.0), cgmath::Vector3::new(0.0, -1.0, 0.0));
    let scale = cgmath::Matrix4::from_scale(0.01);

    let uniform_buffer = vulkano::buffer::Buffer::<([[f32; 4]; 4], [[f32; 4]; 4]), _>
                               ::new(&device, &vulkano::buffer::Usage::all(),
                                     vulkano::memory::HostVisible, &queue)
                               .expect("failed to create buffer");
    {
        let mut mapping = uniform_buffer.try_write().unwrap();
        mapping.0 = (view * scale).into();
        mapping.1 = proj.into();
    }

    mod vs { include!{concat!(env!("OUT_DIR"), "/examples-teapot_vs.rs")} }
    let vs = vs::TeapotShader::load(&device).expect("failed to create shader module");
    mod fs { include!{concat!(env!("OUT_DIR"), "/examples-teapot_fs.rs")} }
    let fs = fs::TeapotShader::load(&device).expect("failed to create shader module");

    let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.lock().unwrap().family())
                                                  .expect("failed to create command buffer pool");

    let images = images.into_iter().map(|image| {
        let image = image.transition(vulkano::image::Layout::PresentSrc, &cb_pool,
                                     &mut queue.lock().unwrap()).unwrap();
        vulkano::image::ImageView::new(&image).expect("failed to create image view")
    }).collect::<Vec<_>>();

    let renderpass = renderpass!{
        device: &device,
        attachments: {
            color [Clear]
        }
    }.unwrap();

    let descriptor_pool = vulkano::descriptor_set::DescriptorPool::new(&device).unwrap();

    let (pipeline_layout, set) = {
        let layout1 = vulkano::descriptor_set::DescriptorSetLayout::new(&device, Default::default()).unwrap();
        let pipeline_layout = vulkano::descriptor_set::PipelineLayout::new(&device, Default::default(), (layout1.clone(), ())).unwrap();
        let set1 = vulkano::descriptor_set::DescriptorSet::new(&descriptor_pool, &layout1, uniform_buffer.clone() as std::sync::Arc<_>).unwrap();
        (pipeline_layout, set1)
    };

    let pipeline = {
        let ia = vulkano::pipeline::input_assembly::InputAssembly {
            topology: vulkano::pipeline::input_assembly::PrimitiveTopology::TriangleList,
            primitive_restart_enable: false,
        };

        let raster = Default::default();
        let ms = vulkano::pipeline::multisample::Multisample::disabled();
        let blend = vulkano::pipeline::blend::Blend {
            logic_op: None,
            blend_constants: Some([0.0; 4]),
        };

        let viewports = vulkano::pipeline::viewport::ViewportsState::Fixed {
            data: vec![(
                vulkano::pipeline::viewport::Viewport {
                    origin: [0.0, 0.0],
                    dimensions: [1244.0, 699.0],
                    depth_range: 0.0 .. 1.0
                },
                vulkano::pipeline::viewport::Scissor {
                    origin: [0, 0],
                    dimensions: [1244, 699],
                }
            )],
        };

        vulkano::pipeline::GraphicsPipeline::new(&device, &vs.main_entry_point(), &ia, &viewports,
                                                 &raster, &ms, &blend, &fs.main_entry_point(),
                                                 &pipeline_layout, &renderpass.subpass(0).unwrap())
                                                 .unwrap()
    };

    let framebuffers = images.iter().map(|image| {
        vulkano::framebuffer::Framebuffer::new(&renderpass, (1244, 699, 1), image).unwrap()
    }).collect::<Vec<_>>();

    let command_buffers = framebuffers.iter().map(|framebuffer| {
        vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool).unwrap()
            .draw_inline(&renderpass, &framebuffer, [0.0, 0.0, 1.0, 1.0])
            .draw_indexed(&pipeline, (vertex_buffer.clone(), normals_buffer.clone()), &index_buffer, &vulkano::command_buffer::DynamicState::none(), (set.clone(), ()))
            .draw_end()
            .build().unwrap()
    }).collect::<Vec<_>>();

    loop {
        let image_num = swapchain.acquire_next_image(1000000).unwrap();
        let mut queue = queue.lock().unwrap();
        command_buffers[image_num].submit(&mut queue).unwrap();
        swapchain.present(&mut queue, image_num).unwrap();
        drop(queue);

        unsafe {
            let mut msg = mem::uninitialized();
            if user32::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) == 0 {
                break;
            }

            user32::TranslateMessage(&msg);
            user32::DispatchMessageW(&msg);
        }
    }
}

unsafe fn create_window() -> winapi::HWND {
    let class_name = register_window_class();

    let title: Vec<u16> = vec![b'V' as u16, b'u' as u16, b'l' as u16, b'k' as u16,
                               b'a' as u16, b'n' as u16, 0];

    user32::CreateWindowExW(winapi::WS_EX_APPWINDOW | winapi::WS_EX_WINDOWEDGE, class_name.as_ptr(),
                            title.as_ptr() as winapi::LPCWSTR,
                            winapi::WS_OVERLAPPEDWINDOW | winapi::WS_CLIPSIBLINGS |
                            winapi::WS_VISIBLE,
                            winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
                            winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
                            ptr::null_mut(), ptr::null_mut(),
                            kernel32::GetModuleHandleW(ptr::null()),
                            ptr::null_mut())
}

unsafe fn register_window_class() -> Vec<u16> {
    let class_name: Vec<u16> = OsStr::new("Window Class").encode_wide().chain(Some(0).into_iter())
                                                         .collect::<Vec<u16>>();

    let class = winapi::WNDCLASSEXW {
        cbSize: mem::size_of::<winapi::WNDCLASSEXW>() as winapi::UINT,
        style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC,
        lpfnWndProc: Some(callback),
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: kernel32::GetModuleHandleW(ptr::null()),
        hIcon: ptr::null_mut(),
        hCursor: ptr::null_mut(),
        hbrBackground: ptr::null_mut(),
        lpszMenuName: ptr::null(),
        lpszClassName: class_name.as_ptr(),
        hIconSm: ptr::null_mut(),
    };

    user32::RegisterClassExW(&class);
    class_name
}

unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
                                   wparam: winapi::WPARAM, lparam: winapi::LPARAM)
                                   -> winapi::LRESULT
{
    user32::DefWindowProcW(window, msg, wparam, lparam)
}<commit_msg>Fix teapot appearance<commit_after>extern crate kernel32;
extern crate gdi32;
extern crate user32;
extern crate winapi;
extern crate cgmath;

#[macro_use]
extern crate vulkano;

#[path = "support/teapot.rs"]
mod teapot;

use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::mem;
use std::ptr;

fn main() {
    // The start of this example is exactly the same as `triangle`. You should read the
    // `triangle` example if you haven't done so yet.

    // TODO: for the moment the AMD driver crashes if you don't pass an ApplicationInfo, but in theory it's optional
    let app = vulkano::instance::ApplicationInfo { application_name: "test", application_version: 1, engine_name: "test", engine_version: 1 };
    let instance = vulkano::instance::Instance::new(Some(&app), &[]).expect("failed to create instance");

    let physical = vulkano::instance::PhysicalDevice::enumerate(&instance)
                            .next().expect("no device available");
    println!("Using device: {} (type: {:?})", physical.name(), physical.ty());

    let window = unsafe { create_window() };
    let surface = unsafe { vulkano::swapchain::Surface::from_hwnd(&instance, kernel32::GetModuleHandleW(ptr::null()), window).unwrap() };

    let queue = physical.queue_families().find(|q| q.supports_graphics() &&
                                                   surface.is_supported(q).unwrap_or(false))
                                                .expect("couldn't find a graphical queue family");

    let (device, queues) = vulkano::device::Device::new(&physical, physical.supported_features(),
                                                        [(queue, 0.5)].iter().cloned(), &[])
                                                                .expect("failed to create device");
    let queue = queues.into_iter().next().unwrap();

    let (swapchain, images) = {
        let caps = surface.get_capabilities(&physical).expect("failed to get surface capabilities");

        let dimensions = caps.current_extent.unwrap_or([1280, 1024]);
        let present = caps.present_modes[0];
        let usage = caps.supported_usage_flags;

        vulkano::swapchain::Swapchain::new(&device, &surface, 3,
                                           vulkano::formats::B8G8R8A8Srgb, dimensions, 1,
                                           &usage, &queue, vulkano::swapchain::SurfaceTransform::Identity,
                                           vulkano::swapchain::CompositeAlpha::Opaque,
                                           present, true).expect("failed to create swapchain")
    };

    let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.lock().unwrap().family())
                                                  .expect("failed to create command buffer pool");

    let depth_buffer = vulkano::image::Image::<vulkano::image::Type2d, vulkano::formats::D16Unorm, _>::new(&device, &vulkano::image::Usage::all(),
                                                  vulkano::memory::DeviceLocal, &queue,
                                                  images[0].dimensions(), (), 1).unwrap();
    let depth_buffer = depth_buffer.transition(vulkano::image::Layout::DepthStencilAttachmentOptimal, &cb_pool, &mut queue.lock().unwrap());

    let vertex_buffer = vulkano::buffer::Buffer::<[teapot::Vertex], _>
                               ::array(&device, teapot::VERTICES.len(),
                                       &vulkano::buffer::Usage::all(),
                                       vulkano::memory::HostVisible, &queue)
                                       .expect("failed to create buffer");

    {
        let mut mapping = vertex_buffer.try_write().unwrap();
        for (o, i) in mapping.iter_mut().zip(teapot::VERTICES.iter()) {
            *o = *i;
        }
    }

    let normals_buffer = vulkano::buffer::Buffer::<[teapot::Normal], _>
                               ::array(&device, teapot::NORMALS.len(),
                                       &vulkano::buffer::Usage::all(),
                                       vulkano::memory::HostVisible, &queue)
                                       .expect("failed to create buffer");

    {
        let mut mapping = normals_buffer.try_write().unwrap();
        for (o, i) in mapping.iter_mut().zip(teapot::NORMALS.iter()) {
            *o = *i;
        }
    }

    let index_buffer = vulkano::buffer::Buffer::<[u16], _>
                               ::array(&device, teapot::INDICES.len(),
                                       &vulkano::buffer::Usage::all(),
                                       vulkano::memory::HostVisible, &queue)
                                       .expect("failed to create buffer");

    {
        let mut mapping = index_buffer.try_write().unwrap();
        for (o, i) in mapping.iter_mut().zip(teapot::INDICES.iter()) {
            *o = *i;
        }
    }

    // note: this teapot was meant for OpenGL where the origin is at the lower left
    //       instead the origin is at the upper left in vulkan, so we reverse the Y axis
    let proj = cgmath::perspective(cgmath::rad(3.141592 / 2.0), { let d = images[0].dimensions(); d[0] as f32 / d[1] as f32 }, 0.01, 100.0);
    let view = cgmath::Matrix4::look_at(cgmath::Point3::new(0.2, 0.2, 1.0), cgmath::Point3::new(0.0, 0.0, 0.0), cgmath::Vector3::new(0.0, -1.0, 0.0));
    let scale = cgmath::Matrix4::from_scale(0.01);

    let uniform_buffer = vulkano::buffer::Buffer::<([[f32; 4]; 4], [[f32; 4]; 4]), _>
                               ::new(&device, &vulkano::buffer::Usage::all(),
                                     vulkano::memory::HostVisible, &queue)
                               .expect("failed to create buffer");
    {
        let mut mapping = uniform_buffer.try_write().unwrap();
        mapping.0 = (view * scale).into();
        mapping.1 = proj.into();
    }

    mod vs { include!{concat!(env!("OUT_DIR"), "/examples-teapot_vs.rs")} }
    let vs = vs::TeapotShader::load(&device).expect("failed to create shader module");
    mod fs { include!{concat!(env!("OUT_DIR"), "/examples-teapot_fs.rs")} }
    let fs = fs::TeapotShader::load(&device).expect("failed to create shader module");

    let images = images.into_iter().map(|image| {
        let image = image.transition(vulkano::image::Layout::PresentSrc, &cb_pool,
                                     &mut queue.lock().unwrap()).unwrap();
        vulkano::image::ImageView::new(&image).expect("failed to create image view")
    }).collect::<Vec<_>>();

    let renderpass = renderpass!{
        device: &device,
        attachments: {
            color [Clear]
        }
    }.unwrap();

    let descriptor_pool = vulkano::descriptor_set::DescriptorPool::new(&device).unwrap();

    let (pipeline_layout, set) = {
        let layout1 = vulkano::descriptor_set::DescriptorSetLayout::new(&device, Default::default()).unwrap();
        let pipeline_layout = vulkano::descriptor_set::PipelineLayout::new(&device, Default::default(), (layout1.clone(), ())).unwrap();
        let set1 = vulkano::descriptor_set::DescriptorSet::new(&descriptor_pool, &layout1, uniform_buffer.clone() as std::sync::Arc<_>).unwrap();
        (pipeline_layout, set1)
    };

    let pipeline = {
        let ia = vulkano::pipeline::input_assembly::InputAssembly {
            topology: vulkano::pipeline::input_assembly::PrimitiveTopology::TriangleList,
            primitive_restart_enable: false,
        };

        let raster = Default::default();
        let ms = vulkano::pipeline::multisample::Multisample::disabled();
        let blend = vulkano::pipeline::blend::Blend {
            logic_op: None,
            blend_constants: Some([0.0; 4]),
        };

        let viewports = vulkano::pipeline::viewport::ViewportsState::Fixed {
            data: vec![(
                vulkano::pipeline::viewport::Viewport {
                    origin: [0.0, 0.0],
                    dimensions: [1244.0, 699.0],
                    depth_range: 0.0 .. 1.0
                },
                vulkano::pipeline::viewport::Scissor {
                    origin: [0, 0],
                    dimensions: [1244, 699],
                }
            )],
        };

        vulkano::pipeline::GraphicsPipeline::new(&device, &vs.main_entry_point(), &ia, &viewports,
                                                 &raster, &ms, &blend, &fs.main_entry_point(),
                                                 &pipeline_layout, &renderpass.subpass(0).unwrap())
                                                 .unwrap()
    };

    let framebuffers = images.iter().map(|image| {
        vulkano::framebuffer::Framebuffer::new(&renderpass, (1244, 699, 1), image).unwrap()
    }).collect::<Vec<_>>();

    let command_buffers = framebuffers.iter().map(|framebuffer| {
        vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool).unwrap()
            .draw_inline(&renderpass, &framebuffer, [0.0, 0.0, 1.0, 1.0])
            .draw_indexed(&pipeline, (vertex_buffer.clone(), normals_buffer.clone()), &index_buffer, &vulkano::command_buffer::DynamicState::none(), (set.clone(), ()))
            .draw_end()
            .build().unwrap()
    }).collect::<Vec<_>>();

    loop {
        let image_num = swapchain.acquire_next_image(1000000).unwrap();
        let mut queue = queue.lock().unwrap();
        command_buffers[image_num].submit(&mut queue).unwrap();
        swapchain.present(&mut queue, image_num).unwrap();
        drop(queue);

        unsafe {
            let mut msg = mem::uninitialized();
            if user32::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) == 0 {
                break;
            }

            user32::TranslateMessage(&msg);
            user32::DispatchMessageW(&msg);
        }
    }
}

unsafe fn create_window() -> winapi::HWND {
    let class_name = register_window_class();

    let title: Vec<u16> = vec![b'V' as u16, b'u' as u16, b'l' as u16, b'k' as u16,
                               b'a' as u16, b'n' as u16, 0];

    user32::CreateWindowExW(winapi::WS_EX_APPWINDOW | winapi::WS_EX_WINDOWEDGE, class_name.as_ptr(),
                            title.as_ptr() as winapi::LPCWSTR,
                            winapi::WS_OVERLAPPEDWINDOW | winapi::WS_CLIPSIBLINGS |
                            winapi::WS_VISIBLE,
                            winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
                            winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
                            ptr::null_mut(), ptr::null_mut(),
                            kernel32::GetModuleHandleW(ptr::null()),
                            ptr::null_mut())
}

unsafe fn register_window_class() -> Vec<u16> {
    let class_name: Vec<u16> = OsStr::new("Window Class").encode_wide().chain(Some(0).into_iter())
                                                         .collect::<Vec<u16>>();

    let class = winapi::WNDCLASSEXW {
        cbSize: mem::size_of::<winapi::WNDCLASSEXW>() as winapi::UINT,
        style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC,
        lpfnWndProc: Some(callback),
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: kernel32::GetModuleHandleW(ptr::null()),
        hIcon: ptr::null_mut(),
        hCursor: ptr::null_mut(),
        hbrBackground: ptr::null_mut(),
        lpszMenuName: ptr::null(),
        lpszClassName: class_name.as_ptr(),
        hIconSm: ptr::null_mut(),
    };

    user32::RegisterClassExW(&class);
    class_name
}

unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
                                   wparam: winapi::WPARAM, lparam: winapi::LPARAM)
                                   -> winapi::LRESULT
{
    user32::DefWindowProcW(window, msg, wparam, lparam)
}<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Support for the 8259 Programmable Interrupt Controller.
//!
//! The 8259 PIC controls all of our IO IRQs. The PIC recieves IRQ requests
//! and feeds them to the CPU in order. An x86 system typically has two PICs,
//! PIC1 and PIC2, each of which provides 8 IRQs. Two PICs provide us with 15
//! unique IRQs, because one interrupt on the leader PIC is linked to interrupts
//! on the follower PIC.
//!
//! Mistakes were made, and Intel boneheadedly decided that it was a good idea
//! to map the vector offset of PIC1 to 8, so that it maps to interrupts
//! 8 ... 15 in the IDT. This conflicts with some of the interrupt numbers
//! used by CPU exceptions. Therefore, we must remap the PIC vectors so that
//! PIC1 starts at 32 and PIC2 at 40.

use super::super::Port;
use spin::Mutex;

use core::mem::transmute;

/// Starting offset for PIC1
const OFFSET: u8 = 0x20;
/// Command port for the follower PIC (PIC2)
const FOLLOWER_CMD_PORT: u16 = 0xA0;
/// Command port for the leader PIC (PIC1)
const LEADER_CMD_PORT: u16 = OFFSET as u16;

/// Commands to send to the PIC
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
enum Command { /// Command to set the PIC to 8086 mode
               Mode8086 = 0x01
             , /// Command to initialize a PIC
               Init     = 0x11
             , /// Command that ends an interrupt request
               EndIRQ   = 0x20
             , /// Command to read the Interrupt Request Register
               ReadIRR  = 0x0a
             , /// Command to read the Interrupt Service Register
               ReadISR  = 0x0b
             }

/// List of IRQs on the x86.
///
/// See [here](https://en.wikibooks.org/wiki/X86_Assembly/Programmable_Interrupt_Controller) for more info.
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
pub enum IRQ { /// System timer IRQ
               Timer        = OFFSET
             , /// PS/2 keyboard controller
               PS2Keyboard  = 1 + OFFSET
             , /// PIC2 cascade IRQ
               Cascade      = 2 + OFFSET
             , /// COM2 serial port
               COM2         = 3 + OFFSET
             , /// COM1 serial port
               COM1         = 4 + OFFSET
             , /// Line printer 2
               LPT2         = 5 + OFFSET
             , /// Floppy disc controller
               Floppy       = 6 + OFFSET
             , /// Line printer 1
               LPT1         = 7 + OFFSET
             , /// CMOS clock
               RTCTimer     = 8 + OFFSET
             , /// PS/2 mouse controller
               PS2Mouse     = 12 + OFFSET
             , /// Floating-point Coprocessor
               FPU          = 13 + OFFSET
             , /// ATA channel 1
               PrimaryATA   = 14 + OFFSET
             , /// ATA channel 2
               SecondaryATA = 15 + OFFSET
             }

/// A 8259 Programmable Interrupt Controller.
pub struct PIC {
    /// The base offset to which interrupts on this PIC are mapped
    offset: u8
  , /// The port on the CPU that sends commands to this PIC.
    command_port: Port
  , /// The port that sends and recieves data from the PIC
    data_port: Port
}

impl PIC {

    /// Construct a new leader PIC
    pub const fn leader() -> PIC {
        unsafe {
            PIC { offset: OFFSET
                , command_port: Port::new(LEADER_CMD_PORT)
                , data_port: Port::new(LEADER_CMD_PORT + 1)
                }
        }
    }

    /// Construct a new follower PIC
    pub const fn follower() -> PIC {
        unsafe {
            PIC { offset: OFFSET + 8
                , command_port: Port::new(FOLLOWER_CMD_PORT)
                , data_port: Port::new(FOLLOWER_CMD_PORT + 1)
                }
        }
    }

    /// Returns true if this PIC is the leader PIC
    #[inline]
    pub fn is_leader(&self) -> bool {
        self.offset == OFFSET
    }

    /// Send a command to the PIC
    #[inline]
    unsafe fn send_command(&self, command: Command) {
        self.command_port
            .out8(command as u8)
    }

    /// Send a byte of data to the PIC
    #[inline]
    pub fn send_data(&self, data: u8) {
        unsafe {
            self.data_port
                .out8(data)
        }
    }

    /// Send the "initialize" command to this PIC
    #[inline]
    pub fn initialize(&self) {
        unsafe { self.send_command(Command::Init) }
    }

    /// Read the contents of the ISR (Interrupt Service Register) from this PIC
    #[inline]
    pub fn read_isr(&self) -> u8 {
        unsafe {
            self.send_command(Command::ReadISR);
            self.data_port.in8()
        }
    }

/// Read the contents of the IRR (Interrupt Request Register) from this PIC
    #[inline]
    pub fn read_irr(&self) -> u8 {
        unsafe {
            self.send_command(Command::ReadIRR);
            self.data_port.in8()
        }
    }

}

/// Trait for something which is capable of handling a PIC IRQ
trait IRQHandler {
    /// Returns whether or not this handler handles the given IRQ
    fn handles(&self, irq: IRQ) -> bool;
    /// End an interrupt request
    fn end_interrupt(&self, irq: IRQ);
}

impl IRQHandler for PIC {

    fn handles(&self, irq: IRQ) -> bool {
        self.offset <= (irq as u8) && (irq as u8) < self.offset + 8
    }

    fn end_interrupt(&self, _: IRQ) {
        unsafe { let _ = self.send_command(Command::EndIRQ); }
    }
}

/// A pair of PICs in cascade mode.
///
/// This is the standard configuration on all modern x86 systems.
struct BothPICs (PIC, PIC);

impl BothPICs {

    /// Constructs the system's pair of PICs
    const fn new() -> Self {
        BothPICs (PIC::leader(), PIC::follower())
    }

    /// Initialize the system's PICs.
    pub unsafe fn initialize(&mut self) {
        let wait_port = Port::new(0x80);
        let wait = || { wait_port.out8(0); };
        // helper macro to avoid writing repetitive code
        macro_rules! send {
            (pic0 => $data:expr) => {
                self.0.send_data($data)
                wait();
            };
            (pic1 => $data:expr) => {
                self.1.send_data($data)
                wait();
            };
        }

        // Read the default interrupt masks from PIC1 and PIC2
        let (saved_mask1, saved_mask2)
            = (self.0.data_port.in8(), self.1.data_port.in8());

        // Send both PICs the 'initialize' command.
        self.0.initialize(); wait();
        self.1.initialize(); wait();

        // Each PIC then expects us to send it the following:
        // 1. the PIC's new vector offset
        send!(pic0 => self.0.offset);
        send!(pic1 => self.1.offset);
        // 2. number to configure PIC cascading
        send!(pic0 => 0x04);
        send!(pic1 => 0x02);
        // 3. command for 8086 mode
        send!(pic0 => Command::Mode8086 as u8);
        send!(pic1 => Command::Mode8086 as u8);
        // 4. finally, the mask we saved earlier
        send!(pic0 => saved_mask1);
        send!(pic1 => saved_mask2);
    }
}

impl IRQHandler for BothPICs {

    fn handles(&self, irq: IRQ) -> bool {
        self.0.handles(irq) ||
        self.1.handles(irq)
    }

    fn end_interrupt(&self, irq: IRQ) {
        if self.1.handles(irq) {
            self.1.end_interrupt(irq);
        }
        self.0.end_interrupt(irq);
    }

}

/// Global PIC instance and mutex
static PICS: Mutex<BothPICs>
    = Mutex::new(BothPICs::new());

/// Initialize the system's Programmable Interrupt Controller
///
/// # Unsafe Because:
///  - This should only ever be called by the kernel boot process.
///    Initializing the PICs once they have already been inicialized
///    will probably cause Bad Things to take place.
pub unsafe fn initialize() {
    PICS.lock()
        .initialize();
    println!("{:<38}{:>40}", " . . Initializing PICs", "[ OKAY ]")

}

/// If an interrupt is being handled by the PICs, end that interrupt.
///
/// This is called by the interrupt handler at the end of all interrupts.
/// If the interrupt is not a PIC interrupt, it silently does nothing.
///
/// # Unsafe Because:
///  - This should only be called by interrupt handler functions.
pub unsafe fn end_pic_interrupt(interrupt_id: u8) {
    let pics = PICS.lock();
    let irq: IRQ = transmute(interrupt_id);

    if pics.handles(irq) {
        pics.end_interrupt(irq)
    }
}
<commit_msg>[x86_all] update malformed macro syntax<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Support for the 8259 Programmable Interrupt Controller.
//!
//! The 8259 PIC controls all of our IO IRQs. The PIC recieves IRQ requests
//! and feeds them to the CPU in order. An x86 system typically has two PICs,
//! PIC1 and PIC2, each of which provides 8 IRQs. Two PICs provide us with 15
//! unique IRQs, because one interrupt on the leader PIC is linked to interrupts
//! on the follower PIC.
//!
//! Mistakes were made, and Intel boneheadedly decided that it was a good idea
//! to map the vector offset of PIC1 to 8, so that it maps to interrupts
//! 8 ... 15 in the IDT. This conflicts with some of the interrupt numbers
//! used by CPU exceptions. Therefore, we must remap the PIC vectors so that
//! PIC1 starts at 32 and PIC2 at 40.

use super::super::Port;
use spin::Mutex;

use core::mem::transmute;

/// Starting offset for PIC1
const OFFSET: u8 = 0x20;
/// Command port for the follower PIC (PIC2)
const FOLLOWER_CMD_PORT: u16 = 0xA0;
/// Command port for the leader PIC (PIC1)
const LEADER_CMD_PORT: u16 = OFFSET as u16;

/// Commands to send to the PIC
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
enum Command { /// Command to set the PIC to 8086 mode
               Mode8086 = 0x01
             , /// Command to initialize a PIC
               Init     = 0x11
             , /// Command that ends an interrupt request
               EndIRQ   = 0x20
             , /// Command to read the Interrupt Request Register
               ReadIRR  = 0x0a
             , /// Command to read the Interrupt Service Register
               ReadISR  = 0x0b
             }

/// List of IRQs on the x86.
///
/// See [here](https://en.wikibooks.org/wiki/X86_Assembly/Programmable_Interrupt_Controller) for more info.
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
pub enum IRQ { /// System timer IRQ
               Timer        = OFFSET
             , /// PS/2 keyboard controller
               PS2Keyboard  = 1 + OFFSET
             , /// PIC2 cascade IRQ
               Cascade      = 2 + OFFSET
             , /// COM2 serial port
               COM2         = 3 + OFFSET
             , /// COM1 serial port
               COM1         = 4 + OFFSET
             , /// Line printer 2
               LPT2         = 5 + OFFSET
             , /// Floppy disc controller
               Floppy       = 6 + OFFSET
             , /// Line printer 1
               LPT1         = 7 + OFFSET
             , /// CMOS clock
               RTCTimer     = 8 + OFFSET
             , /// PS/2 mouse controller
               PS2Mouse     = 12 + OFFSET
             , /// Floating-point Coprocessor
               FPU          = 13 + OFFSET
             , /// ATA channel 1
               PrimaryATA   = 14 + OFFSET
             , /// ATA channel 2
               SecondaryATA = 15 + OFFSET
             }

/// A 8259 Programmable Interrupt Controller.
pub struct PIC {
    /// The base offset to which interrupts on this PIC are mapped
    offset: u8
  , /// The port on the CPU that sends commands to this PIC.
    command_port: Port
  , /// The port that sends and recieves data from the PIC
    data_port: Port
}

impl PIC {

    /// Construct a new leader PIC
    pub const fn leader() -> PIC {
        unsafe {
            PIC { offset: OFFSET
                , command_port: Port::new(LEADER_CMD_PORT)
                , data_port: Port::new(LEADER_CMD_PORT + 1)
                }
        }
    }

    /// Construct a new follower PIC
    pub const fn follower() -> PIC {
        unsafe {
            PIC { offset: OFFSET + 8
                , command_port: Port::new(FOLLOWER_CMD_PORT)
                , data_port: Port::new(FOLLOWER_CMD_PORT + 1)
                }
        }
    }

    /// Returns true if this PIC is the leader PIC
    #[inline]
    pub fn is_leader(&self) -> bool {
        self.offset == OFFSET
    }

    /// Send a command to the PIC
    #[inline]
    unsafe fn send_command(&self, command: Command) {
        self.command_port
            .out8(command as u8)
    }

    /// Send a byte of data to the PIC
    #[inline]
    pub fn send_data(&self, data: u8) {
        unsafe {
            self.data_port
                .out8(data)
        }
    }

    /// Send the "initialize" command to this PIC
    #[inline]
    pub fn initialize(&self) {
        unsafe { self.send_command(Command::Init) }
    }

    /// Read the contents of the ISR (Interrupt Service Register) from this PIC
    #[inline]
    pub fn read_isr(&self) -> u8 {
        unsafe {
            self.send_command(Command::ReadISR);
            self.data_port.in8()
        }
    }

/// Read the contents of the IRR (Interrupt Request Register) from this PIC
    #[inline]
    pub fn read_irr(&self) -> u8 {
        unsafe {
            self.send_command(Command::ReadIRR);
            self.data_port.in8()
        }
    }

}

/// Trait for something which is capable of handling a PIC IRQ
trait IRQHandler {
    /// Returns whether or not this handler handles the given IRQ
    fn handles(&self, irq: IRQ) -> bool;
    /// End an interrupt request
    fn end_interrupt(&self, irq: IRQ);
}

impl IRQHandler for PIC {

    fn handles(&self, irq: IRQ) -> bool {
        self.offset <= (irq as u8) && (irq as u8) < self.offset + 8
    }

    fn end_interrupt(&self, _: IRQ) {
        unsafe { let _ = self.send_command(Command::EndIRQ); }
    }
}

/// A pair of PICs in cascade mode.
///
/// This is the standard configuration on all modern x86 systems.
struct BothPICs (PIC, PIC);

impl BothPICs {

    /// Constructs the system's pair of PICs
    const fn new() -> Self {
        BothPICs (PIC::leader(), PIC::follower())
    }

    /// Initialize the system's PICs.
    pub unsafe fn initialize(&mut self) {
        let wait_port = Port::new(0x80);
        let wait = || { wait_port.out8(0); };
        // helper macro to avoid writing repetitive code
        macro_rules! send {
            (pic0 => $data:expr) => {
                self.0.send_data($data);
                wait();
            };
            (pic1 => $data:expr) => {
                self.1.send_data($data);
                wait();
            };
        }

        // Read the default interrupt masks from PIC1 and PIC2
        let (saved_mask1, saved_mask2)
            = (self.0.data_port.in8(), self.1.data_port.in8());

        // Send both PICs the 'initialize' command.
        self.0.initialize(); wait();
        self.1.initialize(); wait();

        // Each PIC then expects us to send it the following:
        // 1. the PIC's new vector offset
        send!(pic0 => self.0.offset);
        send!(pic1 => self.1.offset);
        // 2. number to configure PIC cascading
        send!(pic0 => 0x04);
        send!(pic1 => 0x02);
        // 3. command for 8086 mode
        send!(pic0 => Command::Mode8086 as u8);
        send!(pic1 => Command::Mode8086 as u8);
        // 4. finally, the mask we saved earlier
        send!(pic0 => saved_mask1);
        send!(pic1 => saved_mask2);
    }
}

impl IRQHandler for BothPICs {

    fn handles(&self, irq: IRQ) -> bool {
        self.0.handles(irq) ||
        self.1.handles(irq)
    }

    fn end_interrupt(&self, irq: IRQ) {
        if self.1.handles(irq) {
            self.1.end_interrupt(irq);
        }
        self.0.end_interrupt(irq);
    }

}

/// Global PIC instance and mutex
static PICS: Mutex<BothPICs>
    = Mutex::new(BothPICs::new());

/// Initialize the system's Programmable Interrupt Controller
///
/// # Unsafe Because:
///  - This should only ever be called by the kernel boot process.
///    Initializing the PICs once they have already been inicialized
///    will probably cause Bad Things to take place.
pub unsafe fn initialize() {
    PICS.lock()
        .initialize();
    println!("{:<38}{:>40}", " . . Initializing PICs", "[ OKAY ]")

}

/// If an interrupt is being handled by the PICs, end that interrupt.
///
/// This is called by the interrupt handler at the end of all interrupts.
/// If the interrupt is not a PIC interrupt, it silently does nothing.
///
/// # Unsafe Because:
///  - This should only be called by interrupt handler functions.
pub unsafe fn end_pic_interrupt(interrupt_id: u8) {
    let pics = PICS.lock();
    let irq: IRQ = transmute(interrupt_id);

    if pics.handles(irq) {
        pics.end_interrupt(irq)
    }
}
<|endoftext|>