<commit_before>use std::cell::RefCell;
use std::rc::Rc;

use actix_http::{Error, Response};
use actix_service::boxed::{self, BoxedNewService, BoxedService};
use actix_service::{
    ApplyTransform, IntoNewService, IntoTransform, NewService, Service, Transform,
};
use futures::future::{ok, Either, FutureResult};
use futures::{Async, Future, IntoFuture, Poll};

use crate::dev::{insert_slash, HttpServiceFactory, ResourceDef, ServiceConfig};
use crate::extract::FromRequest;
use crate::guard::Guard;
use crate::handler::{AsyncFactory, Factory};
use crate::responder::Responder;
use crate::route::{CreateRouteService, Route, RouteService};
use crate::service::{ServiceRequest, ServiceResponse};

type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, Error>;
type HttpNewService<P> =
    BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;

/// *Resource* is an entry in resources table which corresponds to requested URL.
///
/// Resource in turn has at least one route.
/// Route consists of an handlers objects and list of guards
/// (objects that implement `Guard` trait).
/// Resources and rouets uses builder-like pattern for configuration.
/// During request handling, resource object iterate through all routes
/// and check guards for specific route, if request matches all
/// guards, route considered matched and route handler get called.
///
/// ```rust
/// use actix_web::{web, App, HttpResponse};
///
/// fn main() {
///     let app = App::new().service(
///         web::resource("/")
///             .route(web::get().to(|| HttpResponse::Ok())));
/// }
pub struct Resource<P, T = ResourceEndpoint<P>> {
    endpoint: T,
    rdef: String,
    name: Option<String>,
    routes: Vec<Route<P>>,
    guards: Vec<Box<Guard>>,
    default: Rc<RefCell<Option<Rc<HttpNewService<P>>>>>,
    factory_ref: Rc<RefCell<Option<ResourceFactory<P>>>>,
}

impl<P> Resource<P> {
    pub fn new(path: &str) -> Resource<P> {
        let fref = Rc::new(RefCell::new(None));

        Resource {
            routes: Vec::new(),
            rdef: path.to_string(),
            name: None,
            endpoint: ResourceEndpoint::new(fref.clone()),
            factory_ref: fref,
            guards: Vec::new(),
            default: Rc::new(RefCell::new(None)),
        }
    }
}

impl<P, T> Resource<P, T>
where
    P: 'static,
    T: NewService<
        Request = ServiceRequest<P>,
        Response = ServiceResponse,
        Error = Error,
        InitError = (),
    >,
{
    /// Set resource name.
    ///
    /// Name is used for url generation.
    pub fn name(mut self, name: &str) -> Self {
        self.name = Some(name.to_string());
        self
    }

    /// Add match guard to a resource.
    ///
    /// ```rust
    /// use actix_web::{web, guard, App, HttpResponse};
    ///
    /// fn index(data: web::Path<(String, String)>) -> &'static str {
    ///     "Welcome!"
    /// }
    ///
    /// fn main() {
    ///     let app = App::new()
    ///         .service(
    ///             web::resource("/app")
    ///                 .guard(guard::Header("content-type", "text/plain"))
    ///                 .route(web::get().to(index))
    ///         )
    ///         .service(
    ///             web::resource("/app")
    ///                 .guard(guard::Header("content-type", "text/json"))
    ///                 .route(web::get().to(|| HttpResponse::MethodNotAllowed()))
    ///         );
    /// }
    /// ```
    pub fn guard<G: Guard + 'static>(mut self, guard: G) -> Self {
        self.guards.push(Box::new(guard));
        self
    }

    pub(crate) fn add_guards(mut self, guards: Vec<Box<Guard>>) -> Self {
        self.guards.extend(guards);
        self
    }

    /// Register a new route.
    ///
    /// ```rust
    /// use actix_web::{web, guard, App, HttpResponse};
    ///
    /// fn main() {
    ///     let app = App::new().service(
    ///         web::resource("/").route(
    ///             web::route()
    ///                 .guard(guard::Any(guard::Get()).or(guard::Put()))
    ///                 .guard(guard::Header("Content-Type", "text/plain"))
    ///                 .to(|| HttpResponse::Ok()))
    ///     );
    /// }
    /// ```
    ///
    /// Multiple routes could be added to a resource. Resource object uses
    /// match guards for route selection.
    ///
    /// ```rust
    /// use actix_web::{web, guard, App, HttpResponse};
    ///
    /// fn main() {
    ///     let app = App::new().service(
    ///         web::resource("/container/")
    ///              .route(web::get().to(get_handler))
    ///              .route(web::post().to(post_handler))
    ///              .route(web::delete().to(delete_handler))
    ///     );
    /// }
    /// # fn get_handler() {}
    /// # fn post_handler() {}
    /// # fn delete_handler() {}
    /// ```
    pub fn route(mut self, route: Route<P>) -> Self {
        self.routes.push(route.finish());
        self
    }

    /// Register a new route and add handler. This route matches all requests.
    ///
    /// ```rust
    /// use actix_web::*;
    ///
    /// fn index(req: HttpRequest) -> HttpResponse {
    ///     unimplemented!()
    /// }
    ///
    /// App::new().service(web::resource("/").to(index));
    /// ```
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// # use actix_web::*;
    /// # fn index(req: HttpRequest) -> HttpResponse { unimplemented!() }
    /// App::new().service(web::resource("/").route(web::route().to(index)));
    /// ```
    pub fn to<F, I, R>(mut self, handler: F) -> Self
    where
        F: Factory<I, R> + 'static,
        I: FromRequest<P> + 'static,
        R: Responder + 'static,
    {
        self.routes.push(Route::new().to(handler));
        self
    }

    /// Register a new route and add async handler.
    ///
    /// ```rust
    /// use actix_web::*;
    /// use futures::future::{ok, Future};
    ///
    /// fn index(req: HttpRequest) -> impl Future<Item=HttpResponse, Error=Error> {
    ///     ok(HttpResponse::Ok().finish())
    /// }
    ///
    /// App::new().service(web::resource("/").to_async(index));
    /// ```
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # use actix_web::*;
    /// # use futures::future::Future;
    /// # fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
    /// #     unimplemented!()
    /// # }
    /// App::new().service(web::resource("/").route(web::route().to_async(index)));
    /// ```
    #[allow(clippy::wrong_self_convention)]
    pub fn to_async<F, I, R>(mut self, handler: F) -> Self
    where
        F: AsyncFactory<I, R>,
        I: FromRequest<P> + 'static,
        R: IntoFuture + 'static,
        R::Item: Into<Response>,
        R::Error: Into<Error>,
    {
        self.routes.push(Route::new().to_async(handler));
        self
    }

    /// Register a resource middleware.
    ///
    /// This is similar to `App's` middlewares, but middleware get invoked on resource level.
    /// Resource level middlewares are not allowed to change response
    /// type (i.e modify response's body).
    pub fn middleware<M, F>(
        self,
        mw: F,
    ) -> Resource<
        P,
        impl NewService<
            Request = ServiceRequest<P>,
            Response = ServiceResponse,
            Error = Error,
            InitError = (),
        >,
    >
    where
        M: Transform<
            T::Service,
            Request = ServiceRequest<P>,
            Response = ServiceResponse,
            Error = Error,
            InitError = (),
        >,
        F: IntoTransform<M, T::Service>,
    {
        let endpoint = ApplyTransform::new(mw, self.endpoint);
        Resource {
            endpoint,
            rdef: self.rdef,
            name: self.name,
            guards: self.guards,
            routes: self.routes,
            default: self.default,
            factory_ref: self.factory_ref,
        }
    }

    /// Default resource to be used if no matching route could be found.
    pub fn default_resource<F, R, U>(mut self, f: F) -> Self
    where
        F: FnOnce(Resource<P>) -> R,
        R: IntoNewService<U>,
        U: NewService<
                Request = ServiceRequest<P>,
                Response = ServiceResponse,
                Error = Error,
            > + 'static,
    {
        // create and configure default resource
        self.default = Rc::new(RefCell::new(Some(Rc::new(boxed::new_service(
            f(Resource::new("")).into_new_service().map_init_err(|_| ()),
        )))));

        self
    }
}

impl<P, T> HttpServiceFactory<P> for Resource<P, T>
where
    P: 'static,
    T: NewService<
            Request = ServiceRequest<P>,
            Response = ServiceResponse,
            Error = Error,
            InitError = (),
        > + 'static,
{
    fn register(mut self, config: &mut ServiceConfig<P>) {
        if self.default.borrow().is_none() {
            *self.default.borrow_mut() = Some(config.default_service());
        }
        let guards = if self.guards.is_empty() {
            None
        } else {
            Some(std::mem::replace(&mut self.guards, Vec::new()))
        };
        let mut rdef = if config.is_root() || !self.rdef.is_empty() {
            ResourceDef::new(&insert_slash(&self.rdef))
        } else {
            ResourceDef::new(&self.rdef)
        };
        if let Some(ref name) = self.name {
            *rdef.name_mut() = name.clone();
        }
        config.register_service(rdef, guards, self, None)
    }
}

impl<P, T> IntoNewService<T> for Resource<P, T>
where
    T: NewService<
        Request = ServiceRequest<P>,
        Response = ServiceResponse,
        Error = Error,
        InitError = (),
    >,
{
    fn into_new_service(self) -> T {
        *self.factory_ref.borrow_mut() = Some(ResourceFactory {
            routes: self.routes,
            default: self.default,
        });

        self.endpoint
    }
}

pub struct ResourceFactory<P> {
    routes: Vec<Route<P>>,
    default: Rc<RefCell<Option<Rc<HttpNewService<P>>>>>,
}

