<commit_before>use std::{any::type_name, ops::Deref, sync::Arc};

use actix_http::Extensions;
use actix_utils::future::{err, ok, Ready};
use futures_core::future::LocalBoxFuture;
use serde::Serialize;

use crate::{
    dev::Payload, error::ErrorInternalServerError, extract::FromRequest, request::HttpRequest,
    Error,
};

/// Data factory.
pub(crate) trait DataFactory {
    /// Return true if modifications were made to extensions map.
    fn create(&self, extensions: &mut Extensions) -> bool;
}

pub(crate) type FnDataFactory =
    Box<dyn Fn() -> LocalBoxFuture<'static, Result<Box<dyn DataFactory>, ()>>>;

/// Application data wrapper and extractor.
///
/// # Setting Data
/// Data is set using the `app_data` methods on `App`, `Scope`, and `Resource`. If data is wrapped
/// in this `Data` type for those calls, it can be used as an extractor.
///
/// Note that `Data` should be constructed _outside_ the `HttpServer::new` closure if shared,
/// potentially mutable state is desired. `Data` is cheap to clone; internally, it uses an `Arc`.
///
/// See also [`App::app_data`](crate::App::app_data), [`Scope::app_data`](crate::Scope::app_data),
/// and [`Resource::app_data`](crate::Resource::app_data).
///
/// # Extracting `Data`
/// Since the Actix Web router layers application data, the returned object will reference the
/// "closest" instance of the type. For example, if an `App` stores a `u32`, a nested `Scope`
/// also stores a `u32`, and the delegated request handler falls within that `Scope`, then
/// extracting a `web::<Data<u32>>` for that handler will return the `Scope`'s instance.
/// However, using the same router set up and a request that does not get captured by the `Scope`,
/// `web::<Data<u32>>` would return the `App`'s instance.
///
/// If route data is not set for a handler, using `Data<T>` extractor would cause a `500 Internal
/// Server Error` response.
///
/// See also [`HttpRequest::app_data`]
/// and [`ServiceRequest::app_data`](crate::dev::ServiceRequest::app_data).
///
/// # Unsized Data
/// For types that are unsized, most commonly `dyn T`, `Data` can wrap these types by first
/// constructing an `Arc<dyn T>` and using the `From` implementation to convert it.
///
/// ```
/// # use std::{fmt::Display, sync::Arc};
/// # use actix_web::web::Data;
/// let displayable_arc: Arc<dyn Display> = Arc::new(42usize);
/// let displayable_data: Data<dyn Display> = Data::from(displayable_arc);
/// ```
///
/// # Examples
/// ```
/// use std::sync::Mutex;
/// use actix_web::{App, HttpRequest, HttpResponse, Responder, web::{self, Data}};
///
/// struct MyData {
///     counter: usize,
/// }
///
/// /// Use the `Data<T>` extractor to access data in a handler.
/// async fn index(data: Data<Mutex<MyData>>) -> impl Responder {
///     let mut my_data = data.lock().unwrap();
///     my_data.counter += 1;
///     HttpResponse::Ok()
/// }
///
/// /// Alteratively, use the `HttpRequest::app_data` method to access data in a handler.
/// async fn index_alt(req: HttpRequest) -> impl Responder {
///     let data = req.app_data::<Data<Mutex<MyData>>>().unwrap();
///     let mut my_data = data.lock().unwrap();
///     my_data.counter += 1;
///     HttpResponse::Ok()
/// }
///
/// let data = Data::new(Mutex::new(MyData { counter: 0 }));
///
/// let app = App::new()
///     // Store `MyData` in application storage.
///     .app_data(Data::clone(&data))
///     .route("/index.html", web::get().to(index))
///     .route("/index-alt.html", web::get().to(index_alt));
/// ```
#[doc(alias = "state")]
#[derive(Debug)]
pub struct Data<T: ?Sized>(Arc<T>);

impl<T> Data<T> {
    /// Create new `Data` instance.
    pub fn new(state: T) -> Data<T> {
        Data(Arc::new(state))
    }
}

impl<T: ?Sized> Data<T> {
    /// Returns reference to inner `T`.
    pub fn get_ref(&self) -> &T {
        self.0.as_ref()
    }

    /// Unwraps to the internal `Arc<T>`
    pub fn into_inner(self) -> Arc<T> {
        self.0
    }
}

impl<T: ?Sized> Deref for Data<T> {
    type Target = Arc<T>;

    fn deref(&self) -> &Arc<T> {
        &self.0
    }
}

impl<T: ?Sized> Clone for Data<T> {
    fn clone(&self) -> Data<T> {
        Data(self.0.clone())
    }
}

impl<T: ?Sized> From<Arc<T>> for Data<T> {
    fn from(arc: Arc<T>) -> Self {
        Data(arc)
    }
}

impl<T> Serialize for Data<T>
where
    T: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        self.0.serialize(serializer)
    }
}

impl<T: ?Sized + 'static> FromRequest for Data<T> {
    type Error = Error;
    type Future = Ready<Result<Self, Error>>;

    #[inline]
    fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
        if let Some(st) = req.app_data::<Data<T>>() {
            ok(st.clone())
        } else {
            log::debug!(
                "Failed to construct Data extractor type: `{}`. For the Data extractor to work \
                correctly, wrap the data with `Data::new()` and pass it to `App::app_data()`. \
                Ensure that types align in both the set and retrieve calls. \
                Request path: {}",
                type_name::<T>(),
                req.path()
            );

            err(ErrorInternalServerError(
                "Requested application data is not configured. \
                View/enable debug logs for more details.",
            ))
        }
    }
}

impl<T: ?Sized + 'static> DataFactory for Data<T> {
    fn create(&self, extensions: &mut Extensions) -> bool {
        extensions.insert(Data(self.0.clone()));
        true
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{
        dev::Service,
        http::StatusCode,
        test::{init_service, TestRequest},
        web, App, HttpResponse,
    };

    // allow deprecated App::data
    #[allow(deprecated)]
    #[actix_rt::test]
    async fn test_data_extractor() {
        let srv = init_service(App::new().data("TEST".to_string()).service(
            web::resource("/").to(|data: web::Data<String>| {
                assert_eq!(data.to_lowercase(), "test");
                HttpResponse::Ok()
            }),
        ))
        .await;

        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::OK);

        let srv = init_service(
            App::new()
                .data(10u32)
                .service(web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok())),
        )
        .await;
        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);

        let srv = init_service(
            App::new()
                .data(10u32)
                .data(13u32)
                .app_data(12u64)
                .app_data(15u64)
                .default_service(web::to(|n: web::Data<u32>, req: HttpRequest| {
                    // in each case, the latter insertion should be preserved
                    assert_eq!(*req.app_data::<u64>().unwrap(), 15);
                    assert_eq!(*n.into_inner(), 13);
                    HttpResponse::Ok()
                })),
        )
        .await;
        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::OK);
    }

    #[actix_rt::test]
    async fn test_app_data_extractor() {
        let srv = init_service(
            App::new()
                .app_data(Data::new(10usize))
                .service(web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok())),
        )
        .await;

        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::OK);

        let srv = init_service(
            App::new()
                .app_data(Data::new(10u32))
                .service(web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok())),
        )
        .await;
        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
    }

    // allow deprecated App::data
    #[allow(deprecated)]
    #[actix_rt::test]
    async fn test_route_data_extractor() {
        let srv = init_service(
            App::new().service(
                web::resource("/")
                    .data(10usize)
                    .route(web::get().to(|_data: web::Data<usize>| HttpResponse::Ok())),
            ),
        )
        .await;

        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::OK);

        // different type
        let srv = init_service(
            App::new().service(
                web::resource("/")
                    .data(10u32)
                    .route(web::get().to(|_: web::Data<usize>| HttpResponse::Ok())),
            ),
        )
        .await;
        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
    }

    // allow deprecated App::data
    #[allow(deprecated)]
    #[actix_rt::test]
    async fn test_override_data() {
        let srv =
            init_service(App::new().data(1usize).service(
                web::resource("/").data(10usize).route(web::get().to(
                    |data: web::Data<usize>| {
                        assert_eq!(**data, 10);
                        HttpResponse::Ok()
                    },
                )),
            ))
            .await;

        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::OK);
    }

    #[actix_rt::test]
    async fn test_data_from_arc() {
        let data_new = Data::new(String::from("test-123"));
        let data_from_arc = Data::from(Arc::new(String::from("test-123")));
        assert_eq!(data_new.0, data_from_arc.0);
    }

    #[actix_rt::test]
    async fn test_data_from_dyn_arc() {
        trait TestTrait {
            fn get_num(&self) -> i32;
        }
        struct A {}
        impl TestTrait for A {
            fn get_num(&self) -> i32 {
                42
            }
        }
        // This works when Sized is required
        let dyn_arc_box: Arc<Box<dyn TestTrait>> = Arc::new(Box::new(A {}));
        let data_arc_box = Data::from(dyn_arc_box);
        // This works when Data Sized Bound is removed
        let dyn_arc: Arc<dyn TestTrait> = Arc::new(A {});
        let data_arc = Data::from(dyn_arc);
        assert_eq!(data_arc_box.get_num(), data_arc.get_num())
    }

    #[actix_rt::test]
    async fn test_dyn_data_into_arc() {
        trait TestTrait {
            fn get_num(&self) -> i32;
        }
        struct A {}
        impl TestTrait for A {
            fn get_num(&self) -> i32 {
                42
            }
        }
        let dyn_arc: Arc<dyn TestTrait> = Arc::new(A {});
        let data_arc = Data::from(dyn_arc);
        let arc_from_data = data_arc.clone().into_inner();
        assert_eq!(data_arc.get_num(), arc_from_data.get_num())
    }

    #[actix_rt::test]
    async fn test_get_ref_from_dyn_data() {
        trait TestTrait {
            fn get_num(&self) -> i32;
        }
        struct A {}
        impl TestTrait for A {
            fn get_num(&self) -> i32 {
                42
            }
        }
        let dyn_arc: Arc<dyn TestTrait> = Arc::new(A {});
        let data_arc = Data::from(dyn_arc);
        let ref_data = data_arc.get_ref();
        assert_eq!(data_arc.get_num(), ref_data.get_num())
    }
}
<commit_msg>use match name if possible in data debug log<commit_after>use std::{any::type_name, ops::Deref, sync::Arc};

use actix_http::Extensions;
use actix_utils::future::{err, ok, Ready};
use futures_core::future::LocalBoxFuture;
use serde::Serialize;

use crate::{
    dev::Payload, error::ErrorInternalServerError, extract::FromRequest, request::HttpRequest,
    Error,
};

/// Data factory.
pub(crate) trait DataFactory {
    /// Return true if modifications were made to extensions map.
    fn create(&self, extensions: &mut Extensions) -> bool;
}

pub(crate) type FnDataFactory =
    Box<dyn Fn() -> LocalBoxFuture<'static, Result<Box<dyn DataFactory>, ()>>>;

