#![allow(dead_code)]
use std::sync::atomic::{AtomicU32, Ordering};
use crate::{Service, ServiceRegistry, c5_compiled::CompiledServiceRegistry};
static NEXT_REGISTRY_SEAL: AtomicU32 = AtomicU32::new(1);
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(u8)]
enum Method {
Post = 1,
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(u8)]
enum ContentType {
Json = 1,
ManagedBytes = 2,
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(u8)]
enum BodyMode {
None = 1,
ContentLength = 2,
Chunked = 3,
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
struct FramingPolicy {
method: Method,
content_type: ContentType,
body_mode: BodyMode,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct FramingView<'a> {
route_token: &'a [u8],
policy: FramingPolicy,
declared_length: Option<u64>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(transparent)]
pub struct ContractIdentity(u64);
impl ContractIdentity {
pub const fn opaque(self) -> u64 {
self.0
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(transparent)]
pub struct PlanIdentity(u64);
impl PlanIdentity {
pub const fn opaque(self) -> u64 {
self.0
}
const fn index(self) -> usize {
self.0 as u32 as usize
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(transparent)]
pub struct FactoryIdentity(u64);
impl FactoryIdentity {
pub const fn opaque(self) -> u64 {
self.0
}
const fn index(self) -> usize {
self.0 as u32 as usize
}
}
#[derive(Clone, Copy)]
struct RegistrySeal(u32);
impl RegistrySeal {
fn acquire() -> Result<Self, RegistryError> {
NEXT_REGISTRY_SEAL
.fetch_update(Ordering::AcqRel, Ordering::Acquire, |current| {
current.checked_add(1)
})
.map(Self)
.map_err(|_| RegistryError::SizeOverflow)
}
const fn identity(self, index: u32) -> u64 {
((self.0 as u64) << 32) | index as u64
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RegisteredEntryIdentity {
contract: ContractIdentity,
plan: PlanIdentity,
factory: FactoryIdentity,
}
impl RegisteredEntryIdentity {
pub const fn contract(self) -> ContractIdentity {
self.contract
}
pub const fn plan(self) -> PlanIdentity {
self.plan
}
pub const fn factory(self) -> FactoryIdentity {
self.factory
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RegisteredPlanProof {
identity: PlanIdentity,
body_hard_limit: u64,
commitment: u64,
}
impl RegisteredPlanProof {
pub const fn identity(self) -> PlanIdentity {
self.identity
}
pub const fn body_hard_limit(self) -> u64 {
self.body_hard_limit
}
pub const fn commitment(self) -> u64 {
self.commitment
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RegisteredDbDemand {
connections: u64,
operations: u64,
}
impl RegisteredDbDemand {
const NONE: Self = Self {
connections: 0,
operations: 0,
};
pub const fn connections(self) -> u64 {
self.connections
}
pub const fn operations(self) -> u64 {
self.operations
}
pub const fn is_none(self) -> bool {
self.connections == 0 && self.operations == 0
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RegisteredRouteExecutionProof {
identity: RegisteredEntryIdentity,
plan: RegisteredPlanProof,
db_demand: RegisteredDbDemand,
response_capacity: u64,
}
impl RegisteredRouteExecutionProof {
pub const fn identity(self) -> RegisteredEntryIdentity {
self.identity
}
pub const fn plan(self) -> RegisteredPlanProof {
self.plan
}
pub const fn db_demand(self) -> RegisteredDbDemand {
self.db_demand
}
pub const fn response_capacity(self) -> u64 {
self.response_capacity
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RegisteredEntry {
execution: RegisteredRouteExecutionProof,
}
impl RegisteredEntry {
pub(super) const fn from_execution_proof(execution: RegisteredRouteExecutionProof) -> Self {
Self { execution }
}
pub const fn identity(self) -> RegisteredEntryIdentity {
self.execution.identity()
}
pub const fn plan(self) -> RegisteredPlanProof {
self.execution.plan()
}
pub const fn execution_proof(self) -> RegisteredRouteExecutionProof {
self.execution
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RegistryResource {
Routes,
RouteBytes,
Plans,
Factories,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RegistryError {
InvalidLimits,
AllocationFailed,
CapacityExceeded(RegistryResource),
InvalidRouteToken,
AmbiguousRoute,
UnknownPlan,
UnknownFactory,
UnregisteredService,
IncompletePlan,
SizeOverflow,
UnknownRoute,
UnsupportedFraming,
DeclaredLengthRequired,
DeclaredLengthForbidden,
DeclaredLengthTooLarge,
}
#[derive(Clone, Copy, Debug)]
struct RegistryLimits {
max_routes: usize,
max_route_key_bytes: usize,
max_total_route_key_bytes: usize,
max_plans: usize,
max_factories: usize,
}
impl RegistryLimits {
fn validate(self) -> Result<Self, RegistryError> {
if self.max_routes == 0
|| self.max_route_key_bytes == 0
|| self.max_total_route_key_bytes == 0
|| self.max_plans == 0
|| self.max_factories == 0
|| self.max_routes > u32::MAX as usize
|| self.max_plans > u32::MAX as usize
|| self.max_factories > u32::MAX as usize
|| self.max_total_route_key_bytes > u32::MAX as usize
|| self.max_route_key_bytes > self.max_total_route_key_bytes
{
return Err(RegistryError::InvalidLimits);
}
Ok(self)
}
}
#[derive(Clone, Copy, Debug)]
struct PlanDraft {
body_hard_limit: Option<u64>,
managed_body_peak: Option<u64>,
decode_peak: Option<u64>,
business_working_set_peak: Option<u64>,
internal_call_peak: Option<u64>,
response_object_peak: Option<u64>,
encode_destination_peak: Option<u64>,
copy_on_success_peak: Option<u64>,
}
#[derive(Clone, Copy, Debug)]
struct StaticPlan {
identity: PlanIdentity,
body_hard_limit: u64,
commitment: u64,
db_demand: RegisteredDbDemand,
response_capacity: u64,
}
impl PlanDraft {
fn complete(self) -> Result<StaticPlan, RegistryError> {
let body_hard_limit = self.body_hard_limit.ok_or(RegistryError::IncompletePlan)?;
let peaks = [
self.managed_body_peak,
self.decode_peak,
self.business_working_set_peak,
self.internal_call_peak,
self.response_object_peak,
self.encode_destination_peak,
self.copy_on_success_peak,
];
let mut commitment = 0_u64;
for peak in peaks {
commitment = commitment
.checked_add(peak.ok_or(RegistryError::IncompletePlan)?)
.ok_or(RegistryError::SizeOverflow)?;
}
if self.managed_body_peak != Some(body_hard_limit) {
return Err(RegistryError::IncompletePlan);
}
usize::try_from(body_hard_limit).map_err(|_| RegistryError::SizeOverflow)?;
usize::try_from(commitment).map_err(|_| RegistryError::SizeOverflow)?;
Ok(StaticPlan {
identity: PlanIdentity(0),
body_hard_limit,
commitment,
db_demand: RegisteredDbDemand::NONE,
response_capacity: 0,
})
}
}
#[derive(Debug)]
struct RouteDraft {
token_offset: u32,
token_length: u32,
policy: FramingPolicy,
identity: RegisteredEntryIdentity,
}
#[derive(Debug)]
struct FactoryRecord {
identity: FactoryIdentity,
}
struct EntryRegistryBuilder {
seal: RegistrySeal,
limits: RegistryLimits,
routes: Vec<RouteDraft>,
route_bytes: Vec<u8>,
plans: Vec<StaticPlan>,
factories: Vec<FactoryRecord>,
}
impl EntryRegistryBuilder {
fn new(limits: RegistryLimits) -> Result<Self, RegistryError> {
let limits = limits.validate()?;
let seal = RegistrySeal::acquire()?;
let mut routes = Vec::new();
let mut route_bytes = Vec::new();
let mut plans = Vec::new();
let mut factories = Vec::new();
routes
.try_reserve_exact(limits.max_routes)
.map_err(|_| RegistryError::AllocationFailed)?;
route_bytes
.try_reserve_exact(limits.max_total_route_key_bytes)
.map_err(|_| RegistryError::AllocationFailed)?;
plans
.try_reserve_exact(limits.max_plans)
.map_err(|_| RegistryError::AllocationFailed)?;
factories
.try_reserve_exact(limits.max_factories)
.map_err(|_| RegistryError::AllocationFailed)?;
Ok(Self {
seal,
routes,
route_bytes,
plans,
factories,
limits,
})
}
fn register_plan(&mut self, draft: PlanDraft) -> Result<PlanIdentity, RegistryError> {
self.register_compiled_plan(draft, RegisteredDbDemand::NONE, 0)
}
fn register_compiled_plan(
&mut self,
draft: PlanDraft,
db_demand: RegisteredDbDemand,
response_capacity: u64,
) -> Result<PlanIdentity, RegistryError> {
if self.plans.len() == self.limits.max_plans {
return Err(RegistryError::CapacityExceeded(RegistryResource::Plans));
}
let mut plan = draft.complete()?;
plan.db_demand = db_demand;
plan.response_capacity = response_capacity;
let index = u32::try_from(self.plans.len()).map_err(|_| RegistryError::SizeOverflow)?;
let identity = PlanIdentity(self.seal.identity(index));
plan.identity = identity;
self.plans.push(plan);
Ok(identity)
}
fn register_factory(&mut self) -> Result<FactoryIdentity, RegistryError> {
if self.factories.len() == self.limits.max_factories {
return Err(RegistryError::CapacityExceeded(RegistryResource::Factories));
}
let index = u32::try_from(self.factories.len()).map_err(|_| RegistryError::SizeOverflow)?;
let identity = FactoryIdentity(self.seal.identity(index));
self.factories.push(FactoryRecord { identity });
Ok(identity)
}
fn factory_identity(&self, index: usize) -> Result<FactoryIdentity, RegistryError> {
self.factories
.get(index)
.map(|factory| factory.identity)
.ok_or(RegistryError::UnknownFactory)
}
fn register_route(
&mut self,
token: &[u8],
policy: FramingPolicy,
plan: PlanIdentity,
factory: FactoryIdentity,
) -> Result<ContractIdentity, RegistryError> {
if self.routes.len() == self.limits.max_routes {
return Err(RegistryError::CapacityExceeded(RegistryResource::Routes));
}
validate_route_token(token, self.limits.max_route_key_bytes)?;
let total_route_key_bytes = self
.route_bytes
.len()
.checked_add(token.len())
.ok_or(RegistryError::SizeOverflow)?;
if total_route_key_bytes > self.limits.max_total_route_key_bytes {
return Err(RegistryError::CapacityExceeded(
RegistryResource::RouteBytes,
));
}
let index = u32::try_from(self.routes.len()).map_err(|_| RegistryError::SizeOverflow)?;
let contract = ContractIdentity(self.seal.identity(index));
let token_offset =
u32::try_from(self.route_bytes.len()).map_err(|_| RegistryError::SizeOverflow)?;
let token_length = u32::try_from(token.len()).map_err(|_| RegistryError::SizeOverflow)?;
debug_assert!(self.route_bytes.capacity() - self.route_bytes.len() >= token.len());
self.route_bytes.extend_from_slice(token);
self.routes.push(RouteDraft {
token_offset,
token_length,
policy,
identity: RegisteredEntryIdentity {
contract,
plan,
factory,
},
});
Ok(contract)
}
fn freeze(mut self) -> Result<FrozenEntryRegistry, RegistryError> {
for route in &self.routes {
if self
.plans
.get(route.identity.plan.index())
.is_none_or(|plan| plan.identity != route.identity.plan)
{
return Err(RegistryError::UnknownPlan);
}
if self
.factories
.get(route.identity.factory.index())
.is_none_or(|factory| factory.identity != route.identity.factory)
{
return Err(RegistryError::UnknownFactory);
}
}
let route_bytes = &self.route_bytes;
self.routes.sort_unstable_by(|left, right| {
route_order(route_bytes, left).cmp(&route_order(route_bytes, right))
});
if self
.routes
.windows(2)
.any(|pair| route_order(route_bytes, &pair[0]) == route_order(route_bytes, &pair[1]))
{
return Err(RegistryError::AmbiguousRoute);
}
Ok(FrozenEntryRegistry {
max_route_key_bytes: self.limits.max_route_key_bytes,
routes: self.routes,
route_bytes: self.route_bytes,
plans: self.plans,
_factories: self.factories,
})
}
}
fn route_token<'a>(bytes: &'a [u8], route: &RouteDraft) -> &'a [u8] {
let start = route.token_offset as usize;
let end = start + route.token_length as usize;
&bytes[start..end]
}
fn route_order<'a>(bytes: &'a [u8], route: &RouteDraft) -> (&'a [u8], FramingPolicy) {
(route_token(bytes, route), route.policy)
}
#[derive(Debug)]
struct FrozenEntryRegistry {
max_route_key_bytes: usize,
routes: Vec<RouteDraft>,
route_bytes: Vec<u8>,
plans: Vec<StaticPlan>,
_factories: Vec<FactoryRecord>,
}
impl FrozenEntryRegistry {
fn lookup(&self, view: FramingView<'_>) -> Result<RegisteredEntry, RegistryError> {
validate_route_token(view.route_token, self.max_route_key_bytes)?;
let start = self
.routes
.partition_point(|route| route_token(&self.route_bytes, route) < view.route_token);
let end = self
.routes
.partition_point(|route| route_token(&self.route_bytes, route) <= view.route_token);
if start == end {
return Err(RegistryError::UnknownRoute);
}
let route = self.routes[start..end]
.iter()
.find(|route| route.policy == view.policy)
.ok_or(RegistryError::UnsupportedFraming)?;
let plan = self
.plans
.get(route.identity.plan.index())
.ok_or(RegistryError::UnknownPlan)?;
validate_declared_length(view, plan.body_hard_limit)?;
Ok(RegisteredEntry {
execution: RegisteredRouteExecutionProof {
identity: route.identity,
plan: RegisteredPlanProof {
identity: route.identity.plan,
body_hard_limit: plan.body_hard_limit,
commitment: plan.commitment,
},
db_demand: plan.db_demand,
response_capacity: plan.response_capacity,
},
})
}
fn execution_slot(&self, registered: RegisteredEntry) -> Result<usize, RegistryError> {
let proof = registered.execution;
let identity = proof.identity;
let plan = self
.plans
.get(identity.plan.index())
.ok_or(RegistryError::UnknownPlan)?;
let factory = self
._factories
.get(identity.factory.index())
.ok_or(RegistryError::UnknownFactory)?;
let route_exists = self.routes.iter().any(|route| route.identity == identity);
if !route_exists
|| plan.identity != identity.plan
|| factory.identity != identity.factory
|| proof.plan.identity != identity.plan
|| proof.plan.body_hard_limit != plan.body_hard_limit
|| proof.plan.commitment != plan.commitment
|| proof.db_demand != plan.db_demand
|| proof.response_capacity != plan.response_capacity
{
return Err(RegistryError::UnknownFactory);
}
Ok(identity.factory.index())
}
}
fn validate_declared_length(
view: FramingView<'_>,
body_hard_limit: u64,
) -> Result<(), RegistryError> {
match (view.policy.body_mode, view.declared_length) {
(BodyMode::None, None | Some(0)) | (BodyMode::Chunked, None) => Ok(()),
(BodyMode::None | BodyMode::Chunked, Some(_)) => {
Err(RegistryError::DeclaredLengthForbidden)
}
(BodyMode::ContentLength, None) => Err(RegistryError::DeclaredLengthRequired),
(BodyMode::ContentLength, Some(length)) if length > body_hard_limit => {
Err(RegistryError::DeclaredLengthTooLarge)
}
(BodyMode::ContentLength, Some(_)) => Ok(()),
}
}
fn validate_route_token(token: &[u8], max_bytes: usize) -> Result<(), RegistryError> {
if token.len() < 2
|| token.len() > max_bytes
|| token[0] != b'/'
|| token[token.len() - 1] == b'/'
{
return Err(RegistryError::InvalidRouteToken);
}
let mut previous_slash = true;
for byte in &token[1..] {
let allowed = byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'_' | b'.' | b'~');
if *byte == b'/' {
if previous_slash {
return Err(RegistryError::InvalidRouteToken);
}
previous_slash = true;
} else if allowed {
previous_slash = false;
} else {
return Err(RegistryError::InvalidRouteToken);
}
}
Ok(())
}
#[derive(Clone, Copy, Debug)]
pub struct EntryCapabilityLimits {
inner: RegistryLimits,
}
impl EntryCapabilityLimits {
pub const fn new(
max_routes: usize,
max_route_key_bytes: usize,
max_total_route_key_bytes: usize,
max_plans: usize,
max_factories: usize,
) -> Self {
Self {
inner: RegistryLimits {
max_routes,
max_route_key_bytes,
max_total_route_key_bytes,
max_plans,
max_factories,
},
}
}
pub(super) const fn max_routes(self) -> usize {
self.inner.max_routes
}
}
#[derive(Clone, Copy, Debug)]
pub struct EntryPlanSpec {
inner: PlanDraft,
}
impl EntryPlanSpec {
pub const fn new() -> Self {
Self {
inner: PlanDraft {
body_hard_limit: None,
managed_body_peak: None,
decode_peak: None,
business_working_set_peak: None,
internal_call_peak: None,
response_object_peak: None,
encode_destination_peak: None,
copy_on_success_peak: None,
},
}
}
pub const fn body_hard_limit(mut self, bytes: u64) -> Self {
self.inner.body_hard_limit = Some(bytes);
self
}
pub const fn managed_body_peak(mut self, bytes: u64) -> Self {
self.inner.managed_body_peak = Some(bytes);
self
}
pub const fn decode_peak(mut self, bytes: u64) -> Self {
self.inner.decode_peak = Some(bytes);
self
}
pub const fn business_working_set_peak(mut self, bytes: u64) -> Self {
self.inner.business_working_set_peak = Some(bytes);
self
}
pub const fn internal_call_peak(mut self, bytes: u64) -> Self {
self.inner.internal_call_peak = Some(bytes);
self
}
pub const fn response_object_peak(mut self, bytes: u64) -> Self {
self.inner.response_object_peak = Some(bytes);
self
}
pub const fn encode_destination_peak(mut self, bytes: u64) -> Self {
self.inner.encode_destination_peak = Some(bytes);
self
}
pub const fn copy_on_success_peak(mut self, bytes: u64) -> Self {
self.inner.copy_on_success_peak = Some(bytes);
self
}
}
impl Default for EntryPlanSpec {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct EntryFraming {
policy: FramingPolicy,
}
impl EntryFraming {
pub const fn post_managed_content_length() -> Self {
Self {
policy: FramingPolicy {
method: Method::Post,
content_type: ContentType::ManagedBytes,
body_mode: BodyMode::ContentLength,
},
}
}
pub const fn post_managed_chunked() -> Self {
Self {
policy: FramingPolicy {
method: Method::Post,
content_type: ContentType::ManagedBytes,
body_mode: BodyMode::Chunked,
},
}
}
pub const fn post_managed_empty() -> Self {
Self {
policy: FramingPolicy {
method: Method::Post,
content_type: ContentType::ManagedBytes,
body_mode: BodyMode::None,
},
}
}
pub(super) const fn source_code(self) -> [u8; 3] {
[
self.policy.method as u8,
self.policy.content_type as u8,
self.policy.body_mode as u8,
]
}
pub(super) const fn canonical_name(self) -> &'static str {
match self.policy.body_mode {
BodyMode::None => "post_managed_empty",
BodyMode::ContentLength => "post_managed_content_length",
BodyMode::Chunked => "post_managed_chunked",
}
}
}
pub struct ServiceEntryCapabilityBuilder {
registry: ServiceRegistryOwner,
entries: EntryRegistryBuilder,
}
enum ServiceRegistryOwner {
V1(ServiceRegistry),
Compiled(CompiledServiceRegistry),
}
impl ServiceRegistryOwner {
fn entry_count(&self) -> usize {
match self {
Self::V1(registry) => registry.internal_entry_count(),
Self::Compiled(registry) => registry.internal_entry_count(),
}
}
fn entry_index<S>(&self) -> Option<usize>
where
S: Service,
{
match self {
Self::V1(registry) => registry.internal_entry_index::<S>(),
Self::Compiled(registry) => registry.internal_entry_index::<S>(),
}
}
}
impl ServiceEntryCapabilityBuilder {
pub fn new(
registry: ServiceRegistry,
limits: EntryCapabilityLimits,
) -> Result<Self, RegistryError> {
Self::from_owner(ServiceRegistryOwner::V1(registry), limits)
}
pub(super) fn new_compiled(
registry: CompiledServiceRegistry,
limits: EntryCapabilityLimits,
) -> Result<Self, RegistryError> {
Self::from_owner(ServiceRegistryOwner::Compiled(registry), limits)
}
fn from_owner(
registry: ServiceRegistryOwner,
limits: EntryCapabilityLimits,
) -> Result<Self, RegistryError> {
let factory_count = registry.entry_count();
let mut entries = EntryRegistryBuilder::new(limits.inner)?;
for _ in 0..factory_count {
entries.register_factory()?;
}
Ok(Self { registry, entries })
}
pub fn register_plan(
&mut self,
specification: EntryPlanSpec,
) -> Result<PlanIdentity, RegistryError> {
self.entries.register_plan(specification.inner)
}
pub(super) fn register_compiled_plan(
&mut self,
specification: EntryPlanSpec,
connections: u64,
operations: u64,
response_capacity: u64,
) -> Result<PlanIdentity, RegistryError> {
self.entries.register_compiled_plan(
specification.inner,
RegisteredDbDemand {
connections,
operations,
},
response_capacity,
)
}
pub(super) fn service_index<S>(&self) -> Result<usize, RegistryError>
where
S: Service,
{
self.registry
.entry_index::<S>()
.ok_or(RegistryError::UnregisteredService)
}
pub fn expose<S>(
&mut self,
route_token: &[u8],
framing: EntryFraming,
plan: PlanIdentity,
) -> Result<ContractIdentity, RegistryError>
where
S: Service,
{
self.expose_identity::<S>(route_token, framing, plan)
.map(|identity| identity.contract)
}
pub(super) fn expose_compiled<S>(
&mut self,
route_token: &[u8],
framing: EntryFraming,
plan: PlanIdentity,
) -> Result<RegisteredEntryIdentity, RegistryError>
where
S: Service,
{
self.expose_identity::<S>(route_token, framing, plan)
}
fn expose_identity<S>(
&mut self,
route_token: &[u8],
framing: EntryFraming,
plan: PlanIdentity,
) -> Result<RegisteredEntryIdentity, RegistryError>
where
S: Service,
{
let index = self
.registry
.entry_index::<S>()
.ok_or(RegistryError::UnregisteredService)?;
let factory = self.entries.factory_identity(index)?;
let contract = self
.entries
.register_route(route_token, framing.policy, plan, factory)?;
Ok(RegisteredEntryIdentity {
contract,
plan,
factory,
})
}
pub fn freeze(self) -> Result<ServiceEntryCapability, RegistryError> {
Ok(ServiceEntryCapability {
_registry: self.registry,
entries: self.entries.freeze()?,
})
}
}
pub struct ServiceEntryCapability {
_registry: ServiceRegistryOwner,
entries: FrozenEntryRegistry,
}
pub(super) struct CanonicalRouteFact<'a> {
pub(super) token: &'a [u8],
pub(super) framing: EntryFraming,
pub(super) identity: RegisteredEntryIdentity,
}
impl ServiceEntryCapability {
pub fn lookup(
&self,
route_token: &[u8],
framing: EntryFraming,
declared_length: Option<u64>,
) -> Result<RegisteredEntry, RegistryError> {
self.entries.lookup(FramingView {
route_token,
policy: framing.policy,
declared_length,
})
}
pub(super) fn execution_slot(
&self,
registered: RegisteredEntry,
) -> Result<usize, RegistryError> {
self.entries.execution_slot(registered)
}
pub(super) fn canonical_route_facts(
&self,
) -> impl ExactSizeIterator<Item = CanonicalRouteFact<'_>> {
self.entries.routes.iter().map(|route| CanonicalRouteFact {
token: route_token(&self.entries.route_bytes, route),
framing: EntryFraming {
policy: route.policy,
},
identity: route.identity,
})
}
}
#[cfg(test)]
mod tests {
use saddle_admission::{ProcessLedger, ResourceConfig};
use super::*;
use crate::{
ServiceRegistryBuilder,
registry::tests::{Echo, EchoImpl, observer},
};
const POLICY: FramingPolicy = FramingPolicy {
method: Method::Post,
content_type: ContentType::ManagedBytes,
body_mode: BodyMode::ContentLength,
};
fn limits() -> RegistryLimits {
RegistryLimits {
max_routes: 4,
max_route_key_bytes: 32,
max_total_route_key_bytes: 64,
max_plans: 2,
max_factories: 2,
}
}
fn complete_plan(body: u64) -> PlanDraft {
PlanDraft {
body_hard_limit: Some(body),
managed_body_peak: Some(body),
decode_peak: Some(16),
business_working_set_peak: Some(32),
internal_call_peak: Some(8),
response_object_peak: Some(24),
encode_destination_peak: Some(64),
copy_on_success_peak: Some(64),
}
}
fn complete_spec(body: u64) -> EntryPlanSpec {
EntryPlanSpec::new()
.body_hard_limit(body)
.managed_body_peak(body)
.decode_peak(16)
.business_working_set_peak(32)
.internal_call_peak(8)
.response_object_peak(24)
.encode_destination_peak(64)
.copy_on_success_peak(64)
}
fn frozen_registry() -> (
FrozenEntryRegistry,
RegisteredEntryIdentity,
RegisteredEntryIdentity,
) {
let mut builder = EntryRegistryBuilder::new(limits()).unwrap();
let plan = builder.register_plan(complete_plan(128)).unwrap();
let factory = builder.register_factory().unwrap();
let first_contract = builder
.register_route(b"/orders/create", POLICY, plan, factory)
.unwrap();
let second_policy = FramingPolicy {
body_mode: BodyMode::Chunked,
..POLICY
};
let second_contract = builder
.register_route(b"/orders/create", second_policy, plan, factory)
.unwrap();
(
builder.freeze().unwrap(),
RegisteredEntryIdentity {
contract: first_contract,
plan,
factory,
},
RegisteredEntryIdentity {
contract: second_contract,
plan,
factory,
},
)
}
#[test]
fn startup_build_is_bounded_and_freeze_rejects_ambiguity() {
let mut builder = EntryRegistryBuilder::new(limits()).unwrap();
let plan = builder.register_plan(complete_plan(128)).unwrap();
let factory = builder.register_factory().unwrap();
builder
.register_route(b"/orders/create", POLICY, plan, factory)
.unwrap();
builder
.register_route(b"/orders/create", POLICY, plan, factory)
.unwrap();
assert_eq!(builder.freeze().unwrap_err(), RegistryError::AmbiguousRoute);
let mut builder = EntryRegistryBuilder::new(RegistryLimits {
max_routes: 2,
max_route_key_bytes: 14,
max_total_route_key_bytes: 14,
..limits()
})
.unwrap();
let plan = builder.register_plan(complete_plan(1)).unwrap();
let factory = builder.register_factory().unwrap();
builder
.register_route(b"/first", POLICY, plan, factory)
.unwrap();
assert_eq!(
builder
.register_route(b"/too-long", POLICY, plan, factory)
.unwrap_err(),
RegistryError::CapacityExceeded(RegistryResource::RouteBytes)
);
}
#[test]
fn startup_rejects_incomplete_overflowing_and_unknown_closure() {
let mut builder = EntryRegistryBuilder::new(limits()).unwrap();
let mut incomplete = complete_plan(8);
incomplete.internal_call_peak = None;
assert_eq!(
builder.register_plan(incomplete).unwrap_err(),
RegistryError::IncompletePlan
);
let mut overflow = complete_plan(u64::MAX);
overflow.decode_peak = Some(1);
assert_eq!(
builder.register_plan(overflow).unwrap_err(),
RegistryError::SizeOverflow
);
let factory = builder.register_factory().unwrap();
builder
.register_route(b"/unknown", POLICY, PlanIdentity(7), factory)
.unwrap();
assert_eq!(builder.freeze().unwrap_err(), RegistryError::UnknownPlan);
let mut builder = EntryRegistryBuilder::new(limits()).unwrap();
let plan = builder.register_plan(complete_plan(8)).unwrap();
builder
.register_route(b"/unknown", POLICY, plan, FactoryIdentity(7))
.unwrap();
assert_eq!(builder.freeze().unwrap_err(), RegistryError::UnknownFactory);
}
#[test]
fn lookup_is_deterministic_and_fails_explicitly() {
let (registry, fixed, chunked) = frozen_registry();
assert_eq!(
registry
.lookup(FramingView {
route_token: b"/orders/create",
policy: POLICY,
declared_length: Some(128),
})
.map(RegisteredEntry::identity),
Ok(fixed)
);
assert_eq!(
registry
.lookup(FramingView {
route_token: b"/orders/create",
policy: FramingPolicy {
body_mode: BodyMode::Chunked,
..POLICY
},
declared_length: None,
})
.map(RegisteredEntry::identity),
Ok(chunked)
);
assert_eq!(
registry.lookup(FramingView {
route_token: b"/orders/create",
policy: POLICY,
declared_length: Some(129),
}),
Err(RegistryError::DeclaredLengthTooLarge)
);
assert_eq!(
registry.lookup(FramingView {
route_token: b"/orders%2Fcreate",
policy: POLICY,
declared_length: Some(1),
}),
Err(RegistryError::InvalidRouteToken)
);
assert_eq!(
registry.lookup(FramingView {
route_token: b"/missing",
policy: POLICY,
declared_length: Some(1),
}),
Err(RegistryError::UnknownRoute)
);
assert_eq!(
registry.lookup(FramingView {
route_token: b"/orders/create",
policy: FramingPolicy {
content_type: ContentType::Json,
..POLICY
},
declared_length: Some(1),
}),
Err(RegistryError::UnsupportedFraming)
);
}
#[tokio::test(flavor = "current_thread")]
async fn frozen_lookup_allocates_nothing_and_invokes_no_user_code() {
let registry = real_capability();
let expected = registry
.lookup(
b"/orders/create",
EntryFraming::post_managed_content_length(),
Some(64),
)
.unwrap()
.identity();
let ledger = audit_ledger();
let envelope = ledger
.try_envelope(0, 512, |_| async {
for _ in 0..10_000 {
let actual = registry
.lookup(
b"/orders/create",
EntryFraming::post_managed_content_length(),
Some(64),
)
.unwrap();
assert_eq!(actual.identity(), expected);
assert_eq!(actual.plan().body_hard_limit(), 128);
assert_eq!(actual.plan().commitment(), 336);
}
})
.unwrap();
let report = envelope.await.unwrap();
assert_eq!(report.escape_allocations, 0);
assert_eq!(report.managed_allocations, 0);
assert_eq!(report.framework_allocations, 1);
let snapshot = ledger.try_shutdown().unwrap();
assert_eq!(snapshot.active_accounts, 0);
assert_eq!(snapshot.committed, 0);
}
#[tokio::test(flavor = "current_thread")]
async fn preallocated_builder_registers_and_freezes_without_growth() {
let builder = EntryRegistryBuilder::new(limits()).unwrap();
assert_eq!(builder.routes.capacity(), limits().max_routes);
assert_eq!(
builder.route_bytes.capacity(),
limits().max_total_route_key_bytes
);
assert_eq!(builder.plans.capacity(), limits().max_plans);
assert_eq!(builder.factories.capacity(), limits().max_factories);
let ledger = audit_ledger();
let envelope = ledger
.try_envelope(0, 512, |_| async move {
let mut builder = builder;
let plan = builder.register_plan(complete_plan(128)).unwrap();
let factory = builder.register_factory().unwrap();
builder
.register_route(b"/orders/create", POLICY, plan, factory)
.unwrap();
let registry = builder.freeze().unwrap();
assert_eq!(registry.routes.len(), 1);
})
.unwrap();
let report = envelope.await.unwrap();
assert_eq!(report.escape_allocations, 0);
assert_eq!(report.managed_allocations, 0);
let snapshot = ledger.try_shutdown().unwrap();
assert_eq!(snapshot.active_accounts, 0);
}
#[test]
fn transport_result_is_fixed_width_and_contains_no_owner() {
assert_eq!(std::mem::size_of::<ContractIdentity>(), 8);
assert_eq!(std::mem::size_of::<PlanIdentity>(), 8);
assert_eq!(std::mem::size_of::<FactoryIdentity>(), 8);
assert_eq!(std::mem::size_of::<RegisteredEntryIdentity>(), 24);
assert_eq!(std::mem::size_of::<RegisteredPlanProof>(), 24);
assert_eq!(std::mem::size_of::<RegisteredDbDemand>(), 16);
assert_eq!(std::mem::size_of::<RegisteredRouteExecutionProof>(), 72);
assert_eq!(std::mem::size_of::<RegisteredEntry>(), 72);
assert!(!std::mem::needs_drop::<RegisteredEntryIdentity>());
assert!(!std::mem::needs_drop::<RegisteredPlanProof>());
assert!(!std::mem::needs_drop::<RegisteredDbDemand>());
assert!(!std::mem::needs_drop::<RegisteredRouteExecutionProof>());
assert!(!std::mem::needs_drop::<RegisteredEntry>());
}
#[test]
fn capability_is_built_from_real_registry_and_rejects_incomplete_or_missing_service() {
let registry = real_service_registry();
let mut builder =
ServiceEntryCapabilityBuilder::new(registry, capability_limits()).unwrap();
assert_eq!(
builder
.register_plan(EntryPlanSpec::new().body_hard_limit(8))
.unwrap_err(),
RegistryError::IncompletePlan
);
let plan = builder.register_plan(complete_spec(128)).unwrap();
let contract = builder
.expose::<Echo>(
b"/orders/create",
EntryFraming::post_managed_content_length(),
plan,
)
.unwrap();
struct Missing;
impl Service for Missing {
type Request = ();
type Response = ();
}
assert_eq!(
builder
.expose::<Missing>(
b"/missing",
EntryFraming::post_managed_content_length(),
plan,
)
.unwrap_err(),
RegistryError::UnregisteredService
);
let capability = builder.freeze().unwrap();
let entry = capability
.lookup(
b"/orders/create",
EntryFraming::post_managed_content_length(),
Some(64),
)
.unwrap();
assert_eq!(entry.identity().contract(), contract);
assert_eq!(entry.identity().plan(), plan);
assert_eq!(entry.identity().factory().opaque() as u32, 0);
assert_eq!(entry.plan().identity(), plan);
assert_eq!(entry.plan().body_hard_limit(), 128);
assert_eq!(entry.plan().commitment(), 336);
}
#[test]
fn identity_from_another_registry_cannot_be_replayed() {
let mut first =
ServiceEntryCapabilityBuilder::new(real_service_registry(), capability_limits())
.unwrap();
let foreign_plan = first.register_plan(complete_spec(128)).unwrap();
let mut second =
ServiceEntryCapabilityBuilder::new(real_service_registry(), capability_limits())
.unwrap();
second
.register_plan(complete_spec(128))
.expect("second registry has its own plan");
second
.expose::<Echo>(
b"/orders/create",
EntryFraming::post_managed_content_length(),
foreign_plan,
)
.unwrap();
assert!(matches!(second.freeze(), Err(RegistryError::UnknownPlan)));
}
fn real_capability() -> ServiceEntryCapability {
let registry = real_service_registry();
let mut builder =
ServiceEntryCapabilityBuilder::new(registry, capability_limits()).unwrap();
let plan = builder.register_plan(complete_spec(128)).unwrap();
builder
.expose::<Echo>(
b"/orders/create",
EntryFraming::post_managed_content_length(),
plan,
)
.unwrap();
builder.freeze().unwrap()
}
fn real_service_registry() -> ServiceRegistry {
let mut builder = ServiceRegistryBuilder::new();
builder
.register::<Echo, _>(
crate::ServiceDescriptor::new("orders", "create", "call"),
EchoImpl,
)
.unwrap();
builder.build(observer()).unwrap()
}
fn capability_limits() -> EntryCapabilityLimits {
EntryCapabilityLimits::new(4, 32, 64, 2, 2)
}
fn audit_ledger() -> ProcessLedger {
let process_state_reserve = ProcessLedger::minimum_process_state_reserve(1).unwrap();
ProcessLedger::new(ResourceConfig {
managed_capacity: 0,
entry_reserve: 1,
framework_reserve: 512,
task_reserve: 512,
process_state_reserve,
system_estimate: 1_024,
safety_margin: 512,
process_limit: 2_561 + process_state_reserve,
max_active_requests: 1,
})
.unwrap()
}
}