impl<P: 'static> NewService for ResourceFactory<P> {
    type Request = ServiceRequest<P>;
    type Response = ServiceResponse;
    type Error = Error;
    type InitError = ();
    type Service = ResourceService<P>;
    type Future = CreateResourceService<P>;

    fn new_service(&self, _: &()) -> Self::Future {
        let default_fut = if let Some(ref default) = *self.default.borrow() {
            Some(default.new_service(&()))
        } else {
            None
        };

        CreateResourceService {
            fut: self
                .routes
                .iter()
                .map(|route| CreateRouteServiceItem::Future(route.new_service(&())))
                .collect(),
            default: None,
            default_fut,
        }
    }
}

enum CreateRouteServiceItem<P> {
    Future(CreateRouteService<P>),
    Service(RouteService<P>),
}

pub struct CreateResourceService<P> {
    fut: Vec<CreateRouteServiceItem<P>>,
    default: Option<HttpService<P>>,
    default_fut: Option<Box<Future<Item = HttpService<P>, Error = ()>>>,
}

impl<P> Future for CreateResourceService<P> {
    type Item = ResourceService<P>;
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut done = true;

        if let Some(ref mut fut) = self.default_fut {
            match fut.poll()? {
                Async::Ready(default) => self.default = Some(default),
                Async::NotReady => done = false,
            }
        }

        // poll http services
        for item in &mut self.fut {
            match item {
                CreateRouteServiceItem::Future(ref mut fut) => match fut.poll()? {
                    Async::Ready(route) => {
                        *item = CreateRouteServiceItem::Service(route)
                    }
                    Async::NotReady => {
                        done = false;
                    }
                },
                CreateRouteServiceItem::Service(_) => continue,
            };
        }

        if done {
            let routes = self
                .fut
                .drain(..)
                .map(|item| match item {
                    CreateRouteServiceItem::Service(service) => service,
                    CreateRouteServiceItem::Future(_) => unreachable!(),
                })
                .collect();
            Ok(Async::Ready(ResourceService {
                routes,
                default: self.default.take(),
            }))
        } else {
            Ok(Async::NotReady)
        }
    }
}

pub struct ResourceService<P> {
    routes: Vec<RouteService<P>>,
    default: Option<HttpService<P>>,
}

impl<P> Service for ResourceService<P> {
    type Request = ServiceRequest<P>;
    type Response = ServiceResponse;
    type Error = Error;
    type Future = Either<
        Box<Future<Item = ServiceResponse, Error = Error>>,
        Either<
            Box<Future<Item = Self::Response, Error = Self::Error>>,
            FutureResult<Self::Response, Self::Error>,
        >,
    >;

    fn poll_ready(&mut self) -> Poll<(), Self::Error> {
        Ok(Async::Ready(()))
    }

    fn call(&mut self, mut req: ServiceRequest<P>) -> Self::Future {
        for route in self.routes.iter_mut() {
            if route.check(&mut req) {
                return Either::A(route.call(req));
            }
        }
        if let Some(ref mut default) = self.default {
            Either::B(Either::A(default.call(req)))
        } else {
            let req = req.into_request();
            Either::B(Either::B(ok(ServiceResponse::new(
                req,
                Response::NotFound().finish(),
            ))))
        }
    }
}

#[doc(hidden)]
pub struct ResourceEndpoint<P> {
    factory: Rc<RefCell<Option<ResourceFactory<P>>>>,
}

impl<P> ResourceEndpoint<P> {
    fn new(factory: Rc<RefCell<Option<ResourceFactory<P>>>>) -> Self {
        ResourceEndpoint { factory }
    }
}

impl<P: 'static> NewService for ResourceEndpoint<P> {
    type Request = ServiceRequest<P>;
    type Response = ServiceResponse;
    type Error = Error;
    type InitError = ();
    type Service = ResourceService<P>;
    type Future = CreateResourceService<P>;

    fn new_service(&self, _: &()) -> Self::Future {
        self.factory.borrow_mut().as_mut().unwrap().new_service(&())
    }
}
<commit_msg>do not use default resource from app, return 405 if no matching route found<commit_after>use std::cell::RefCell;
use std::rc::Rc;

use actix_http::{Error, Response};
use actix_service::boxed::{self, BoxedNewService, BoxedService};
use actix_service::{
    ApplyTransform, IntoNewService, IntoTransform, NewService, Service, Transform,
};
use futures::future::{ok, Either, FutureResult};
use futures::{Async, Future, IntoFuture, Poll};

use crate::dev::{insert_slash, HttpServiceFactory, ResourceDef, ServiceConfig};
use crate::extract::FromRequest;
use crate::guard::Guard;
use crate::handler::{AsyncFactory, Factory};
use crate::responder::Responder;
use crate::route::{CreateRouteService, Route, RouteService};
use crate::service::{ServiceRequest, ServiceResponse};

type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, Error>;
type HttpNewService<P> =
    BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;

/// *Resource* is an entry in resources table which corresponds to requested URL.
///
/// Resource in turn has at least one route.
/// Route consists of an handlers objects and list of guards
/// (objects that implement `Guard` trait).
/// Resources and rouets uses builder-like pattern for configuration.
/// During request handling, resource object iterate through all routes
/// and check guards for specific route, if request matches all
/// guards, route considered matched and route handler get called.
///
/// ```rust
/// use actix_web::{web, App, HttpResponse};
///
/// fn main() {
///     let app = App::new().service(
///         web::resource("/")
///             .route(web::get().to(|| HttpResponse::Ok())));
/// }
/// ```
///
/// If no matching route could be found, *405* response code get returned.
/// Default behavior could be overriden with `default_resource()` method.
pub struct Resource<P, T = ResourceEndpoint<P>> {
    endpoint: T,
    rdef: String,
    name: Option<String>,
    routes: Vec<Route<P>>,
    guards: Vec<Box<Guard>>,
    default: Rc<RefCell<Option<Rc<HttpNewService<P>>>>>,
    factory_ref: Rc<RefCell<Option<ResourceFactory<P>>>>,
}

impl<P> Resource<P> {
    pub fn new(path: &str) -> Resource<P> {
        let fref = Rc::new(RefCell::new(None));

        Resource {
            routes: Vec::new(),
            rdef: path.to_string(),
            name: None,
            endpoint: ResourceEndpoint::new(fref.clone()),
            factory_ref: fref,
            guards: Vec::new(),
            default: Rc::new(RefCell::new(None)),
        }
    }
}

impl<P, T> Resource<P, T>
where
    P: 'static,
    T: NewService<
        Request = ServiceRequest<P>,
        Response = ServiceResponse,
        Error = Error,
        InitError = (),
    >,
{
    /// Set resource name.
    ///
    /// Name is used for url generation.
    pub fn name(mut self, name: &str) -> Self {
        self.name = Some(name.to_string());
        self
    }

    /// Add match guard to a resource.
    ///
    /// ```rust
    /// use actix_web::{web, guard, App, HttpResponse};
    ///
    /// fn index(data: web::Path<(String, String)>) -> &'static str {
    ///     "Welcome!"
    /// }
    ///
    /// fn main() {
    ///     let app = App::new()
    ///         .service(
    ///             web::resource("/app")
    ///                 .guard(guard::Header("content-type", "text/plain"))
    ///                 .route(web::get().to(index))
    ///         )
    ///         .service(
    ///             web::resource("/app")
    ///                 .guard(guard::Header("content-type", "text/json"))
    ///                 .route(web::get().to(|| HttpResponse::MethodNotAllowed()))
    ///         );
    /// }
    /// ```
    pub fn guard<G: Guard + 'static>(mut self, guard: G) -> Self {
        self.guards.push(Box::new(guard));
        self
    }

    pub(crate) fn add_guards(mut self, guards: Vec<Box<Guard>>) -> Self {
        self.guards.extend(guards);
        self
    }

    /// Register a new route.
    ///
    /// ```rust
    /// use actix_web::{web, guard, App, HttpResponse};
    ///
    /// fn main() {
    ///     let app = App::new().service(
    ///         web::resource("/").route(
    ///             web::route()
    ///                 .guard(guard::Any(guard::Get()).or(guard::Put()))
    ///                 .guard(guard::Header("Content-Type", "text/plain"))
    ///                 .to(|| HttpResponse::Ok()))
    ///     );
    /// }
    /// ```
    ///
    /// Multiple routes could be added to a resource. Resource object uses
    /// match guards for route selection.
    ///
    /// ```rust
    /// use actix_web::{web, guard, App, HttpResponse};
    ///
    /// fn main() {
    ///     let app = App::new().service(
    ///         web::resource("/container/")
    ///              .route(web::get().to(get_handler))
    ///              .route(web::post().to(post_handler))
    ///              .route(web::delete().to(delete_handler))
    ///     );
    /// }
    /// # fn get_handler() {}
    /// # fn post_handler() {}
    /// # fn delete_handler() {}
    /// ```
    pub fn route(mut self, route: Route<P>) -> Self {
        self.routes.push(route.finish());
        self
    }

    /// Register a new route and add handler. This route matches all requests.
    ///
    /// ```rust
    /// use actix_web::*;
    ///
    /// fn index(req: HttpRequest) -> HttpResponse {
    ///     unimplemented!()
    /// }
    ///
    /// App::new().service(web::resource("/").to(index));
    /// ```
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// # use actix_web::*;
    /// # fn index(req: HttpRequest) -> HttpResponse { unimplemented!() }
    /// App::new().service(web::resource("/").route(web::route().to(index)));
    /// ```
    pub fn to<F, I, R>(mut self, handler: F) -> Self
    where
        F: Factory<I, R> + 'static,
        I: FromRequest<P> + 'static,
        R: Responder + 'static,
    {
        self.routes.push(Route::new().to(handler));
        self
    }

    /// Register a new route and add async handler.
    ///
    /// ```rust
    /// use actix_web::*;
    /// use futures::future::{ok, Future};
    ///
    /// fn index(req: HttpRequest) -> impl Future<Item=HttpResponse, Error=Error> {
    ///     ok(HttpResponse::Ok().finish())
    /// }
    ///
    /// App::new().service(web::resource("/").to_async(index));
    /// ```
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # use actix_web::*;
    /// # use futures::future::Future;
    /// # fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
    /// #     unimplemented!()
    /// # }
    /// App::new().service(web::resource("/").route(web::route().to_async(index)));
    /// ```
    #[allow(clippy::wrong_self_convention)]
    pub fn to_async<F, I, R>(mut self, handler: F) -> Self
    where
        F: AsyncFactory<I, R>,
        I: FromRequest<P> + 'static,
        R: IntoFuture + 'static,
        R::Item: Into<Response>,
        R::Error: Into<Error>,
    {
        self.routes.push(Route::new().to_async(handler));
        self
    }

    /// Register a resource middleware.
    ///
    /// This is similar to `App's` middlewares, but middleware get invoked on resource level.
    /// Resource level middlewares are not allowed to change response
    /// type (i.e modify response's body).
    pub fn middleware<M, F>(
        self,
        mw: F,
    ) -> Resource<
        P,
        impl NewService<
            Request = ServiceRequest<P>,
            Response = ServiceResponse,
            Error = Error,
            InitError = (),
        >,
    >
    where
        M: Transform<
            T::Service,
            Request = ServiceRequest<P>,
            Response = ServiceResponse,
            Error = Error,
            InitError = (),
        >,
        F: IntoTransform<M, T::Service>,
    {
        let endpoint = ApplyTransform::new(mw, self.endpoint);
        Resource {
            endpoint,
            rdef: self.rdef,
            name: self.name,
            guards: self.guards,
            routes: self.routes,
            default: self.default,
            factory_ref: self.factory_ref,
        }
    }

    /// Default resource to be used if no matching route could be found.
    /// By default *405* response get returned. Resource does not use
    /// default handler from `App` or `Scope`.
    pub fn default_resource<F, R, U>(mut self, f: F) -> Self
    where
        F: FnOnce(Resource<P>) -> R,
        R: IntoNewService<U>,
        U: NewService<
                Request = ServiceRequest<P>,
                Response = ServiceResponse,
                Error = Error,
            > + 'static,
    {
        // create and configure default resource
        self.default = Rc::new(RefCell::new(Some(Rc::new(boxed::new_service(
            f(Resource::new("")).into_new_service().map_init_err(|_| ()),
        )))));

        self
    }
}