/// Application data wrapper and extractor.
///
/// # Setting Data
/// Data is set using the `app_data` methods on `App`, `Scope`, and `Resource`. If data is wrapped
/// in this `Data` type for those calls, it can be used as an extractor.
///
/// Note that `Data` should be constructed _outside_ the `HttpServer::new` closure if shared,
/// potentially mutable state is desired. `Data` is cheap to clone; internally, it uses an `Arc`.
///
/// See also [`App::app_data`](crate::App::app_data), [`Scope::app_data`](crate::Scope::app_data),
/// and [`Resource::app_data`](crate::Resource::app_data).
///
/// # Extracting `Data`
/// Since the Actix Web router layers application data, the returned object will reference the
/// "closest" instance of the type. For example, if an `App` stores a `u32`, a nested `Scope`
/// also stores a `u32`, and the delegated request handler falls within that `Scope`, then
/// extracting a `web::<Data<u32>>` for that handler will return the `Scope`'s instance.
/// However, using the same router set up and a request that does not get captured by the `Scope`,
/// `web::<Data<u32>>` would return the `App`'s instance.
///
/// If route data is not set for a handler, using `Data<T>` extractor would cause a `500 Internal
/// Server Error` response.
///
/// See also [`HttpRequest::app_data`]
/// and [`ServiceRequest::app_data`](crate::dev::ServiceRequest::app_data).
///
/// # Unsized Data
/// For types that are unsized, most commonly `dyn T`, `Data` can wrap these types by first
/// constructing an `Arc<dyn T>` and using the `From` implementation to convert it.
///
/// ```
/// # use std::{fmt::Display, sync::Arc};
/// # use actix_web::web::Data;
/// let displayable_arc: Arc<dyn Display> = Arc::new(42usize);
/// let displayable_data: Data<dyn Display> = Data::from(displayable_arc);
/// ```
///
/// # Examples
/// ```
/// use std::sync::Mutex;
/// use actix_web::{App, HttpRequest, HttpResponse, Responder, web::{self, Data}};
///
/// struct MyData {
///     counter: usize,
/// }
///
/// /// Use the `Data<T>` extractor to access data in a handler.
/// async fn index(data: Data<Mutex<MyData>>) -> impl Responder {
///     let mut my_data = data.lock().unwrap();
///     my_data.counter += 1;
///     HttpResponse::Ok()
/// }
///
/// /// Alteratively, use the `HttpRequest::app_data` method to access data in a handler.
/// async fn index_alt(req: HttpRequest) -> impl Responder {
///     let data = req.app_data::<Data<Mutex<MyData>>>().unwrap();
///     let mut my_data = data.lock().unwrap();
///     my_data.counter += 1;
///     HttpResponse::Ok()
/// }
///
/// let data = Data::new(Mutex::new(MyData { counter: 0 }));
///
/// let app = App::new()
///     // Store `MyData` in application storage.
///     .app_data(Data::clone(&data))
///     .route("/index.html", web::get().to(index))
///     .route("/index-alt.html", web::get().to(index_alt));
/// ```
#[doc(alias = "state")]
#[derive(Debug)]
pub struct Data<T: ?Sized>(Arc<T>);

impl<T> Data<T> {
    /// Create new `Data` instance.
    pub fn new(state: T) -> Data<T> {
        Data(Arc::new(state))
    }
}

impl<T: ?Sized> Data<T> {
    /// Returns reference to inner `T`.
    pub fn get_ref(&self) -> &T {
        self.0.as_ref()
    }

    /// Unwraps to the internal `Arc<T>`
    pub fn into_inner(self) -> Arc<T> {
        self.0
    }
}

impl<T: ?Sized> Deref for Data<T> {
    type Target = Arc<T>;

    fn deref(&self) -> &Arc<T> {
        &self.0
    }
}

impl<T: ?Sized> Clone for Data<T> {
    fn clone(&self) -> Data<T> {
        Data(self.0.clone())
    }
}

impl<T: ?Sized> From<Arc<T>> for Data<T> {
    fn from(arc: Arc<T>) -> Self {
        Data(arc)
    }
}

impl<T> Serialize for Data<T>
where
    T: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        self.0.serialize(serializer)
    }
}

impl<T: ?Sized + 'static> FromRequest for Data<T> {
    type Error = Error;
    type Future = Ready<Result<Self, Error>>;

    #[inline]
    fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
        if let Some(st) = req.app_data::<Data<T>>() {
            ok(st.clone())
        } else {
            log::debug!(
                "Failed to extract `Data<{}>` for `{}` handler. For the Data extractor to work \
                correctly, wrap the data with `Data::new()` and pass it to `App::app_data()`. \
                Ensure that types align in both the set and retrieve calls.",
                type_name::<T>(),
                req.match_name().unwrap_or_else(|| req.path())
            );

            err(ErrorInternalServerError(
                "Requested application data is not configured correctly. \
                View/enable debug logs for more details.",
            ))
        }
    }
}

impl<T: ?Sized + 'static> DataFactory for Data<T> {
    fn create(&self, extensions: &mut Extensions) -> bool {
        extensions.insert(Data(self.0.clone()));
        true
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{
        dev::Service,
        http::StatusCode,
        test::{init_service, TestRequest},
        web, App, HttpResponse,
    };

    // allow deprecated App::data
    #[allow(deprecated)]
    #[actix_rt::test]
    async fn test_data_extractor() {
        let srv = init_service(App::new().data("TEST".to_string()).service(
            web::resource("/").to(|data: web::Data<String>| {
                assert_eq!(data.to_lowercase(), "test");
                HttpResponse::Ok()
            }),
        ))
        .await;

        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::OK);

        let srv = init_service(
            App::new()
                .data(10u32)
                .service(web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok())),
        )
        .await;
        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);

        let srv = init_service(
            App::new()
                .data(10u32)
                .data(13u32)
                .app_data(12u64)
                .app_data(15u64)
                .default_service(web::to(|n: web::Data<u32>, req: HttpRequest| {
                    // in each case, the latter insertion should be preserved
                    assert_eq!(*req.app_data::<u64>().unwrap(), 15);
                    assert_eq!(*n.into_inner(), 13);
                    HttpResponse::Ok()
                })),
        )
        .await;
        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::OK);
    }

    #[actix_rt::test]
    async fn test_app_data_extractor() {
        let srv = init_service(
            App::new()
                .app_data(Data::new(10usize))
                .service(web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok())),
        )
        .await;

        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::OK);

        let srv = init_service(
            App::new()
                .app_data(Data::new(10u32))
                .service(web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok())),
        )
        .await;
        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
    }

    // allow deprecated App::data
    #[allow(deprecated)]
    #[actix_rt::test]
    async fn test_route_data_extractor() {
        let srv = init_service(
            App::new().service(
                web::resource("/")
                    .data(10usize)
                    .route(web::get().to(|_data: web::Data<usize>| HttpResponse::Ok())),
            ),
        )
        .await;

        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::OK);

        // different type
        let srv = init_service(
            App::new().service(
                web::resource("/")
                    .data(10u32)
                    .route(web::get().to(|_: web::Data<usize>| HttpResponse::Ok())),
            ),
        )
        .await;
        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
    }

    // allow deprecated App::data
    #[allow(deprecated)]
    #[actix_rt::test]
    async fn test_override_data() {
        let srv =
            init_service(App::new().data(1usize).service(
                web::resource("/").data(10usize).route(web::get().to(
                    |data: web::Data<usize>| {
                        assert_eq!(**data, 10);
                        HttpResponse::Ok()
                    },
                )),
            ))
            .await;

        let req = TestRequest::default().to_request();
        let resp = srv.call(req).await.unwrap();
        assert_eq!(resp.status(), StatusCode::OK);
    }

    #[actix_rt::test]
    async fn test_data_from_arc() {
        let data_new = Data::new(String::from("test-123"));
        let data_from_arc = Data::from(Arc::new(String::from("test-123")));
        assert_eq!(data_new.0, data_from_arc.0);
    }

    #[actix_rt::test]
    async fn test_data_from_dyn_arc() {
        trait TestTrait {
            fn get_num(&self) -> i32;
        }
        struct A {}
        impl TestTrait for A {
            fn get_num(&self) -> i32 {
                42
            }
        }
        // This works when Sized is required
        let dyn_arc_box: Arc<Box<dyn TestTrait>> = Arc::new(Box::new(A {}));
        let data_arc_box = Data::from(dyn_arc_box);
        // This works when Data Sized Bound is removed
        let dyn_arc: Arc<dyn TestTrait> = Arc::new(A {});
        let data_arc = Data::from(dyn_arc);
        assert_eq!(data_arc_box.get_num(), data_arc.get_num())
    }

    #[actix_rt::test]
    async fn test_dyn_data_into_arc() {
        trait TestTrait {
            fn get_num(&self) -> i32;
        }
        struct A {}
        impl TestTrait for A {
            fn get_num(&self) -> i32 {
                42
            }
        }
        let dyn_arc: Arc<dyn TestTrait> = Arc::new(A {});
        let data_arc = Data::from(dyn_arc);
        let arc_from_data = data_arc.clone().into_inner();
        assert_eq!(data_arc.get_num(), arc_from_data.get_num())
    }

    #[actix_rt::test]
    async fn test_get_ref_from_dyn_data() {
        trait TestTrait {
            fn get_num(&self) -> i32;
        }
        struct A {}
        impl TestTrait for A {
            fn get_num(&self) -> i32 {
                42
            }
        }
        let dyn_arc: Arc<dyn TestTrait> = Arc::new(A {});
        let data_arc = Data::from(dyn_arc);
        let ref_data = data_arc.get_ref();
        assert_eq!(data_arc.get_num(), ref_data.get_num())
    }
}
<|endoftext|>


<commit_before>// This file will include the Data (struct or enum) which will represent the
// different pieces of data which can be passed via HTTP style Request / Response.

type UserID = u64;
//type UserMap = HashMap<UserID, Data::User>;

pub enum Data {
    User {
        name: String
    },
    Group {
        id: u64
    },
    Message {
        text: String
    }
}
<commit_msg>Adding the structs for serialization<commit_after>// This file will include the Data (struct or enum) which will represent the
// different pieces of data which can be passed via HTTP style Request / Response.

type UserID = u64;
//type UserMap = HashMap<UserID, Data::User>;

#[deriving(Debug, Serialize, Deserialize)]
pub struct Message {
    user_id: UserID,
    message_body: String,
    flags: u64,
}

#[deriving(Debug, Serialize, Deserialize)]
pub struct InfoRequest {

}

#[deriving(Debug, Serialize, Deserialize)]
pub struct User {
    user_id: UserID, // will be an username / email address.
}

enum Info {

}

<|endoftext|>


<commit_before>use std::fmt;
use hex_slice::AsHex;
use rand::random;

#[derive(Clone, Default)]
pub struct InfoPool {
    data: Vec<u8>,
}

#[derive(Clone, Default)]
pub struct InfoTap<'a> {
    data: &'a [u8],
    off: usize,
}

