pzzld_server/cli/cmd/
serve.rs

1/*
2    Appellation: serve <module>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5use crate::{platform::Context, workers::serve::Server, AsyncHandle};
6
7#[derive(
8    Clone,
9    Debug,
10    Default,
11    Eq,
12    Hash,
13    Ord,
14    PartialEq,
15    PartialOrd,
16    clap::Parser,
17    serde::Deserialize,
18    serde::Serialize,
19)]
20pub struct ServeCmd {
21    #[clap(subcommand)]
22    pub args: Option<ServeOpts>,
23    #[clap(long, short = 'H')]
24    pub host: Option<String>,
25    #[clap(long, short)]
26    pub port: Option<u16>,
27    #[clap(long, short)]
28    pub workdir: Option<String>,
29}
30
31#[derive(
32    Clone,
33    Debug,
34    Eq,
35    Hash,
36    Ord,
37    PartialEq,
38    PartialOrd,
39    clap::Subcommand,
40    serde::Deserialize,
41    serde::Serialize,
42)]
43pub enum ServeOpts {
44    Run {
45        #[clap(long, short)]
46        prefix: Option<String>,
47    },
48}
49
50impl ServeCmd {
51    pub fn new() -> Self {
52        clap::Parser::parse()
53    }
54
55    pub fn args(&self) -> Option<&ServeOpts> {
56        self.args.as_ref()
57    }
58
59    pub fn addr(&self) -> Option<core::net::SocketAddr> {
60        let addr = format!("{}:{}", self.host()?, self.port()?)
61            .parse()
62            .unwrap();
63        Some(addr)
64    }
65
66    pub fn host(&self) -> Option<&str> {
67        self.host.as_deref()
68    }
69
70    pub fn port(&self) -> Option<u16> {
71        self.port
72    }
73
74    #[tracing::instrument(skip_all, name = "handle", target = "serve")]
75    pub async fn handle<Ctx>(self, ctx: &mut Ctx) -> <Self as AsyncHandle<Ctx>>::Output
76    where
77        Self: AsyncHandle<Ctx>,
78        Ctx: core::fmt::Debug,
79    {
80        <Self as AsyncHandle<Ctx>>::handle(self, ctx).await
81    }
82}
83
84#[async_trait::async_trait]
85impl AsyncHandle<Context> for ServeCmd {
86    type Output = anyhow::Result<()>;
87
88    async fn handle(self, ctx: &mut Context) -> Self::Output {
89        if let Some(host) = self.host {
90            ctx.config_mut().network_mut().set_host(host);
91        }
92        if let Some(port) = self.port {
93            ctx.config_mut().network_mut().set_port(port);
94        }
95        // update the workdir; if it was set
96        ctx.config_mut().set_some_workdir(self.workdir);
97        // get a reference to the network address
98        let addr = ctx.config().network().address();
99        // get a reference to the scope
100        let scope = ctx.config().scope().clone();
101        // create a new server instance
102        let server = Server::new(addr.as_socket_addr(), scope);
103        // start the server
104        tokio::join!(server.serve());
105        Ok(())
106    }
107}