<commit_before>//! `Middleware` to normalize request's URI
use std::task::{Context, Poll};

use actix_http::http::{PathAndQuery, Uri};
use actix_service::{Service, Transform};
use bytes::Bytes;
use futures_util::future::{ok, Ready};
use regex::Regex;

use crate::service::{ServiceRequest, ServiceResponse};
use crate::Error;

/// To be used when constructing `NormalizePath` to define it's behavior.
#[non_exhaustive]
#[derive(Clone, Copy)]
pub enum TrailingSlash {
    /// Always add a trailing slash to the end of the path.
    /// This will require all routes to end in a trailing slash for them to be accessible.
    Always,
    /// Only merge any present multiple trailing slashes.
    ///
    /// Note: This option provides the best compatibility with the v2 version of this middlware.
    MergeOnly,
    /// Trim trailing slashes from the end of the path.
    Trim,
}

impl Default for TrailingSlash {
    fn default() -> Self {
        TrailingSlash::Always
    }
}

#[derive(Default, Clone, Copy)]
/// `Middleware` to normalize request's URI in place
///
/// Performs following:
///
/// - Merges multiple slashes into one.
/// - Appends a trailing slash if one is not present, removes one if present, or keeps trailing
///   slashes as-is, depending on the supplied `TrailingSlash` variant.
///
/// ```rust
/// use actix_web::{web, http, middleware, App, HttpResponse};
///
/// # fn main() {
/// let app = App::new()
///     .wrap(middleware::NormalizePath::default())
///     .service(
///         web::resource("/test")
///             .route(web::get().to(|| HttpResponse::Ok()))
///             .route(web::method(http::Method::HEAD).to(|| HttpResponse::MethodNotAllowed()))
///     );
/// # }
/// ```

pub struct NormalizePath(TrailingSlash);

impl NormalizePath {
    /// Create new `NormalizePath` middleware with the specified trailing slash style.
    pub fn new(trailing_slash_style: TrailingSlash) -> Self {
        NormalizePath(trailing_slash_style)
    }
}

impl<S, B> Transform<S> for NormalizePath
where
    S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
{
    type Request = ServiceRequest;
    type Response = ServiceResponse<B>;
    type Error = Error;
    type InitError = ();
    type Transform = NormalizePathNormalization<S>;
    type Future = Ready<Result<Self::Transform, Self::InitError>>;

    fn new_transform(&self, service: S) -> Self::Future {
        ok(NormalizePathNormalization {
            service,
            merge_slash: Regex::new("//+").unwrap(),
            trailing_slash_behavior: self.0,
        })
    }
}

#[doc(hidden)]
pub struct NormalizePathNormalization<S> {
    service: S,
    merge_slash: Regex,
    trailing_slash_behavior: TrailingSlash,
}

impl<S, B> Service for NormalizePathNormalization<S>
where
    S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
{
    type Request = ServiceRequest;
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Future = S::Future;

    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.service.poll_ready(cx)
    }

    fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
        let head = req.head_mut();

        let original_path = head.uri.path();

        // Either adds a string to the end (duplicates will be removed anyways) or trims all slashes from the end
        let path = match self.trailing_slash_behavior {
            TrailingSlash::Always => original_path.to_string() + "/",
            TrailingSlash::MergeOnly => original_path.to_string(),
            TrailingSlash::Trim => original_path.trim_end_matches('/').to_string(),
        };

        // normalize multiple /'s to one /
        let path = self.merge_slash.replace_all(&path, "/");

        // Ensure root paths are still resolvable. If resulting path is blank after previous step
        // it means the path was one or more slashes. Reduce to single slash.
        let path = if path.is_empty() { "/" } else { path.as_ref() };

        // Check whether the path has been changed
        //
        // This check was previously implemented as string length comparison
        //
        // That approach fails when a trailing slash is added,
        // and a duplicate slash is removed,
        // since the length of the strings remains the same
        //
        // For example, the path "/v1//s" will be normalized to "/v1/s/"
        // Both of the paths have the same length,
        // so the change can not be deduced from the length comparison
        if path != original_path {
            let mut parts = head.uri.clone().into_parts();
            let query = parts.path_and_query.as_ref().and_then(|pq| pq.query());

            let path = if let Some(q) = query {
                Bytes::from(format!("{}?{}", path, q))
            } else {
                Bytes::copy_from_slice(path.as_bytes())
            };
            parts.path_and_query = Some(PathAndQuery::from_maybe_shared(path).unwrap());

            let uri = Uri::from_parts(parts).unwrap();
            req.match_info_mut().get_mut().update(&uri);
            req.head_mut().uri = uri;
        }

        self.service.call(req)
    }
}

#[cfg(test)]
mod tests {
    use actix_service::IntoService;

    use super::*;
    use crate::dev::ServiceRequest;
    use crate::test::{call_service, init_service, TestRequest};
    use crate::{web, App, HttpResponse};

    #[actix_rt::test]
    async fn test_wrap() {
        let mut app = init_service(
            App::new()
                .wrap(NormalizePath::default())
                .service(web::resource("/").to(HttpResponse::Ok))
                .service(web::resource("/v1/something/").to(HttpResponse::Ok)),
        )
        .await;

        let req = TestRequest::with_uri("/").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req = TestRequest::with_uri("/?query=test").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req = TestRequest::with_uri("///").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req = TestRequest::with_uri("/v1//something////").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req2 = TestRequest::with_uri("//v1/something").to_request();
        let res2 = call_service(&mut app, req2).await;
        assert!(res2.status().is_success());

        let req3 = TestRequest::with_uri("//v1//////something").to_request();
        let res3 = call_service(&mut app, req3).await;
        assert!(res3.status().is_success());

        let req4 = TestRequest::with_uri("/v1//something").to_request();
        let res4 = call_service(&mut app, req4).await;
        assert!(res4.status().is_success());
    }

    #[actix_rt::test]
    async fn trim_trailing_slashes() {
        let mut app = init_service(
            App::new()
                .wrap(NormalizePath(TrailingSlash::Trim))
                .service(web::resource("/").to(HttpResponse::Ok))
                .service(web::resource("/v1/something").to(HttpResponse::Ok)),
        )
        .await;

        // root paths should still work
        let req = TestRequest::with_uri("/").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req = TestRequest::with_uri("/?query=test").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req = TestRequest::with_uri("///").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req = TestRequest::with_uri("/v1/something////").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req2 = TestRequest::with_uri("/v1/something/").to_request();
        let res2 = call_service(&mut app, req2).await;
        assert!(res2.status().is_success());

        let req3 = TestRequest::with_uri("//v1//something//").to_request();
        let res3 = call_service(&mut app, req3).await;
        assert!(res3.status().is_success());

        let req4 = TestRequest::with_uri("//v1//something").to_request();
        let res4 = call_service(&mut app, req4).await;
        assert!(res4.status().is_success());
    }

    #[actix_rt::test]
    async fn keep_trailing_slash_unchange() {
        let mut app = init_service(
            App::new()
                .wrap(NormalizePath(TrailingSlash::MergeOnly))
                .service(web::resource("/").to(HttpResponse::Ok))
                .service(web::resource("/v1/something").to(HttpResponse::Ok))
                .service(web::resource("/v1/").to(HttpResponse::Ok)),
        )
        .await;

        let tests = vec![
            ("/", true), // root paths should still work
            ("/?query=test", true),
            ("///", true),
            ("/v1/something////", false),
            ("/v1/something/", false),
            ("//v1//something", true),
            ("/v1/", true),
            ("/v1", false),
            ("/v1////", true),
            ("//v1//", true),
            ("///v1", false),
        ];

        for (path, success) in tests {
            let req = TestRequest::with_uri(path).to_request();
            let res = call_service(&mut app, req).await;
            assert_eq!(res.status().is_success(), success);
        }
    }

    #[actix_rt::test]
    async fn test_in_place_normalization() {
        let srv = |req: ServiceRequest| {
            assert_eq!("/v1/something/", req.path());
            ok(req.into_response(HttpResponse::Ok().finish()))
        };

        let mut normalize = NormalizePath::default()
            .new_transform(srv.into_service())
            .await
            .unwrap();

        let req = TestRequest::with_uri("/v1//something////").to_srv_request();
        let res = normalize.call(req).await.unwrap();
        assert!(res.status().is_success());

        let req2 = TestRequest::with_uri("///v1/something").to_srv_request();
        let res2 = normalize.call(req2).await.unwrap();
        assert!(res2.status().is_success());

        let req3 = TestRequest::with_uri("//v1///something").to_srv_request();
        let res3 = normalize.call(req3).await.unwrap();
        assert!(res3.status().is_success());

        let req4 = TestRequest::with_uri("/v1//something").to_srv_request();
        let res4 = normalize.call(req4).await.unwrap();
        assert!(res4.status().is_success());
    }

    #[actix_rt::test]
    async fn should_normalize_nothing() {
        const URI: &str = "/v1/something/";

        let srv = |req: ServiceRequest| {
            assert_eq!(URI, req.path());
            ok(req.into_response(HttpResponse::Ok().finish()))
        };

        let mut normalize = NormalizePath::default()
            .new_transform(srv.into_service())
            .await
            .unwrap();

        let req = TestRequest::with_uri(URI).to_srv_request();
        let res = normalize.call(req).await.unwrap();
        assert!(res.status().is_success());
    }