impl fmt::Debug for InfoPool {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("InfoPool")
            .field("data", &format_args!("{:x}", self.data.as_hex()))
            .finish()
    }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct PoolExhausted;

pub type Maybe<T> = Result<T, PoolExhausted>;

impl InfoPool {
    pub fn of_vec(data: Vec<u8>) -> Self {
        InfoPool { data: data }
    }
    pub fn random_of_size(size: usize) -> Self {
        Self::of_vec((0..size).map(|_| random()).collect::<Vec<u8>>())
    }

    pub fn buffer(&self) -> &[u8] {
        &*self.data
    }

    pub fn tap(&self) -> InfoTap {
        InfoTap {
            data: &*self.data,
            off: 0,
        }
    }
}

impl<'a> InfoTap<'a> {
    pub fn next_byte(&mut self) -> Maybe<u8> {
        let res = self.data.get(self.off).cloned();
        self.off += 1;
        res.ok_or(PoolExhausted)
    }
}

impl<'a> Iterator for InfoTap<'a> {
    type Item = u8;
    fn next(&mut self) -> Option<u8> {
        self.next_byte().ok()
    }
}

fn minimize_via_removal<F: Fn(InfoTap) -> bool>(
    p: &InfoPool,
    candidate: &mut InfoPool,
    pred: &F,
) -> Option<InfoPool> {
    // First shrink tactic: item removal
    println!("minimizing by removal: {:?}", p);
    for i in 0..p.data.len() {
        candidate.clone_from(&p);
        candidate.data.remove(i);

        let test = pred(candidate.tap());
        println!("removed {}: {:?}; test result {}", i, candidate, test);
        if test {
            if let Some(res) = minimize(&candidate, pred) {
                println!("Returning shrunk: {:?}", res);
                return Some(res);
            } else {
                println!("Returning original: {:?}", candidate);
                return Some(candidate.clone());
            }
        }
    }
    None
}

fn minimize_via_scalar_shrink<F: Fn(InfoTap) -> bool>(
    p: &InfoPool,
    candidate: &mut InfoPool,
    pred: &F,
) -> Option<InfoPool> {
    // Second shrink tactic: make values smaller
    println!("minimizing by scalar shrink: {:?}", p);
    for i in 0..p.data.len() {
        candidate.clone_from(&p);

        for bitoff in 1..8 {
            candidate.data[i] = p.data[i] - (p.data[i] >> bitoff);
            println!(
                "shrunk item -(bitoff:{}) {} {}->{}: {:?}",
                bitoff,
                i,
                p.data[i],
                candidate.data[i],
                candidate
            );

            if candidate.buffer() == p.buffer() {
                println!("No change");
                continue;
            }

            let test = pred(candidate.tap());
            println!("test result {}", test);
            if test {
                if let Some(res) = minimize(&candidate, pred) {
                    println!("Returning shrunk: {:?}", res);
                    return Some(res);
                } else {
                    println!("Returning original: {:?}", candidate);
                    return Some(candidate.clone());
                }
            }
        }
    }

    None
}

pub fn minimize<F: Fn(InfoTap) -> bool>(p: &InfoPool, pred: &F) -> Option<InfoPool> {
    let mut candidate = p.clone();
    if let Some(res) = minimize_via_removal(p, &mut candidate, pred) {
        return Some(res);
    }

    if let Some(res) = minimize_via_scalar_shrink(p, &mut candidate, pred) {
        return Some(res);
    }

    println!("Nothing smaller found than {:?}", p);
    None
}

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

    #[test]
    fn should_take_each_item_in_pool() {
        let p = InfoPool::of_vec(vec![0, 1, 2, 3]);
        let mut t = p.tap();
        assert_eq!(t.next_byte(), Ok(0));
        assert_eq!(t.next_byte(), Ok(1));
        assert_eq!(t.next_byte(), Ok(2));
        assert_eq!(t.next_byte(), Ok(3));
        assert_eq!(t.next_byte(), Err(PoolExhausted));
    }

    #[test]
    fn should_generate_random_data_of_size() {
        let size = 100;
        let p = InfoPool::random_of_size(size);
        let mut t = p.tap();
        for _ in 0..size {
            assert!(t.next_byte().is_ok());
        }
        assert!(t.next_byte().is_err());
    }

    #[test]
    fn should_allow_restarting_read() {
        let p = InfoPool::random_of_size(4);
        let mut t = p.tap();
        let mut v0 = Vec::new();
        while let Ok(val) = t.next_byte() {
            v0.push(val)
        }

        let mut t = p.tap();
        let mut v1 = Vec::new();
        while let Ok(val) = t.next_byte() {
            v1.push(val)
        }

        assert_eq!(v0, v1)
    }

    #[test]
    fn should_allow_borrowing_buffer() {
        let p = InfoPool::of_vec(vec![1]);
        assert_eq!(p.buffer(), &[1]);
    }

    #[test]
    fn tap_can_act_as_iterator() {
        let buf = vec![4, 3, 2, 1];
        let p = InfoPool::of_vec(buf.clone());
        let _: &Iterator<Item = u8> = &p.tap();

        assert_eq!(p.tap().collect::<Vec<_>>(), buf)
    }
    #[test]
    fn minimiser_should_minimise_to_empty() {
        let p = InfoPool::of_vec(vec![1]);
        let min = minimize(&p, &|_| true);

        assert_eq!(min.as_ref().map(|p| p.buffer()), Some([].as_ref()))
    }

    #[test]
    fn minimiser_should_minimise_to_minimum_given_size() {
        let p = InfoPool::of_vec(vec![0; 4]);
        let min = minimize(&p, &|t| t.count() > 1).expect("some smaller pool");

        assert_eq!(min.buffer(), &[0, 0])
    }

    #[test]
    fn minimiser_should_minimise_scalar_values() {
        let p = InfoPool::of_vec(vec![255; 3]);
        let min = minimize(&p, &|mut t| t.any(|v| v >= 3)).expect("some smaller pool");

        assert_eq!(min.buffer(), &[3])
    }

    #[test]
    fn minimiser_should_minimise_scalar_values_by_search() {
        let p = InfoPool::of_vec(vec![255; 3]);
        let min = minimize(&p, &|mut t| t.any(|v| v >= 13)).expect("some smaller pool");

        assert_eq!(min.buffer(), &[13])
    }
    #[test]
    fn minimiser_should_minimise_scalar_values_accounting_for_overflow() {
        let p = InfoPool::of_vec(vec![255; 3]);
        let min = minimize(&p, &|mut t| t.any(|v| v >= 251)).expect("some smaller pool");

        assert_eq!(min.buffer(), &[251])
    }
}
<commit_msg>Ensure we minimise as much as we can.<commit_after>use std::fmt;
use hex_slice::AsHex;
use rand::random;

#[derive(Clone, Default)]
pub struct InfoPool {
    data: Vec<u8>,
}

#[derive(Clone, Default)]
pub struct InfoTap<'a> {
    data: &'a [u8],
    off: usize,
}

impl fmt::Debug for InfoPool {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("InfoPool")
            .field("data", &format_args!("{:x}", self.data.as_hex()))
            .finish()
    }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct PoolExhausted;

pub type Maybe<T> = Result<T, PoolExhausted>;

impl InfoPool {
    pub fn of_vec(data: Vec<u8>) -> Self {
        InfoPool { data: data }
    }
    pub fn random_of_size(size: usize) -> Self {
        Self::of_vec((0..size).map(|_| random()).collect::<Vec<u8>>())
    }

    pub fn buffer(&self) -> &[u8] {
        &*self.data
    }

    pub fn tap(&self) -> InfoTap {
        InfoTap {
            data: &*self.data,
            off: 0,
        }
    }
}

impl<'a> InfoTap<'a> {
    pub fn next_byte(&mut self) -> Maybe<u8> {
        let res = self.data.get(self.off).cloned();
        self.off += 1;
        res.ok_or(PoolExhausted)
    }
}

impl<'a> Iterator for InfoTap<'a> {
    type Item = u8;
    fn next(&mut self) -> Option<u8> {
        self.next_byte().ok()
    }
}

fn minimize_via_removal<F: Fn(InfoTap) -> bool>(
    p: &InfoPool,
    candidate: &mut InfoPool,
    pred: &F,
) -> Option<InfoPool> {
    // First shrink tactic: item removal
    println!("minimizing by removal: {:?}", p);
    for i in 0..p.data.len() {
        candidate.clone_from(&p);
        candidate.data.remove(i);

        let test = pred(candidate.tap());
        println!("removed {}: {:?}; test result {}", i, candidate, test);
        if test {
            if let Some(res) = minimize(&candidate, pred) {
                println!("Returning shrunk: {:?}", res);
                return Some(res);
            } else {
                println!("Returning original: {:?}", candidate);
                return Some(candidate.clone());
            }
        }
    }
    None
}

fn minimize_via_scalar_shrink<F: Fn(InfoTap) -> bool>(
    p: &InfoPool,
    candidate: &mut InfoPool,
    pred: &F,
) -> Option<InfoPool> {
    // Second shrink tactic: make values smaller
    println!("minimizing by scalar shrink: {:?}", p);
    for i in 0..p.data.len() {
        candidate.clone_from(&p);

        for bitoff in 0..8 {
            candidate.data[i] = p.data[i] - (p.data[i] >> bitoff);
            println!(
                "shrunk item -(bitoff:{}) {} {}->{}: {:?}",
                bitoff,
                i,
                p.data[i],
                candidate.data[i],
                candidate
            );

            if candidate.buffer() == p.buffer() {
                println!("No change");
                continue;
            }

            let test = pred(candidate.tap());
            println!("test result {}", test);
            if test {
                if let Some(res) = minimize(&candidate, pred) {
                    println!("Returning shrunk: {:?}", res);
                    return Some(res);
                } else {
                    println!("Returning original: {:?}", candidate);
                    return Some(candidate.clone());
                }
            }
        }
    }

    None
}

