<commit_before>use hyper::header::{CookiePair as Cookie, ContentLength, ContentType, Header, Location, SetCookie};
use hyper::status::StatusCode as Status;

use hyper::{Control, Headers, Next};

use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};

use handlebars::Handlebars;
use serde::ser::Serialize as ToJson;

pub use serde_json::value as value;

use std::any::Any;
use std::fmt::Debug;
use std::borrow::Cow;
use std::io::{ErrorKind, Read, Result, Write};
use std::marker::PhantomData;

use std::fs::{File, read_dir};
use std::path::Path;

use std::cell::UnsafeCell;
use std::ptr;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

use buffer::Buffer;

#[derive(Debug)]
pub struct Resp {
    status: Status,
    headers: Headers,
    body: Buffer,

    ctrl: Control,
    ended_or_notify: AtomicBool
}

impl Resp {
    pub fn new(ctrl: Control) -> Resp {
        Resp {
            status: Status::Ok,
            headers: Headers::default(),
            body: Buffer::new(),

            ctrl: ctrl,
            ended_or_notify: AtomicBool::new(false)
        }
    }

    /// called by handler to know whether we can write the response or not
    ///
    /// two possible cases:
    ///   - done before can_write: in synchronous style, done is called first,
    ///     sets ended_or_notify to true and does not notify the handler
    ///   - can_write before done: response not done yet, can_write is called first,
    ///     sets ended_or_notify to true so that when done is called, it will notify the handler
    fn can_write(&self) -> bool {
        if self.ended_or_notify.compare_and_swap(false, true, Ordering::AcqRel) {
            // if true, response already ended, we can write it
            true
        } else {
            // if false, response did not end yet
            // ended has been set to true to mean "need to notify handler"
            false
        }
    }

    /// mirror function of can_write, called by Response
    fn done(&self) {
        if self.ended_or_notify.compare_and_swap(false, true, Ordering::AcqRel) {
            // if true, means we need to notify, the flag is not updated
            self.ctrl.ready(Next::write()).unwrap();
        } else {
            // if previously false: no need to notify
            // ended has been set to true to mean "response ended"
        }
    }

    fn status(&mut self, status: Status) {
        self.status = status;
    }

    fn has_header<H: Header>(&self) -> bool {
        self.headers.has::<H>()
    }

    fn header<H: Header>(&mut self, header: H) {
        self.headers.set(header);
    }

    fn header_raw<K: Into<Cow<'static, str>> + Debug>(&mut self, name: K, value: Vec<Vec<u8>>) {
        self.headers.set_raw(name, value);
    }

    fn push_cookie(&mut self, cookie: Cookie) {
        self.headers.get_mut::<SetCookie>().unwrap().push(cookie)
    }

    fn len(&self) -> usize {
        self.body.len()
    }

    fn append<D: AsRef<[u8]>>(&self, content: D) {
        // TODO use deque self.body.append(content.as_ref());
    }

    fn send<D: Into<Vec<u8>>>(&mut self, content: D) {
        self.body.send(content);
    }
}

/// This holds data for the response.
pub struct ResponseHolder {
    resp: Arc<UnsafeCell<Resp>>
}

impl ResponseHolder {    

    pub fn new(control: Control) -> ResponseHolder {
        ResponseHolder {
            resp: Arc::new(UnsafeCell::new(Resp::new(control)))
        }
    }

    pub fn new_response(&mut self) -> Response {
        Response {
            resp: self.resp.get(),
            _marker: PhantomData
        }
    }

    fn resp(&self) -> &Resp {
        unsafe { &*self.resp.get() }
    }

    fn resp_mut(&self) -> &mut Resp {
        unsafe { &mut *self.resp.get() }
    }

    pub fn get_status(&self) -> Status {
        self.resp().status
    }

    pub fn set_headers(&self, headers: &mut Headers) {
        *headers = unsafe { ptr::read(&self.resp().headers) };
    }

    pub fn body(&self) -> &mut Buffer {
        &mut self.resp_mut().body
    }

    /// two possible cases:
    ///   - done before can_write: in synchronous style, done is called first,
    ///     sets ended_or_notify to true and does not notify the handler
    ///   - can_write before done: response not done yet, can_write is called first,
    ///     sets ended_or_notify to true so that when done is called, it will notify the handler
    pub fn can_write(&self) -> bool {
        unsafe { return (&*(self.resp.get())).can_write(); }
    }
}

/// This represents the response that will be sent back to the application.
///
/// Includes a status code (default 200 OK), headers, and a body.
/// The response can be updated and sent back immediately in a synchronous way,
/// or deferred pending some computation (asynchronous mode).
///
/// The response is sent when it is dropped.
pub struct Response<W: Any = Fresh> {
    resp: *mut Resp,
    _marker: PhantomData<W>
}

// no worries, the response is always modified by only one thread at a time
unsafe impl Send for Response {}

impl Drop for ResponseHolder {
    fn drop(&mut self) {
        println!("dropping response holder");
    }
}