    #[actix_rt::test]
    async fn should_normalize_notrail() {
        const URI: &str = "/v1/something";

        let srv = |req: ServiceRequest| {
            assert_eq!(URI.to_string() + "/", req.path());
            ok(req.into_response(HttpResponse::Ok().finish()))
        };

        let mut normalize = NormalizePath::default()
            .new_transform(srv.into_service())
            .await
            .unwrap();

        let req = TestRequest::with_uri(URI).to_srv_request();
        let res = normalize.call(req).await.unwrap();
        assert!(res.status().is_success());
    }
}
<commit_msg>improve NormalizePath docs (#1839)<commit_after>//! For middleware documentation, see [`NormalizePath`].

use std::task::{Context, Poll};

use actix_http::http::{PathAndQuery, Uri};
use actix_service::{Service, Transform};
use bytes::Bytes;
use futures_util::future::{ready, Ready};
use regex::Regex;

use crate::service::{ServiceRequest, ServiceResponse};
use crate::Error;

/// To be used when constructing `NormalizePath` to define it's behavior.
#[non_exhaustive]
#[derive(Clone, Copy)]
pub enum TrailingSlash {
    /// Always add a trailing slash to the end of the path.
    /// This will require all routes to end in a trailing slash for them to be accessible.
    Always,

    /// Only merge any present multiple trailing slashes.
    ///
    /// Note: This option provides the best compatibility with the v2 version of this middleware.
    MergeOnly,

    /// Trim trailing slashes from the end of the path.
    Trim,
}

impl Default for TrailingSlash {
    fn default() -> Self {
        TrailingSlash::Always
    }
}

#[derive(Default, Clone, Copy)]
/// Middleware to normalize a request's path so that routes can be matched less strictly.
///
/// # Normalization Steps
/// - Merges multiple consecutive slashes into one. (For example, `/path//one` always
///   becomes `/path/one`.)
/// - Appends a trailing slash if one is not present, removes one if present, or keeps trailing
///   slashes as-is, depending on which [`TrailingSlash`] variant is supplied
///   to [`new`](NormalizePath::new()).
///
/// # Default Behavior
/// The default constructor chooses to strip trailing slashes from the end
/// ([`TrailingSlash::Trim`]), the effect is that route definitions should be defined without
/// trailing slashes or else they will be inaccessible.
///
/// # Example
/// ```rust
/// use actix_web::{web, middleware, App};
///
/// # #[actix_rt::test]
/// # async fn normalize() {
/// let app = App::new()
///     .wrap(middleware::NormalizePath::default())
///     .route("/test", web::get().to(|| async { "test" }))
///     .route("/unmatchable/", web::get().to(|| async { "unmatchable" }));
///
/// use actix_web::http::StatusCode;
/// use actix_web::test::{call_service, init_service, TestRequest};
///
/// let mut app = init_service(app).await;
///
/// let req = TestRequest::with_uri("/test").to_request();
/// let res = call_service(&mut app, req).await;
/// assert_eq!(res.status(), StatusCode::OK);
///
/// let req = TestRequest::with_uri("/test/").to_request();
/// let res = call_service(&mut app, req).await;
/// assert_eq!(res.status(), StatusCode::OK);
///
/// let req = TestRequest::with_uri("/unmatchable").to_request();
/// let res = call_service(&mut app, req).await;
/// assert_eq!(res.status(), StatusCode::NOT_FOUND);
///
/// let req = TestRequest::with_uri("/unmatchable/").to_request();
/// let res = call_service(&mut app, req).await;
/// assert_eq!(res.status(), StatusCode::NOT_FOUND);
/// # }
/// ```
pub struct NormalizePath(TrailingSlash);

impl NormalizePath {
    /// Create new `NormalizePath` middleware with the specified trailing slash style.
    pub fn new(trailing_slash_style: TrailingSlash) -> Self {
        NormalizePath(trailing_slash_style)
    }
}

impl<S, B> Transform<S> for NormalizePath
where
    S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
{
    type Request = ServiceRequest;
    type Response = ServiceResponse<B>;
    type Error = Error;
    type InitError = ();
    type Transform = NormalizePathNormalization<S>;
    type Future = Ready<Result<Self::Transform, Self::InitError>>;

    fn new_transform(&self, service: S) -> Self::Future {
        ready(Ok(NormalizePathNormalization {
            service,
            merge_slash: Regex::new("//+").unwrap(),
            trailing_slash_behavior: self.0,
        }))
    }
}

#[doc(hidden)]
pub struct NormalizePathNormalization<S> {
    service: S,
    merge_slash: Regex,
    trailing_slash_behavior: TrailingSlash,
}

impl<S, B> Service for NormalizePathNormalization<S>
where
    S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
{
    type Request = ServiceRequest;
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Future = S::Future;

    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.service.poll_ready(cx)
    }

    fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
        let head = req.head_mut();

        let original_path = head.uri.path();

        // Either adds a string to the end (duplicates will be removed anyways) or trims all slashes from the end
        let path = match self.trailing_slash_behavior {
            TrailingSlash::Always => original_path.to_string() + "/",
            TrailingSlash::MergeOnly => original_path.to_string(),
            TrailingSlash::Trim => original_path.trim_end_matches('/').to_string(),
        };

        // normalize multiple /'s to one /
        let path = self.merge_slash.replace_all(&path, "/");

        // Ensure root paths are still resolvable. If resulting path is blank after previous step
        // it means the path was one or more slashes. Reduce to single slash.
        let path = if path.is_empty() { "/" } else { path.as_ref() };

        // Check whether the path has been changed
        //
        // This check was previously implemented as string length comparison
        //
        // That approach fails when a trailing slash is added,
        // and a duplicate slash is removed,
        // since the length of the strings remains the same
        //
        // For example, the path "/v1//s" will be normalized to "/v1/s/"
        // Both of the paths have the same length,
        // so the change can not be deduced from the length comparison
        if path != original_path {
            let mut parts = head.uri.clone().into_parts();
            let query = parts.path_and_query.as_ref().and_then(|pq| pq.query());

            let path = if let Some(q) = query {
                Bytes::from(format!("{}?{}", path, q))
            } else {
                Bytes::copy_from_slice(path.as_bytes())
            };
            parts.path_and_query = Some(PathAndQuery::from_maybe_shared(path).unwrap());

            let uri = Uri::from_parts(parts).unwrap();
            req.match_info_mut().get_mut().update(&uri);
            req.head_mut().uri = uri;
        }

        self.service.call(req)
    }
}

#[cfg(test)]
mod tests {
    use actix_service::IntoService;

    use super::*;
    use crate::{
        dev::ServiceRequest,
        test::{call_service, init_service, TestRequest},
        web, App, HttpResponse,
    };

    #[actix_rt::test]
    async fn test_wrap() {
        let mut app = init_service(
            App::new()
                .wrap(NormalizePath::default())
                .service(web::resource("/").to(HttpResponse::Ok))
                .service(web::resource("/v1/something/").to(HttpResponse::Ok)),
        )
        .await;

        let req = TestRequest::with_uri("/").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req = TestRequest::with_uri("/?query=test").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req = TestRequest::with_uri("///").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req = TestRequest::with_uri("/v1//something////").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req2 = TestRequest::with_uri("//v1/something").to_request();
        let res2 = call_service(&mut app, req2).await;
        assert!(res2.status().is_success());

        let req3 = TestRequest::with_uri("//v1//////something").to_request();
        let res3 = call_service(&mut app, req3).await;
        assert!(res3.status().is_success());

        let req4 = TestRequest::with_uri("/v1//something").to_request();
        let res4 = call_service(&mut app, req4).await;
        assert!(res4.status().is_success());
    }

    #[actix_rt::test]
    async fn trim_trailing_slashes() {
        let mut app = init_service(
            App::new()
                .wrap(NormalizePath(TrailingSlash::Trim))
                .service(web::resource("/").to(HttpResponse::Ok))
                .service(web::resource("/v1/something").to(HttpResponse::Ok)),
        )
        .await;

        // root paths should still work
        let req = TestRequest::with_uri("/").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req = TestRequest::with_uri("/?query=test").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req = TestRequest::with_uri("///").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req = TestRequest::with_uri("/v1/something////").to_request();
        let res = call_service(&mut app, req).await;
        assert!(res.status().is_success());

        let req2 = TestRequest::with_uri("/v1/something/").to_request();
        let res2 = call_service(&mut app, req2).await;
        assert!(res2.status().is_success());

        let req3 = TestRequest::with_uri("//v1//something//").to_request();
        let res3 = call_service(&mut app, req3).await;
        assert!(res3.status().is_success());

        let req4 = TestRequest::with_uri("//v1//something").to_request();
        let res4 = call_service(&mut app, req4).await;
        assert!(res4.status().is_success());
    }

    #[actix_rt::test]
    async fn keep_trailing_slash_unchanged() {
        let mut app = init_service(
            App::new()
                .wrap(NormalizePath(TrailingSlash::MergeOnly))
                .service(web::resource("/").to(HttpResponse::Ok))
                .service(web::resource("/v1/something").to(HttpResponse::Ok))
                .service(web::resource("/v1/").to(HttpResponse::Ok)),
        )
        .await;

        let tests = vec![
            ("/", true), // root paths should still work
            ("/?query=test", true),
            ("///", true),
            ("/v1/something////", false),
            ("/v1/something/", false),
            ("//v1//something", true),
            ("/v1/", true),
            ("/v1", false),
            ("/v1////", true),
            ("//v1//", true),
            ("///v1", false),
        ];

        for (path, success) in tests {
            let req = TestRequest::with_uri(path).to_request();
            let res = call_service(&mut app, req).await;
            assert_eq!(res.status().is_success(), success);
        }
    }

    #[actix_rt::test]
    async fn test_in_place_normalization() {
        let srv = |req: ServiceRequest| {
            assert_eq!("/v1/something/", req.path());
            ready(Ok(req.into_response(HttpResponse::Ok().finish())))
        };

        let mut normalize = NormalizePath::default()
            .new_transform(srv.into_service())
            .await
            .unwrap();

        let req = TestRequest::with_uri("/v1//something////").to_srv_request();
        let res = normalize.call(req).await.unwrap();
        assert!(res.status().is_success());

        let req2 = TestRequest::with_uri("///v1/something").to_srv_request();
        let res2 = normalize.call(req2).await.unwrap();
        assert!(res2.status().is_success());

        let req3 = TestRequest::with_uri("//v1///something").to_srv_request();
        let res3 = normalize.call(req3).await.unwrap();
        assert!(res3.status().is_success());

        let req4 = TestRequest::with_uri("/v1//something").to_srv_request();
        let res4 = normalize.call(req4).await.unwrap();
        assert!(res4.status().is_success());
    }

    #[actix_rt::test]
    async fn should_normalize_nothing() {
        const URI: &str = "/v1/something/";

        let srv = |req: ServiceRequest| {
            assert_eq!(URI, req.path());
            ready(Ok(req.into_response(HttpResponse::Ok().finish())))
        };

        let mut normalize = NormalizePath::default()
            .new_transform(srv.into_service())
            .await
            .unwrap();

        let req = TestRequest::with_uri(URI).to_srv_request();
        let res = normalize.call(req).await.unwrap();
        assert!(res.status().is_success());
    }

    #[actix_rt::test]
    async fn should_normalize_no_trail() {
        const URI: &str = "/v1/something";

        let srv = |req: ServiceRequest| {
            assert_eq!(URI.to_string() + "/", req.path());
            ready(Ok(req.into_response(HttpResponse::Ok().finish())))
        };

        let mut normalize = NormalizePath::default()
            .new_transform(srv.into_service())
            .await
            .unwrap();

        let req = TestRequest::with_uri(URI).to_srv_request();
        let res = normalize.call(req).await.unwrap();
        assert!(res.status().is_success());
    }
}
<|endoftext|>


<commit_before><commit_msg>Tweak to Datum head function<commit_after><|endoftext|>


<commit_before><commit_msg>Exploratory logging.<commit_after><|endoftext|>


<commit_before>use std::cmp;
use std::ops::DerefMut;
use rand::Rng;
use ecs::*;
use game::*;
use game::data::*;
use game::terrain::util;
use coord::Coord;
use grid::*;
use perlin::*;
use math::*;
use direction::*;

const MAP_WIDTH_MAX: usize = 21;
const MAP_WIDTH_MIN: usize = 20;
const MAP_HEIGHT: usize = 30;
const ROAD_HEIGHT: usize = 6;
const ROAD_TOP: usize = (MAP_HEIGHT + ROAD_HEIGHT) / 2;
const ROAD_BOTTOM: usize = ROAD_TOP - ROAD_HEIGHT;
const START_COORD: Coord = Coord { x: 0, y: MAP_HEIGHT as isize / 2 };

const PERLIN_ZOOM: usize = 5;
const PERLIN_ZOOM_F: f64 = PERLIN_ZOOM as f64;
const PERLIN_MIN: f64 = 0.2;
const PERLIN_MAX: f64 = 0.5;

