redevplugin-worker-sdk 2.0.10

Rust SDK for ReDevPlugin WASM workers
Documentation
use crate::api;
use crate::error::Result;
use crate::resource::{Handle, MAX_IO_CHUNK_BYTES};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize)]
pub struct TcpConnect {
    pub host: String,
    pub port: u16,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub timeout_ms: Option<u32>,
    #[serde(default)]
    pub no_delay: bool,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub keep_alive_ms: Option<u32>,
}

pub type ConnectOptions = TcpConnect;

#[derive(Deserialize)]
struct HandleResult {
    handle: u64,
}

pub struct TcpStream {
    handle: Handle,
}

impl TcpStream {
    pub fn connect(options: TcpConnect) -> Result<Self> {
        let opened: HandleResult = api::call("net.tcp.connect", &options)?;
        Ok(Self {
            handle: Handle::new(opened.handle)?,
        })
    }

    pub fn read(&mut self, capacity: usize) -> Result<(Vec<u8>, u32)> {
        self.handle.read(capacity)
    }

    pub fn write_all(&mut self, bytes: &[u8]) -> Result<()> {
        for chunk in bytes.chunks(MAX_IO_CHUNK_BYTES) {
            self.handle.write(chunk, 0)?;
        }
        Ok(())
    }

    pub fn shutdown(&mut self, direction: Shutdown) -> Result<()> {
        #[derive(Serialize)]
        struct Arguments {
            handle: u64,
            direction: Shutdown,
        }
        let _: serde_json::Value = api::call(
            "net.tcp.shutdown",
            &Arguments {
                handle: self.handle.id(),
                direction,
            },
        )?;
        Ok(())
    }

    pub fn close(mut self) -> Result<()> {
        self.handle.close()
    }
}

#[derive(Debug, Clone, Copy, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Shutdown {
    Read,
    Write,
    Both,
}

#[derive(Debug, Clone, Serialize)]
pub struct TcpListen {
    pub host: String,
    pub port: u16,
}

pub type ListenOptions = TcpListen;

#[derive(Deserialize)]
struct ListenResult {
    handle: u64,
    address: String,
}

pub struct TcpListener {
    handle: Handle,
    pub address: String,
}

impl TcpListener {
    pub fn listen(options: TcpListen) -> Result<Self> {
        let opened: ListenResult = api::call("net.tcp.listen", &options)?;
        Ok(Self {
            handle: Handle::new(opened.handle)?,
            address: opened.address,
        })
    }

    pub fn accept(&mut self, no_delay: bool, keep_alive_ms: Option<u32>) -> Result<TcpStream> {
        #[derive(Serialize)]
        struct Arguments {
            handle: u64,
            no_delay: bool,
            #[serde(skip_serializing_if = "Option::is_none")]
            keep_alive_ms: Option<u32>,
        }
        let opened: HandleResult = api::call(
            "net.tcp.accept",
            &Arguments {
                handle: self.handle.id(),
                no_delay,
                keep_alive_ms,
            },
        )?;
        Ok(TcpStream {
            handle: Handle::new(opened.handle)?,
        })
    }

    pub fn close(mut self) -> Result<()> {
        self.handle.close()
    }
}