pub fn minimize<F: Fn(InfoTap) -> bool>(p: &InfoPool, pred: &F) -> Option<InfoPool> {
    let mut candidate = p.clone();
    if let Some(res) = minimize_via_removal(p, &mut candidate, pred) {
        return Some(res);
    }

    if let Some(res) = minimize_via_scalar_shrink(p, &mut candidate, pred) {
        return Some(res);
    }

    println!("Nothing smaller found than {:?}", p);
    None
}

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

    #[test]
    fn should_take_each_item_in_pool() {
        let p = InfoPool::of_vec(vec![0, 1, 2, 3]);
        let mut t = p.tap();
        assert_eq!(t.next_byte(), Ok(0));
        assert_eq!(t.next_byte(), Ok(1));
        assert_eq!(t.next_byte(), Ok(2));
        assert_eq!(t.next_byte(), Ok(3));
        assert_eq!(t.next_byte(), Err(PoolExhausted));
    }

    #[test]
    fn should_generate_random_data_of_size() {
        let size = 100;
        let p = InfoPool::random_of_size(size);
        let mut t = p.tap();
        for _ in 0..size {
            assert!(t.next_byte().is_ok());
        }
        assert!(t.next_byte().is_err());
    }

    #[test]
    fn should_allow_restarting_read() {
        let p = InfoPool::random_of_size(4);
        let mut t = p.tap();
        let mut v0 = Vec::new();
        while let Ok(val) = t.next_byte() {
            v0.push(val)
        }

        let mut t = p.tap();
        let mut v1 = Vec::new();
        while let Ok(val) = t.next_byte() {
            v1.push(val)
        }

        assert_eq!(v0, v1)
    }

    #[test]
    fn should_allow_borrowing_buffer() {
        let p = InfoPool::of_vec(vec![1]);
        assert_eq!(p.buffer(), &[1]);
    }

    #[test]
    fn tap_can_act_as_iterator() {
        let buf = vec![4, 3, 2, 1];
        let p = InfoPool::of_vec(buf.clone());
        let _: &Iterator<Item = u8> = &p.tap();

        assert_eq!(p.tap().collect::<Vec<_>>(), buf)
    }
    #[test]
    fn minimiser_should_minimise_to_empty() {
        let p = InfoPool::of_vec(vec![1]);
        let min = minimize(&p, &|_| true);

        assert_eq!(min.as_ref().map(|p| p.buffer()), Some([].as_ref()))
    }

    #[test]
    fn minimiser_should_minimise_to_minimum_given_size() {
        let p = InfoPool::of_vec(vec![0; 4]);
        let min = minimize(&p, &|t| t.count() > 1).expect("some smaller pool");

        assert_eq!(min.buffer(), &[0, 0])
    }

    #[test]
    fn minimiser_should_minimise_scalar_values() {
        let p = InfoPool::of_vec(vec![255; 3]);
        let min = minimize(&p, &|mut t| t.any(|v| v >= 3)).expect("some smaller pool");

        assert_eq!(min.buffer(), &[3])
    }
    #[test]
    fn minimiser_should_minimise_scalar_values_to_zero() {
        let p = InfoPool::of_vec(vec![255; 3]);
        let min = minimize(&p, &|mut t| t.any(|_| true)).expect("some smaller pool");

        assert_eq!(min.buffer(), &[0])
    }

    #[test]
    fn minimiser_should_minimise_scalar_values_by_search() {
        let p = InfoPool::of_vec(vec![255; 3]);
        let min = minimize(&p, &|mut t| t.any(|v| v >= 13)).expect("some smaller pool");

        assert_eq!(min.buffer(), &[13])
    }
    #[test]
    fn minimiser_should_minimise_scalar_values_accounting_for_overflow() {
        let p = InfoPool::of_vec(vec![255; 3]);
        let min = minimize(&p, &|mut t| t.any(|v| v >= 251)).expect("some smaller pool");

        assert_eq!(min.buffer(), &[251])
    }
}
<|endoftext|>


<commit_before>
use std::collections::HashMap;
use parse::*;
use clap::ArgMatches;
use intercom_common::utils;
use intercom_common::guid::*;
use error::*;
use std::io;

/// Runs the 'cpp' subcommand.
pub fn run( cpp_params : &ArgMatches ) -> AppResult {

    // Parse the sources and convert the result into an IDL.
    let ( renames, result ) = parse_crate(
            cpp_params.value_of( "path" ).unwrap() )?;
    result_to_cpp( &result, &renames, &mut io::stdout() );

    Ok(())
}

/// Converts the parse result into an header  that gets written to stdout.
fn result_to_cpp(
    r : &ParseResult,
    rn : &HashMap<String, String>,
    out : &mut io::Write,
) {
    // Introduce all interfaces so we don't get errors on undeclared items.
    let itf_forward_declarations = r.interfaces.iter().map(|itf| {
        format!( "{}struct {};", get_indentation( 1 ), try_rename( rn, &itf.name ) )
    } ).collect::<Vec<_>>().join( "\n" );

    // Raw interfaces that give direct access to the components implemented in Rust.
    let itfs = r.interfaces.iter().map(|itf| {
        generate_raw_interface( rn, itf, 1 )
    } ).collect::<Vec<_>>().join( "\n" );

    // Generate class descriptors.
    let class_descriptors = r.class_names.iter().map(|class_name| {

        // Get the class details by matching the name.
        let class  = r.classes.iter().find(|cls| &cls.name == class_name )
            .unwrap();

        generate_class_descriptor( rn, &r.libname, class_name, class, 1 )
    } ).collect::<Vec<_>>().join( "\n" );

    // Generate using statements that flatten the raw interfaces
    // to mimic the results of a Microsoft MIDL compiler.
    let flat_interface_declarations = r.interfaces.iter().map(|itf| {
        flatten_interface( rn, &r.libname, itf, 1 )
    } ).collect::<Vec<_>>().join( "\n" );

    // Generate using statements that flatten the class descriptors
    // to mimic the results of a Microsoft MIDL compiler.
    let flat_class_descriptor_declarations = r.class_names.iter().map(|class_name| {

                // Get the class details by matching the name.
        let class  = r.classes.iter().find(|cls| &cls.name == class_name )
            .unwrap();

        flatten_class_descriptor( class_name, class, 1 )
    } ).collect::<Vec<_>>().join( "\n" );

    // We got the interfaces and classes. We can format and output the raw interfaces.
    let raw_namespace: String = format!( r###"
>       #include <intercom.h>
>       namespace {}
>       {{
>       namespace raw
>       {{
>       {}
>       {}
>       {}
>       }}
>       }}
>       #ifdef INTERCOM_FLATTEN_DECLARATIONS
>       {}
>       {}
>       #endif
>       "###,
        &r.libname, itf_forward_declarations, itfs, class_descriptors,
        flat_interface_declarations, flat_class_descriptor_declarations );
    let raw_namespace = raw_namespace.replace( ">       ", "" );
    writeln!( out, "{}", raw_namespace ).unwrap();
}

fn generate_raw_interface(
    rn : &HashMap<String, String>,
    interface: &Interface,
    base_indentation: usize
) -> String {

    // Now that we have methods sorted out, we can construct the final
    // interface definition.
    let indentation = get_indentation( base_indentation );
    let interface_text = format!( "{}struct {} : IUnknown\n{}{{\n{}static constexpr intercom::IID ID = {};\n\n{}\n{}}};\n",
            indentation, try_rename( rn, &interface.name ), indentation,
            get_indentation( base_indentation + 1 ), guid_to_binary( &interface.iid ),
            generate_raw_methods( interface, base_indentation + 1 ), indentation );
    interface_text
}