impl<P, T> HttpServiceFactory<P> for Resource<P, T>
where
    P: 'static,
    T: NewService<
            Request = ServiceRequest<P>,
            Response = ServiceResponse,
            Error = Error,
            InitError = (),
        > + 'static,
{
    fn register(mut self, config: &mut ServiceConfig<P>) {
        let guards = if self.guards.is_empty() {
            None
        } else {
            Some(std::mem::replace(&mut self.guards, Vec::new()))
        };
        let mut rdef = if config.is_root() || !self.rdef.is_empty() {
            ResourceDef::new(&insert_slash(&self.rdef))
        } else {
            ResourceDef::new(&self.rdef)
        };
        if let Some(ref name) = self.name {
            *rdef.name_mut() = name.clone();
        }
        config.register_service(rdef, guards, self, None)
    }
}

impl<P, T> IntoNewService<T> for Resource<P, T>
where
    T: NewService<
        Request = ServiceRequest<P>,
        Response = ServiceResponse,
        Error = Error,
        InitError = (),
    >,
{
    fn into_new_service(self) -> T {
        *self.factory_ref.borrow_mut() = Some(ResourceFactory {
            routes: self.routes,
            default: self.default,
        });

        self.endpoint
    }
}

pub struct ResourceFactory<P> {
    routes: Vec<Route<P>>,
    default: Rc<RefCell<Option<Rc<HttpNewService<P>>>>>,
}

impl<P: 'static> NewService for ResourceFactory<P> {
    type Request = ServiceRequest<P>;
    type Response = ServiceResponse;
    type Error = Error;
    type InitError = ();
    type Service = ResourceService<P>;
    type Future = CreateResourceService<P>;

    fn new_service(&self, _: &()) -> Self::Future {
        let default_fut = if let Some(ref default) = *self.default.borrow() {
            Some(default.new_service(&()))
        } else {
            None
        };

        CreateResourceService {
            fut: self
                .routes
                .iter()
                .map(|route| CreateRouteServiceItem::Future(route.new_service(&())))
                .collect(),
            default: None,
            default_fut,
        }
    }
}

enum CreateRouteServiceItem<P> {
    Future(CreateRouteService<P>),
    Service(RouteService<P>),
}

pub struct CreateResourceService<P> {
    fut: Vec<CreateRouteServiceItem<P>>,
    default: Option<HttpService<P>>,
    default_fut: Option<Box<Future<Item = HttpService<P>, Error = ()>>>,
}

impl<P> Future for CreateResourceService<P> {
    type Item = ResourceService<P>;
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut done = true;

        if let Some(ref mut fut) = self.default_fut {
            match fut.poll()? {
                Async::Ready(default) => self.default = Some(default),
                Async::NotReady => done = false,
            }
        }

        // poll http services
        for item in &mut self.fut {
            match item {
                CreateRouteServiceItem::Future(ref mut fut) => match fut.poll()? {
                    Async::Ready(route) => {
                        *item = CreateRouteServiceItem::Service(route)
                    }
                    Async::NotReady => {
                        done = false;
                    }
                },
                CreateRouteServiceItem::Service(_) => continue,
            };
        }

        if done {
            let routes = self
                .fut
                .drain(..)
                .map(|item| match item {
                    CreateRouteServiceItem::Service(service) => service,
                    CreateRouteServiceItem::Future(_) => unreachable!(),
                })
                .collect();
            Ok(Async::Ready(ResourceService {
                routes,
                default: self.default.take(),
            }))
        } else {
            Ok(Async::NotReady)
        }
    }
}

pub struct ResourceService<P> {
    routes: Vec<RouteService<P>>,
    default: Option<HttpService<P>>,
}

impl<P> Service for ResourceService<P> {
    type Request = ServiceRequest<P>;
    type Response = ServiceResponse;
    type Error = Error;
    type Future = Either<
        Box<Future<Item = ServiceResponse, Error = Error>>,
        Either<
            Box<Future<Item = Self::Response, Error = Self::Error>>,
            FutureResult<Self::Response, Self::Error>,
        >,
    >;

    fn poll_ready(&mut self) -> Poll<(), Self::Error> {
        Ok(Async::Ready(()))
    }

    fn call(&mut self, mut req: ServiceRequest<P>) -> Self::Future {
        for route in self.routes.iter_mut() {
            if route.check(&mut req) {
                return Either::A(route.call(req));
            }
        }
        if let Some(ref mut default) = self.default {
            Either::B(Either::A(default.call(req)))
        } else {
            let req = req.into_request();
            Either::B(Either::B(ok(ServiceResponse::new(
                req,
                Response::MethodNotAllowed().finish(),
            ))))
        }
    }
}

#[doc(hidden)]
pub struct ResourceEndpoint<P> {
    factory: Rc<RefCell<Option<ResourceFactory<P>>>>,
}

impl<P> ResourceEndpoint<P> {
    fn new(factory: Rc<RefCell<Option<ResourceFactory<P>>>>) -> Self {
        ResourceEndpoint { factory }
    }
}

impl<P: 'static> NewService for ResourceEndpoint<P> {
    type Request = ServiceRequest<P>;
    type Response = ServiceResponse;
    type Error = Error;
    type InitError = ();
    type Service = ResourceService<P>;
    type Future = CreateResourceService<P>;

    fn new_service(&self, _: &()) -> Self::Future {
        self.factory.borrow_mut().as_mut().unwrap().new_service(&())
    }
}

#[cfg(test)]
mod tests {
    use crate::http::{Method, StatusCode};
    use crate::test::{call_success, init_service, TestRequest};
    use crate::{web, App, HttpResponse};

    #[test]
    fn test_default_resource() {
        let mut srv = init_service(
            App::new()
                .service(
                    web::resource("/test").route(web::get().to(|| HttpResponse::Ok())),
                )
                .default_resource(|r| r.to(|| HttpResponse::BadRequest())),
        );
        let req = TestRequest::with_uri("/test").to_request();
        let resp = call_success(&mut srv, req);
        assert_eq!(resp.status(), StatusCode::OK);

        let req = TestRequest::with_uri("/test")
            .method(Method::POST)
            .to_request();
        let resp = call_success(&mut srv, req);
        assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);

        let mut srv = init_service(
            App::new().service(
                web::resource("/test")
                    .route(web::get().to(|| HttpResponse::Ok()))
                    .default_resource(|r| r.to(|| HttpResponse::BadRequest())),
            ),
        );

        let req = TestRequest::with_uri("/test").to_request();
        let resp = call_success(&mut srv, req);
        assert_eq!(resp.status(), StatusCode::OK);