#[derive(Clone, Copy, PartialEq, Eq)]
enum EntityType {
    Dirt,
    Road,
    Acid,
    Goal,
    Wreck,
    Barrel,
    Letter,
    Zombie,
    Car,
    Bike,
}

const RANDOM_ENTITY_TYPES: [EntityType; 6] = [
    EntityType::Wreck,
    EntityType::Barrel,
    EntityType::Letter,
    EntityType::Zombie,
    EntityType::Car,
    EntityType::Bike,
];
const RANDOM_ENTITY_DIRT_WEIGHTS: [usize; 6] = [5, 10, 2, 40, 0, 0];
const RANDOM_ENTITY_ROAD_WEIGHTS: [usize; 6] = [10, 10, 4, 5, 0, 0];
const RANDOM_ENTITY_TOTAL: usize = 1000;

fn choose_random_entity<R: Rng>(types: &[EntityType], weights: &[usize], total: usize, rng: &mut R) -> Option<EntityType> {
    let mut roll = rng.gen::<usize>() % total;
    for (weight, entity_type) in izip!(weights.iter(), types.iter()) {
        if roll < *weight {
            return Some(*entity_type);
        }
        roll -= *weight;
    }

    None
}

pub fn road<S: TurnScheduleQueue>(ids: &EntityIdReserver,
                                  rng: &GameRng,
                                  schedule: &mut S,
                                  g: &mut EcsAction,
                                  difficulty: usize) -> TerrainMetadata {

    let map_width = rng.gen_usize() % (MAP_WIDTH_MAX - MAP_WIDTH_MIN) + MAP_WIDTH_MIN;
    let mut grid: StaticGrid<Vec<EntityType>> = StaticGrid::new_default(map_width, MAP_HEIGHT);

    let perlin = PerlinGrid::new(map_width / PERLIN_ZOOM, MAP_HEIGHT / PERLIN_ZOOM,
                                 PerlinWrapType::Repeat, rng.inner_mut().deref_mut());

    let random_entity_dirt_weights = [
        5, /* Wreck */
        10, /* Barrrel */
        3, /* Letter */
        20 + cmp::min(difficulty * 10, 60), /* Zombie */
        cmp::min(difficulty / 4, 4), /* Car */
        1 + cmp::min(difficulty / 2, 8), /* Bike */
    ];

    let random_entity_road_weights = [
        5, /* Wreck */
        10, /* Barrrel */
        3, /* Letter */
        10 + cmp::min(difficulty * 5, 30), /* Zombie */
        1 + cmp::min(difficulty / 3, 6), /* Car */
        cmp::min(difficulty / 3, 6), /* Bike */
    ];

    for (coord, cell_mut) in izip!(grid.coord_iter(), grid.iter_mut()) {

        let mut acid = false;
        let perlin_coord = Vector2::new(coord.x as f64 / PERLIN_ZOOM_F, coord.y as f64 / PERLIN_ZOOM_F);
        if let Some(noise) = perlin.noise(perlin_coord.x, perlin_coord.y) {
            if noise > PERLIN_MIN && noise <= PERLIN_MAX {
                acid = true;
            }
        }

        if acid {
            cell_mut.push(EntityType::Acid);
        } else if coord.y > ROAD_BOTTOM as isize && coord.y <= ROAD_TOP as isize {
            cell_mut.push(EntityType::Road);
            if let Some(entity_type) = choose_random_entity(&RANDOM_ENTITY_TYPES,
                                                            &random_entity_road_weights,
                                                            RANDOM_ENTITY_TOTAL,
                                                            rng.inner_mut().deref_mut()) {
                cell_mut.push(entity_type);
            }
        } else {
            cell_mut.push(EntityType::Dirt);
            if let Some(entity_type) = choose_random_entity(&RANDOM_ENTITY_TYPES,
                                                            &random_entity_dirt_weights,
                                                            RANDOM_ENTITY_TOTAL,
                                                            rng.inner_mut().deref_mut()) {
                cell_mut.push(entity_type);
            }
        }

        if coord.x == map_width as isize - 1 {
            cell_mut.push(EntityType::Goal);
        }
    }

    for (coord, cell) in izip!(grid.coord_iter(), grid.iter()) {
        for entity_type in cell.iter() {
            match *entity_type {
                EntityType::Dirt => {
                    prototypes::dirt(g.entity_mut(ids.new_id()), coord, rng);
                }
                EntityType::Road => {
                    prototypes::road(g.entity_mut(ids.new_id()), coord, rng);
                }
                EntityType::Acid => {
                    prototypes::acid(g.entity_mut(ids.new_id()), coord, rng);
                }
                EntityType::Goal => {
                    prototypes::goal(g.entity_mut(ids.new_id()), coord, LevelSwitch::LeaveLevel);
                }
                EntityType::Wreck => {
                    prototypes::wreck(g.entity_mut(ids.new_id()), coord, rng);
                }
                EntityType::Barrel => {
                    prototypes::barrel(g.entity_mut(ids.new_id()), coord);
                }
                EntityType::Letter => {
                    prototypes::letter(g.entity_mut(ids.new_id()), coord);
                }
                EntityType::Zombie => {
                    prototypes::dirt(g.entity_mut(ids.new_id()), coord, rng);
                    let id = ids.new_id();
                    prototypes::zombie(g.entity_mut(id), coord);
                    let turn_offset = g.turn_offset(id).expect("Expected component turn_offset");
                    let ticket = schedule.schedule_turn(id, turn_offset);
                    g.insert_schedule_ticket(id, ticket);
                }
                EntityType::Car => {
                    prototypes::dirt(g.entity_mut(ids.new_id()), coord, rng);
                    let id = ids.new_id();
                    prototypes::car(g.entity_mut(id), coord);
                    let turn_offset = g.turn_offset(id).expect("Expected component turn_offset");
                    let ticket = schedule.schedule_turn(id, turn_offset);
                    g.insert_schedule_ticket(id, ticket);

                    let gun_id = ids.new_id();
                    prototypes::shotgun(g.entity_mut(gun_id));
                    g.weapon_slots_mut(id).unwrap().insert(Direction::North, gun_id);
                    g.weapon_slots_mut(id).unwrap().insert(Direction::South, gun_id);
                }
                EntityType::Bike => {
                    prototypes::dirt(g.entity_mut(ids.new_id()), coord, rng);
                    let id = ids.new_id();
                    prototypes::bike(g.entity_mut(id), coord);
                    let turn_offset = g.turn_offset(id).expect("Expected component turn_offset");
                    let ticket = schedule.schedule_turn(id, turn_offset);
                    g.insert_schedule_ticket(id, ticket);

                    let gun_id = ids.new_id();
                    prototypes::pistol(g.entity_mut(gun_id));
                    g.weapon_slots_mut(id).unwrap().insert(Direction::North, gun_id);
                    g.weapon_slots_mut(id).unwrap().insert(Direction::South, gun_id);
                    g.weapon_slots_mut(id).unwrap().insert(Direction::East, gun_id);
                    g.weapon_slots_mut(id).unwrap().insert(Direction::West, gun_id);
                }
            }
        }
    }

    util::add_management_entities(ids, schedule, g);

    TerrainMetadata {
        width: map_width,
        height: MAP_HEIGHT,
        start_coord: START_COORD,
        connection_report: LevelConnectionReport::new(),
    }
}
<commit_msg>Removed debugging level size<commit_after>use std::cmp;
use std::ops::DerefMut;
use rand::Rng;
use ecs::*;
use game::*;
use game::data::*;
use game::terrain::util;
use coord::Coord;
use grid::*;
use perlin::*;
use math::*;
use direction::*;

const MAP_WIDTH_MAX: usize = 120;
const MAP_WIDTH_MIN: usize = 60;
const MAP_HEIGHT: usize = 30;
const ROAD_HEIGHT: usize = 6;
const ROAD_TOP: usize = (MAP_HEIGHT + ROAD_HEIGHT) / 2;
const ROAD_BOTTOM: usize = ROAD_TOP - ROAD_HEIGHT;
const START_COORD: Coord = Coord { x: 0, y: MAP_HEIGHT as isize / 2 };

const PERLIN_ZOOM: usize = 5;
const PERLIN_ZOOM_F: f64 = PERLIN_ZOOM as f64;
const PERLIN_MIN: f64 = 0.2;
const PERLIN_MAX: f64 = 0.5;

#[derive(Clone, Copy, PartialEq, Eq)]
enum EntityType {
    Dirt,
    Road,
    Acid,
    Goal,
    Wreck,
    Barrel,
    Letter,
    Zombie,
    Car,
    Bike,
}

const RANDOM_ENTITY_TYPES: [EntityType; 6] = [
    EntityType::Wreck,
    EntityType::Barrel,
    EntityType::Letter,
    EntityType::Zombie,
    EntityType::Car,
    EntityType::Bike,
];
const RANDOM_ENTITY_DIRT_WEIGHTS: [usize; 6] = [5, 10, 2, 40, 0, 0];
const RANDOM_ENTITY_ROAD_WEIGHTS: [usize; 6] = [10, 10, 4, 5, 0, 0];
const RANDOM_ENTITY_TOTAL: usize = 1000;

fn choose_random_entity<R: Rng>(types: &[EntityType], weights: &[usize], total: usize, rng: &mut R) -> Option<EntityType> {
    let mut roll = rng.gen::<usize>() % total;
    for (weight, entity_type) in izip!(weights.iter(), types.iter()) {
        if roll < *weight {
            return Some(*entity_type);
        }
        roll -= *weight;
    }

    None
}

