<commit_before>use std::io;
use runner::runner;
use std::io::{Read,Write};
use std::net::SocketAddr;
use context::{Context, Transfer};
use context::stack::ProtectedFixedSizeStack;
use mio::net::{TcpStream,UdpSocket,TcpListener};
use mio::event::Evented;
use mio::{Ready,Poll,PollOpt,Token};
use std::marker::PhantomData;
use wheel::Token as WToken;
use std::time::Duration;
use std::collections::VecDeque;
use native_tls::{TlsStream, TlsConnector, TlsAcceptor, MidHandshakeTlsStream};

/// Fiber execute function. It receives current fiber, parameter that was used
/// to start the fiber and returns result that will be result of fiber.
///
/// Generally you return from function once socket is closed or read/write times out.
///
/// This function will be called on an independent execution stack which is much more limited
/// so you must either be careful with how deep your stack can get, or set the stack to a high value.
///
/// You must test your code for any possible SIGBUS situations and be careful with calling external crates.
pub type FiberFn<P,R> = fn(Fiber<P,R>,P) -> Option<R>;

/// Available within the fiber execute function to configure fiber or create child fibers. Child fibers
/// return results to parent fibers instead of poller on main stack.
#[derive(PartialEq,Debug)]
pub struct Fiber<P,R> {
    pub(crate) id: usize,
    param: PhantomData<P>,
    resp: PhantomData<R>,
}

impl<P,R> Fiber<P,R> {
    pub(crate) fn new(pos: usize) -> Fiber<P,R> {
        Fiber {
            id: pos,
            param: PhantomData,
            resp: PhantomData,
        }
    }
}

impl<P,R> Fiber<P,R> {
    /// How long to wait on socket operations before timing out. You probably want to set something.
    pub fn socket_timeout(&self, t: Option<Duration>) {
        runner::<P,R>().socket_timeout(self.id, t)
    }

    /// Return intermediate result. A fiber can stream responses to poller or to its parent fiber.
    ///
    /// This function blocks fiber until response is received to poller or parent.
    pub fn resp_chunk(&self, chunk: R) {
        runner::<P,R>().resp_chunk(self.id, chunk);
    }

    /// Accept TCP socket. Works only on fibers from TcpListener.
    pub fn accept_tcp(&self) -> io::Result<(TcpStream, SocketAddr)> {
        runner::<P,R>().accept_tcp(self.id)
    }

    /// Start fiber on TCP socket.
    ///
    /// This function does not block and fiber gets executed on next poll(). There is no relationship
    /// between calling and created fiber.
    pub fn new_tcp(&self, tcp: TcpStream, func: FiberFn<P,R>, param: P) -> io::Result<()> {
        runner().register(Some(self.id), func, FiberSock::Tcp(tcp), param, None).map(|_|{()})
    }

    /// Convert fiber from TcpStream created with TcpStream::connect to TlsStream.
    ///
    /// This function does not block and fiber gets executed on next poll(). There is no relationship
    /// between calling and created fiber.
    pub fn tcp_tls_connect(&self, con: TlsConnector, domain: &str) -> io::Result<()> {
        runner::<P,R>().tcp_tls_connect(self.id, con, domain)
    }

    /// Convert fiber from TcpStream created with TcpListener::accept to TlsStream.
    ///
    /// This function does not block and fiber gets executed on next poll(). There is no relationship
    /// between calling and created fiber.
    pub fn tcp_tls_accept(&self, con: TlsAcceptor) -> io::Result<()> {
        runner::<P,R>().tcp_tls_accept(self.id, con)
    }

    /// Start fiber on TCP listener.
    ///
    /// This function does not block and fiber gets executed on next poll(). There is no relationship
    /// between calling and created fiber.
    pub fn new_listener(&self, tcp: TcpListener, func: FiberFn<P,R>, param: P) -> io::Result<()> {
        runner().register(Some(self.id), func, FiberSock::Listener(tcp), param, None).map(|_|{()})
    }

    /// Start fiber on UDP socket.
    ///
    /// This function does not block and fiber gets executed on next poll(). There is no relationship
    /// between calling and created fiber.
    pub fn new_udp(&self, udp: UdpSocket, func: FiberFn<P,R>, param: P) -> io::Result<()> {
        runner().register(Some(self.id), func, FiberSock::Udp(udp), param, None).map(|_|{()})
    }