fn generate_raw_methods(
    itf: &Interface,
    indentation: usize
) -> String {

    // Get the method definitions for the current interface.
    let methods = itf.methods.iter().enumerate().map(|(_i,m)| {

        // Construct the argument list.
        let args = m.arguments.iter().map(|a| {

            // Argument direction affects both the argument attribute and
            // whether the argument is passed by pointer or value.
            let out_ptr = match a.dir {
                ArgDirection::In => "",
                ArgDirection::Out => "*",
                ArgDirection::Return => "*",
            };
            format!( "{}{} {}", to_cpp_type( &a.ty ), out_ptr, a.name )

        } ).collect::<Vec<_>>().join( ", " );

        // Format the method.
        // To maintain backwards compatibility all new methods should
        // be added to the end of the traits.
        format!( r###"{}virtual {} INTERCOM_CC {}( {} ) = 0;"###, get_indentation( indentation ), to_cpp_type( &m.rvalue ), utils::pascal_case( &m.name ), args )

    } ).collect::<Vec<_>>().join( "\n" );
    return methods;
}

fn flatten_interface(
    rn : &HashMap<String, String>,
    libname: &str,
    interface: &Interface,
    indentation: usize
) -> String {
    let interface_name = try_rename( rn, &interface.name );
    let using_iid = format!( "static constexpr intercom::IID IID_{} = {};",
            utils::pascal_case( &interface_name ), guid_to_binary( &interface.iid ) );
    let using_interface = format!( "using {} = {}::raw::{};", utils::pascal_case( &interface_name ), libname,  &interface_name );
    let indentation = get_indentation( indentation );
    format!("{}{}\n{}{}", indentation, using_iid, indentation, using_interface )
}

fn flatten_class_descriptor(
    class_name: &str,
    coclass: &CoClass,
    indentation: usize
) -> String {
    let using_clsid = format!( "static constexpr CLSID CLSID_{} = {};",
            utils::pascal_case( class_name ), guid_to_binary( &coclass.clsid ) );
    let indentation = get_indentation( indentation );
    format!("{}{}", indentation, using_clsid )
}

fn generate_class_descriptor(
    rn : &HashMap<String, String>,
    libname: &str,
    class_name: &str,
    coclass: &CoClass,
    indentation: usize
) -> String {

    // Create a list of interfaces to be declared in the class descriptor.
    let interfaces =  coclass.interfaces.iter().map(|itf| {
            format!( r###"{}{}::raw::{}::ID"###,
                &get_indentation( indentation + 2 ), libname, try_rename( rn, itf ) )
        } ).collect::<Vec<_>>().join( ",\n" );

    // Class descriptors hold information about COM classes implemented by the library.
    let clsid = guid_to_binary( &coclass.clsid );
    let class_descriptor: String = format!( r###"
>       class {}Descriptor
>       {{
>           static constexpr CLSID ID = {};

>           static constexpr std::array<intercom::IID, {}> INTERFACES = {{
{}
>           }};

>           {}Descriptor() = delete;
>           ~{}Descriptor() = delete;

>       }};
>       "###,
    class_name, clsid, coclass.interfaces.len(), interfaces, class_name, class_name );
    class_descriptor.replace( ">       ", &get_indentation( indentation ) )
}

/// Gets an empty string for ind One level of indentation is four spaces.
fn get_indentation(
    level: usize
) -> String {
    let spaces = level * 4;
    let indentation = format!( r###"{: <1$}"###, "", spaces );
    indentation
}

/// Converts a Rust type into applicable C++ type.
fn to_cpp_type(
    ty: &str
) -> &str {

    match ty {
        "int8" => "int8_t",
        "uint8" => "uint8_t",
        "int16" => "int16_t",
        "uint16" => "uint16_t",
        "int32" => "int32_t",
        "uint32" => "uint32_t",
        "int64" => "int64_t",
        "uint64" => "uint64_t",
        "BStr" => "intercom::BSTR",
        "HRESULT" => "intercom::HRESULT",
        _ => ty,
    }
}

/// Converts a guid to binarys representation.
fn guid_to_binary(
    g: &GUID
) -> String {

    format!( "{{0x{:08x},0x{:04x},0x{:04x},{{0x{:02x},0x{:02x},0x{:02x},0x{:02x},0x{:02x},0x{:02x},0x{:02x},0x{:02x}}}}}",
            g.data1, g.data2, g.data3,
            g.data4[0], g.data4[1], g.data4[2], g.data4[3],
            g.data4[4], g.data4[5], g.data4[6], g.data4[7] )
}
<commit_msg>Fixed unnecessary return statement<commit_after>
use std::collections::HashMap;
use parse::*;
use clap::ArgMatches;
use intercom_common::utils;
use intercom_common::guid::*;
use error::*;
use std::io;

/// Runs the 'cpp' subcommand.
pub fn run( cpp_params : &ArgMatches ) -> AppResult {

    // Parse the sources and convert the result into an IDL.
    let ( renames, result ) = parse_crate(
            cpp_params.value_of( "path" ).unwrap() )?;
    result_to_cpp( &result, &renames, &mut io::stdout() );

    Ok(())
}

/// Converts the parse result into an header  that gets written to stdout.
fn result_to_cpp(
    r : &ParseResult,
    rn : &HashMap<String, String>,
    out : &mut io::Write,
) {
    // Introduce all interfaces so we don't get errors on undeclared items.
    let itf_forward_declarations = r.interfaces.iter().map(|itf| {
        format!( "{}struct {};", get_indentation( 1 ), try_rename( rn, &itf.name ) )
    } ).collect::<Vec<_>>().join( "\n" );

    // Raw interfaces that give direct access to the components implemented in Rust.
    let itfs = r.interfaces.iter().map(|itf| {
        generate_raw_interface( rn, itf, 1 )
    } ).collect::<Vec<_>>().join( "\n" );

    // Generate class descriptors.
    let class_descriptors = r.class_names.iter().map(|class_name| {

        // Get the class details by matching the name.
        let class  = r.classes.iter().find(|cls| &cls.name == class_name )
            .unwrap();

        generate_class_descriptor( rn, &r.libname, class_name, class, 1 )
    } ).collect::<Vec<_>>().join( "\n" );

    // Generate using statements that flatten the raw interfaces
    // to mimic the results of a Microsoft MIDL compiler.
    let flat_interface_declarations = r.interfaces.iter().map(|itf| {
        flatten_interface( rn, &r.libname, itf, 1 )
    } ).collect::<Vec<_>>().join( "\n" );

    // Generate using statements that flatten the class descriptors
    // to mimic the results of a Microsoft MIDL compiler.
    let flat_class_descriptor_declarations = r.class_names.iter().map(|class_name| {

                // Get the class details by matching the name.
        let class  = r.classes.iter().find(|cls| &cls.name == class_name )
            .unwrap();

        flatten_class_descriptor( class_name, class, 1 )
    } ).collect::<Vec<_>>().join( "\n" );

    // We got the interfaces and classes. We can format and output the raw interfaces.
    let raw_namespace: String = format!( r###"
>       #include <intercom.h>
>       namespace {}
>       {{
>       namespace raw
>       {{
>       {}
>       {}
>       {}
>       }}
>       }}
>       #ifdef INTERCOM_FLATTEN_DECLARATIONS
>       {}
>       {}
>       #endif
>       "###,
        &r.libname, itf_forward_declarations, itfs, class_descriptors,
        flat_interface_declarations, flat_class_descriptor_declarations );
    let raw_namespace = raw_namespace.replace( ">       ", "" );
    writeln!( out, "{}", raw_namespace ).unwrap();
}

fn generate_raw_interface(
    rn : &HashMap<String, String>,
    interface: &Interface,
    base_indentation: usize
) -> String {

    // Now that we have methods sorted out, we can construct the final
    // interface definition.
    let indentation = get_indentation( base_indentation );
    let interface_text = format!( "{}struct {} : IUnknown\n{}{{\n{}static constexpr intercom::IID ID = {};\n\n{}\n{}}};\n",
            indentation, try_rename( rn, &interface.name ), indentation,
            get_indentation( base_indentation + 1 ), guid_to_binary( &interface.iid ),
            generate_raw_methods( interface, base_indentation + 1 ), indentation );
    interface_text
}

fn generate_raw_methods(
    itf: &Interface,
    indentation: usize
) -> String {

    // Get the method definitions for the current interface.
    itf.methods.iter().enumerate().map(|(_i,m)| {

        // Construct the argument list.
        let args = m.arguments.iter().map(|a| {

            // Argument direction affects both the argument attribute and
            // whether the argument is passed by pointer or value.
            let out_ptr = match a.dir {
                ArgDirection::In => "",
                ArgDirection::Out => "*",
                ArgDirection::Return => "*",
            };
            format!( "{}{} {}", to_cpp_type( &a.ty ), out_ptr, a.name )

        } ).collect::<Vec<_>>().join( ", " );

        // Format the method.
        // To maintain backwards compatibility all new methods should
        // be added to the end of the traits.
        format!( r###"{}virtual {} INTERCOM_CC {}( {} ) = 0;"###, get_indentation( indentation ), to_cpp_type( &m.rvalue ), utils::pascal_case( &m.name ), args )

    } ).collect::<Vec<_>>().join( "\n" )
}

fn flatten_interface(
    rn : &HashMap<String, String>,
    libname: &str,
    interface: &Interface,
    indentation: usize
) -> String {
    let interface_name = try_rename( rn, &interface.name );
    let using_iid = format!( "static constexpr intercom::IID IID_{} = {};",
            utils::pascal_case( &interface_name ), guid_to_binary( &interface.iid ) );
    let using_interface = format!( "using {} = {}::raw::{};", utils::pascal_case( &interface_name ), libname,  &interface_name );
    let indentation = get_indentation( indentation );
    format!("{}{}\n{}{}", indentation, using_iid, indentation, using_interface )
}

fn flatten_class_descriptor(
    class_name: &str,
    coclass: &CoClass,
    indentation: usize
) -> String {
    let using_clsid = format!( "static constexpr CLSID CLSID_{} = {};",
            utils::pascal_case( class_name ), guid_to_binary( &coclass.clsid ) );
    let indentation = get_indentation( indentation );
    format!("{}{}", indentation, using_clsid )
}

fn generate_class_descriptor(
    rn : &HashMap<String, String>,
    libname: &str,
    class_name: &str,
    coclass: &CoClass,
    indentation: usize
) -> String {

    // Create a list of interfaces to be declared in the class descriptor.
    let interfaces =  coclass.interfaces.iter().map(|itf| {
            format!( r###"{}{}::raw::{}::ID"###,
                &get_indentation( indentation + 2 ), libname, try_rename( rn, itf ) )
        } ).collect::<Vec<_>>().join( ",\n" );

    // Class descriptors hold information about COM classes implemented by the library.
    let clsid = guid_to_binary( &coclass.clsid );
    let class_descriptor: String = format!( r###"
>       class {}Descriptor
>       {{
>           static constexpr CLSID ID = {};

>           static constexpr std::array<intercom::IID, {}> INTERFACES = {{
{}
>           }};

>           {}Descriptor() = delete;
>           ~{}Descriptor() = delete;

>       }};
>       "###,
    class_name, clsid, coclass.interfaces.len(), interfaces, class_name, class_name );
    class_descriptor.replace( ">       ", &get_indentation( indentation ) )
}

/// Gets an empty string for ind One level of indentation is four spaces.
fn get_indentation(
    level: usize
) -> String {
    let spaces = level * 4;
    let indentation = format!( r###"{: <1$}"###, "", spaces );
    indentation
}

/// Converts a Rust type into applicable C++ type.
fn to_cpp_type(
    ty: &str
) -> &str {

    match ty {
        "int8" => "int8_t",
        "uint8" => "uint8_t",
        "int16" => "int16_t",
        "uint16" => "uint16_t",
        "int32" => "int32_t",
        "uint32" => "uint32_t",
        "int64" => "int64_t",
        "uint64" => "uint64_t",
        "BStr" => "intercom::BSTR",
        "HRESULT" => "intercom::HRESULT",
        _ => ty,
    }
}

/// Converts a guid to binarys representation.
fn guid_to_binary(
    g: &GUID
) -> String {

    format!( "{{0x{:08x},0x{:04x},0x{:04x},{{0x{:02x},0x{:02x},0x{:02x},0x{:02x},0x{:02x},0x{:02x},0x{:02x},0x{:02x}}}}}",
            g.data1, g.data2, g.data3,
            g.data4[0], g.data4[1], g.data4[2], g.data4[3],
            g.data4[4], g.data4[5], g.data4[6], g.data4[7] )
}
<|endoftext|>


<commit_before>
use std::num::Float;
use sdl::video::{Surface};
use sdl::event::{Key};

use world::{World};
use math::{LineSeg, Vec2, Mat3};
use input::{InputState};

const SPEED: f32 = 0.4;
const TURN: f32 = 0.03;

const FOV_DIV: f32 = 600.0;
const VISPLANE_DIST: f32 = 600.0;
const WALL_HEIGHT: f32 = 10.0;
const PERSON_HEIGHT: f32 = 5.0;

pub struct Game<'a> {
    pub pos: Vec2,
    pub face_angle: f32,
    pub world: &'a World,
    pub show_map: bool,
}

impl<'a> Game<'a> {
    pub fn step(&mut self, input: &InputState) {
        if input.has_key(Key::Left)  { self.face_angle -= TURN; }
        if input.has_key(Key::Right) { self.face_angle += TURN; }

        if input.has_key(Key::W) { self.do_move( 1.0,  0.0); }
        if input.has_key(Key::S) { self.do_move(-1.0,  0.0); }
        if input.has_key(Key::A) { self.do_move( 0.0, -1.0); }
        if input.has_key(Key::D) { self.do_move( 0.0,  1.0); }

        self.show_map = input.has_key(Key::Tab);
    }

    fn do_move(&mut self, para: f32, perp: f32) {
        let sin = SPEED*Float::sin(self.face_angle);
        let cos = SPEED*Float::cos(self.face_angle);
        self.pos.x +=  sin*para + cos*perp;
        self.pos.y += -cos*para + sin*perp;
    }

    pub fn render(&self, surf: &Surface) {
        if self.show_map {
            self.render_map(&surf);
        } else {
            self.render_game(&surf);
        }
    }

    fn render_map(&self, surf: &Surface) {
        let trans = Mat3::rotation(-self.face_angle)
                  * Mat3::translation(-self.pos);

        surf.clear();
        for wall in self.world.walls.iter() {
            draw_seg(&surf, wall.transform(trans), 0xFF, 0x00, 0x00);
        }

        let w = surf.get_width() as usize;
        for x in 0..w {
            let offset = ((x as f32) - (w as f32) / 2.0) / FOV_DIV;

            self.world.cast_ray(self.pos, self.face_angle + offset).map(|(_, pos, _)| {
                let draw_sg = LineSeg::new(self.pos.x, self.pos.y, pos.x, pos.y);
                draw_seg(&surf, draw_sg.transform(trans), 0x00, 0xFF, 0x00);
            });
        }
    }

    fn render_game(&self, surf: &Surface) {
        let w = surf.get_width() as usize;
        let h = surf.get_height() as usize;

        surf.clear();
        surf.with_lock(|pixels| {
            for x in 0..w {
                let offset = ((x as f32) - (w as f32) / 2.0) / FOV_DIV;

                let cast = self.world.cast_ray(self.pos, self.face_angle + offset);
                if !cast.is_some() { continue; }
                let (dist, hit_pos, along) = cast.unwrap();

                let cast_dist = dist * Float::cos(offset);
                let px_height = (VISPLANE_DIST * WALL_HEIGHT / cast_dist) as usize;
                let top = if h > px_height { (h - px_height) / 2 } else { 0 };
                let bottom = h - top;

                for y in 0..top { put_px(pixels, w, x, y,  0x00, 0x66, 0xFF); }

                let brightness = ((0xFF - top) as f32) / 255.0;
                for y in top..bottom {
                    let tex_lookup = ((along * 36.0) as u8)
                                   ^ ((255.0*(((y-top)as f32)/(bottom-top)as f32)) as u8);
                    let color = ((tex_lookup as f32) * brightness) as u8;
                    put_px(pixels, w, x, y, color, 0x00, 0x00);
                }

                for y in bottom..h {
                    let dist_floor = VISPLANE_DIST * PERSON_HEIGHT / ((y as f32) - (h as f32)/2.0);
                    let floor_pos = self.pos + (hit_pos - self.pos) * dist_floor / cast_dist;
                    let color = ((floor_pos.x * 10.0) as u8) ^ ((floor_pos.y * 10.0) as u8);
                    put_px(pixels, w, x, y, 0x00, color, 0x00);
                }
            }
            true
        });
    }
}

fn put_px(pixels: &mut [u8], w: usize, x: usize, y: usize, r: u8, g: u8, b: u8) {
    pixels[3*(w*y+x) + 0] = b;
    pixels[3*(w*y+x) + 1] = g;
    pixels[3*(w*y+x) + 2] = r;
}

fn draw_seg(surf: &Surface, seg: LineSeg, r: u8, g: u8, b: u8) {
    let w = surf.get_width() as usize;
    let h = surf.get_height() as usize;
    let len = seg.get_length();

    surf.with_lock(|pixels| {
        for t in 0..(len as usize) {
            let pt = seg.at(t as f32 / len);
            let ux = (pt.x + (w/2) as f32) as usize;
            let uy = (pt.y + (h/2) as f32) as usize;

            if ux < w && uy < h {
                put_px(pixels, w, ux, uy, r, g, b);
            }
        };
        true
    });
}
<commit_msg>Applied lighting to floor<commit_after>
use std::num::Float;
use sdl::video::{Surface};
use sdl::event::{Key};

use world::{World};
use math::{LineSeg, Vec2, Mat3};
use input::{InputState};

const SPEED: f32 = 0.4;
const TURN: f32 = 0.03;

const FOV_DIV: f32 = 600.0;
const VISPLANE_DIST: f32 = 600.0;
const WALL_HEIGHT: f32 = 10.0;
const PERSON_HEIGHT: f32 = 5.0;

pub struct Game<'a> {
    pub pos: Vec2,
    pub face_angle: f32,
    pub world: &'a World,
    pub show_map: bool,
}

impl<'a> Game<'a> {
    pub fn step(&mut self, input: &InputState) {
        if input.has_key(Key::Left)  { self.face_angle -= TURN; }
        if input.has_key(Key::Right) { self.face_angle += TURN; }

        if input.has_key(Key::W) { self.do_move( 1.0,  0.0); }
        if input.has_key(Key::S) { self.do_move(-1.0,  0.0); }
        if input.has_key(Key::A) { self.do_move( 0.0, -1.0); }
        if input.has_key(Key::D) { self.do_move( 0.0,  1.0); }

        self.show_map = input.has_key(Key::Tab);
    }

    fn do_move(&mut self, para: f32, perp: f32) {
        let sin = SPEED*Float::sin(self.face_angle);
        let cos = SPEED*Float::cos(self.face_angle);
        self.pos.x +=  sin*para + cos*perp;
        self.pos.y += -cos*para + sin*perp;
    }

    pub fn render(&self, surf: &Surface) {
        if self.show_map {
            self.render_map(&surf);
        } else {
            self.render_game(&surf);
        }
    }

    fn render_map(&self, surf: &Surface) {
        let trans = Mat3::rotation(-self.face_angle)
                  * Mat3::translation(-self.pos);

        surf.clear();
        for wall in self.world.walls.iter() {
            draw_seg(&surf, wall.transform(trans), 0xFF, 0x00, 0x00);
        }

        let w = surf.get_width() as usize;
        for x in 0..w {
            let offset = ((x as f32) - (w as f32) / 2.0) / FOV_DIV;

            self.world.cast_ray(self.pos, self.face_angle + offset).map(|(_, pos, _)| {
                let draw_sg = LineSeg::new(self.pos.x, self.pos.y, pos.x, pos.y);
                draw_seg(&surf, draw_sg.transform(trans), 0x00, 0xFF, 0x00);
            });
        }
    }

    fn render_game(&self, surf: &Surface) {
        let w = surf.get_width() as usize;
        let h = surf.get_height() as usize;

        surf.clear();
        surf.with_lock(|pixels| {
            for x in 0..w {
                let offset = ((x as f32) - (w as f32) / 2.0) / FOV_DIV;

                let cast = self.world.cast_ray(self.pos, self.face_angle + offset);
                if !cast.is_some() { continue; }
                let (dist, hit_pos, along) = cast.unwrap();

                let cast_dist = dist * Float::cos(offset);
                let px_height = (VISPLANE_DIST * WALL_HEIGHT / cast_dist) as usize;
                let top = if h > px_height { (h - px_height) / 2 } else { 0 };
                let bottom = h - top;

                for y in 0..top { put_px(pixels, w, x, y,  0x00, 0x66, 0xFF); }

                let brightness = ((0xFF - top) as f32) / 255.0;
                for y in top..bottom {
                    let tex_lookup = ((along * 36.0) as u8)
                                   ^ ((255.0*(((y-top)as f32)/(bottom-top)as f32)) as u8);
                    let color = ((tex_lookup as f32) * brightness) as u8;
                    put_px(pixels, w, x, y, color, 0x00, 0x00);
                }

                for y in bottom..h {
                    let dist_floor = VISPLANE_DIST * PERSON_HEIGHT / ((y as f32) - (h as f32)/2.0);
                    let brightness = ((0xFF - (h-y)) as f32) / 255.0;
                    let floor_pos = self.pos + (hit_pos - self.pos) * dist_floor / cast_dist;
                    let tex_lookup = ((floor_pos.x * 10.0) as u8) ^ ((floor_pos.y * 10.0) as u8);
                    let color = ((tex_lookup as f32) * brightness) as u8;
                    put_px(pixels, w, x, y, 0x00, color, 0x00);
                }
            }
            true
        });
    }
}

fn put_px(pixels: &mut [u8], w: usize, x: usize, y: usize, r: u8, g: u8, b: u8) {
    pixels[3*(w*y+x) + 0] = b;
    pixels[3*(w*y+x) + 1] = g;
    pixels[3*(w*y+x) + 2] = r;
}

fn draw_seg(surf: &Surface, seg: LineSeg, r: u8, g: u8, b: u8) {
    let w = surf.get_width() as usize;
    let h = surf.get_height() as usize;
    let len = seg.get_length();

    surf.with_lock(|pixels| {
        for t in 0..(len as usize) {
            let pt = seg.at(t as f32 / len);
            let ux = (pt.x + (w/2) as f32) as usize;
            let uy = (pt.y + (h/2) as f32) as usize;

            if ux < w && uy < h {
                put_px(pixels, w, ux, uy, r, g, b);
            }
        };
        true
    });
}
<|endoftext|>


<commit_before>//! IPC for way-cooler

use std::thread;
use std::env;
use std::path::PathBuf;
use std::fs;

use unix_socket::UnixListener;

mod channel;
mod command;
mod event;

#[cfg(test)]
mod tests;

/// Versions are incremented.
pub const VERSION: u64 = 0u64; // Increment to 1 on release.

/// Very much not cross-platform!
/// Submit an issue when Wayland is ported to Windoze.
pub const TEMP_FOLDER: &'static str = "/tmp/way-cooler/";
/// Socket over which synchronous communication is made with clients.
pub const COMMAND_SOCKET: &'static str = "command";
/// Socket over which events are sent to clients.
pub const EVENT_SOCKET: &'static str = "event";
/// Folder in which sockets are created
pub const PATH_VAR: &'static str = "WAY_COOLER_TEMPFOLDER";
/// We need random folder names to place sockets in, but they don't need
/// to be _that_ random.
pub fn unique_ish_id() -> u32 {
    use std::hash::{Hash, Hasher, SipHasher};
    use std::time::Instant;

    // If you shift a u64 hash right by this you get a "checksum",
    // a number which retains some of the entropy of the hash but
    // is small enough to fit a more comfortable file name.
    const MAGIC_SHIFT_NUMBER: u64 = 0b110000;

    // Instant doesn't implement hash, and it's supposed to be an opaque
    // struct, but it does implement debug...
    let now = Instant::now();
    let mut hasher = SipHasher::new();
    format!("{:?}", now).hash(&mut hasher);
    (hasher.finish() >> MAGIC_SHIFT_NUMBER) as u32
}

/// Initialize the Lua server.
pub fn init() {
    trace!("Initializing way-cooler IPC...");
    let id = unique_ish_id();
    info!("Starting IPC with unique ID {}", id);

    let mut path = PathBuf::from(TEMP_FOLDER);
    path.push(id.to_string());

    env::set_var(PATH_VAR, path.clone());

    if let Err(ioerr) = fs::create_dir_all(path.clone()) {
        // How can we handle not having a socket?
        // In the future, we could log and continue.
        // We could have a config option to not create/create-if-possible
        error!("Unable to create temp folder: {:?}", ioerr);
        return;
    }
    else {
        let command_socket = UnixListener::bind(path.join(COMMAND_SOCKET))
            .expect("Unable to open command socket!");

        let event_socket = UnixListener::bind(path.join(EVENT_SOCKET))
            .expect("Unable to open event socket!");

        debug!("IPC initialized, now listening for clients.");

        let _server_handle = thread::Builder::new()
            .name("Command socket listener".to_string())
            .spawn(move || { command_thread(command_socket) });

        let _event_handle = thread::Builder::new()
            .name("Event socket listener".to_string())
            .spawn(move || { event_thread(event_socket) });

        trace!("IPC initialized.");
    }
}

fn command_thread(socket: UnixListener) {
    for stream in socket.incoming() {
        trace!("Sever: new connection: {:?}", stream);
        match stream {
            Ok(mut stream) => {
                info!("Command: connected to {:?}", stream);
                let _handle = thread::Builder::new()
                    .name("IPC server helper".to_string())
                    .spawn(move || command::thread(&mut stream));
            },
            Err(err) => {
                info!("Error receiving a stream: {}", err);
            }
        }
    }
}

fn event_thread(socket: UnixListener) {
    for stream in socket.incoming() {
        trace!("Event: new connection: {:?}", stream);
        match stream {
            Ok(mut stream) => {
                info!("Event: connected to {:?}", stream);
                let _handle = thread::Builder::new()
                    .name("IPC evemt helper".to_string())
                    .spawn(move || event::thread(&mut stream));
            },
            Err(err) => {
                info!("Error receiving a stream: {}", err);
            }
        }
    }
}
<commit_msg>Change socket path to /run<commit_after>//! IPC for way-cooler

use std::thread;
use std::env;
use std::path::PathBuf;
use std::fs;

use unix_socket::UnixListener;

mod channel;
mod command;
mod event;

#[cfg(test)]
mod tests;

/// Versions are incremented.
pub const VERSION: u64 = 0u64; // Increment to 1 on release.

/// Very much not cross-platform!
/// Submit an issue when Wayland is ported to Windoze.
pub const TEMP_FOLDER: &'static str = "/run/way-cooler/";
/// Socket over which synchronous communication is made with clients.
pub const COMMAND_SOCKET: &'static str = "command";
/// Socket over which events are sent to clients.
pub const EVENT_SOCKET: &'static str = "event";
/// Folder in which sockets are created
pub const PATH_VAR: &'static str = "WAY_COOLER_SOCKET_FOLDER";
/// We need random folder names to place sockets in, but they don't need
/// to be _that_ random.
pub fn unique_ish_id() -> u32 {
    use std::hash::{Hash, Hasher, SipHasher};
    use std::time::Instant;

    // If you shift a u64 hash right by this you get a "checksum",
    // a number which retains some of the entropy of the hash but
    // is small enough to fit a more comfortable file name.
    const MAGIC_SHIFT_NUMBER: u64 = 0b110000;

    // Instant doesn't implement hash, and it's supposed to be an opaque
    // struct, but it does implement debug...
    let now = Instant::now();
    let mut hasher = SipHasher::new();
    format!("{:?}", now).hash(&mut hasher);
    (hasher.finish() >> MAGIC_SHIFT_NUMBER) as u32
}

/// Initialize the Lua server.
pub fn init() {
    trace!("Initializing way-cooler IPC...");
    let id = unique_ish_id();
    info!("Starting IPC with unique ID {}", id);

    let mut path = PathBuf::from(TEMP_FOLDER);
    path.push(id.to_string());

    if let Err(ioerr) = fs::create_dir_all(path.clone()) {
        // How can we handle not having a socket?
        // In the future, we could log and continue.
        // We could have a config option to not create/create-if-possible
        error!("Unable to create temp folder: {:?}", ioerr);
        return;
    }
    else {
        let command_socket = UnixListener::bind(path.join(COMMAND_SOCKET))
            .expect("Unable to open command socket!");

        let event_socket = UnixListener::bind(path.join(EVENT_SOCKET))
            .expect("Unable to open event socket!");

        env::set_var(PATH_VAR, path.clone());

        debug!("IPC initialized, now listening for clients.");

        let _server_handle = thread::Builder::new()
            .name("Command socket listener".to_string())
            .spawn(move || { command_thread(command_socket) });

        let _event_handle = thread::Builder::new()
            .name("Event socket listener".to_string())
            .spawn(move || { event_thread(event_socket) });

        trace!("IPC initialized.");
    }
}

fn command_thread(socket: UnixListener) {
    for stream in socket.incoming() {
        trace!("Sever: new connection: {:?}", stream);
        match stream {
            Ok(mut stream) => {
                info!("Command: connected to {:?}", stream);
                let _handle = thread::Builder::new()
                    .name("IPC server helper".to_string())
                    .spawn(move || command::thread(&mut stream));
            },
            Err(err) => {
                info!("Error receiving a stream: {}", err);
            }
        }
    }
}

fn event_thread(socket: UnixListener) {
    for stream in socket.incoming() {
        trace!("Event: new connection: {:?}", stream);
        match stream {
            Ok(mut stream) => {
                info!("Event: connected to {:?}", stream);
                let _handle = thread::Builder::new()
                    .name("IPC evemt helper".to_string())
                    .spawn(move || event::thread(&mut stream));
            },
            Err(err) => {
                info!("Error receiving a stream: {}", err);
            }
        }
    }
}
<|endoftext|>


<commit_before>//! The default matrix data storage allocator.
//!
//! This will use stack-allocated buffers for matrices with dimensions known at compile-time, and
//! heap-allocated buffers for matrices with at least one dimension unknown at compile-time.

use std::cmp;
use std::mem;
use std::ops::Mul;
use std::ptr;

#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::vec::Vec;

use generic_array::ArrayLength;
use typenum::Prod;

use crate::base::allocator::{Allocator, Reallocator};
#[cfg(any(feature = "alloc", feature = "std"))]
use crate::base::dimension::Dynamic;
use crate::base::dimension::{Dim, DimName};
use crate::base::array_storage::ArrayStorage;
#[cfg(any(feature = "std", feature = "alloc"))]
use crate::base::vec_storage::VecStorage;
use crate::base::storage::{Storage, StorageMut};
use crate::base::Scalar;

/*
 *
 * Allocator.
 *
 */
/// An allocator based on `GenericArray` and `VecStorage` for statically-sized and dynamically-sized
/// matrices respectively.
pub struct DefaultAllocator;

// Static - Static
impl<N, R, C> Allocator<N, R, C> for DefaultAllocator
where
    N: Scalar,
    R: DimName,
    C: DimName,
    R::Value: Mul<C::Value>,
    Prod<R::Value, C::Value>: ArrayLength<N>,
{
    type Buffer = ArrayStorage<N, R, C>;

    #[inline]
    unsafe fn allocate_uninitialized(_: R, _: C) -> Self::Buffer {
        mem::MaybeUninit::<Self::Buffer>::uninit().assume_init()
    }

    #[inline]
    fn allocate_from_iterator<I: IntoIterator<Item = N>>(
        nrows: R,
        ncols: C,
        iter: I,
    ) -> Self::Buffer
    {
        let mut res = unsafe { Self::allocate_uninitialized(nrows, ncols) };
        let mut count = 0;

        for (res, e) in res.iter_mut().zip(iter.into_iter()) {
            *res = e;
            count += 1;
        }

        assert!(
            count == nrows.value() * ncols.value(),
            "Matrix init. from iterator: iterator not long enough."
        );

        res
    }
}

// Dynamic - Static
// Dynamic - Dynamic
#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, C: Dim> Allocator<N, Dynamic, C> for DefaultAllocator {
    type Buffer = VecStorage<N, Dynamic, C>;

    #[inline]
    unsafe fn allocate_uninitialized(nrows: Dynamic, ncols: C) -> Self::Buffer {
        let mut res = Vec::new();
        let length = nrows.value() * ncols.value();
        res.reserve_exact(length);
        res.set_len(length);

        VecStorage::new(nrows, ncols, res)
    }

    #[inline]
    fn allocate_from_iterator<I: IntoIterator<Item = N>>(
        nrows: Dynamic,
        ncols: C,
        iter: I,
    ) -> Self::Buffer
    {
        let it = iter.into_iter();
        let res: Vec<N> = it.collect();
        assert!(res.len() == nrows.value() * ncols.value(),
                "Allocation from iterator error: the iterator did not yield the correct number of elements.");

        VecStorage::new(nrows, ncols, res)
    }
}

// Static - Dynamic
#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, R: DimName> Allocator<N, R, Dynamic> for DefaultAllocator {
    type Buffer = VecStorage<N, R, Dynamic>;

    #[inline]
    unsafe fn allocate_uninitialized(nrows: R, ncols: Dynamic) -> Self::Buffer {
        let mut res = Vec::new();
        let length = nrows.value() * ncols.value();
        res.reserve_exact(length);
        res.set_len(length);

        VecStorage::new(nrows, ncols, res)
    }

    #[inline]
    fn allocate_from_iterator<I: IntoIterator<Item = N>>(
        nrows: R,
        ncols: Dynamic,
        iter: I,
    ) -> Self::Buffer
    {
        let it = iter.into_iter();
        let res: Vec<N> = it.collect();
        assert!(res.len() == nrows.value() * ncols.value(),
                "Allocation from iterator error: the iterator did not yield the correct number of elements.");

        VecStorage::new(nrows, ncols, res)
    }
}