pub fn road<S: TurnScheduleQueue>(ids: &EntityIdReserver,
                                  rng: &GameRng,
                                  schedule: &mut S,
                                  g: &mut EcsAction,
                                  difficulty: usize) -> TerrainMetadata {

    let map_width = rng.gen_usize() % (MAP_WIDTH_MAX - MAP_WIDTH_MIN) + MAP_WIDTH_MIN;
    let mut grid: StaticGrid<Vec<EntityType>> = StaticGrid::new_default(map_width, MAP_HEIGHT);

    let perlin = PerlinGrid::new(map_width / PERLIN_ZOOM, MAP_HEIGHT / PERLIN_ZOOM,
                                 PerlinWrapType::Repeat, rng.inner_mut().deref_mut());

    let random_entity_dirt_weights = [
        5, /* Wreck */
        10, /* Barrrel */
        3, /* Letter */
        20 + cmp::min(difficulty * 10, 60), /* Zombie */
        cmp::min(difficulty / 4, 4), /* Car */
        1 + cmp::min(difficulty / 2, 8), /* Bike */
    ];

    let random_entity_road_weights = [
        5, /* Wreck */
        10, /* Barrrel */
        3, /* Letter */
        10 + cmp::min(difficulty * 5, 30), /* Zombie */
        1 + cmp::min(difficulty / 3, 6), /* Car */
        cmp::min(difficulty / 3, 6), /* Bike */
    ];

    for (coord, cell_mut) in izip!(grid.coord_iter(), grid.iter_mut()) {

        let mut acid = false;
        let perlin_coord = Vector2::new(coord.x as f64 / PERLIN_ZOOM_F, coord.y as f64 / PERLIN_ZOOM_F);
        if let Some(noise) = perlin.noise(perlin_coord.x, perlin_coord.y) {
            if noise > PERLIN_MIN && noise <= PERLIN_MAX {
                acid = true;
            }
        }

        if acid {
            cell_mut.push(EntityType::Acid);
        } else if coord.y > ROAD_BOTTOM as isize && coord.y <= ROAD_TOP as isize {
            cell_mut.push(EntityType::Road);
            if let Some(entity_type) = choose_random_entity(&RANDOM_ENTITY_TYPES,
                                                            &random_entity_road_weights,
                                                            RANDOM_ENTITY_TOTAL,
                                                            rng.inner_mut().deref_mut()) {
                cell_mut.push(entity_type);
            }
        } else {
            cell_mut.push(EntityType::Dirt);
            if let Some(entity_type) = choose_random_entity(&RANDOM_ENTITY_TYPES,
                                                            &random_entity_dirt_weights,
                                                            RANDOM_ENTITY_TOTAL,
                                                            rng.inner_mut().deref_mut()) {
                cell_mut.push(entity_type);
            }
        }

        if coord.x == map_width as isize - 1 {
            cell_mut.push(EntityType::Goal);
        }
    }

    for (coord, cell) in izip!(grid.coord_iter(), grid.iter()) {
        for entity_type in cell.iter() {
            match *entity_type {
                EntityType::Dirt => {
                    prototypes::dirt(g.entity_mut(ids.new_id()), coord, rng);
                }
                EntityType::Road => {
                    prototypes::road(g.entity_mut(ids.new_id()), coord, rng);
                }
                EntityType::Acid => {
                    prototypes::acid(g.entity_mut(ids.new_id()), coord, rng);
                }
                EntityType::Goal => {
                    prototypes::goal(g.entity_mut(ids.new_id()), coord, LevelSwitch::LeaveLevel);
                }
                EntityType::Wreck => {
                    prototypes::wreck(g.entity_mut(ids.new_id()), coord, rng);
                }
                EntityType::Barrel => {
                    prototypes::barrel(g.entity_mut(ids.new_id()), coord);
                }
                EntityType::Letter => {
                    prototypes::letter(g.entity_mut(ids.new_id()), coord);
                }
                EntityType::Zombie => {
                    prototypes::dirt(g.entity_mut(ids.new_id()), coord, rng);
                    let id = ids.new_id();
                    prototypes::zombie(g.entity_mut(id), coord);
                    let turn_offset = g.turn_offset(id).expect("Expected component turn_offset");
                    let ticket = schedule.schedule_turn(id, turn_offset);
                    g.insert_schedule_ticket(id, ticket);
                }
                EntityType::Car => {
                    prototypes::dirt(g.entity_mut(ids.new_id()), coord, rng);
                    let id = ids.new_id();
                    prototypes::car(g.entity_mut(id), coord);
                    let turn_offset = g.turn_offset(id).expect("Expected component turn_offset");
                    let ticket = schedule.schedule_turn(id, turn_offset);
                    g.insert_schedule_ticket(id, ticket);

                    let gun_id = ids.new_id();
                    prototypes::shotgun(g.entity_mut(gun_id));
                    g.weapon_slots_mut(id).unwrap().insert(Direction::North, gun_id);
                    g.weapon_slots_mut(id).unwrap().insert(Direction::South, gun_id);
                }
                EntityType::Bike => {
                    prototypes::dirt(g.entity_mut(ids.new_id()), coord, rng);
                    let id = ids.new_id();
                    prototypes::bike(g.entity_mut(id), coord);
                    let turn_offset = g.turn_offset(id).expect("Expected component turn_offset");
                    let ticket = schedule.schedule_turn(id, turn_offset);
                    g.insert_schedule_ticket(id, ticket);

                    let gun_id = ids.new_id();
                    prototypes::pistol(g.entity_mut(gun_id));
                    g.weapon_slots_mut(id).unwrap().insert(Direction::North, gun_id);
                    g.weapon_slots_mut(id).unwrap().insert(Direction::South, gun_id);
                    g.weapon_slots_mut(id).unwrap().insert(Direction::East, gun_id);
                    g.weapon_slots_mut(id).unwrap().insert(Direction::West, gun_id);
                }
            }
        }
    }

    util::add_management_entities(ids, schedule, g);

    TerrainMetadata {
        width: map_width,
        height: MAP_HEIGHT,
        start_coord: START_COORD,
        connection_report: LevelConnectionReport::new(),
    }
}
<|endoftext|>


<commit_before>
use num::*;
use std::fmt;
use std::ops::*;

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Vec2<T: Num + Copy> {
    pub x: T,
    pub y: T
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Vec3<T: Num + Copy> {
    pub x: T,
    pub y: T,
    pub z: T
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Vec4<T: Num + Copy> {
    pub x: T,
    pub y: T,
    pub z: T,
    pub w: T
}

// General functions
impl<T: Num + Copy> Vec2<T> {
    /// Creates a new vector with the given components
    pub fn new(x: T, y: T) -> Vec2<T> { Vec2 { x: x, y: y } }
    /// Creates a new vector with all components set to 0
    pub fn zero() -> Vec2<T> { Vec2 { x: T::zero(), y: T::zero() } }

    /// Calculates the length of this vector, raised to the power of two.
    /// Note that this is cheaper than computing the actual length, as it
    /// does not require a `sqrt()`
    pub fn len_sqr(&self) -> T {
        self.x*self.x + self.y*self.y
    }

    pub fn dot(a: Vec2<T>, b: Vec2<T>) -> T {
        a.x*b.x + a.y*b.y
    }
}
impl<T: Num + Copy> Vec3<T> {
    /// Creates a new vector with the given components
    pub fn new(x: T, y: T, z: T) -> Vec3<T> { Vec3 { x: x, y: y, z: z } }
    /// Creates a new vector with all components set to 0
    pub fn zero() -> Vec3<T> { Vec3 { x: T::zero(), y: T::zero(), z: T::zero() } }

    /// Calculates the length of this vector, raised to the power of two.
    /// Note that this is cheaper than computing the actual length, as it
    /// does not require a `sqrt()`
    pub fn len_sqr(&self) -> T {
        self.x*self.x + self.y*self.y + self.z*self.z
    }

    pub fn dot(a: Vec3<T>, b: Vec3<T>) -> T {
        a.x*b.x + a.y*b.y + a.z*b.z
    }
}
impl<T: Num + Copy> Vec4<T> {
    /// Creates a new vector with the given components
    pub fn new(x: T, y: T, z: T, w: T) -> Vec4<T> { Vec4 { x: x, y: y, z: z, w: w } }
    /// Creates a new vector with all components set to 0
    pub fn zero() -> Vec4<T> { Vec4 { x: T::zero(), y: T::zero(), z: T::zero(), w: T::zero() } }

    /// Calculates the length of this vector, raised to the power of two.
    /// Note that this is cheaper than computing the actual length, as it
    /// does not require a `sqrt()`
    pub fn len_sqr(&self) -> T {
        self.x*self.x + self.y*self.y + self.z*self.z + self.w*self.w
    }

    pub fn dot(a: Vec4<T>, b: Vec4<T>) -> T {
        a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w
    }
}

impl<T: Float> Vec2<T> {
    /// Calculates the length of this vector
    pub fn len(&self) -> T {
        (self.x*self.x + self.y*self.y).sqrt()
    }
}
impl<T: Float> Vec3<T> {
    /// Calculates the length of this vector
    pub fn len(&self) -> T {
        (self.x*self.x + self.y*self.y + self.z*self.z).sqrt()
    }
}
impl<T: Float> Vec4<T> {
    /// Calculates the length of this vector
    pub fn len(&self) -> T {
        (self.x*self.x + self.y*self.y + self.z*self.z + self.w*self.w).sqrt()
    }
}

// Addition and subtraction
impl<T: Num + Copy> Add for Vec2<T> {
    type Output = Self;
    fn add(self, other: Self) -> Self { Vec2::new(self.x + other.x, self.y + other.y) }
}
impl<T: Num + Copy> Add for Vec3<T> {
    type Output = Self;
    fn add(self, other: Self) -> Vec3<T> { Vec3::new(self.x + other.x, self.y + other.y, self.z + other.z) }
}
impl<T: Num + Copy> Add for Vec4<T> {
    type Output = Self;
    fn add(self, other: Self) -> Self { Vec4::new(self.x + other.x, self.y + other.y, self.z + other.z, self.w + other.w) }
}
impl<T: Num + Copy> Sub for Vec2<T> {
    type Output = Self;
    fn sub(self, other: Self) -> Self { Vec2::new(self.x - other.x, self.y - other.y) }
}
impl<T: Num + Copy> Sub for Vec3<T> {
    type Output = Self;
    fn sub(self, other: Self) -> Self { Vec3::new(self.x - other.x, self.y - other.y, self.z - other.z) }
}
impl<T: Num + Copy> Sub for Vec4<T> {
    type Output = Self;
    fn sub(self, other: Self) -> Self { Vec4::new(self.x - other.x, self.y - other.y, self.z - other.z, self.w - other.w) }
}

impl<T: Num + Copy> AddAssign for Vec2<T> {
    fn add_assign(&mut self, other: Self) {
        self.x = self.x + other.x;
        self.y = self.y + other.y;
    }
}
impl<T: Num + Copy> AddAssign for Vec3<T> {
    fn add_assign(&mut self, other: Self) {
        self.x = self.x + other.x;
        self.y = self.y + other.y;
        self.z = self.z + other.z;
    }
}
impl<T: Num + Copy> AddAssign for Vec4<T> {
    fn add_assign(&mut self, other: Self) {
        self.x = self.x + other.x;
        self.y = self.y + other.y;
        self.z = self.z + other.z;
        self.w = self.w + other.w;
    }
}
impl<T: Num + Copy> SubAssign for Vec2<T> {
    fn sub_assign(&mut self, other: Self) {
        self.x = self.x - other.x;
        self.y = self.y - other.y;
    }
}
impl<T: Num + Copy> SubAssign for Vec3<T> {
    fn sub_assign(&mut self, other: Self) {
        self.x = self.x - other.x;
        self.y = self.y - other.y;
        self.z = self.z - other.z;
    }
}
impl<T: Num + Copy> SubAssign for Vec4<T> {
    fn sub_assign(&mut self, other: Self) {
        self.x = self.x - other.x;
        self.y = self.y - other.y;
        self.z = self.z - other.z;
        self.w = self.w - other.w;
    }
}

// Printing
impl<T: fmt::Display + Num + Copy> fmt::Display for Vec2<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}
impl<T: fmt::Display + Num + Copy> fmt::Display for Vec3<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {}, {})", self.x, self.y, self.z)
    }
}
impl<T: fmt::Display + Num + Copy> fmt::Display for Vec4<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {}, {}, {})", self.x, self.y, self.z, self.w)
    }
}

