<commit_before>use std::cell::RefCell;
use std::fmt;
use std::marker::PhantomData;
use std::rc::Rc;

use actix_http::body::{Body, MessageBody};
use actix_server_config::ServerConfig;
use actix_service::boxed::{self, BoxedNewService};
use actix_service::{
    apply_transform, IntoNewService, IntoTransform, NewService, Transform,
};
use futures::IntoFuture;

use crate::app_service::{AppEntry, AppInit, AppRoutingFactory};
use crate::config::{AppConfig, AppConfigInner, ServiceConfig};
use crate::data::{Data, DataFactory};
use crate::dev::ResourceDef;
use crate::error::Error;
use crate::resource::Resource;
use crate::route::Route;
use crate::service::{
    HttpServiceFactory, ServiceFactory, ServiceFactoryWrapper, ServiceRequest,
    ServiceResponse,
};

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

/// Application builder - structure that follows the builder pattern
/// for building application instances.
pub struct App<T, B> {
    endpoint: T,
    services: Vec<Box<ServiceFactory>>,
    default: Option<Rc<HttpNewService>>,
    factory_ref: Rc<RefCell<Option<AppRoutingFactory>>>,
    data: Vec<Box<DataFactory>>,
    config: AppConfigInner,
    external: Vec<ResourceDef>,
    _t: PhantomData<(B)>,
}

impl App<AppEntry, Body> {
    /// Create application builder. Application can be configured with a builder-like pattern.
    pub fn new() -> Self {
        let fref = Rc::new(RefCell::new(None));
        App {
            endpoint: AppEntry::new(fref.clone()),
            data: Vec::new(),
            services: Vec::new(),
            default: None,
            factory_ref: fref,
            config: AppConfigInner::default(),
            external: Vec::new(),
            _t: PhantomData,
        }
    }
}

impl<T, B> App<T, B>
where
    B: MessageBody,
    T: NewService<
        Request = ServiceRequest,
        Response = ServiceResponse<B>,
        Error = Error,
        InitError = (),
    >,
{
    /// Set application data. Application data could be accessed
    /// by using `Data<T>` extractor where `T` is data type.
    ///
    /// **Note**: http server accepts an application factory rather than
    /// an application instance. Http server constructs an application
    /// instance for each thread, thus application data must be constructed
    /// multiple times. If you want to share data between different
    /// threads, a shared object should be used, e.g. `Arc`. Application
    /// data does not need to be `Send` or `Sync`.
    ///
    /// ```rust
    /// use std::cell::Cell;
    /// use actix_web::{web, App};
    ///
    /// struct MyData {
    ///     counter: Cell<usize>,
    /// }
    ///
    /// fn index(data: web::Data<MyData>) {
    ///     data.counter.set(data.counter.get() + 1);
    /// }
    ///
    /// fn main() {
    ///     let app = App::new()
    ///         .data(MyData{ counter: Cell::new(0) })
    ///         .service(
    ///             web::resource("/index.html").route(
    ///                 web::get().to(index)));
    /// }
    /// ```
    pub fn data<U: Into<Data<U>> + 'static>(mut self, data: U) -> Self {
        self.data.push(Box::new(data.into()));
        self
    }

    /// Run external configuration as part of the application building
    /// process
    ///
    /// This function is useful for moving parts of configuration to a
    /// different module or even library. For example,
    /// some of the resource's configuration could be moved to different module.
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// use actix_web::{web, middleware, App, HttpResponse};
    ///
    /// // this function could be located in different module
    /// fn config(cfg: &mut web::ServiceConfig) {
    ///     cfg.service(web::resource("/test")
    ///         .route(web::get().to(|| HttpResponse::Ok()))
    ///         .route(web::head().to(|| HttpResponse::MethodNotAllowed()))
    ///     );
    /// }
    ///
    /// fn main() {
    ///     let app = App::new()
    ///         .wrap(middleware::Logger::default())
    ///         .configure(config)  // <- register resources
    ///         .route("/index.html", web::get().to(|| HttpResponse::Ok()));
    /// }
    /// ```
    pub fn configure<F>(mut self, f: F) -> Self
    where
        F: Fn(&mut ServiceConfig),
    {
        let mut cfg = ServiceConfig::new();
        f(&mut cfg);
        self.data.extend(cfg.data);
        self.services.extend(cfg.services);
        self.external.extend(cfg.external);
        self
    }

    /// Configure route for a specific path.
    ///
    /// This is a simplified version of the `App::service()` method.
    /// This method can be used multiple times with same path, in that case
    /// multiple resources with one route would be registered for same resource path.
    ///
    /// ```rust
    /// use actix_web::{web, App, HttpResponse};
    ///<commit_msg>Make `App::configure` take an `FnOnce` (#825)<commit_after>use std::cell::RefCell;
use std::fmt;
use std::marker::PhantomData;
use std::rc::Rc;