        let req = TestRequest::with_uri("/test")
            .method(Method::POST)
            .to_request();
        let resp = call_success(&mut srv, req);
        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Random number generators and adapters
//!
//! ## Background: Random number generators (RNGs)
//!
//! Computers cannot produce random numbers from nowhere. We classify
//! random number generators as follows:
//!
//! -   "True" random number generators (TRNGs) use hard-to-predict data sources
//!     (e.g. the high-resolution parts of event timings and sensor jitter) to
//!     harvest random bit-sequences, apply algorithms to remove bias and
//!     estimate available entropy, then combine these bits into a byte-sequence
//!     or an entropy pool. This job is usually done by the operating system or
//!     a hardware generator (HRNG).
//! -   "Pseudo"-random number generators (PRNGs) use algorithms to transform a
//!     seed into a sequence of pseudo-random numbers. These generators can be
//!     fast and produce well-distributed unpredictable random numbers (or not).
//!     They are usually deterministic: given algorithm and seed, the output
//!     sequence can be reproduced. They have finite period and eventually loop;
//!     with many algorithms this period is fixed and can be proven sufficiently
//!     long, while others are chaotic and the period depends on the seed.
//! -   "Cryptographically secure" pseudo-random number generators (CSPRNGs)
//!     are the sub-set of PRNGs which are secure. Security of the generator
//!     relies both on hiding the internal state and using a strong algorithm.
//!
//! ## Traits and functionality
//!
//! All RNGs implement the [`RngCore`] trait, as a consequence of which the
//! [`Rng`] extension trait is automatically implemented. Secure RNGs may
//! additionally implement the [`CryptoRng`] trait.
//!
//! All PRNGs require a seed to produce their random number sequence. The
//! [`SeedableRng`] trait provides three ways of constructing PRNGs:
//!
//! -   `from_seed` accepts a type specific to the PRNG
//! -   `from_rng` allows a PRNG to be seeded from any other RNG
//! -   `seed_from_u64` allows any PRNG to be seeded from a `u64` insecurely
//! -   `from_entropy` securely seeds a PRNG from fresh entropy
//!
//! Use the [`rand_core`] crate when implementing your own RNGs.
//!
//! ## Our generators
//!
//! This crate provides several random number generators:
//!
//! -   [`OsRng`] is an interface to the operating system's random number
//!     source. Typically the operating system uses a CSPRNG with entropy
//!     provided by a TRNG and some type of on-going re-seeding.
//! -   [`ThreadRng`], provided by the [`thread_rng`] function, is a handle to a
//!     thread-local CSPRNG with periodic seeding from [`OsRng`]. Because this
//!     is local, it is typically much faster than [`OsRng`]. It should be
//!     secure, though the paranoid may prefer [`OsRng`].
//! -   [`StdRng`] is a CSPRNG chosen for good performance and trust of security
//!     (based on reviews, maturity and usage). The current algorithm is HC-128,
//!     which is one of the recommendations by ECRYPT's eSTREAM project.
//!     [`StdRng`] provides the algorithm used by [`ThreadRng`] but without
//!     periodic reseeding.
//! -   [`SmallRng`] is an **insecure** PRNG designed to be fast, simple, require
//!     little memory, and have good output quality.
//!
//! The algorithms selected for [`StdRng`] and [`SmallRng`] may change in any
//! release and may be platform-dependent, therefore they should be considered
//! **not reproducible**.
//!
//! ## Additional generators
//!
//! **TRNGs**: The [`rdrand`] crate provides an interface to the RDRAND and
//! RDSEED instructions available in modern Intel and AMD CPUs.
//! The [`rand_jitter`] crate provides a user-space implementation of
//! entropy harvesting from CPU timer jitter, but is very slow and has
//! [security issues](https://github.com/rust-random/rand/issues/699).
//!
//! **PRNGs**: Several companion crates are available, providing individual or
//! families of PRNG algorithms. These provide the implementations behind
//! [`StdRng`] and [`SmallRng`] but can also be used directly, indeed *should*
//! be used directly when **reproducibility** matters.
//! Some suggestions are: [`rand_chacha`], [`rand_pcg`], [`rand_xoshiro`].
//! A full list can be found by searching for crates with the [`rng` tag].
//!
//! [`SmallRng`]: rngs::SmallRng
//! [`StdRng`]: rngs::StdRng
//! [`OsRng`]: rngs::OsRng
//! [`ThreadRng`]: rngs::ThreadRng
//! [`mock::StepRng`]: rngs::mock::StepRng
//! [`adapter::ReadRng`]: rngs::adapter::ReadRng
//! [`adapter::ReseedingRng`]: rngs::adapter::ReseedingRng
//! [`rdrand`]: https://crates.io/crates/rdrand
//! [`rand_jitter`]: https://crates.io/crates/rand_jitter
//! [`rand_chacha`]: https://crates.io/crates/rand_chacha
//! [`rand_pcg`]: https://crates.io/crates/rand_pcg
//! [`rand_xoshiro`]: https://crates.io/crates/rand_xoshiro
//! [`rng` tag]: https://crates.io/keywords/rng

pub mod adapter;

#[cfg(feature="std")] mod entropy;
pub mod mock;   // Public so we don't export `StepRng` directly, making it a bit
                // more clear it is intended for testing.
#[cfg(feature="small_rng")]
mod small;
mod std;
#[cfg(feature="std")] pub(crate) mod thread;

#[allow(deprecated)]
#[cfg(feature="std")] pub use self::entropy::EntropyRng;

#[cfg(feature="small_rng")]
pub use self::small::SmallRng;
pub use self::std::StdRng;
#[cfg(feature="std")] pub use self::thread::ThreadRng;

#[cfg(feature="getrandom")] mod os;
#[cfg(feature="getrandom")] pub use self::os::OsRng;
<commit_msg>Mention ChaCha20 instead of the no longer used HC-128<commit_after>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Random number generators and adapters
//!
//! ## Background: Random number generators (RNGs)
//!
//! Computers cannot produce random numbers from nowhere. We classify
//! random number generators as follows:
//!
//! -   "True" random number generators (TRNGs) use hard-to-predict data sources
//!     (e.g. the high-resolution parts of event timings and sensor jitter) to
//!     harvest random bit-sequences, apply algorithms to remove bias and
//!     estimate available entropy, then combine these bits into a byte-sequence
//!     or an entropy pool. This job is usually done by the operating system or
//!     a hardware generator (HRNG).
//! -   "Pseudo"-random number generators (PRNGs) use algorithms to transform a
//!     seed into a sequence of pseudo-random numbers. These generators can be
//!     fast and produce well-distributed unpredictable random numbers (or not).
//!     They are usually deterministic: given algorithm and seed, the output
//!     sequence can be reproduced. They have finite period and eventually loop;
//!     with many algorithms this period is fixed and can be proven sufficiently
//!     long, while others are chaotic and the period depends on the seed.
//! -   "Cryptographically secure" pseudo-random number generators (CSPRNGs)
//!     are the sub-set of PRNGs which are secure. Security of the generator
//!     relies both on hiding the internal state and using a strong algorithm.
//!
//! ## Traits and functionality
//!
//! All RNGs implement the [`RngCore`] trait, as a consequence of which the
//! [`Rng`] extension trait is automatically implemented. Secure RNGs may
//! additionally implement the [`CryptoRng`] trait.
//!
//! All PRNGs require a seed to produce their random number sequence. The
//! [`SeedableRng`] trait provides three ways of constructing PRNGs:
//!
//! -   `from_seed` accepts a type specific to the PRNG
//! -   `from_rng` allows a PRNG to be seeded from any other RNG
//! -   `seed_from_u64` allows any PRNG to be seeded from a `u64` insecurely
//! -   `from_entropy` securely seeds a PRNG from fresh entropy
//!
//! Use the [`rand_core`] crate when implementing your own RNGs.
//!
//! ## Our generators
//!
//! This crate provides several random number generators:
//!
//! -   [`OsRng`] is an interface to the operating system's random number
//!     source. Typically the operating system uses a CSPRNG with entropy
//!     provided by a TRNG and some type of on-going re-seeding.
//! -   [`ThreadRng`], provided by the [`thread_rng`] function, is a handle to a
//!     thread-local CSPRNG with periodic seeding from [`OsRng`]. Because this
//!     is local, it is typically much faster than [`OsRng`]. It should be
//!     secure, though the paranoid may prefer [`OsRng`].
//! -   [`StdRng`] is a CSPRNG chosen for good performance and trust of security
//!     (based on reviews, maturity and usage). The current algorithm is ChaCha20,
//!     which is well established and rigorously analysed.
//!     [`StdRng`] provides the algorithm used by [`ThreadRng`] but without
//!     periodic reseeding.
//! -   [`SmallRng`] is an **insecure** PRNG designed to be fast, simple, require
//!     little memory, and have good output quality.
//!
//! The algorithms selected for [`StdRng`] and [`SmallRng`] may change in any
//! release and may be platform-dependent, therefore they should be considered
//! **not reproducible**.
//!
//! ## Additional generators
//!
//! **TRNGs**: The [`rdrand`] crate provides an interface to the RDRAND and
//! RDSEED instructions available in modern Intel and AMD CPUs.
//! The [`rand_jitter`] crate provides a user-space implementation of
//! entropy harvesting from CPU timer jitter, but is very slow and has
//! [security issues](https://github.com/rust-random/rand/issues/699).
//!
//! **PRNGs**: Several companion crates are available, providing individual or
//! families of PRNG algorithms. These provide the implementations behind
//! [`StdRng`] and [`SmallRng`] but can also be used directly, indeed *should*
//! be used directly when **reproducibility** matters.
//! Some suggestions are: [`rand_chacha`], [`rand_pcg`], [`rand_xoshiro`].
//! A full list can be found by searching for crates with the [`rng` tag].
//!
//! [`SmallRng`]: rngs::SmallRng
//! [`StdRng`]: rngs::StdRng
//! [`OsRng`]: rngs::OsRng
//! [`ThreadRng`]: rngs::ThreadRng
//! [`mock::StepRng`]: rngs::mock::StepRng
//! [`adapter::ReadRng`]: rngs::adapter::ReadRng
//! [`adapter::ReseedingRng`]: rngs::adapter::ReseedingRng
//! [`rdrand`]: https://crates.io/crates/rdrand
//! [`rand_jitter`]: https://crates.io/crates/rand_jitter
//! [`rand_chacha`]: https://crates.io/crates/rand_chacha
//! [`rand_pcg`]: https://crates.io/crates/rand_pcg
//! [`rand_xoshiro`]: https://crates.io/crates/rand_xoshiro
//! [`rng` tag]: https://crates.io/keywords/rng

pub mod adapter;

#[cfg(feature="std")] mod entropy;
pub mod mock;   // Public so we don't export `StepRng` directly, making it a bit
                // more clear it is intended for testing.
#[cfg(feature="small_rng")]
mod small;
mod std;
#[cfg(feature="std")] pub(crate) mod thread;

#[allow(deprecated)]
#[cfg(feature="std")] pub use self::entropy::EntropyRng;

#[cfg(feature="small_rng")]
pub use self::small::SmallRng;
pub use self::std::StdRng;
#[cfg(feature="std")] pub use self::thread::ThreadRng;

#[cfg(feature="getrandom")] mod os;
#[cfg(feature="getrandom")] pub use self::os::OsRng;
<|endoftext|>


<commit_before>
use std::sync::atomic::{AtomicUsize, Ordering};

struct CircularBuffer<T : Copy> {
  seqno       : AtomicUsize,        // the ID of the last written item
  data        : Vec<T>,             // (2*n)+1 preallocated elements
  size        : usize,              // n