<commit_msg>Added basic vector tests<commit_after>
use num::*;
use std::fmt;
use std::ops::*;

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Vec2<T: Num + Copy> {
    pub x: T,
    pub y: T
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Vec3<T: Num + Copy> {
    pub x: T,
    pub y: T,
    pub z: T
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Vec4<T: Num + Copy> {
    pub x: T,
    pub y: T,
    pub z: T,
    pub w: T
}

// General functions
impl<T: Num + Copy> Vec2<T> {
    /// Creates a new vector with the given components
    pub fn new(x: T, y: T) -> Vec2<T> { Vec2 { x: x, y: y } }
    /// Creates a new vector with all components set to 0
    pub fn zero() -> Vec2<T> { Vec2 { x: T::zero(), y: T::zero() } }

    /// Calculates the length of this vector, raised to the power of two.
    /// Note that this is cheaper than computing the actual length, as it
    /// does not require a `sqrt()`
    pub fn len_sqr(&self) -> T {
        self.x*self.x + self.y*self.y
    }

    pub fn dot(a: Vec2<T>, b: Vec2<T>) -> T {
        a.x*b.x + a.y*b.y
    }
}
impl<T: Num + Copy> Vec3<T> {
    /// Creates a new vector with the given components
    pub fn new(x: T, y: T, z: T) -> Vec3<T> { Vec3 { x: x, y: y, z: z } }
    /// Creates a new vector with all components set to 0
    pub fn zero() -> Vec3<T> { Vec3 { x: T::zero(), y: T::zero(), z: T::zero() } }

    /// Calculates the length of this vector, raised to the power of two.
    /// Note that this is cheaper than computing the actual length, as it
    /// does not require a `sqrt()`
    pub fn len_sqr(&self) -> T {
        self.x*self.x + self.y*self.y + self.z*self.z
    }

    pub fn dot(a: Vec3<T>, b: Vec3<T>) -> T {
        a.x*b.x + a.y*b.y + a.z*b.z
    }
}
impl<T: Num + Copy> Vec4<T> {
    /// Creates a new vector with the given components
    pub fn new(x: T, y: T, z: T, w: T) -> Vec4<T> { Vec4 { x: x, y: y, z: z, w: w } }
    /// Creates a new vector with all components set to 0
    pub fn zero() -> Vec4<T> { Vec4 { x: T::zero(), y: T::zero(), z: T::zero(), w: T::zero() } }

    /// Calculates the length of this vector, raised to the power of two.
    /// Note that this is cheaper than computing the actual length, as it
    /// does not require a `sqrt()`
    pub fn len_sqr(&self) -> T {
        self.x*self.x + self.y*self.y + self.z*self.z + self.w*self.w
    }

    pub fn dot(a: Vec4<T>, b: Vec4<T>) -> T {
        a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w
    }
}

impl<T: Float> Vec2<T> {
    /// Calculates the length of this vector
    pub fn len(&self) -> T {
        (self.x*self.x + self.y*self.y).sqrt()
    }
}
impl<T: Float> Vec3<T> {
    /// Calculates the length of this vector
    pub fn len(&self) -> T {
        (self.x*self.x + self.y*self.y + self.z*self.z).sqrt()
    }
}
impl<T: Float> Vec4<T> {
    /// Calculates the length of this vector
    pub fn len(&self) -> T {
        (self.x*self.x + self.y*self.y + self.z*self.z + self.w*self.w).sqrt()
    }
}

// Addition and subtraction
impl<T: Num + Copy> Add for Vec2<T> {
    type Output = Self;
    fn add(self, other: Self) -> Self { Vec2::new(self.x + other.x, self.y + other.y) }
}
impl<T: Num + Copy> Add for Vec3<T> {
    type Output = Self;
    fn add(self, other: Self) -> Vec3<T> { Vec3::new(self.x + other.x, self.y + other.y, self.z + other.z) }
}
impl<T: Num + Copy> Add for Vec4<T> {
    type Output = Self;
    fn add(self, other: Self) -> Self { Vec4::new(self.x + other.x, self.y + other.y, self.z + other.z, self.w + other.w) }
}
impl<T: Num + Copy> Sub for Vec2<T> {
    type Output = Self;
    fn sub(self, other: Self) -> Self { Vec2::new(self.x - other.x, self.y - other.y) }
}
impl<T: Num + Copy> Sub for Vec3<T> {
    type Output = Self;
    fn sub(self, other: Self) -> Self { Vec3::new(self.x - other.x, self.y - other.y, self.z - other.z) }
}
impl<T: Num + Copy> Sub for Vec4<T> {
    type Output = Self;
    fn sub(self, other: Self) -> Self { Vec4::new(self.x - other.x, self.y - other.y, self.z - other.z, self.w - other.w) }
}

impl<T: Num + Copy> AddAssign for Vec2<T> {
    fn add_assign(&mut self, other: Self) {
        self.x = self.x + other.x;
        self.y = self.y + other.y;
    }
}
impl<T: Num + Copy> AddAssign for Vec3<T> {
    fn add_assign(&mut self, other: Self) {
        self.x = self.x + other.x;
        self.y = self.y + other.y;
        self.z = self.z + other.z;
    }
}
impl<T: Num + Copy> AddAssign for Vec4<T> {
    fn add_assign(&mut self, other: Self) {
        self.x = self.x + other.x;
        self.y = self.y + other.y;
        self.z = self.z + other.z;
        self.w = self.w + other.w;
    }
}
impl<T: Num + Copy> SubAssign for Vec2<T> {
    fn sub_assign(&mut self, other: Self) {
        self.x = self.x - other.x;
        self.y = self.y - other.y;
    }
}
impl<T: Num + Copy> SubAssign for Vec3<T> {
    fn sub_assign(&mut self, other: Self) {
        self.x = self.x - other.x;
        self.y = self.y - other.y;
        self.z = self.z - other.z;
    }
}
impl<T: Num + Copy> SubAssign for Vec4<T> {
    fn sub_assign(&mut self, other: Self) {
        self.x = self.x - other.x;
        self.y = self.y - other.y;
        self.z = self.z - other.z;
        self.w = self.w - other.w;
    }
}

// Printing
impl<T: fmt::Display + Num + Copy> fmt::Display for Vec2<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}
impl<T: fmt::Display + Num + Copy> fmt::Display for Vec3<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {}, {})", self.x, self.y, self.z)
    }
}
impl<T: fmt::Display + Num + Copy> fmt::Display for Vec4<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {}, {}, {})", self.x, self.y, self.z, self.w)
    }
}

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

    #[test]
    fn addition() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(4, -3);

        assert_eq!(a, a + Vec2::zero());
        assert_eq!(b, b + Vec2::zero());

        assert_eq!(Vec2::new(5, -1), a + b);

        let mut c = a;
        c += Vec2::new(1, 1);
        assert_eq!(Vec2::new(2, 3), c);

        c += c;
        assert_eq!(Vec2::new(4, 6), c);
    }

    #[test]
    fn subtraction() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(4, -3);

        assert_eq!(a, a - Vec2::zero());
        assert_eq!(b, b - Vec2::zero());

        assert_eq!(Vec2::new(-3, 5), a - b);

        let mut c = a;
        c -= Vec2::new(2, 1);
        assert_eq!(Vec2::new(-1, 1), c);

        c -= c;
        assert_eq!(Vec2::new(0, 0), c);
    }

    #[test]
    fn len() {
        assert_eq!(0.0, Vec2::<f32>::zero().len());

        let a = Vec2::new(4, 4);
        let b = Vec2::new(4.0, -3.0);

        assert_eq!(32, a.len_sqr());
        assert_eq!(5.0, b.len());
    }

    #[test]
    fn dot() {
        assert_eq!(0.0, Vec2::dot(Vec2::zero(), Vec2::zero()));
        assert_eq!(0.0, Vec3::dot(Vec3::zero(), Vec3::zero()));
        assert_eq!(0.0, Vec4::dot(Vec4::zero(), Vec4::zero()));

        let a = Vec3::new(0.0, 1.0, 1.0);
        let b = Vec3::new(1.0, 0.0, 0.0);
        assert_eq!(0.0, Vec3::dot(a, b));

        assert_eq!(14, Vec4::dot(Vec4::new(1, 3, 2, 5), Vec4::new(-1, 3, -2, 2)));
    }
}

<|endoftext|>


<commit_before>use crate::mem;
use crate::slice;

pub fn hashmap_random_keys() -> (u64, u64) {
    let mut v = (0, 0);
    unsafe {
        let view = slice::from_raw_parts_mut(&mut v as *mut _ as *mut u8,
                                             mem::size_of_val(&v));
        imp::fill_bytes(view);
    }
    return v
}

mod imp {
    use libc;
    use crate::io;

    extern "C" {
        fn randBytes (randBuf: *mut libc::c_uchar,
                      numOfBytes: libc::c_int) -> libc::c_int;
    }

    pub fn fill_bytes(v: &mut [u8]) {
        let ret = unsafe {
            randBytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int)
        };
        if ret == -1 {
            panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
        }
    }
}
<commit_msg>use randSecure and randABytes<commit_after>use crate::mem;
use crate::slice;

pub fn hashmap_random_keys() -> (u64, u64) {
    let mut v = (0, 0);
    unsafe {
        let view = slice::from_raw_parts_mut(&mut v as *mut _ as *mut u8,
                                             mem::size_of_val(&v));
        imp::fill_bytes(view);
    }
    return v
}

mod imp {
    use libc;
    use crate::io;
    use core::sync::atomic::{AtomicBool, Ordering::Relaxed};

    pub fn fill_bytes(v: &mut [u8]) {
        static RNG_INIT: AtomicBool = AtomicBool::new(false);
        while !RNG_INIT.load(Relaxed) {
            let ret = unsafe { libc::randSecure() };
            if ret < 0 {
                panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
            } else if ret > 0 {
                RNG_INIT.store(true, Relaxed);
                break;
            }
            unsafe { libc::usleep(10) };
        }
        let ret = unsafe {
            libc::randABytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int)
        };
        if ret < 0 {
            panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
        }
    }
}
<|endoftext|>


<commit_before>use bot::LalafellBot;
use listeners::ReceivesEvents;
use discord::model::{Event, Message, MessageId};
use database::models::{Message as DbMessage, NewMessage, NewEdit};

use diesel::prelude::*;

use std::sync::Arc;

#[allow(dead_code)]
pub struct TrackChanges {
  bot: Arc<LalafellBot>
}

impl TrackChanges {
  pub fn new(bot: Arc<LalafellBot>) -> Self {
    TrackChanges {
      bot: bot
    }
  }

  fn handle_message(&self, message: &Message) {
    ::bot::CONNECTION.with(|c| {
      let new_message = NewMessage {
        message_id: message.id.0.to_string(),
        channel_id: message.channel_id.0.to_string(),
        content: message.content.to_owned()
      };
      let res = ::diesel::insert(&new_message)
        .into(::database::schema::messages::table)
        .execute(c);
      if let Err(e) = res {
        warn!("couldn't add message to database: {}", e);
      }
    });
  }

  fn handle_message_update(&self, id: MessageId, content: String) {
    ::bot::CONNECTION.with(|c| {
      use database::schema::messages::dsl;
      let message: Result<DbMessage, _> = dsl::messages
        .filter(dsl::message_id.eq(id.0.to_string()))
        .first(c);
      if let Ok(m) = message {
        let new_edit = NewEdit {
          message_id: m.id,
          content: content
        };
        let res = ::diesel::insert(&new_edit)
          .into(::database::schema::edits::table)
          .execute(c);
        if let Err(e) = res {
          warn!("couldn't add edit to database: {}", e);
        }
      }
    });
  }
}