/*
 *
 * Reallocator.
 *
 */
// Anything -> Static × Static
impl<N: Scalar, RFrom, CFrom, RTo, CTo> Reallocator<N, RFrom, CFrom, RTo, CTo> for DefaultAllocator
where
    RFrom: Dim,
    CFrom: Dim,
    RTo: DimName,
    CTo: DimName,
    Self: Allocator<N, RFrom, CFrom>,
    RTo::Value: Mul<CTo::Value>,
    Prod<RTo::Value, CTo::Value>: ArrayLength<N>,
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: RTo,
        cto: CTo,
        buf: <Self as Allocator<N, RFrom, CFrom>>::Buffer,
    ) -> ArrayStorage<N, RTo, CTo>
    {
        let mut res = <Self as Allocator<N, RTo, CTo>>::allocate_uninitialized(rto, cto);

        let (rfrom, cfrom) = buf.shape();

        let len_from = rfrom.value() * cfrom.value();
        let len_to = rto.value() * cto.value();
        ptr::copy_nonoverlapping(buf.ptr(), res.ptr_mut(), cmp::min(len_from, len_to));

        res
    }
}

// Static × Static -> Dynamic × Any
#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, RFrom, CFrom, CTo> Reallocator<N, RFrom, CFrom, Dynamic, CTo> for DefaultAllocator
where
    RFrom: DimName,
    CFrom: DimName,
    CTo: Dim,
    RFrom::Value: Mul<CFrom::Value>,
    Prod<RFrom::Value, CFrom::Value>: ArrayLength<N>,
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: Dynamic,
        cto: CTo,
        buf: ArrayStorage<N, RFrom, CFrom>,
    ) -> VecStorage<N, Dynamic, CTo>
    {
        let mut res = <Self as Allocator<N, Dynamic, CTo>>::allocate_uninitialized(rto, cto);

        let (rfrom, cfrom) = buf.shape();

        let len_from = rfrom.value() * cfrom.value();
        let len_to = rto.value() * cto.value();
        ptr::copy_nonoverlapping(buf.ptr(), res.ptr_mut(), cmp::min(len_from, len_to));

        res
    }
}