  buffer      : Vec<AtomicUsize>,   // (positions+seqno)[]
  read_priv   : Vec<usize>,         // positions belong to the reader
  write_tmp   : usize,              // temporary position where the writer writes first
  max_read    : usize,              // reader's last read seqno
}

struct CircularBufferIterator<'a, T: 'a + Copy> {
  data   : &'a [T],
  revpos : &'a [usize],
  count  : usize,
}

impl <T : Copy> CircularBuffer<T> {

  fn new(size : usize, default_value : T) -> CircularBuffer<T> {

    if size == 0 { panic!("size cannot be zero"); }

    let mut ret = CircularBuffer {
      seqno      : AtomicUsize::new(0),
      data       : vec![],
      size       : size,
      buffer     : vec![],
      read_priv  : vec![],
      write_tmp  : 0,
      max_read   : 0,
    };

    // make sure there is enough place and fill it with the
    // default value
    ret.data.resize((size*2)+1, default_value);

    for i in 0..size {
      ret.buffer.push(AtomicUsize::new((1+i) << 16));
      ret.read_priv.push(1+size+i);
    }

    ret
  }

  fn put<F>(&mut self, setter: F) -> usize
    where F : FnMut(&mut T)
  {
    let mut setter = setter;

    // get a reference to the data
    let mut opt : Option<&mut T> = self.data.get_mut(self.write_tmp);

    // write the data to the temporary writer buffer
    match opt.as_mut() {
      Some(v) => setter(v),
      None    => { panic!("write tmp pos is out of bounds {}", self.write_tmp); }
    }

    // calculate writer flag position
    let seqno  = self.seqno.load(Ordering::SeqCst);
    let pos    = seqno % self.size;

    // get a reference to the writer flag
    match self.buffer.get_mut(pos) {
      Some(v) => {
        let mut old_flag : usize = (*v).load(Ordering::SeqCst);
        let mut old_pos  : usize = old_flag >> 16;
        let new_flag     : usize = (self.write_tmp << 16) + (seqno & 0xffff);

        loop {
          let result = (*v).compare_and_swap(old_flag,
                                             new_flag,
                                             Ordering::SeqCst);
          if result == old_flag {
            self.write_tmp = old_pos;
            break;
          } else {
            old_flag = result;
            old_pos  = old_flag >> 16;
          };
        };
      },
      None => { panic!("buffer index is out of bounds {}", pos); }
    }

    // increase sequence number
    self.seqno.fetch_add(1, Ordering::SeqCst)
  }

  fn iter(&mut self) -> CircularBufferIterator<T> {
    let mut seqno : usize = self.seqno.load(Ordering::SeqCst);
    let mut count : usize = 0;
    let max_read : usize = self.max_read;
    self.max_read = seqno;

    loop {
      if count >= self.size || seqno <= max_read || seqno == 0 { break; }
      let pos = (seqno-1) % self.size;

      match self.read_priv.get_mut(count) {
        Some(r) => {
          match self.buffer.get_mut(pos) {
            Some(v) => {
              let old_flag : usize = (*v).load(Ordering::SeqCst);
              let old_pos  : usize = old_flag >> 16;
              let old_seq  : usize = old_flag & 0xffff;
              let new_flag : usize = (*r << 16) + (old_seq & 0xffff);

              if old_flag == (*v).compare_and_swap(old_flag, new_flag, Ordering::SeqCst) {
                *r = old_pos;
                seqno -=1;
                count += 1;
              } else {
                break;
              }
            },
            None => { panic!("buffer index is out of bounds {}", pos); }
          }
        },
        None => { panic!("read_priv index is out of bounds {}", count); }
      }
    }

    CircularBufferIterator {
      data    : self.data.as_slice(),
      revpos  : self.read_priv.as_slice(),
      count   : count,
    }
  }
}

impl <'_, T: '_ + Copy> Iterator for CircularBufferIterator<'_, T> {
  type Item = T;

  fn next(&mut self) -> Option<T> {
    if self.count > 0 {
      self.count -= 1;
      let pos : usize = self.revpos[self.count];
      Some(self.data[pos])
    } else {
      None
    }
  }
}

pub fn tests() {
  let mut x = CircularBuffer::new(4, 0 as i32);

  {
    x.put(|v| *v = 1);
    x.put(|v| *v = 2);
    x.put(|v| *v = 3);
    x.put(|v| *v = 4);
    x.put(|v| *v = 5);
  }

  {
    for i in x.iter() {
      println!("--: {}", i);
    }
  }
}

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

  #[test]
  #[should_panic]
  fn create_zero_sized() {
    let _x = CircularBuffer::new(0, 0 as i32);
  }

  #[test]
  fn empty_buffer() {
    let mut x = CircularBuffer::new(1, 0 as i32);
    assert_eq!(x.iter().count(), 0);
  }

  #[test]
  fn sum_available() {
    let mut x = CircularBuffer::new(4, 0 as i32);
    x.put(|v| *v = 2);
    x.put(|v| *v = 4);
    x.put(|v| *v = 6);
    x.put(|v| *v = 8);
    x.put(|v| *v = 10);
    let sum = x.iter().take(3).fold(0, |acc, num| acc + num);
    assert_eq!(sum, 18);
  }

  #[test]
  fn overload_buffer() {
    let mut x = CircularBuffer::new(2, 0 as i32);
    x.put(|v| *v = 1);
    x.put(|v| *v = 2);
    x.put(|v| *v = 3);
    assert_eq!(x.iter().count(), 2);
  }

  #[test]
  fn read_twice() {
    let mut x = CircularBuffer::new(2, 0 as i32);
    x.put(|v| *v = 1);
    assert_eq!(x.iter().count(), 1);
    assert_eq!(x.iter().count(), 0);
    x.put(|v| *v = 2);
    x.put(|v| *v = 3);
    assert_eq!(x.iter().count(), 2);
    assert_eq!(x.iter().count(), 0);
  }
}
<commit_msg>integrate into Rust multithreading<commit_after>
use std::sync::atomic::{AtomicUsize, Ordering};

struct CircularBuffer<T : Copy + Send> {
  seqno       : AtomicUsize,        // the ID of the last written item
  data        : Vec<T>,             // (2*n)+1 preallocated elements
  size        : usize,              // n

  buffer      : Vec<AtomicUsize>,   // (positions+seqno)[]
  read_priv   : Vec<usize>,         // positions belong to the reader
  write_tmp   : usize,              // temporary position where the writer writes first
  max_read    : usize,              // reader's last read seqno
}

struct CircularBufferIterator<'a, T: 'a + Copy + Send> {
  data   : &'a [T],
  revpos : &'a [usize],
  count  : usize,
}

impl <T : Copy + Send> CircularBuffer<T> {

  fn new(size : usize, default_value : T) -> CircularBuffer<T> {

    if size == 0 { panic!("size cannot be zero"); }

    let mut ret = CircularBuffer {
      seqno      : AtomicUsize::new(0),
      data       : vec![],
      size       : size,
      buffer     : vec![],
      read_priv  : vec![],
      write_tmp  : 0,
      max_read   : 0,
    };

    // make sure there is enough place and fill it with the
    // default value
    ret.data.resize((size*2)+1, default_value);

    for i in 0..size {
      ret.buffer.push(AtomicUsize::new((1+i) << 16));
      ret.read_priv.push(1+size+i);
    }

    ret
  }

  fn put<F>(&mut self, setter: F) -> usize
    where F : FnMut(&mut T)
  {
    let mut setter = setter;

    // get a reference to the data
    let mut opt : Option<&mut T> = self.data.get_mut(self.write_tmp);

    // write the data to the temporary writer buffer
    match opt.as_mut() {
      Some(v) => setter(v),
      None    => { panic!("write tmp pos is out of bounds {}", self.write_tmp); }
    }

    // calculate writer flag position
    let seqno  = self.seqno.load(Ordering::SeqCst);
    let pos    = seqno % self.size;

    // get a reference to the writer flag
    match self.buffer.get_mut(pos) {
      Some(v) => {
        let mut old_flag : usize = (*v).load(Ordering::SeqCst);
        let mut old_pos  : usize = old_flag >> 16;
        let new_flag     : usize = (self.write_tmp << 16) + (seqno & 0xffff);

        loop {
          let result = (*v).compare_and_swap(old_flag,
                                             new_flag,
                                             Ordering::SeqCst);
          if result == old_flag {
            self.write_tmp = old_pos;
            break;
          } else {
            old_flag = result;
            old_pos  = old_flag >> 16;
          };
        };
      },
      None => { panic!("buffer index is out of bounds {}", pos); }
    }

    // increase sequence number
    self.seqno.fetch_add(1, Ordering::SeqCst)
  }

  fn iter(&mut self) -> CircularBufferIterator<T> {
    let mut seqno : usize = self.seqno.load(Ordering::SeqCst);
    let mut count : usize = 0;
    let max_read : usize = self.max_read;
    self.max_read = seqno;

    loop {
      if count >= self.size || seqno <= max_read || seqno == 0 { break; }
      let pos = (seqno-1) % self.size;

      match self.read_priv.get_mut(count) {
        Some(r) => {
          match self.buffer.get_mut(pos) {
            Some(v) => {
              let old_flag : usize = (*v).load(Ordering::SeqCst);
              let old_pos  : usize = old_flag >> 16;
              let old_seq  : usize = old_flag & 0xffff;
              let chk_flag : usize = (old_pos << 16) + ((seqno-1) & 0xffff);
              let new_flag : usize = (*r << 16) + (old_seq & 0xffff);

              if chk_flag == (*v).compare_and_swap(chk_flag, new_flag, Ordering::SeqCst) {
                *r = old_pos;
                seqno -=1;
                count += 1;
              } else {
                break;
              }
            },
            None => { panic!("buffer index is out of bounds {}", pos); }
          }
        },
        None => { panic!("read_priv index is out of bounds {}", count); }
      }
    }

    CircularBufferIterator {
      data    : self.data.as_slice(),
      revpos  : self.read_priv.as_slice(),
      count   : count,
    }
  }
}