impl<T: Any> Drop for Response<T> {
    fn drop(&mut self) {
        println!("dropping response");
    }
}<commit_msg>trying to use Box instead of Arc<UnsafeCell><commit_after>use hyper::header::{CookiePair as Cookie, ContentLength, ContentType, Header, Location, SetCookie};
use hyper::status::StatusCode as Status;

use hyper::{Control, Headers, Next};

use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};

use handlebars::Handlebars;
use serde::ser::Serialize as ToJson;

pub use serde_json::value as value;

use std::any::Any;
use std::fmt::Debug;
use std::borrow::Cow;
use std::io::{ErrorKind, Read, Result, Write};
use std::marker::PhantomData;

use std::fs::{File, read_dir};
use std::path::Path;

use std::boxed::Box;
use std::sync::atomic::{AtomicBool, Ordering};

use buffer::Buffer;

#[derive(Debug)]
pub struct Resp {
    status: Status,
    headers: Headers,
    body: Buffer,

    ctrl: Control,
    ended_or_notify: AtomicBool
}

impl Resp {
    pub fn new(ctrl: Control) -> Resp {
        Resp {
            status: Status::Ok,
            headers: Headers::default(),
            body: Buffer::new(),

            ctrl: ctrl,
            ended_or_notify: AtomicBool::new(false)
        }
    }

    /// called by handler to know whether we can write the response or not
    ///
    /// two possible cases:
    ///   - done before can_write: in synchronous style, done is called first,
    ///     sets ended_or_notify to true and does not notify the handler
    ///   - can_write before done: response not done yet, can_write is called first,
    ///     sets ended_or_notify to true so that when done is called, it will notify the handler
    fn can_write(&self) -> bool {
        if self.ended_or_notify.compare_and_swap(false, true, Ordering::AcqRel) {
            // if true, response already ended, we can write it
            true
        } else {
            // if false, response did not end yet
            // ended has been set to true to mean "need to notify handler"
            false
        }
    }

    /// mirror function of can_write, called by Response
    fn done(&self) {
        if self.ended_or_notify.compare_and_swap(false, true, Ordering::AcqRel) {
            // if true, means we need to notify, the flag is not updated
            self.ctrl.ready(Next::write()).unwrap();
        } else {
            // if previously false: no need to notify
            // ended has been set to true to mean "response ended"
        }
    }

    fn status(&mut self, status: Status) {
        self.status = status;
    }

    fn has_header<H: Header>(&self) -> bool {
        self.headers.has::<H>()
    }

    fn header<H: Header>(&mut self, header: H) {
        self.headers.set(header);
    }

    fn header_raw<K: Into<Cow<'static, str>> + Debug>(&mut self, name: K, value: Vec<Vec<u8>>) {
        self.headers.set_raw(name, value);
    }

    fn push_cookie(&mut self, cookie: Cookie) {
        self.headers.get_mut::<SetCookie>().unwrap().push(cookie)
    }

    fn len(&self) -> usize {
        self.body.len()
    }

    fn append<D: AsRef<[u8]>>(&self, content: D) {
        // TODO use deque self.body.append(content.as_ref());
    }

    fn send<D: Into<Vec<u8>>>(&mut self, content: D) {
        self.body.send(content);
    }
}

/// This holds data for the response.
pub struct ResponseHolder {
    resp: Box<Resp>
}

impl ResponseHolder {    

    pub fn new(control: Control) -> ResponseHolder {
        ResponseHolder {
            resp: Box::new(Resp::new(control))
        }
    }

    pub fn new_response(&mut self) -> Response {
        Response {
            resp: &mut *self.resp as *mut Resp,
            _marker: PhantomData
        }
    }

    pub fn get_status(&self) -> Status {
        self.resp.status
    }

    pub fn set_headers(&self, headers: &mut Headers) {
        *headers = self.resp.headers.clone();
    }

    pub fn body(&mut self) -> &mut Buffer {
        &mut self.resp.body
    }

    /// two possible cases:
    ///   - done before can_write: in synchronous style, done is called first,
    ///     sets ended_or_notify to true and does not notify the handler
    ///   - can_write before done: response not done yet, can_write is called first,
    ///     sets ended_or_notify to true so that when done is called, it will notify the handler
    pub fn can_write(&self) -> bool {
        self.resp.can_write()
    }
}

/// This represents the response that will be sent back to the application.
///
/// Includes a status code (default 200 OK), headers, and a body.
/// The response can be updated and sent back immediately in a synchronous way,
/// or deferred pending some computation (asynchronous mode).
///
/// The response is sent when it is dropped.
pub struct Response<W: Any = Fresh> {
    resp: *mut Resp,
    _marker: PhantomData<W>
}

// no worries, the response is always modified by only one thread at a time
unsafe impl Send for Response {}

impl Drop for ResponseHolder {
    fn drop(&mut self) {
        println!("dropping response holder");
    }
}

impl<T: Any> Drop for Response<T> {
    fn drop(&mut self) {
        println!("dropping response");
    }
}
{'fraction_non_alphanumeric': 0.12489091437990885, 'fraction_numerical': 0.0011635799476389023, 'mean_word_length': 2.4518072289156625, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 63, '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': '1823990', 'n_tokens_mistral': 3146, 'n_tokens_neox': 3089, 'n_words': 1024}