// Static × Static -> Static × Dynamic
#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, RFrom, CFrom, RTo> Reallocator<N, RFrom, CFrom, RTo, Dynamic> for DefaultAllocator
where
    RFrom: DimName,
    CFrom: DimName,
    RTo: DimName,
    RFrom::Value: Mul<CFrom::Value>,
    Prod<RFrom::Value, CFrom::Value>: ArrayLength<N>,
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: RTo,
        cto: Dynamic,
        buf: ArrayStorage<N, RFrom, CFrom>,
    ) -> VecStorage<N, RTo, Dynamic>
    {
        let mut res = <Self as Allocator<N, RTo, Dynamic>>::allocate_uninitialized(rto, cto);

        let (rfrom, cfrom) = buf.shape();

        let len_from = rfrom.value() * cfrom.value();
        let len_to = rto.value() * cto.value();
        ptr::copy_nonoverlapping(buf.ptr(), res.ptr_mut(), cmp::min(len_from, len_to));

        res
    }
}

// All conversion from a dynamic buffer to a dynamic buffer.
#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, CFrom: Dim, CTo: Dim> Reallocator<N, Dynamic, CFrom, Dynamic, CTo>
    for DefaultAllocator
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: Dynamic,
        cto: CTo,
        buf: VecStorage<N, Dynamic, CFrom>,
    ) -> VecStorage<N, Dynamic, CTo>
    {
        let new_buf = buf.resize(rto.value() * cto.value());
        VecStorage::new(rto, cto, new_buf)
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, CFrom: Dim, RTo: DimName> Reallocator<N, Dynamic, CFrom, RTo, Dynamic>
    for DefaultAllocator
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: RTo,
        cto: Dynamic,
        buf: VecStorage<N, Dynamic, CFrom>,
    ) -> VecStorage<N, RTo, Dynamic>
    {
        let new_buf = buf.resize(rto.value() * cto.value());
        VecStorage::new(rto, cto, new_buf)
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, RFrom: DimName, CTo: Dim> Reallocator<N, RFrom, Dynamic, Dynamic, CTo>
    for DefaultAllocator
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: Dynamic,
        cto: CTo,
        buf: VecStorage<N, RFrom, Dynamic>,
    ) -> VecStorage<N, Dynamic, CTo>
    {
        let new_buf = buf.resize(rto.value() * cto.value());
        VecStorage::new(rto, cto, new_buf)
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, RFrom: DimName, RTo: DimName> Reallocator<N, RFrom, Dynamic, RTo, Dynamic>
    for DefaultAllocator
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: RTo,
        cto: Dynamic,
        buf: VecStorage<N, RFrom, Dynamic>,
    ) -> VecStorage<N, RTo, Dynamic>
    {
        let new_buf = buf.resize(rto.value() * cto.value());
        VecStorage::new(rto, cto, new_buf)
    }
}
<commit_msg>Add TODO notice and reference to issue<commit_after>//! The default matrix data storage allocator.
//!
//! This will use stack-allocated buffers for matrices with dimensions known at compile-time, and
//! heap-allocated buffers for matrices with at least one dimension unknown at compile-time.