use actix_http::body::{Body, MessageBody};
use actix_server_config::ServerConfig;
use actix_service::boxed::{self, BoxedNewService};
use actix_service::{
    apply_transform, IntoNewService, IntoTransform, NewService, Transform,
};
use futures::IntoFuture;

use crate::app_service::{AppEntry, AppInit, AppRoutingFactory};
use crate::config::{AppConfig, AppConfigInner, ServiceConfig};
use crate::data::{Data, DataFactory};
use crate::dev::ResourceDef;
use crate::error::Error;
use crate::resource::Resource;
use crate::route::Route;
use crate::service::{
    HttpServiceFactory, ServiceFactory, ServiceFactoryWrapper, ServiceRequest,
    ServiceResponse,
};

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

/// Application builder - structure that follows the builder pattern
/// for building application instances.
pub struct App<T, B> {
    endpoint: T,
    services: Vec<Box<ServiceFactory>>,
    default: Option<Rc<HttpNewService>>,
    factory_ref: Rc<RefCell<Option<AppRoutingFactory>>>,
    data: Vec<Box<DataFactory>>,
    config: AppConfigInner,
    external: Vec<ResourceDef>,
    _t: PhantomData<(B)>,
}

impl App<AppEntry, Body> {
    /// Create application builder. Application can be configured with a builder-like pattern.
    pub fn new() -> Self {
        let fref = Rc::new(RefCell::new(None));
        App {
            endpoint: AppEntry::new(fref.clone()),
            data: Vec::new(),
            services: Vec::new(),
            default: None,
            factory_ref: fref,
            config: AppConfigInner::default(),
            external: Vec::new(),
            _t: PhantomData,
        }
    }
}

impl<T, B> App<T, B>
where
    B: MessageBody,
    T: NewService<
        Request = ServiceRequest,
        Response = ServiceResponse<B>,
        Error = Error,
        InitError = (),
    >,
{
    /// Set application data. Application data could be accessed
    /// by using `Data<T>` extractor where `T` is data type.
    ///
    /// **Note**: http server accepts an application factory rather than
    /// an application instance. Http server constructs an application
    /// instance for each thread, thus application data must be constructed
    /// multiple times. If you want to share data between different
    /// threads, a shared object should be used, e.g. `Arc`. Application
    /// data does not need to be `Send` or `Sync`.
    ///
    /// ```rust
    /// use std::cell::Cell;
    /// use actix_web::{web, App};
    ///
    /// struct MyData {
    ///     counter: Cell<usize>,
    /// }
    ///
    /// fn index(data: web::Data<MyData>) {
    ///     data.counter.set(data.counter.get() + 1);
    /// }
    ///
    /// fn main() {
    ///     let app = App::new()
    ///         .data(MyData{ counter: Cell::new(0) })
    ///         .service(
    ///             web::resource("/index.html").route(
    ///                 web::get().to(index)));
    /// }
    /// ```
    pub fn data<U: Into<Data<U>> + 'static>(mut self, data: U) -> Self {
        self.data.push(Box::new(data.into()));
        self
    }

    /// Run external configuration as part of the application building
    /// process
    ///
    /// This function is useful for moving parts of configuration to a
    /// different module or even library. For example,
    /// some of the resource's configuration could be moved to different module.
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// use actix_web::{web, middleware, App, HttpResponse};
    ///
    /// // this function could be located in different module
    /// fn config(cfg: &mut web::ServiceConfig) {
    ///     cfg.service(web::resource("/test")
    ///         .route(web::get().to(|| HttpResponse::Ok()))
    ///         .route(web::head().to(|| HttpResponse::MethodNotAllowed()))
    ///     );
    /// }
    ///
    /// fn main() {
    ///     let app = App::new()
    ///         .wrap(middleware::Logger::default())
    ///         .configure(config)  // <- register resources
    ///         .route("/index.html", web::get().to(|| HttpResponse::Ok()));
    /// }
    /// ```
    pub fn configure<F>(mut self, f: F) -> Self
    where
        F: FnOnce(&mut ServiceConfig),
    {
        let mut cfg = ServiceConfig::new();
        f(&mut cfg);
        self.data.extend(cfg.data);
        self.services.extend(cfg.services);
        self.external.extend(cfg.external);
        self
    }

    /// Configure route for a specific path.
    ///
    /// This is a simplified version of the `App::service()` method.
    /// This method can be used multiple times with same path, in that case
    /// multiple resources with one route would be registered for same resource path.
    ///
    /// ```rust
    /// use actix_web::{web, App, HttpResponse};
    ///
{'fraction_non_alphanumeric': 0.16071065989847716, 'fraction_numerical': 0.0007106598984771574, 'mean_word_length': 2.339322033898305, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2909983', 'n_tokens_mistral': 2829, 'n_tokens_neox': 2828, 'n_words': 797}