impl ReceivesEvents for TrackChanges {
  fn receive(&self, event: &Event) {
    match *event {
      Event::MessageCreate(ref m) => self.handle_message(m),
      Event::MessageUpdate {
        ref id,
        ref content,
        ..
      } => {
        self.handle_message_update(*id, content.clone().unwrap_or_default());
      },
      _ => {}
    }
  }
}
<commit_msg>fix: don't log messages from the bot itself<commit_after>use bot::LalafellBot;
use listeners::ReceivesEvents;
use discord::model::{Event, Message, MessageId, UserId};
use database::models::{Message as DbMessage, NewMessage, NewEdit};

use diesel::prelude::*;

use std::sync::Arc;

#[allow(dead_code)]
pub struct TrackChanges {
  bot: Arc<LalafellBot>
}

impl TrackChanges {
  pub fn new(bot: Arc<LalafellBot>) -> Self {
    TrackChanges {
      bot: bot
    }
  }

  fn get_user_id(&self) -> UserId {
    let opt_state = self.bot.state.read().unwrap();
    let state = opt_state.as_ref().unwrap();
    state.user().id
  }

  fn handle_message(&self, message: &Message) {
    if message.author.id == self.get_user_id() {
      return;
    }
    ::bot::CONNECTION.with(|c| {
      let new_message = NewMessage {
        message_id: message.id.0.to_string(),
        channel_id: message.channel_id.0.to_string(),
        content: message.content.to_owned()
      };
      let res = ::diesel::insert(&new_message)
        .into(::database::schema::messages::table)
        .execute(c);
      if let Err(e) = res {
        warn!("couldn't add message to database: {}", e);
      }
    });
  }

  fn handle_message_update(&self, id: MessageId, content: String) {
    ::bot::CONNECTION.with(|c| {
      use database::schema::messages::dsl;
      let message: Result<DbMessage, _> = dsl::messages
        .filter(dsl::message_id.eq(id.0.to_string()))
        .first(c);
      if let Ok(m) = message {
        let new_edit = NewEdit {
          message_id: m.id,
          content: content
        };
        let res = ::diesel::insert(&new_edit)
          .into(::database::schema::edits::table)
          .execute(c);
        if let Err(e) = res {
          warn!("couldn't add edit to database: {}", e);
        }
      }
    });
  }
}

impl ReceivesEvents for TrackChanges {
  fn receive(&self, event: &Event) {
    match *event {
      Event::MessageCreate(ref m) => self.handle_message(m),
      Event::MessageUpdate {
        ref id,
        ref content,
        ..
      } => {
        self.handle_message_update(*id, content.clone().unwrap_or_default());
      },
      _ => {}
    }
  }
}
<|endoftext|>


<commit_before>extern crate cgmath;
extern crate ggez;
extern crate rand;

use ggez::audio;
use ggez::conf;
use ggez::event;
use ggez::filesystem;
use ggez::graphics;
use ggez::graphics::Color;
use ggez::timer;
use ggez::{Context, GameResult};
use std::env;
use std::path;

struct MainState {
    a: i32,
    direction: i32,
    image: graphics::Image,
    text: graphics::Text,
    pixel_sized_text: graphics::Text,
    // Not actually dead, see BUGGO below
    #[allow(dead_code)]
    sound: audio::Source,
}

impl MainState {
    fn draw_crazy_lines(&self, ctx: &mut Context) -> GameResult {
        let num_lines = 100;
        let mut colors = Vec::new();
        for _ in 0..num_lines {
            let r: u8 = rand::random();
            let g: u8 = rand::random();
            let b: u8 = rand::random();
            colors.push(Color::from((r, g, b, 255)));
        }

        let mut last_point = cgmath::Point2::new(400.0, 300.0);
        for color in colors {
            let x = (rand::random::<i32>() % 50) as f32;
            let y = (rand::random::<i32>() % 50) as f32;
            let point = cgmath::Point2::new(last_point.x + x, last_point.y + y);
            graphics::line(ctx, color, &[last_point, point], 3.0)?;
            last_point = point;
        }

        Ok(())
    }

    fn new(ctx: &mut Context) -> GameResult<MainState> {
        filesystem::print_all(ctx);

        let image = graphics::Image::new(ctx, "/dragon1.png").unwrap();

        let font = graphics::Font::new(ctx, "/DejaVuSerif.ttf").unwrap();
        let text = graphics::Text::new(("Hello world!", font, 48.0));
        let sound = audio::Source::new(ctx, "/sound.ogg").unwrap();

        let pixel_sized_text =
            graphics::Text::new(("This text is 32 pixels high", font, 32.0));

        let _ = sound.play();

        let s = MainState {
            a: 0,
            direction: 1,
            image,
            text,
            pixel_sized_text,
            // BUGGO: We never use sound again,
            // but we have to hang on to it, Or Else!
            // The optimizer will decide we don't need it
            // since play() has "no side effects" and free it.
            // Or something.
            sound,
        };

        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult {
        const DESIRED_FPS: u32 = 60;
        while timer::check_update_time(ctx, DESIRED_FPS) {
            self.a += self.direction;
            if self.a > 250 || self.a <= 0 {
                self.direction *= -1;

                println!("Delta frame time: {:?} ", timer::get_delta(ctx));
                println!("Average FPS: {}", timer::get_fps(ctx));
            }
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        let c = self.a as u8;
        graphics::clear(ctx, [0.1, 0.2, 0.3, 1.0].into());

        let color = Color::from((c, c, c, 255));
        let dest_point = cgmath::Point2::new(0.0, 0.0);
        graphics::draw(ctx, &self.image, (dest_point, 0.0, color))?;
        graphics::draw(ctx, &self.text, (dest_point, 0.0, color))?;

        let dest_point2 = cgmath::Point2::new(0.0, 256.0);
        graphics::rectangle(
            ctx,
            Color::from((0, 0, 0, 255)),
            graphics::DrawMode::Fill,
            graphics::Rect::new(0.0, 256.0, 500.0, 32.0),
        )?;
        graphics::draw(
            ctx,
            &self.pixel_sized_text,
            (dest_point2, 0.0, graphics::WHITE),
        )?;

        self.draw_crazy_lines(ctx)?;
        graphics::present(ctx)?;

        timer::yield_now();
        Ok(())
    }
}

// Creating a gamestate depends on having an SDL context to load resources.
// Creating a context depends on loading a config file.
// Loading a config file depends on having FS (or we can just fake our way around it
// by creating an FS and then throwing it away; the costs are not huge.)
pub fn main() -> GameResult {
    let c = conf::Conf::new();
    println!("Starting with default config: {:#?}", c);
    let (ctx, events_loop) = &mut Context::load_from_conf("imageview", "ggez", c)?;

    // We add the CARGO_MANIFEST_DIR/resources do the filesystems paths so
    // we we look in the cargo project for files.
    if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        filesystem::mount(ctx, &path, true);
    }

    let state = &mut MainState::new(ctx)?;
    event::run(ctx, events_loop, state)
}
<commit_msg>sound.play() requires mut<commit_after>extern crate cgmath;
extern crate ggez;
extern crate rand;

use ggez::audio;
use ggez::conf;
use ggez::event;
use ggez::filesystem;
use ggez::graphics;
use ggez::graphics::Color;
use ggez::timer;
use ggez::{Context, GameResult};
use std::env;
use std::path;

struct MainState {
    a: i32,
    direction: i32,
    image: graphics::Image,
    text: graphics::Text,
    pixel_sized_text: graphics::Text,
    // Not actually dead, see BUGGO below
    #[allow(dead_code)]
    sound: audio::Source,
}

impl MainState {
    fn draw_crazy_lines(&self, ctx: &mut Context) -> GameResult {
        let num_lines = 100;
        let mut colors = Vec::new();
        for _ in 0..num_lines {
            let r: u8 = rand::random();
            let g: u8 = rand::random();
            let b: u8 = rand::random();
            colors.push(Color::from((r, g, b, 255)));
        }

        let mut last_point = cgmath::Point2::new(400.0, 300.0);
        for color in colors {
            let x = (rand::random::<i32>() % 50) as f32;
            let y = (rand::random::<i32>() % 50) as f32;
            let point = cgmath::Point2::new(last_point.x + x, last_point.y + y);
            graphics::line(ctx, color, &[last_point, point], 3.0)?;
            last_point = point;
        }

        Ok(())
    }

    fn new(ctx: &mut Context) -> GameResult<MainState> {
        filesystem::print_all(ctx);

        let image = graphics::Image::new(ctx, "/dragon1.png").unwrap();

        let font = graphics::Font::new(ctx, "/DejaVuSerif.ttf").unwrap();
        let text = graphics::Text::new(("Hello world!", font, 48.0));
        let mut sound = audio::Source::new(ctx, "/sound.ogg").unwrap();

        let pixel_sized_text =
            graphics::Text::new(("This text is 32 pixels high", font, 32.0));

        let _ = sound.play();

        let s = MainState {
            a: 0,
            direction: 1,
            image,
            text,
            pixel_sized_text,
            // BUGGO: We never use sound again,
            // but we have to hang on to it, Or Else!
            // The optimizer will decide we don't need it
            // since play() has "no side effects" and free it.
            // Or something.
            sound,
        };

        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult {
        const DESIRED_FPS: u32 = 60;
        while timer::check_update_time(ctx, DESIRED_FPS) {
            self.a += self.direction;
            if self.a > 250 || self.a <= 0 {
                self.direction *= -1;

                println!("Delta frame time: {:?} ", timer::get_delta(ctx));
                println!("Average FPS: {}", timer::get_fps(ctx));
            }
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        let c = self.a as u8;
        graphics::clear(ctx, [0.1, 0.2, 0.3, 1.0].into());

        let color = Color::from((c, c, c, 255));
        let dest_point = cgmath::Point2::new(0.0, 0.0);
        graphics::draw(ctx, &self.image, (dest_point, 0.0, color))?;
        graphics::draw(ctx, &self.text, (dest_point, 0.0, color))?;

        let dest_point2 = cgmath::Point2::new(0.0, 256.0);
        graphics::rectangle(
            ctx,
            Color::from((0, 0, 0, 255)),
            graphics::DrawMode::Fill,
            graphics::Rect::new(0.0, 256.0, 500.0, 32.0),
        )?;
        graphics::draw(
            ctx,
            &self.pixel_sized_text,
            (dest_point2, 0.0, graphics::WHITE),
        )?;

        self.draw_crazy_lines(ctx)?;
        graphics::present(ctx)?;

        timer::yield_now();
        Ok(())
    }
}

// Creating a gamestate depends on having an SDL context to load resources.
// Creating a context depends on loading a config file.
// Loading a config file depends on having FS (or we can just fake our way around it
// by creating an FS and then throwing it away; the costs are not huge.)
pub fn main() -> GameResult {
    let c = conf::Conf::new();
    println!("Starting with default config: {:#?}", c);
    let (ctx, events_loop) = &mut Context::load_from_conf("imageview", "ggez", c)?;

    // We add the CARGO_MANIFEST_DIR/resources do the filesystems paths so
    // we we look in the cargo project for files.
    if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        filesystem::mount(ctx, &path, true);
    }

    let state = &mut MainState::new(ctx)?;
    event::run(ctx, events_loop, state)
}
<|endoftext|>


<commit_before>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.1

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::{SocketAddr, Ipv4Addr};
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::arc;
use std::comm::*;

static PORT:    int = 4414;
static IPV4_LOOPBACK: &'static str = "127.0.0.1";
static mut visitor_count: uint = 0;

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath
}

fn main() {
    let req_vec: ~[sched_msg] = ~[];
    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    // add file requests into queue.
    do spawn {
        while(true) {
            do add_vec.write |vec| {
                let tf:sched_msg = port.recv();
                (*vec).push(tf);
                println("add to queue");
            }
        }
    }

    // take file requests from queue, and send a response.
    do spawn {
        while(true) {
            do take_vec.write |vec| {
                let mut tf = (*vec).pop();

                match io::read_whole_file(tf.filepath) {
                    Ok(file_data) => {
                        tf.stream.write(file_data);
                    }
                    Err(err) => {
                        println(err);
                    }
                }
            }
        }
    }

    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: Ipv4Addr(127,0,0,1), port: PORT as u16});

    println(fmt!("Listening on tcp port %d ...", PORT));
    let mut acceptor = socket.listen().unwrap();

    // we can limit the incoming connection count.
    //for stream in acceptor.incoming().take(10 as uint) {
    for stream in acceptor.incoming() {
        let stream = Cell::new(stream);

        // Start a new task to handle the connection
        let child_chan = chan.clone();
        do spawn {
            unsafe {
                visitor_count += 1;
            }

            let mut stream = stream.take();
            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
            if req_group.len() > 2 {
                let path = req_group[1];
                println(fmt!("Request for path: \n%?", path));

                let file_path = ~os::getcwd().push(path.replace("/../", ""));
                if !os::path_exists(file_path) || os::path_is_dir(file_path) {
                    println(fmt!("Request received:\n%s", request_str));
                    let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                         <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

                         \r\n", unsafe{visitor_count});

                    stream.write(response.as_bytes());
                }
                else {
                    // may do scheduling here
                    let msg: sched_msg = sched_msg{stream: stream, filepath: file_path.clone()};
                    child_chan.send(msg);

                    println(fmt!("get file request: %?", file_path));
                }
            }
            println!("connection terminates")
        }
    }
}
<commit_msg>Update PS3 starting code.<commit_after>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.2

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::SocketAddr;
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::arc;
use std::comm::*;

