use alloc::string::String;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
pub use ids::{Sri, Srn};
pub use names::{Command, Event};
pub use naming::{NameError, ROOT_NS, child_sri, resolve_target, sri_of_path, validate_segment};
mod ids;
mod names;
pub mod naming;
pub mod spawn_ref;
pub const ERR_CELL_CMD_TIMEOUT: i32 = -7;
pub const ERR_CELL_CMD_CELL_NOT_PRESENT: i32 = -2;
pub const ERR_CELL_CMD_COMMAND_NOT_PRESENT: i32 = -3;
pub const ERR_CELL_CMD_CELL_ERROR: i32 = -4;
pub const ERR_CELL_CMD_INTERNAL: i32 = -5;
pub const ERR_CELL_CMD_SMALL_BUFFER: i32 = -6;
pub const ERR_SERIALISATION: i32 = -127;
#[derive(Serialize, Deserialize, Debug)]
#[allow(missing_docs)]
pub struct CommandRequest {
pub sri: Sri,
pub command: Command,
pub payload: Option<Vec<u8>>,
}
#[derive(Serialize, Deserialize, Debug)]
#[allow(missing_docs)]
pub struct EventPublishRequest {
pub event: Event,
pub payload: Option<Vec<u8>>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct CreateTimerRequest {
pub export_name: String,
pub delay_ms: u64,
pub period_ms: u64,
pub count: Option<u32>,
pub fixed_delay: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ClassRef {
Hash([u8; 32]),
Name(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpawnRequest {
pub class: ClassRef,
pub local_name: Option<String>,
pub tags: Option<Vec<String>>,
pub arguments: Option<Vec<u8>>,
pub detached: bool,
pub grace_ms: Option<u64>,
pub deadline_ms: Option<u64>,
}
pub const STATUS_OK: core::ffi::c_int = 0;
pub const SPAWN_ERR_CLASS_NOT_FOUND: core::ffi::c_int = -10;
pub const SPAWN_ERR_ALREADY_EXISTS: core::ffi::c_int = -11;
pub const SPAWN_ERR_DEPLOY_FAILED: core::ffi::c_int = -12;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SpawnError {
ClassNotFound,
AlreadyExists,
DeployFailed,
}
impl TryFrom<core::ffi::c_int> for SpawnError {
type Error = core::ffi::c_int;
fn try_from(code: core::ffi::c_int) -> Result<Self, Self::Error> {
match code {
SPAWN_ERR_CLASS_NOT_FOUND => Ok(Self::ClassNotFound),
SPAWN_ERR_ALREADY_EXISTS => Ok(Self::AlreadyExists),
SPAWN_ERR_DEPLOY_FAILED => Ok(Self::DeployFailed),
_ => Err(code),
}
}
}
impl From<SpawnError> for &'static str {
fn from(err: SpawnError) -> Self {
match err {
SpawnError::ClassNotFound => "class not found",
SpawnError::AlreadyExists => "already exists",
SpawnError::DeployFailed => "deploy failed",
}
}
}
pub const SYS_CELL_LOST: &str = "__sys_cell_lost";
pub const SYS_COMMAND_PREFIX: &str = "__sys";
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum LostReason {
NodeLost,
Crashed,
Stopped {
code: Option<u32>,
},
Terminated,
SpawnFailed,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CellLost {
pub cell: Sri,
pub local_name: Option<String>,
pub reason: LostReason,
}
pub const TERMINATE_ERR_NOT_FOUND: core::ffi::c_int = -20;
pub const TERMINATE_ERR_UNDEPLOY_FAILED: core::ffi::c_int = -21;
pub const TERMINATE_ERR_ERASE_FAILED: core::ffi::c_int = -22;
pub const TERMINATE_ERR_NOT_PERMITTED: core::ffi::c_int = -23;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TerminateError {
NotFound,
UndeployFailed,
EraseFailed,
NotPermitted,
}
impl TryFrom<core::ffi::c_int> for TerminateError {
type Error = core::ffi::c_int;
fn try_from(code: core::ffi::c_int) -> Result<Self, Self::Error> {
match code {
TERMINATE_ERR_NOT_FOUND => Ok(Self::NotFound),
TERMINATE_ERR_UNDEPLOY_FAILED => Ok(Self::UndeployFailed),
TERMINATE_ERR_ERASE_FAILED => Ok(Self::EraseFailed),
TERMINATE_ERR_NOT_PERMITTED => Ok(Self::NotPermitted),
_ => Err(code),
}
}
}
impl From<TerminateError> for &'static str {
fn from(err: TerminateError) -> Self {
match err {
TerminateError::NotFound => "not found",
TerminateError::UndeployFailed => "undeploy failed",
TerminateError::EraseFailed => "erase failed",
TerminateError::NotPermitted => "not permitted",
}
}
}
#[cfg(test)]
mod cell_lost_tests {
use alloc::string::ToString;
use super::*;
#[test]
fn cell_lost_round_trips_all_reasons() {
for reason in [
LostReason::NodeLost,
LostReason::Crashed,
LostReason::Stopped { code: Some(3) },
LostReason::Stopped { code: None },
LostReason::Terminated,
LostReason::SpawnFailed,
] {
let v = CellLost {
cell: sri_of_path("round-trip-test").unwrap().into(),
local_name: Some("pump".to_string()),
reason: reason.clone(),
};
let bytes = postcard::to_allocvec(&v).unwrap();
assert_eq!(postcard::from_bytes::<CellLost>(&bytes).unwrap(), v);
}
}
#[test]
fn sys_cell_lost_is_a_valid_command_name() {
assert!(Command::new(SYS_CELL_LOST.to_string()).is_ok());
assert!(SYS_CELL_LOST.starts_with(SYS_COMMAND_PREFIX));
}
}