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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//! Nemesis server implementations.

use mruby::Mrb;
use std::collections::HashMap;
use std::sync::Arc;

use crate::adapter::{AppFactory, RackApp};
use crate::interpreter::{ExecMode, InitFunc};
use crate::Error;

mod rocket;

/// Server implementation backend.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Backend {
    /// A [Rocket](::rocket)-based server implementation.
    Rocket,
}

impl Default for Backend {
    fn default() -> Self {
        Backend::Rocket
    }
}

#[derive(Default, Debug, Clone)]
struct AssetRegistry(HashMap<String, Vec<u8>>);

#[derive(Default, Clone)]
struct MountRegistry(HashMap<String, Mount>);

#[derive(Default, Clone)]
pub struct Builder {
    assets: AssetRegistry,
    mounts: MountRegistry,
    backend: Backend,
}

impl Builder {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn add_mount(mut self, mount: Mount) -> Self {
        self.mounts.0.insert(mount.path.clone(), mount);
        self
    }

    pub fn add_static_asset(self, path: String, asset: Vec<u8>) -> Self {
        let mut assets = HashMap::default();
        assets.insert(path, asset);
        self.add_static_assets(assets)
    }

    pub fn add_static_assets(mut self, assets: HashMap<String, Vec<u8>>) -> Self {
        self.assets.0.extend(assets);
        self
    }

    pub fn set_backend(mut self, backend: Backend) -> Self {
        self.backend = backend;
        self
    }

    pub fn serve(self) -> Result<(), Error> {
        let Backend::Rocket = self.backend;
        rocket::launcher(self)
    }
}

#[derive(Clone)]
pub struct Mount {
    path: String,
    app: Arc<AppFactory>,
    interp_init: Option<Arc<InitFunc>>,
    exec_mode: ExecMode,
}

impl Mount {
    pub fn from_rackup(name: &str, rackup: &str, mount_path: &str) -> Self {
        let name = name.to_owned();
        let path = mount_path.to_owned();
        let rackup = rackup.to_owned();
        let app = move |interp: &Mrb| {
            RackApp::from_rackup(interp, &rackup.clone(), &name.clone(), &path.clone())
        };
        Self {
            path: mount_path.to_owned(),
            app: Arc::new(Box::new(app)),
            interp_init: None,
            exec_mode: ExecMode::default(),
        }
    }

    pub fn with_init(self, init: InitFunc) -> Self {
        Self {
            path: self.path,
            app: self.app,
            interp_init: Some(Arc::new(init)),
            exec_mode: self.exec_mode,
        }
    }

    pub fn with_shared_interpreter(self, max_requests: Option<usize>) -> Self {
        Self {
            path: self.path,
            app: self.app,
            interp_init: self.interp_init,
            exec_mode: ExecMode::PerAppPerWorker {
                max_requests: max_requests.unwrap_or_default(),
            },
        }
    }
}