    /// Get result of child. If fiber has multiple children it will return first available result.
    /// Will block current fiber if nothing available immediately.
    ///
    /// If none is returned all children have finished executing.
    pub fn get_child(&self) -> Option<R> {
        runner::<P,R>().child_iter(self.id)
    }

    /// Start a child fiber with tcp socket.
    ///
    /// This function does not block current fiber.
    pub fn join_tcp(&self, tcp: TcpStream, func: FiberFn<P,R>, param: P) -> io::Result<()> {
        match runner::<P,R>().register(Some(self.id), func, FiberSock::Tcp(tcp), param, Some(self.id)) {
            Ok(Some(_)) => {
                Ok(())
            }
            Ok(None) => {
                Err(io::Error::new(io::ErrorKind::Other, "can not create child"))
            }
            Err(e) => {
                Err(e)
            }
        }
    }

    /// Start a child fiber with an udp socket.
    ///
    /// This function does not block current fiber.
    pub fn join_udp(&self, udp: UdpSocket, func: FiberFn<P,R>, param: P) -> io::Result<()> {
        match runner::<P,R>().register(Some(self.id), func, FiberSock::Udp(udp), param, Some(self.id)) {
            Ok(Some(_)) => {
                Ok(())
            }
            Ok(None) => {
                Err(io::Error::new(io::ErrorKind::Other, "can not create child"))
            }
            Err(e) => {
                Err(e)
            }
        }
    }

    /// Call main stack.
    ///
    /// This function blocks until main stack produces response.
    pub fn join_main(&self, param: P) -> R {
        runner::<P,R>().join_main(self.id)
    }
}

// We use unwrap directly as we do not allow
// creating fiber without a poller.
impl<P,R> Read for Fiber<P,R> {
    /// Read data from socket. If no data is available to read, fiber will be scheduled out for another one,
    /// until there is data available.
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        runner::<P,R>().read(self.id, buf)
    }
}

impl<'a,P,R> Read for &'a Fiber<P,R> {
    /// Read data from socket. If no data is available to read, fiber will be scheduled out for another one,<commit_msg>fix doc<commit_after>use std::io;
use runner::runner;
use std::io::{Read,Write};
use std::net::SocketAddr;
use context::{Context, Transfer};
use context::stack::ProtectedFixedSizeStack;
use mio::net::{TcpStream,UdpSocket,TcpListener};
use mio::event::Evented;
use mio::{Ready,Poll,PollOpt,Token};
use std::marker::PhantomData;
use wheel::Token as WToken;
use std::time::Duration;
use std::collections::VecDeque;
use native_tls::{TlsStream, TlsConnector, TlsAcceptor, MidHandshakeTlsStream};

/// Fiber execute function. It receives current fiber, parameter that was used
/// to start the fiber and returns result that will be result of fiber.
///
/// Generally you return from function once socket is closed or read/write times out.
///
/// This function will be called on an independent execution stack which is much more limited
/// so you must either be careful with how deep your stack can get, or set the stack to a high value.
///
/// You must test your code for any possible SIGBUS situations and be careful with calling external crates.
pub type FiberFn<P,R> = fn(Fiber<P,R>,P) -> Option<R>;

/// Available within the fiber execute function to configure fiber or create child fibers. Child fibers
/// return results to parent fibers instead of poller on main stack.
#[derive(PartialEq,Debug)]
pub struct Fiber<P,R> {
    pub(crate) id: usize,
    param: PhantomData<P>,
    resp: PhantomData<R>,
}

impl<P,R> Fiber<P,R> {
    pub(crate) fn new(pos: usize) -> Fiber<P,R> {
        Fiber {
            id: pos,
            param: PhantomData,
            resp: PhantomData,
        }
    }
}

impl<P,R> Fiber<P,R> {
    /// How long to wait on socket operations before timing out. You probably want to set something.
    pub fn socket_timeout(&self, t: Option<Duration>) {
        runner::<P,R>().socket_timeout(self.id, t)
    }

    /// Return intermediate result. A fiber can stream responses to poller or to its parent fiber.
    ///
    /// This function blocks fiber until response is received to poller or parent.
    pub fn resp_chunk(&self, chunk: R) {
        runner::<P,R>().resp_chunk(self.id, chunk);
    }