impl <'_, T: '_ + Copy + Send> Iterator for CircularBufferIterator<'_, T> {
  type Item = T;

  fn next(&mut self) -> Option<T> {
    if self.count > 0 {
      self.count -= 1;
      let pos : usize = self.revpos[self.count];
      Some(self.data[pos])
    } else {
      None
    }
  }
}

// integrate into Rust multithreading
use std::cell::UnsafeCell;
use std::sync::Arc;

pub struct Sender<T: Copy + Send> {
  inner: Arc<UnsafeCell<CircularBuffer<T>>>,
}

unsafe impl<T: Copy + Send> Send for Sender<T> { }

pub struct Receiver<T: Copy + Send> {
  inner: Arc<UnsafeCell<CircularBuffer<T>>>,
}

unsafe impl<T: Copy + Send> Send for Receiver<T> { }

pub fn channel<T: Copy + Send>(size : usize,
                               default_value : T) -> (Sender<T>, Receiver<T>) {
    let a = Arc::new(UnsafeCell::new(CircularBuffer::new(size, default_value)));
    (Sender::new(a.clone()), Receiver::new(a))
}

impl<T: Copy + Send> Sender<T> {
  fn new(inner: Arc<UnsafeCell<CircularBuffer<T>>>) -> Sender<T> {
    Sender { inner: inner, }
  }

  fn put<F>(&mut self, setter: F) -> usize
    where F : FnMut(&mut T)
  {
    unsafe { (*self.inner.get()).put(setter) }
  }
}

impl<T: Copy + Send> Receiver<T> {
  fn new(inner: Arc<UnsafeCell<CircularBuffer<T>>>) -> Receiver<T> {
    Receiver { inner: inner, }
  }

  fn iter(&mut self) -> CircularBufferIterator<T> {
    unsafe { (*self.inner.get()).iter() }
  }
}

pub fn tests() {
  use std::thread;

  let mut x = CircularBuffer::new(4, 0 as i32);

  {
    x.put(|v| *v = 1);
    x.put(|v| *v = 2);
    x.put(|v| *v = 3);
    x.put(|v| *v = 4);
    x.put(|v| *v = 5);
    x.put(|v| *v = 6);
    x.put(|v| *v = 7);
  }

  {
    for i in x.iter() {
      println!("--: {}", i);
    }
  }

  let (mut tx, mut rx) = channel(7, 0 as i32);
  let t = thread::spawn(move|| {
    for i in 1..1000000 {
      tx.put(|v| *v = i);
    }
  });

  for _k in 1..1000 {
    let mut prev = 0;
    for i in rx.iter() {
      if i < prev { panic!("invalid value read!"); }
      prev = i;
    }
  }

  t.join().unwrap();
}

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

  #[test]
  #[should_panic]
  fn create_zero_sized() {
    let _x = CircularBuffer::new(0, 0 as i32);
  }

  #[test]
  fn empty_buffer() {
    let mut x = CircularBuffer::new(1, 0 as i32);
    assert_eq!(x.iter().count(), 0);
  }

  #[test]
  fn sum_available() {
    let mut x = CircularBuffer::new(4, 0 as i32);
    x.put(|v| *v = 2);
    x.put(|v| *v = 4);
    x.put(|v| *v = 6);
    x.put(|v| *v = 8);
    x.put(|v| *v = 10);
    let sum = x.iter().take(3).fold(0, |acc, num| acc + num);
    assert_eq!(sum, 18);
  }

  #[test]
  fn overload_buffer() {
    let mut x = CircularBuffer::new(2, 0 as i32);
    x.put(|v| *v = 1);
    x.put(|v| *v = 2);
    x.put(|v| *v = 3);
    assert_eq!(x.iter().count(), 2);
  }

  #[test]
  fn read_twice() {
    let mut x = CircularBuffer::new(2, 0 as i32);
    x.put(|v| *v = 1);
    assert_eq!(x.iter().count(), 1);
    assert_eq!(x.iter().count(), 0);
    x.put(|v| *v = 2);
    x.put(|v| *v = 3);
    assert_eq!(x.iter().count(), 2);
    assert_eq!(x.iter().count(), 0);
  }
}
<|endoftext|>


<commit_before>#![cfg(test)]

use std::collections::HashMap;
use rustc_serialize::json;
use rustc_serialize::json::{Json, Object};
use rustc_serialize::{Decoder, Decodable};
use std::io::prelude::*;
use std::fs::File;
use std::io::Result;
use token::{Token, ReservedWord};

#[derive(RustcDecodable)]
pub struct ExpectPass {
    source: String,
    expected: Json,
    options: Option<Json>
}

pub struct ExpectFail {
    source: String,
    error: String,
    options: Option<Json>
}

pub enum TestCase {
    Pass(ExpectPass),
    Fail(ExpectFail)
}

trait JsonExt {
    fn into_array(self) -> json::Array;
    fn into_string(self) -> String;
    fn into_string_opt(self) -> Option<String>;
}

impl JsonExt for Json {
    fn into_array(self) -> json::Array {
        match self {
            Json::Array(array) => array,
            _ => panic!("expected array")
        }
    }
    fn into_string(self) -> String {
        match self {
            Json::String(string) => string,
            _ => panic!("expected string")
        }
    }
    fn into_string_opt(self) -> Option<String> {
        match self {
            Json::Null => None,
            Json::String(string) => Some(string),
            _ => panic!("expected string or null")
        }
    }
}

<commit_msg>trying to push the part that stays as Json to a wrapper struct but I can't figure out the type signature; the docs don't say what "Error" is src/test/mod.rs:17:54: 17:59 error: use of undeclared type name `Error` src/test/mod.rs:17     fn decode<D: Decoder>(d: &mut D) -> Result<Self, Error> {                                                                         ^~~~~<commit_after>#![cfg(test)]

use std::collections::HashMap;
use rustc_serialize::json;
use rustc_serialize::json::{Json, Object};
use rustc_serialize::{Decoder, Decodable};
use std::io::prelude::*;
use std::fs::File;
use std::io::Result;
use token::{Token, ReservedWord};

pub struct DynJson {
    json: Json
}

impl Decodable for DynJson {
    fn decode<D: Decoder>(d: &mut D) -> Result<Self, Error> {
        unimplemented!()
    }
}

#[derive(RustcDecodable)]
pub struct ExpectPass {
    source: String,
    expected: DynJson,
    options: Option<DynJson>
}

pub struct ExpectFail {
    source: String,
    error: String,
    options: Option<Json>
}

pub enum TestCase {
    Pass(ExpectPass),
    Fail(ExpectFail)
}

trait JsonExt {
    fn into_array(self) -> json::Array;
    fn into_string(self) -> String;
    fn into_string_opt(self) -> Option<String>;
}

impl JsonExt for Json {
    fn into_array(self) -> json::Array {
        match self {
            Json::Array(array) => array,
            _ => panic!("expected array")
        }
    }
    fn into_string(self) -> String {
        match self {
            Json::String(string) => string,
            _ => panic!("expected string")
        }
    }
    fn into_string_opt(self) -> Option<String> {
        match self {
            Json::Null => None,
            Json::String(string) => Some(string),
            _ => panic!("expected string or null")
        }
    }
}

<|endoftext|>


<commit_before>use super::{CloneCell, Color, Event, Place, Point, Rect, Renderer, Widget, Window};
use super::callback::{Click, Enter};
use super::cell::CheckSet;

use std::cell::Cell;
use std::cmp::min;
use std::ops::Deref;
use std::sync::Arc;

/// Find next character index
fn next_i(text: &str, text_i: usize) -> usize {
    let slice = &text[text_i..];
    slice.char_indices().skip(1).next().unwrap_or((slice.len(), '\0')).0 + text_i
}

/// Find last character index
fn prev_i(text: &str, text_i: usize) -> usize {
    let slice = &text[.. text_i];
    slice.char_indices().rev().next().unwrap_or((0, '\0')).0
}

pub struct TextBox {
    pub rect: Cell<Rect>,
    pub text: CloneCell<String>,
    pub text_i: Cell<usize>,
    pub bg: Color,
    pub fg: Color,
    pub fg_cursor: Color,
    click_callback: Option<Arc<Fn(&TextBox, Point)>>,
    enter_callback: Option<Arc<Fn(&TextBox)>>,
    pressed: Cell<bool>,
}

impl TextBox {
    pub fn new() -> Self {
        TextBox {
            rect: Cell::new(Rect::default()),
            text: CloneCell::new(String::new()),
            text_i: Cell::new(0),
            bg: Color::rgb(255, 255, 255),
            fg: Color::rgb(0, 0, 0),
            fg_cursor: Color::rgb(128, 128, 128),
            click_callback: None,
            enter_callback: None,
            pressed: Cell::new(false),
        }
    }

    pub fn place(self, window: &mut Window) -> Arc<Self> {
        let arc = Arc::new(self);

        window.widgets.push(arc.clone());

        arc
    }

    pub fn text(self, text: &str) -> Self {
        self.text.set(text.to_owned());
        self.text_i.set(text.len());
        self
    }
}

impl Click for TextBox {
    fn emit_click(&self, point: Point) {
        if let Some(ref click_callback) = self.click_callback {
            click_callback(self, point);
        }
    }

    fn on_click<T: Fn(&Self, Point) + 'static>(mut self, func: T) -> Self {
        self.click_callback = Some(Arc::new(func));

        self
    }
}

