use alloc::string::String;
use alloc::vec::Vec;
use zerodds_corba_ir::{IrResult, RepositoryId};
pub trait Servant: core::fmt::Debug + Send + Sync {
fn primary_interface(&self) -> String;
fn primary_repository_id(&self) -> IrResult<RepositoryId> {
RepositoryId::parse(&self.primary_interface())
}
fn all_interfaces(&self) -> Vec<String> {
alloc::vec![self.primary_interface()]
}
fn is_a(&self, repository_id: &str) -> bool {
self.all_interfaces().iter().any(|i| i == repository_id)
}
fn is_a_typed(&self, repository_id: &RepositoryId) -> bool {
self.is_a(&repository_id.to_canonical())
}
fn invoke(&self, operation: &str, request_body: &[u8]) -> Vec<u8>;
}
#[cfg(test)]
#[derive(Debug)]
pub(crate) struct EchoServant {
pub repo_id: String,
}
#[cfg(test)]
impl Servant for EchoServant {
fn primary_interface(&self) -> String {
self.repo_id.clone()
}
fn invoke(&self, _operation: &str, request_body: &[u8]) -> Vec<u8> {
request_body.to_vec()
}
}
#[cfg(test)]
#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
mod tests {
use super::*;
#[test]
fn echo_servant_returns_body() {
let s = EchoServant {
repo_id: "IDL:demo/Echo:1.0".into(),
};
let out = s.invoke("ping", &[1, 2, 3]);
assert_eq!(out, alloc::vec![1, 2, 3]);
}
#[test]
fn is_a_checks_repository_ids() {
let s = EchoServant {
repo_id: "IDL:demo/Echo:1.0".into(),
};
assert!(s.is_a("IDL:demo/Echo:1.0"));
assert!(!s.is_a("IDL:demo/Other:1.0"));
}
#[test]
fn primary_repository_id_parses_to_typed_form() {
let s = EchoServant {
repo_id: "IDL:demo/Echo:1.0".into(),
};
let r = s.primary_repository_id().expect("parse");
assert_eq!(r.scoped_name, "demo/Echo");
assert_eq!(r.major, 1);
assert_eq!(r.minor, 0);
assert!(s.is_a_typed(&r));
}
#[test]
fn primary_repository_id_invalid_form_returns_error() {
#[derive(Debug)]
struct Bad;
impl Servant for Bad {
fn primary_interface(&self) -> String {
"not-a-repo-id".into()
}
fn invoke(&self, _: &str, _: &[u8]) -> Vec<u8> {
Vec::new()
}
}
assert!(Bad.primary_repository_id().is_err());
}
}