static PORT:    int = 4414;
static IP: &'static str = "0.0.0.0";
static mut visitor_count: uint = 0;

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath
}

fn main() {
    let req_vec: ~[sched_msg] = ~[];
    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    // add file requests into queue.
    do spawn {
        loop {
            do add_vec.write |vec| {
                // port.recv() will block the code and keep locking the RWArc, so we simply use peek() to check if there's message to recv.
                // But a asynchronous solution will be much better.
                if (port.peek()) {
                    let tf:sched_msg = port.recv();
                    (*vec).push(tf);
                    println(fmt!("add to queue, size: %ud", (*vec).len()));
                }
            }
        }
    }

    // take file requests from queue, and send a response.
    // FIFO
    do spawn {
        loop {
            do take_vec.write |vec| {
                if ((*vec).len() > 0) {
                    // FILO didn't make sense in service scheduling, so we modify it as FIFO by using shift_opt() rather than pop().
                    let tf_opt: Option<sched_msg> = (*vec).shift_opt();
                    let mut tf = tf_opt.unwrap();
                    println(fmt!("shift from queue, size: %ud", (*vec).len()));

                    match io::read_whole_file(tf.filepath) { // killed if file size is larger than memory size.
                        Ok(file_data) => {
                            println(fmt!("begin serving file [%?]", tf.filepath));
                            // A web server should always reply a HTTP header for any legal HTTP request.
                            tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream; charset=UTF-8\r\n\r\n".as_bytes());
                            tf.stream.write(file_data);
                            println(fmt!("finish file [%?]", tf.filepath));
                        }
                        Err(err) => {
                            println(err);
                        }
                    }
                }
            }
        }
    }

    let ip = match FromStr::from_str(IP) { Some(ip) => ip,
                                           None => { println(fmt!("Error: Invalid IP address <%s>", IP));
                                                     return;},
                                         };

    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16});

    println(fmt!("Listening on tcp port %d ...", PORT));
    let mut acceptor = socket.listen().unwrap();

    // we can limit the incoming connection count.
    //for stream in acceptor.incoming().take(10 as uint) {
    for stream in acceptor.incoming() {
        let stream = Cell::new(stream);

        // Start a new task to handle the connection
        let child_chan = chan.clone();
        do spawn {
            unsafe {
                visitor_count += 1;
            }

            let mut stream = stream.take();
            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
            if req_group.len() > 2 {
                let path = req_group[1];
                println(fmt!("Request for path: \n%?", path));

                let file_path = ~os::getcwd().push(path.replace("/../", ""));
                if !os::path_exists(file_path) || os::path_is_dir(file_path) {
                    println(fmt!("Request received:\n%s", request_str));
                    let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                         <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

                         \r\n", unsafe{visitor_count});

                    stream.write(response.as_bytes());
                }
                else {
                    // may do scheduling here
                    let msg: sched_msg = sched_msg{stream: stream, filepath: file_path.clone()};
                    child_chan.send(msg);

                    println(fmt!("get file request: %?", file_path));
                }
            }
            println!("connection terminates")
        }
    }
}
<|endoftext|>


<commit_before>use {Function,Global,Module,Value,Expression,Type};
use util::{Id,Identifiable};

pub enum ResolvableInfo
{
    Function {
        ty: ::types::Function,
    },
    Global {
        ty: Type,
    },
}

/// Something that may be resolved.
pub trait Resolvable : Identifiable
{
    fn name(&self) -> &str;
    fn give_to(self: Box<Self>, module: &mut Module);
    fn info(&self) -> ResolvableInfo;
}

impl Resolvable for Function {
    fn name(&self) -> &str { Function::name(self) }
    fn give_to(self: Box<Self>, module: &mut Module) {
        module.add_function(*self);
    }
    fn info(&self) -> ResolvableInfo {
        ResolvableInfo::Function {
            ty: ::types::Function::new(self.signature().clone()),
        }
    }
}

impl Resolvable for Global {
    fn name(&self) -> &str { Global::name(self) }
    fn give_to(self: Box<Self>, module: &mut Module) where Self: Sized {
        module.add_global(*self)
    }
    fn info(&self) -> ResolvableInfo {
        ResolvableInfo::Global {
            ty: self.ty()
        }
    }
}

pub struct Resolve
{
    items: Vec<ResolveItem>,
}

impl Resolve
{
    /// Creates a new resolver.
    pub fn new() -> Self {
        Resolve {
            items: Vec::new(),
        }
    }

    /// Gives back an `ID` which will be used to reference an item.
    pub fn reference(&mut self, name: String) -> Expression {
        if let Some(item) = self.lookup_name(&name) {
            return Expression::UnresolvedRef(item.id);
        }

        let id = Id::next();

        self.items.push(ResolveItem::unresolved(id, name));

        Expression::UnresolvedRef(id)
    }

    pub fn give<T>(&mut self, item: T)
        where T: Resolvable + 'static {
        if let Some(a) =  self.lookup_name_mut(item.name()) {
            a.resolve(item);
            return;
        }

        // otherwise create a new item
        self.items.push(ResolveItem::resolved(
            item.get_id(),
            item.name().to_owned(),
            item,
        ));
    }

    pub fn resolve(&mut self, mut module: Module)
        -> Module {
        // move the actual items (functions, globals)
        // into the module
        for item in self.items.iter_mut() {
            item.give_to(&mut module);
        }

        module.map_values(|v| self.resolve_value(v))
    }

    fn resolve_value(&mut self, value: Value) -> Value {
        let a = value.map_subvalues(|v| self.resolve_value(v));

        a.map_expression(|expr| match expr {
            Expression::UnresolvedRef(id) => self.resolve_reference(id),
            other => other,
        })
    }

    fn resolve_reference(&self, id: Id) -> Expression {
        match self.maybe_resolve_reference(id) {
            Some(expr) => expr,
            None => Expression::UnresolvedRef(id),
        }
    }

    fn maybe_resolve_reference(&self, id: Id) -> Option<Expression> {
        self.find_id(id).make_reference()
    }

    fn find_id(&self, id: Id) -> &ResolveItem {
        self.items.iter().find(|a| a.id == id)
            .expect("no item with that ID was found")
    }

    fn lookup_name(&self, name: &str)
        -> Option<&ResolveItem> {
        self.items.iter().find(|a| a.name == name)
    }

    fn lookup_name_mut(&mut self, name: &str)
        -> Option<&mut ResolveItem> {
        self.items.iter_mut().find(|a| a.name == name)
    }
}

struct ResolveItem
{
    id: Id,
    name: String,
    item: Option<Box<Resolvable>>,
    info: Option<ResolvableInfo>,
}

impl ResolveItem
{
    pub fn unresolved(id: Id,
                      name: String) -> Self {
        ResolveItem {
            id: id,
            name: name,
            item: None,
            info: None,
        }
    }

    pub fn resolved<T>(id: Id,
                       name: String,
                       item: T) -> Self
        where T: Resolvable + 'static {
        ResolveItem {
            id: id,
            name: name,
            info: Some(item.info()),
            item: Some(Box::new(item)),
        }
    }

    pub fn give_to(&mut self, module: &mut Module) {
        use std::mem;

        let item = mem::replace(&mut self.item, None);

        if let Some(i) = item { i.give_to(module) }
    }

    pub fn resolve<T>(&mut self, mut item: T)
        where T: Resolvable + 'static {
        // Make the item have the ID we have have been referring to it as.
        item.internal_set_id(self.id);

        self.info = Some(item.info());
        self.item = Some(Box::new(item));
    }

    pub fn make_reference(&self) -> Option<Expression> {
        use ::value::{FunctionRef,GlobalRef};

        let info = if let Some(ref i) = self.info { i } else { return None; };

        match *info {
            ResolvableInfo::Function { ref ty } => {
                Some(FunctionRef::new(
                    self.id,
                    self.name.clone(),
                    ty.clone()
                ).into())
            },
            ResolvableInfo::Global { ref ty } => {
                Some(GlobalRef::new(
                    self.id,
                    ty.clone(),
                ).into())
            },
        }
    }
}

<commit_msg>Rename ResolvableInfo to Info<commit_after>use {Function,Global,Module,Value,Expression,Type};
use util::{Id,Identifiable};

pub enum Info
{
    Function {
        ty: ::types::Function,
    },
    Global {
        ty: Type,
    },
}

/// Something that may be resolved.
pub trait Resolvable : Identifiable
{
    fn name(&self) -> &str;
    fn give_to(self: Box<Self>, module: &mut Module);
    fn info(&self) -> Info;
}