    /// Accept TCP socket. Works only on fibers from TcpListener.
    pub fn accept_tcp(&self) -> io::Result<(TcpStream, SocketAddr)> {
        runner::<P,R>().accept_tcp(self.id)
    }

    /// Convert fiber from TcpStream created with TcpStream::connect to TlsStream.
    pub fn tcp_tls_connect(&self, con: TlsConnector, domain: &str) -> io::Result<()> {
        runner::<P,R>().tcp_tls_connect(self.id, con, domain)
    }

    /// Convert fiber from TcpStream created with TcpListener::accept to TlsStream.
    pub fn tcp_tls_accept(&self, con: TlsAcceptor) -> io::Result<()> {
        runner::<P,R>().tcp_tls_accept(self.id, con)
    }

    /// Start fiber on TCP socket.
    ///
    /// This function does not block and fiber gets executed on next poll(). There is no relationship
    /// between calling and created fiber.
    pub fn new_tcp(&self, tcp: TcpStream, func: FiberFn<P,R>, param: P) -> io::Result<()> {
        runner().register(Some(self.id), func, FiberSock::Tcp(tcp), param, None).map(|_|{()})
    }

    /// Start fiber on TCP listener.
    ///
    /// This function does not block and fiber gets executed on next poll(). There is no relationship
    /// between calling and created fiber.
    pub fn new_listener(&self, tcp: TcpListener, func: FiberFn<P,R>, param: P) -> io::Result<()> {
        runner().register(Some(self.id), func, FiberSock::Listener(tcp), param, None).map(|_|{()})
    }

    /// Start fiber on UDP socket.
    ///
    /// This function does not block and fiber gets executed on next poll(). There is no relationship
    /// between calling and created fiber.
    pub fn new_udp(&self, udp: UdpSocket, func: FiberFn<P,R>, param: P) -> io::Result<()> {
        runner().register(Some(self.id), func, FiberSock::Udp(udp), param, None).map(|_|{()})
    }

    /// Start a child fiber with tcp socket.
    ///
    /// This function does not block current fiber.
    pub fn join_tcp(&self, tcp: TcpStream, func: FiberFn<P,R>, param: P) -> io::Result<()> {
        match runner::<P,R>().register(Some(self.id), func, FiberSock::Tcp(tcp), param, Some(self.id)) {
            Ok(Some(_)) => {
                Ok(())
            }
            Ok(None) => {
                Err(io::Error::new(io::ErrorKind::Other, "can not create child"))
            }
            Err(e) => {
                Err(e)
            }
        }
    }

    /// Start a child fiber with an udp socket.
    ///
    /// This function does not block current fiber.
    pub fn join_udp(&self, udp: UdpSocket, func: FiberFn<P,R>, param: P) -> io::Result<()> {
        match runner::<P,R>().register(Some(self.id), func, FiberSock::Udp(udp), param, Some(self.id)) {
            Ok(Some(_)) => {
                Ok(())
            }
            Ok(None) => {
                Err(io::Error::new(io::ErrorKind::Other, "can not create child"))
            }
            Err(e) => {
                Err(e)
            }
        }
    }

    /// Call main stack.
    ///
    /// This function blocks until main stack produces response.
    pub fn join_main(&self, param: P) -> R {
        runner::<P,R>().join_main(self.id)
    }

    /// Get result of child. If fiber has multiple children it will return first available result.
    /// Will block current fiber if nothing available immediately.
    ///
    /// If none is returned all children have finished executing.
    pub fn get_child(&self) -> Option<R> {
        runner::<P,R>().child_iter(self.id)
    }
}

// We use unwrap directly as we do not allow
// creating fiber without a poller.
impl<P,R> Read for Fiber<P,R> {
    /// Read data from socket. If no data is available to read, fiber will be scheduled out for another one,
    /// until there is data available.
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        runner::<P,R>().read(self.id, buf)
    }
}

impl<'a,P,R> Read for &'a Fiber<P,R> {
    /// Read data from socket. If no data is available to read, fiber will be scheduled out for another one,
{'fraction_non_alphanumeric': 0.1428343695201658, 'fraction_numerical': 0.00015941335883947074, 'mean_word_length': 2.6601516919486583, 'pattern_counts': {'":': 0, '<': 85, '<?xml version=': 0, '>': 123, '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': '7004950', 'n_tokens_mistral': 3852, 'n_tokens_neox': 3793, 'n_words': 1292}