impl Enter for TextBox {
    fn emit_enter(&self) {
        if let Some(ref enter_callback) = self.enter_callback {
            enter_callback(self)
        }
    }

    fn on_enter<T: Fn(&Self) + 'static>(mut self, func: T) -> Self {
        self.enter_callback = Some(Arc::new(func));

        self
    }
}

impl Place for TextBox {
    fn rect(&self) -> &Cell<Rect> {
        &self.rect
    }
}

impl Widget for TextBox {
    fn draw(&self, renderer: &mut Renderer, focused: bool) {
        let rect = self.rect.get();

        renderer.rect(rect, self.bg);

        let text_i = self.text_i.get();
        let text = self.text.borrow();

        let mut x = 0;
        let mut y = 0;
        for (i, c) in text.char_indices() {
            if c == '\n' {
                if i == text_i && focused && x + 8 <= rect.width as i32 &&
                   y + 16 <= rect.height as i32 {
                    renderer.rect(Rect::new(x + rect.x, y + rect.y, 8, 16), self.fg_cursor);
                }

                x = 0;
                y += 16;
            } else if c == '\t' {
                if x + 8 * 4 <= rect.width as i32 && y + 16 <= rect.height as i32 {
                    if i == text_i && focused {
                        renderer.rect(Rect::new(x + rect.x, y + rect.y, 8 * 4, 16), self.fg_cursor);
                    }
                }
                x += 8 * 4;
            } else {
                if x + 8 <= rect.width as i32 && y + 16 <= rect.height as i32 {
                    if i == text_i && focused {
                        renderer.rect(Rect::new(x + rect.x, y + rect.y, 8, 16), self.fg_cursor);
                    }
                    renderer.char(Point::new(x, y) + rect.point(), c, self.fg);
                }

                x += 8;
            }
        }

        if text.len() == text_i && focused && x + 8 <= rect.width as i32 &&
           y + 16 <= rect.height as i32 {
            renderer.rect(Rect::new(x + rect.x, y + rect.y, 8, 16), self.fg_cursor);
        }
    }

    fn event(&self, event: Event, mut focused: bool, redraw: &mut bool) -> bool {
        match event {
            Event::Mouse { point, left_button, .. } => {
                let mut click = false;

                let rect = self.rect.get();
                if rect.contains(point) {
                    if left_button {
                        if self.pressed.check_set(true) {
                            *redraw = true;
                        }
                    } else {
                        if self.pressed.check_set(false) {
                            click = true;
                            *redraw = true;
                        }
                    }
                } else {
                    if ! left_button {
                        if self.pressed.check_set(false) {
                            *redraw = true;
                        }
                    }
                }

                if click {
                    focused = true;

                    let click_point: Point = point - rect.point();
                    {
                        let text = self.text.borrow();

                        let mut new_text_i = None;

                        let mut x = 0;
                        let mut y = 0;
                        for (i, c) in text.char_indices() {
                            if c == '\n' {
                                if x + 8 <= rect.width as i32 && click_point.x >= x &&
                                   y + 16 <= rect.height as i32 &&
                                   click_point.y >= y &&
                                   click_point.y < y + 16 {
                                    new_text_i = Some(i);
                                    break;
                                }
                                x = 0;
                                y += 16;
                            } else if c == '\t' {
                                if x + 8 * 4 <= rect.width as i32 && click_point.x >= x &&
                                   click_point.x < x + 8 * 4 &&
                                   y + 16 <= rect.height as i32 &&
                                   click_point.y >= y &&
                                   click_point.y < y + 16 {
                                    new_text_i = Some(i);
                                    break;
                                }
                                x += 8 * 4;
                            } else {
                                if x + 8 <= rect.width as i32 && click_point.x >= x &&
                                   click_point.x < x + 8 &&
                                   y + 16 <= rect.height as i32 &&
                                   click_point.y >= y &&
                                   click_point.y < y + 16 {
                                    new_text_i = Some(i);
                                    break;
                                }
                                x += 8;
                            }
                        }

                        if new_text_i.is_none() && x + 8 <= rect.width as i32 &&
                           click_point.x >= x &&
                           y + 16 <= rect.height as i32 &&
                           click_point.y >= y ||
                           click_point.y >= y + 16 {
                            new_text_i = Some(text.len());
                        }

                        if let Some(text_i) = new_text_i {
                            self.text_i.set(text_i);
                        }
                    }

                    self.emit_click(click_point);
                }
            }
            Event::Text { c } => {
                if focused {
                    let mut text = self.text.borrow_mut();
                    let text_i = self.text_i.get();
                    text.insert(text_i, c);
                    self.text_i.set(next_i(text.deref(), text_i));
                    *redraw = true;
                }
            }
            Event::Enter => {
                if focused {
                    if self.enter_callback.is_some() {
                        self.emit_enter();
                    } else {
                        let mut text = self.text.borrow_mut();
                        let text_i = self.text_i.get();
                        text.insert(text_i, '\n');
                        self.text_i.set(next_i(text.deref(), text_i));
                    }
                    *redraw = true;
                }
            }
            Event::Backspace => {
                if focused {
                    let mut text = self.text.borrow_mut();
                    let mut text_i = self.text_i.get();
                    if text_i > 0 {
                        text_i = prev_i(text.deref(), text_i);
                        if text_i < text.len() {
                            text.remove(text_i);
                            self.text_i.set(min(text_i, text.len()));
                        }
                    }
                    *redraw = true;
                }
            }
            Event::Delete => {
                if focused {
                    let mut text = self.text.borrow_mut();
                    let text_i = self.text_i.get();
                    if text_i < text.len() {
                        text.remove(text_i);
                        self.text_i.set(min(text_i, text.len()));
                    }
                    *redraw = true;
                }
            }
            Event::Home => {
                if focused {
                    let text = self.text.borrow();
                    let mut text_i = self.text_i.get();
                    while text_i > 0 {
                        if text[.. text_i].chars().rev().next() == Some('\n') {
                            break;
                        }
                        text_i = prev_i(text.deref(), text_i);
                    }
                    self.text_i.set(text_i);
                    *redraw = true;
                }
            }
            Event::End => {
                if focused {
                    let text = self.text.borrow();
                    let mut text_i = self.text_i.get();
                    while text_i < text.len() {
                        if text[text_i ..].chars().next() == Some('\n') {
                            break;
                        }
                        text_i = next_i(text.deref(), text_i);
                    }
                    self.text_i.set(text_i);
                    *redraw = true;
                }
            }
            Event::UpArrow => {
                if focused {
                    let text = self.text.borrow();
                    let mut text_i = self.text_i.get();

                    // Count back to last newline
                    let mut offset = 0;
                    while text_i > 0 {
                        let c = text[.. text_i].chars().rev().next();
                        text_i = prev_i(text.deref(), text_i);
                        if c == Some('\n') {
                            break;
                        }
                        offset += 1;
                    }

                    // Go to newline before last newline
                    while text_i > 0 {
                        if text[.. text_i].chars().rev().next() == Some('\n') {
                            break;
                        }
                        text_i = prev_i(text.deref(), text_i);
                    }

                    // Add back offset
                    while offset > 0 && text_i < text.len() {
                        if text[text_i ..].chars().next() == Some('\n') {
                            break;
                        }
                        text_i = next_i(text.deref(), text_i);
                        offset -= 1;
                    }

                    self.text_i.set(text_i);
                    *redraw = true;
                }
            }
            Event::DownArrow => {
                if focused {
                    let text = self.text.borrow();
                    let mut text_i = self.text_i.get();

                    // Count back to last newline
                    let mut offset = 0;
                    while text_i > 0 {
                        if text[.. text_i].chars().rev().next() == Some('\n') {
                            break;
                        }
                        text_i = prev_i(text.deref(), text_i);
                        offset += 1;
                    }

                    // Go to next newline
                    while text_i < text.len() {
                        let c = text[text_i ..].chars().next();
                        text_i = next_i(text.deref(), text_i);
                        if c == Some('\n') {
                            break;
                        }
                    }

                    // Add back offset
                    while offset > 0 && text_i < text.len() {
                        if text[text_i ..].chars().next() == Some('\n') {
                            break;
                        }
                        text_i = next_i(text.deref(), text_i);
                        offset -= 1;
                    }

                    self.text_i.set(text_i);
                    *redraw = true;
                }
            }
            Event::LeftArrow => {
                if focused {
                    let text = self.text.borrow();
                    let text_i = self.text_i.get();
                    if text_i > 0 {
                        self.text_i.set(prev_i(text.deref(), text_i));
                    }
                    *redraw = true;
                }
            }
            Event::RightArrow => {
                if focused {
                    let text = self.text.borrow();
                    let text_i = self.text_i.get();
                    if text_i < text.len() {
                        self.text_i.set(next_i(text.deref(), text_i));
                    }
                    *redraw = true;
                }
            }
            _ => (),
        }

        focused
    }
}
<commit_msg>Update text_box.rs with `WidgetCore`<commit_after>use super::{CloneCell, Color, Event, Place, Point, Rect, Renderer, Widget, WidgetCore, Window};
use super::callback::{Click, Enter};
use super::cell::CheckSet;

use std::cell::Cell;
use std::cmp::min;
use std::ops::Deref;
use std::sync::Arc;

/// Find next character index
fn next_i(text: &str, text_i: usize) -> usize {
    let slice = &text[text_i..];
    slice.char_indices().skip(1).next().unwrap_or((slice.len(), '\0')).0 + text_i
}

/// Find last character index
fn prev_i(text: &str, text_i: usize) -> usize {
    let slice = &text[.. text_i];
    slice.char_indices().rev().next().unwrap_or((0, '\0')).0
}

pub struct TextBox {
    pub core: WidgetCore,
    pub text: CloneCell<String>,
    pub text_i: Cell<usize>,
    pub fg_cursor: Color,
    click_callback: Option<Arc<Fn(&TextBox, Point)>>,
    enter_callback: Option<Arc<Fn(&TextBox)>>,
    pressed: Cell<bool>,
}