impl Resolvable for Function {
    fn name(&self) -> &str { Function::name(self) }
    fn give_to(self: Box<Self>, module: &mut Module) {
        module.add_function(*self);
    }
    fn info(&self) -> Info {
        Info::Function {
            ty: ::types::Function::new(self.signature().clone()),
        }
    }
}

impl Resolvable for Global {
    fn name(&self) -> &str { Global::name(self) }
    fn give_to(self: Box<Self>, module: &mut Module) where Self: Sized {
        module.add_global(*self)
    }
    fn info(&self) -> Info {
        Info::Global {
            ty: self.ty()
        }
    }
}

pub struct Resolve
{
    items: Vec<ResolveItem>,
}

impl Resolve
{
    /// Creates a new resolver.
    pub fn new() -> Self {
        Resolve {
            items: Vec::new(),
        }
    }

    /// Gives back an `ID` which will be used to reference an item.
    pub fn reference(&mut self, name: String) -> Expression {
        if let Some(item) = self.lookup_name(&name) {
            return Expression::UnresolvedRef(item.id);
        }

        let id = Id::next();

        self.items.push(ResolveItem::unresolved(id, name));

        Expression::UnresolvedRef(id)
    }

    pub fn give<T>(&mut self, item: T)
        where T: Resolvable + 'static {
        if let Some(a) =  self.lookup_name_mut(item.name()) {
            a.resolve(item);
            return;
        }

        // otherwise create a new item
        self.items.push(ResolveItem::resolved(
            item.get_id(),
            item.name().to_owned(),
            item,
        ));
    }

    pub fn resolve(&mut self, mut module: Module)
        -> Module {
        // move the actual items (functions, globals)
        // into the module
        for item in self.items.iter_mut() {
            item.give_to(&mut module);
        }

        module.map_values(|v| self.resolve_value(v))
    }

    fn resolve_value(&mut self, value: Value) -> Value {
        let a = value.map_subvalues(|v| self.resolve_value(v));

        a.map_expression(|expr| match expr {
            Expression::UnresolvedRef(id) => self.resolve_reference(id),
            other => other,
        })
    }

    fn resolve_reference(&self, id: Id) -> Expression {
        match self.maybe_resolve_reference(id) {
            Some(expr) => expr,
            None => Expression::UnresolvedRef(id),
        }
    }

    fn maybe_resolve_reference(&self, id: Id) -> Option<Expression> {
        self.find_id(id).make_reference()
    }

    fn find_id(&self, id: Id) -> &ResolveItem {
        self.items.iter().find(|a| a.id == id)
            .expect("no item with that ID was found")
    }

    fn lookup_name(&self, name: &str)
        -> Option<&ResolveItem> {
        self.items.iter().find(|a| a.name == name)
    }

    fn lookup_name_mut(&mut self, name: &str)
        -> Option<&mut ResolveItem> {
        self.items.iter_mut().find(|a| a.name == name)
    }
}

struct ResolveItem
{
    id: Id,
    name: String,
    item: Option<Box<Resolvable>>,
    info: Option<Info>,
}

impl ResolveItem
{
    pub fn unresolved(id: Id,
                      name: String) -> Self {
        ResolveItem {
            id: id,
            name: name,
            item: None,
            info: None,
        }
    }

    pub fn resolved<T>(id: Id,
                       name: String,
                       item: T) -> Self
        where T: Resolvable + 'static {
        ResolveItem {
            id: id,
            name: name,
            info: Some(item.info()),
            item: Some(Box::new(item)),
        }
    }

    pub fn give_to(&mut self, module: &mut Module) {
        use std::mem;

        let item = mem::replace(&mut self.item, None);

        if let Some(i) = item { i.give_to(module) }
    }

    pub fn resolve<T>(&mut self, mut item: T)
        where T: Resolvable + 'static {
        // Make the item have the ID we have have been referring to it as.
        item.internal_set_id(self.id);

        self.info = Some(item.info());
        self.item = Some(Box::new(item));
    }

    pub fn make_reference(&self) -> Option<Expression> {
        use ::value::{FunctionRef,GlobalRef};

        let info = if let Some(ref i) = self.info { i } else { return None; };

        match *info {
            Info::Function { ref ty } => {
                Some(FunctionRef::new(
                    self.id,
                    self.name.clone(),
                    ty.clone()
                ).into())
            },
            Info::Global { ref ty } => {
                Some(GlobalRef::new(
                    self.id,
                    ty.clone(),
                ).into())
            },
        }
    }
}

<|endoftext|>


<commit_before>//! Debug tracing macros.
//!
//! This module defines the `dbg!` macro which works like `println!` except it writes to the
//! Cretonne tracing output file if enabled.
//!
//! Tracing can be enabled by setting the `CRETONNE_DBG` environment variable to something
/// other than `0`.
///
/// The output will appear in files named `cretonne.dbg.*`, where the suffix is named after the
/// thread doing the logging.

use std::ascii::AsciiExt;
use std::cell::RefCell;
use std::env;
use std::ffi::OsStr;
use std::fmt;
use std::fs::File;
use std::io::{Write, BufWriter};
use std::sync::atomic;
use std::thread;

static STATE: atomic::AtomicIsize = atomic::ATOMIC_ISIZE_INIT;

/// Is debug tracing enabled?
///
/// Debug tracing can be enabled by setting the `CRETONNE_DBG` environment variable to something
/// other than `0`.
///
/// This inline function turns into a constant `false` when debug assertions are disabled.
#[inline]
pub fn enabled() -> bool {
    if cfg!(debug_assertions) {
        match STATE.load(atomic::Ordering::Relaxed) {
            0 => initialize(),
            s => s > 0,
        }
    } else {
        false
    }
}

/// Initialize `STATE` from the environment variable.
fn initialize() -> bool {
    let enable = match env::var_os("CRETONNE_DBG") {
        Some(s) => s != OsStr::new("0"),
        None => false,
    };

    if enable {
        STATE.store(1, atomic::Ordering::Relaxed);
    } else {
        STATE.store(-1, atomic::Ordering::Relaxed);
    }

    enable
}

thread_local! {
    static WRITER : RefCell<BufWriter<File>> = RefCell::new(open_file());
}

/// Execute a closure with mutable access to the tracing file writer.
///
/// This is for use by the `dbg!` macro.
pub fn with_writer<F, R>(f: F) -> R
    where F: FnOnce(&mut Write) -> R
{
    WRITER.with(|rc| f(&mut *rc.borrow_mut()))
}

/// Open the tracing file for the current thread.
fn open_file() -> BufWriter<File> {
    let file = match thread::current().name() {
            None => File::create("cretonne.dbg"),
            Some(name) => {
                let mut path = "cretonne.dbg.".to_owned();
                for ch in name.chars() {
                    if ch.is_ascii() && ch.is_alphanumeric() {
                        path.push(ch);
                    }
                }
                File::create(path)
            }
        }
        .expect("Can't open tracing file");
    BufWriter::new(file)
}

/// Write a line to the debug trace file if tracing is enabled.
///
/// Arguments are the same as for `printf!`.
#[macro_export]
macro_rules! dbg {
    ($($arg:tt)+) => {
        if $crate::dbg::enabled() {
            // Drop the error result so we don't get compiler errors for ignoring it.
            // What are you going to do, log the error?
            $crate::dbg::with_writer(|w| { writeln!(w, $($arg)+).ok(); })
        }
    }
}

/// Helper for printing lists.
pub struct DisplayList<'a, T>(pub &'a [T]) where T: 'a + fmt::Display;

impl<'a, T> fmt::Display for DisplayList<'a, T>
    where T: 'a + fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0.split_first() {
            None => write!(f, "[]"),
            Some((first, rest)) => {
                write!(f, "[{}", first)?;
                for x in rest {
                    write!(f, ", {}", x)?;
                }
                write!(f, "]")
            }
        }
    }
}
<commit_msg>Avoid evaluating dbg!() arguments in a closure.<commit_after>//! Debug tracing macros.
//!
//! This module defines the `dbg!` macro which works like `println!` except it writes to the
//! Cretonne tracing output file if enabled.
//!
//! Tracing can be enabled by setting the `CRETONNE_DBG` environment variable to something
/// other than `0`.
///
/// The output will appear in files named `cretonne.dbg.*`, where the suffix is named after the
/// thread doing the logging.

use std::ascii::AsciiExt;
use std::cell::RefCell;
use std::env;
use std::ffi::OsStr;
use std::fmt;
use std::fs::File;
use std::io::{self, Write};
use std::sync::atomic;
use std::thread;

static STATE: atomic::AtomicIsize = atomic::ATOMIC_ISIZE_INIT;

/// Is debug tracing enabled?
///
/// Debug tracing can be enabled by setting the `CRETONNE_DBG` environment variable to something
/// other than `0`.
///
/// This inline function turns into a constant `false` when debug assertions are disabled.
#[inline]
pub fn enabled() -> bool {
    if cfg!(debug_assertions) {
        match STATE.load(atomic::Ordering::Relaxed) {
            0 => initialize(),
            s => s > 0,
        }
    } else {
        false
    }
}

/// Initialize `STATE` from the environment variable.
fn initialize() -> bool {
    let enable = match env::var_os("CRETONNE_DBG") {
        Some(s) => s != OsStr::new("0"),
        None => false,
    };

    if enable {
        STATE.store(1, atomic::Ordering::Relaxed);
    } else {
        STATE.store(-1, atomic::Ordering::Relaxed);
    }

    enable
}

thread_local! {
    static WRITER : RefCell<io::BufWriter<File>> = RefCell::new(open_file());
}

/// Write a line with the given format arguments.
///
/// This is for use by the `dbg!` macro.
pub fn writeln_with_format_args(args: fmt::Arguments) -> io::Result<()> {
    WRITER.with(|rc| writeln!(*rc.borrow_mut(), "{}", args))
}

/// Open the tracing file for the current thread.
fn open_file() -> io::BufWriter<File> {
    let file = match thread::current().name() {
            None => File::create("cretonne.dbg"),
            Some(name) => {
                let mut path = "cretonne.dbg.".to_owned();
                for ch in name.chars() {
                    if ch.is_ascii() && ch.is_alphanumeric() {
                        path.push(ch);
                    }
                }
                File::create(path)
            }
        }
        .expect("Can't open tracing file");
    io::BufWriter::new(file)
}

/// Write a line to the debug trace file if tracing is enabled.
///
/// Arguments are the same as for `printf!`.
#[macro_export]
macro_rules! dbg {
    ($($arg:tt)+) => {
        if $crate::dbg::enabled() {
            // Drop the error result so we don't get compiler errors for ignoring it.
            // What are you going to do, log the error?
            $crate::dbg::writeln_with_format_args(format_args!($($arg)+)).ok();
        }
    }
}

/// Helper for printing lists.
pub struct DisplayList<'a, T>(pub &'a [T]) where T: 'a + fmt::Display;

impl<'a, T> fmt::Display for DisplayList<'a, T>
    where T: 'a + fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0.split_first() {
            None => write!(f, "[]"),
            Some((first, rest)) => {
                write!(f, "[{}", first)?;
                for x in rest {
                    write!(f, ", {}", x)?;
                }
                write!(f, "]")
            }
        }
    }
}
<|endoftext|>