1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
#![forbid(unsafe_code)]

pub use darpi_code_gen::{
    app, handler, job_factory, middleware, req_formatter, resp_formatter, Path, Query,
};
pub use darpi_web::{
    handler::Args, handler::Handler, job, job::RequestJobFactory, job::ResponseJobFactory, logger,
    logger::ReqFormatter, logger::RespFormatter, middleware::RequestMiddleware,
    middleware::ResponseMiddleware, request, response, xml::Xml, yaml::Yaml, Json,
};

use crate::job::Job;
pub use async_trait::async_trait;
pub use chrono;
pub use darpi_route::{ReqRoute, Route};
pub use futures;
pub use http::{header, request::Parts as RequestParts, Method, StatusCode};
pub use hyper::upgrade;
pub use hyper::{self, body, body::HttpBody, service, Body, Error, Request, Response, Server};
pub use log;
pub use rayon;
use serde::{de, Deserialize, Deserializer};
pub use serde_json;
use std::fmt::Display;
use std::str::FromStr;
use std::sync::mpsc::SendError;
pub use tokio;
use tokio::sync::oneshot;
use tokio::sync::oneshot::Receiver;

pub fn from_str<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
    T: FromStr,
    T::Err: Display,
    D: Deserializer<'de>,
{
    let s = String::deserialize(deserializer)?;
    T::from_str(&s).map_err(de::Error::custom)
}

pub async fn oneshot<T>(job: impl Into<Job<T>>) -> Result<Receiver<T>, SendError<Job<T>>>
where
    T: Send + 'static,
{
    let job = job.into();
    match job {
        Job::Future(fut) => {
            let (otx, recv) = oneshot::channel();
            let handle = tokio::runtime::Handle::current();
            handle.spawn(async {
                let _ = otx.send(fut.into_inner().await);
            });
            Ok(recv)
        }
        Job::CpuBound(cpu) => {
            let (otx, recv) = oneshot::channel();
            rayon::spawn(move || {
                let _ = otx.send(cpu.into_inner()());
            });
            Ok(recv)
        }
        Job::IOBlocking(io_blocking) => {
            let (otx, recv) = oneshot::channel();
            let handle = tokio::runtime::Handle::current();
            handle.spawn_blocking(move || {
                let _ = otx.send(io_blocking.into_inner()());
            });
            Ok(recv)
        }
    }
}

pub async fn spawn<T>(job: impl Into<Job<T>>) -> Result<(), SendError<Job<T>>>
where
    T: Send + 'static,
{
    let job = job.into();
    match job {
        Job::Future(fut) => {
            let handle = tokio::runtime::Handle::current();
            handle.spawn(async {
                fut.into_inner().await;
            });
            Ok(())
        }
        Job::CpuBound(cpu) => {
            rayon::spawn(move || {
                cpu.into_inner()();
            });
            Ok(())
        }
        Job::IOBlocking(io_blocking) => {
            let handle = tokio::runtime::Handle::current();
            handle.spawn_blocking(move || {
                io_blocking.into_inner()();
            });
            Ok(())
        }
    }
}