impl TextBox {
    pub fn new() -> Self {
        TextBox {
            core: WidgetCore::new(Color::white(), Color::black()),
            text: CloneCell::new(String::new()),
            text_i: Cell::new(0),
            fg_cursor: Color::gray(),
            click_callback: None,
            enter_callback: None,
            pressed: Cell::new(false),
        }
    }

    pub fn place(self, window: &mut Window) -> Arc<Self> {
        let arc = Arc::new(self);

        window.widgets.push(arc.clone());

        arc
    }

    pub fn text(self, text: &str) -> Self {
        self.text.set(text.to_owned());
        self.text_i.set(text.len());
        self
    }
}

impl Click for TextBox {
    fn emit_click(&self, point: Point) {
        if let Some(ref click_callback) = self.click_callback {
            click_callback(self, point);
        }
    }

    fn on_click<T: Fn(&Self, Point) + 'static>(mut self, func: T) -> Self {
        self.click_callback = Some(Arc::new(func));

        self
    }
}

impl Enter for TextBox {
    fn emit_enter(&self) {
        if let Some(ref enter_callback) = self.enter_callback {
            enter_callback(self)
        }
    }

    fn on_enter<T: Fn(&Self) + 'static>(mut self, func: T) -> Self {
        self.enter_callback = Some(Arc::new(func));

        self
    }
}

impl Place for TextBox {
    fn rect(&self) -> &Cell<Rect> {
        &self.core.rect
    }
}

impl Widget for TextBox {
    fn draw(&self, renderer: &mut Renderer, focused: bool) {
        let rect = self.core.rect.get();

        renderer.rect(rect, self.core.bg);

        let text_i = self.text_i.get();
        let text = self.text.borrow();

        let mut x = 0;
        let mut y = 0;
        for (i, c) in text.char_indices() {
            if c == '\n' {
                if i == text_i && focused && x + 8 <= rect.width as i32 &&
                   y + 16 <= rect.height as i32 {
                    renderer.rect(Rect::new(x + rect.x, y + rect.y, 8, 16), self.fg_cursor);
                }

                x = 0;
                y += 16;
            } else if c == '\t' {
                if x + 8 * 4 <= rect.width as i32 && y + 16 <= rect.height as i32 {
                    if i == text_i && focused {
                        renderer.rect(Rect::new(x + rect.x, y + rect.y, 8 * 4, 16), self.fg_cursor);
                    }
                }
                x += 8 * 4;
            } else {
                if x + 8 <= rect.width as i32 && y + 16 <= rect.height as i32 {
                    if i == text_i && focused {
                        renderer.rect(Rect::new(x + rect.x, y + rect.y, 8, 16), self.fg_cursor);
                    }
                    renderer.char(Point::new(x, y) + rect.point(), c, self.core.fg);
                }

                x += 8;
            }
        }

        if text.len() == text_i && focused && x + 8 <= rect.width as i32 &&
           y + 16 <= rect.height as i32 {
            renderer.rect(Rect::new(x + rect.x, y + rect.y, 8, 16), self.fg_cursor);
        }
    }

    fn event(&self, event: Event, mut focused: bool, redraw: &mut bool) -> bool {
        match event {
            Event::Mouse { point, left_button, .. } => {
                let mut click = false;

                let rect = self.core.rect.get();
                if rect.contains(point) {
                    if left_button {
                        if self.pressed.check_set(true) {
                            *redraw = true;
                        }
                    } else {
                        if self.pressed.check_set(false) {
                            click = true;
                            *redraw = true;
                        }
                    }
                } else {
                    if ! left_button {
                        if self.pressed.check_set(false) {
                            *redraw = true;
                        }
                    }
                }

                if click {
                    focused = true;

                    let click_point: Point = point - rect.point();
                    {
                        let text = self.text.borrow();

                        let mut new_text_i = None;

                        let mut x = 0;
                        let mut y = 0;
                        for (i, c) in text.char_indices() {
                            if c == '\n' {
                                if x + 8 <= rect.width as i32 && click_point.x >= x &&
                                   y + 16 <= rect.height as i32 &&
                                   click_point.y >= y &&
                                   click_point.y < y + 16 {
                                    new_text_i = Some(i);
                                    break;
                                }
                                x = 0;
                                y += 16;
                            } else if c == '\t' {
                                if x + 8 * 4 <= rect.width as i32 && click_point.x >= x &&
                                   click_point.x < x + 8 * 4 &&
                                   y + 16 <= rect.height as i32 &&
                                   click_point.y >= y &&
                                   click_point.y < y + 16 {
                                    new_text_i = Some(i);
                                    break;
                                }
                                x += 8 * 4;
                            } else {
                                if x + 8 <= rect.width as i32 && click_point.x >= x &&
                                   click_point.x < x + 8 &&
                                   y + 16 <= rect.height as i32 &&
                                   click_point.y >= y &&
                                   click_point.y < y + 16 {
                                    new_text_i = Some(i);
                                    break;
                                }
                                x += 8;
                            }
                        }

                        if new_text_i.is_none() && x + 8 <= rect.width as i32 &&
                           click_point.x >= x &&
                           y + 16 <= rect.height as i32 &&
                           click_point.y >= y ||
                           click_point.y >= y + 16 {
                            new_text_i = Some(text.len());
                        }

                        if let Some(text_i) = new_text_i {
                            self.text_i.set(text_i);
                        }
                    }

                    self.emit_click(click_point);
                }
            }
            Event::Text { c } => {
                if focused {
                    let mut text = self.text.borrow_mut();
                    let text_i = self.text_i.get();
                    text.insert(text_i, c);
                    self.text_i.set(next_i(text.deref(), text_i));
                    *redraw = true;
                }
            }
            Event::Enter => {
                if focused {
                    if self.enter_callback.is_some() {
                        self.emit_enter();
                    } else {
                        let mut text = self.text.borrow_mut();
                        let text_i = self.text_i.get();
                        text.insert(text_i, '\n');
                        self.text_i.set(next_i(text.deref(), text_i));
                    }
                    *redraw = true;
                }
            }
            Event::Backspace => {
                if focused {
                    let mut text = self.text.borrow_mut();
                    let mut text_i = self.text_i.get();
                    if text_i > 0 {
                        text_i = prev_i(text.deref(), text_i);
                        if text_i < text.len() {
                            text.remove(text_i);
                            self.text_i.set(min(text_i, text.len()));
                        }
                    }
                    *redraw = true;
                }
            }
            Event::Delete => {
                if focused {
                    let mut text = self.text.borrow_mut();
                    let text_i = self.text_i.get();
                    if text_i < text.len() {
                        text.remove(text_i);
                        self.text_i.set(min(text_i, text.len()));
                    }
                    *redraw = true;
                }
            }
            Event::Home => {
                if focused {
                    let text = self.text.borrow();
                    let mut text_i = self.text_i.get();
                    while text_i > 0 {
                        if text[.. text_i].chars().rev().next() == Some('\n') {
                            break;
                        }
                        text_i = prev_i(text.deref(), text_i);
                    }
                    self.text_i.set(text_i);
                    *redraw = true;
                }
            }
            Event::End => {
                if focused {
                    let text = self.text.borrow();
                    let mut text_i = self.text_i.get();
                    while text_i < text.len() {
                        if text[text_i ..].chars().next() == Some('\n') {
                            break;
                        }
                        text_i = next_i(text.deref(), text_i);
                    }
                    self.text_i.set(text_i);
                    *redraw = true;
                }
            }
            Event::UpArrow => {
                if focused {
                    let text = self.text.borrow();
                    let mut text_i = self.text_i.get();

                    // Count back to last newline
                    let mut offset = 0;
                    while text_i > 0 {
                        let c = text[.. text_i].chars().rev().next();
                        text_i = prev_i(text.deref(), text_i);
                        if c == Some('\n') {
                            break;
                        }
                        offset += 1;
                    }

                    // Go to newline before last newline
                    while text_i > 0 {
                        if text[.. text_i].chars().rev().next() == Some('\n') {
                            break;
                        }
                        text_i = prev_i(text.deref(), text_i);
                    }

                    // Add back offset
                    while offset > 0 && text_i < text.len() {
                        if text[text_i ..].chars().next() == Some('\n') {
                            break;
                        }
                        text_i = next_i(text.deref(), text_i);
                        offset -= 1;
                    }

                    self.text_i.set(text_i);
                    *redraw = true;
                }
            }
            Event::DownArrow => {
                if focused {
                    let text = self.text.borrow();
                    let mut text_i = self.text_i.get();

                    // Count back to last newline
                    let mut offset = 0;
                    while text_i > 0 {
                        if text[.. text_i].chars().rev().next() == Some('\n') {
                            break;
                        }
                        text_i = prev_i(text.deref(), text_i);
                        offset += 1;
                    }

                    // Go to next newline
                    while text_i < text.len() {
                        let c = text[text_i ..].chars().next();
                        text_i = next_i(text.deref(), text_i);
                        if c == Some('\n') {
                            break;
                        }
                    }

                    // Add back offset
                    while offset > 0 && text_i < text.len() {
                        if text[text_i ..].chars().next() == Some('\n') {
                            break;
                        }
                        text_i = next_i(text.deref(), text_i);
                        offset -= 1;
                    }

                    self.text_i.set(text_i);
                    *redraw = true;
                }
            }
            Event::LeftArrow => {
                if focused {
                    let text = self.text.borrow();
                    let text_i = self.text_i.get();
                    if text_i > 0 {
                        self.text_i.set(prev_i(text.deref(), text_i));
                    }
                    *redraw = true;
                }
            }
            Event::RightArrow => {
                if focused {
                    let text = self.text.borrow();
                    let text_i = self.text_i.get();
                    if text_i < text.len() {
                        self.text_i.set(next_i(text.deref(), text_i));
                    }
                    *redraw = true;
                }
            }
            _ => (),
        }

        focused
    }
}
<|endoftext|>