use std::cmp;
use std::mem;
use std::ops::Mul;
use std::ptr;

#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::vec::Vec;

use generic_array::ArrayLength;
use typenum::Prod;

use crate::base::allocator::{Allocator, Reallocator};
#[cfg(any(feature = "alloc", feature = "std"))]
use crate::base::dimension::Dynamic;
use crate::base::dimension::{Dim, DimName};
use crate::base::array_storage::ArrayStorage;
#[cfg(any(feature = "std", feature = "alloc"))]
use crate::base::vec_storage::VecStorage;
use crate::base::storage::{Storage, StorageMut};
use crate::base::Scalar;

/*
 *
 * Allocator.
 *
 */
/// An allocator based on `GenericArray` and `VecStorage` for statically-sized and dynamically-sized
/// matrices respectively.
pub struct DefaultAllocator;

// Static - Static
impl<N, R, C> Allocator<N, R, C> for DefaultAllocator
where
    N: Scalar,
    R: DimName,
    C: DimName,
    R::Value: Mul<C::Value>,
    Prod<R::Value, C::Value>: ArrayLength<N>,
{
    type Buffer = ArrayStorage<N, R, C>;

    #[inline]
    unsafe fn allocate_uninitialized(_: R, _: C) -> Self::Buffer {
        // TODO: Undefined behavior, see #556
        mem::MaybeUninit::<Self::Buffer>::uninit().assume_init()
    }

    #[inline]
    fn allocate_from_iterator<I: IntoIterator<Item = N>>(
        nrows: R,
        ncols: C,
        iter: I,
    ) -> Self::Buffer
    {
        let mut res = unsafe { Self::allocate_uninitialized(nrows, ncols) };
        let mut count = 0;

        for (res, e) in res.iter_mut().zip(iter.into_iter()) {
            *res = e;
            count += 1;
        }

        assert!(
            count == nrows.value() * ncols.value(),
            "Matrix init. from iterator: iterator not long enough."
        );

        res
    }
}

// Dynamic - Static
// Dynamic - Dynamic
#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, C: Dim> Allocator<N, Dynamic, C> for DefaultAllocator {
    type Buffer = VecStorage<N, Dynamic, C>;

    #[inline]
    unsafe fn allocate_uninitialized(nrows: Dynamic, ncols: C) -> Self::Buffer {
        let mut res = Vec::new();
        let length = nrows.value() * ncols.value();
        res.reserve_exact(length);
        res.set_len(length);

        VecStorage::new(nrows, ncols, res)
    }

    #[inline]
    fn allocate_from_iterator<I: IntoIterator<Item = N>>(
        nrows: Dynamic,
        ncols: C,
        iter: I,
    ) -> Self::Buffer
    {
        let it = iter.into_iter();
        let res: Vec<N> = it.collect();
        assert!(res.len() == nrows.value() * ncols.value(),
                "Allocation from iterator error: the iterator did not yield the correct number of elements.");

        VecStorage::new(nrows, ncols, res)
    }
}

// Static - Dynamic
#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, R: DimName> Allocator<N, R, Dynamic> for DefaultAllocator {
    type Buffer = VecStorage<N, R, Dynamic>;

    #[inline]
    unsafe fn allocate_uninitialized(nrows: R, ncols: Dynamic) -> Self::Buffer {
        let mut res = Vec::new();
        let length = nrows.value() * ncols.value();
        res.reserve_exact(length);
        res.set_len(length);

        VecStorage::new(nrows, ncols, res)
    }

    #[inline]
    fn allocate_from_iterator<I: IntoIterator<Item = N>>(
        nrows: R,
        ncols: Dynamic,
        iter: I,
    ) -> Self::Buffer
    {
        let it = iter.into_iter();
        let res: Vec<N> = it.collect();
        assert!(res.len() == nrows.value() * ncols.value(),
                "Allocation from iterator error: the iterator did not yield the correct number of elements.");

        VecStorage::new(nrows, ncols, res)
    }
}

/*
 *
 * Reallocator.
 *
 */
// Anything -> Static × Static
impl<N: Scalar, RFrom, CFrom, RTo, CTo> Reallocator<N, RFrom, CFrom, RTo, CTo> for DefaultAllocator
where
    RFrom: Dim,
    CFrom: Dim,
    RTo: DimName,
    CTo: DimName,
    Self: Allocator<N, RFrom, CFrom>,
    RTo::Value: Mul<CTo::Value>,
    Prod<RTo::Value, CTo::Value>: ArrayLength<N>,
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: RTo,
        cto: CTo,
        buf: <Self as Allocator<N, RFrom, CFrom>>::Buffer,
    ) -> ArrayStorage<N, RTo, CTo>
    {
        let mut res = <Self as Allocator<N, RTo, CTo>>::allocate_uninitialized(rto, cto);

        let (rfrom, cfrom) = buf.shape();

        let len_from = rfrom.value() * cfrom.value();
        let len_to = rto.value() * cto.value();
        ptr::copy_nonoverlapping(buf.ptr(), res.ptr_mut(), cmp::min(len_from, len_to));

        res
    }
}

// Static × Static -> Dynamic × Any
#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, RFrom, CFrom, CTo> Reallocator<N, RFrom, CFrom, Dynamic, CTo> for DefaultAllocator
where
    RFrom: DimName,
    CFrom: DimName,
    CTo: Dim,
    RFrom::Value: Mul<CFrom::Value>,
    Prod<RFrom::Value, CFrom::Value>: ArrayLength<N>,
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: Dynamic,
        cto: CTo,
        buf: ArrayStorage<N, RFrom, CFrom>,
    ) -> VecStorage<N, Dynamic, CTo>
    {
        let mut res = <Self as Allocator<N, Dynamic, CTo>>::allocate_uninitialized(rto, cto);

        let (rfrom, cfrom) = buf.shape();

        let len_from = rfrom.value() * cfrom.value();
        let len_to = rto.value() * cto.value();
        ptr::copy_nonoverlapping(buf.ptr(), res.ptr_mut(), cmp::min(len_from, len_to));

        res
    }
}

// Static × Static -> Static × Dynamic
#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, RFrom, CFrom, RTo> Reallocator<N, RFrom, CFrom, RTo, Dynamic> for DefaultAllocator
where
    RFrom: DimName,
    CFrom: DimName,
    RTo: DimName,
    RFrom::Value: Mul<CFrom::Value>,
    Prod<RFrom::Value, CFrom::Value>: ArrayLength<N>,
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: RTo,
        cto: Dynamic,
        buf: ArrayStorage<N, RFrom, CFrom>,
    ) -> VecStorage<N, RTo, Dynamic>
    {
        let mut res = <Self as Allocator<N, RTo, Dynamic>>::allocate_uninitialized(rto, cto);

        let (rfrom, cfrom) = buf.shape();

        let len_from = rfrom.value() * cfrom.value();
        let len_to = rto.value() * cto.value();
        ptr::copy_nonoverlapping(buf.ptr(), res.ptr_mut(), cmp::min(len_from, len_to));

        res
    }
}

// All conversion from a dynamic buffer to a dynamic buffer.
#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, CFrom: Dim, CTo: Dim> Reallocator<N, Dynamic, CFrom, Dynamic, CTo>
    for DefaultAllocator
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: Dynamic,
        cto: CTo,
        buf: VecStorage<N, Dynamic, CFrom>,
    ) -> VecStorage<N, Dynamic, CTo>
    {
        let new_buf = buf.resize(rto.value() * cto.value());
        VecStorage::new(rto, cto, new_buf)
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, CFrom: Dim, RTo: DimName> Reallocator<N, Dynamic, CFrom, RTo, Dynamic>
    for DefaultAllocator
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: RTo,
        cto: Dynamic,
        buf: VecStorage<N, Dynamic, CFrom>,
    ) -> VecStorage<N, RTo, Dynamic>
    {
        let new_buf = buf.resize(rto.value() * cto.value());
        VecStorage::new(rto, cto, new_buf)
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, RFrom: DimName, CTo: Dim> Reallocator<N, RFrom, Dynamic, Dynamic, CTo>
    for DefaultAllocator
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: Dynamic,
        cto: CTo,
        buf: VecStorage<N, RFrom, Dynamic>,
    ) -> VecStorage<N, Dynamic, CTo>
    {
        let new_buf = buf.resize(rto.value() * cto.value());
        VecStorage::new(rto, cto, new_buf)
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl<N: Scalar, RFrom: DimName, RTo: DimName> Reallocator<N, RFrom, Dynamic, RTo, Dynamic>
    for DefaultAllocator
{
    #[inline]
    unsafe fn reallocate_copy(
        rto: RTo,
        cto: Dynamic,
        buf: VecStorage<N, RFrom, Dynamic>,
    ) -> VecStorage<N, RTo, Dynamic>
    {
        let new_buf = buf.resize(rto.value() * cto.value());
        VecStorage::new(rto, cto, new_buf)
    }
}
<|endoftext|>