fix: align interface macros with canonical values

This commit is contained in:
2026-09-29 06:11:07 +09:00
parent 7f4e0e4460
commit 2d524723a4
14 changed files with 740 additions and 528 deletions
+34 -32
View File
@@ -31,7 +31,7 @@
#![deny(missing_docs)]
use std::any::TypeId;
use std::collections::{HashMap, HashSet};
use std::collections::{BTreeMap, HashMap, HashSet};
use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::marker::PhantomData;
@@ -42,8 +42,7 @@ use wip_interface::DispatchError;
pub use wip_interface::{InterfaceDefinition, InterfaceImplementation};
pub use wip_protocol;
use wip_protocol::{
InterfaceDescriptor, NamedValue, Object, ObjectId, OperationCall, OperationTarget,
ProtocolError, ProtocolErrorCategory, ValidationError, Value,
InterfaceDescriptor, Object, ProtocolError, ProtocolErrorCode, ValidationError, Value,
};
/// Opaque bytes used as a conditional execution precondition.
@@ -64,6 +63,14 @@ impl Validator {
}
}
/// Host-local identity used by the legacy request-scoped publication API.
///
/// Canonical protocol calls target a Worldspace path. This wrapper remains
/// temporarily host-local so T-5 can adapt generated values without assigning
/// object identity semantics to the protocol descriptor model.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ObjectId(pub String);
/// Opaque host-assigned reference to one registered interface artifact.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InterfaceRef(String);
@@ -161,8 +168,8 @@ impl InterfaceRegistry {
/// `validator` should be present when the host intends the reference to
/// represent a versioned descriptor. Its presence makes the same value a
/// mandatory precondition for dispatch. Registration finalizes the
/// descriptor's protocol `name` to the assigned opaque reference so it
/// corresponds directly to [`Object::interfaces`].
/// descriptor remains independent of both registration and its assigned
/// opaque reference.
pub fn register<D>(
&mut self,
_definition: D,
@@ -176,7 +183,7 @@ impl InterfaceRegistry {
return Err(RegistrationError::AlreadyRegistered);
}
let mut descriptor = D::descriptor();
let descriptor = D::descriptor();
descriptor
.validate()
.map_err(RegistrationError::InvalidDescriptor)?;
@@ -185,11 +192,6 @@ impl InterfaceRegistry {
"wip-interface:{}:{}",
self.namespace, self.next_reference
));
// The protocol model currently carries the interface identifier in the
// descriptor's `name` field. Finalize that identity to the same opaque
// reference placed on published objects; the generated Rust trait name
// is registration-local metadata, not wire identity.
descriptor.name = reference.0.clone();
self.next_reference = self
.next_reference
.checked_add(1)
@@ -289,7 +291,7 @@ pub trait WipObject {
}
}
type DispatchFn<T> = fn(&T, &str, Vec<NamedValue>) -> Result<Option<Value>, DispatchError>;
type DispatchFn<T> = fn(&T, &str, BTreeMap<String, Value>) -> Result<Value, DispatchError>;
struct BoundInterface<T> {
artifact: Arc<InterfaceArtifact>,
@@ -350,13 +352,20 @@ impl<T: WipObject> PublishedObject<T> {
/// Builds the protocol object metadata with interface insertion order intact.
#[must_use]
pub fn protocol_object(&self) -> Object {
let id = self.implementation.id();
let object = Object {
id: self.implementation.id(),
name: id.0.clone(),
description: None,
interfaces: self
.interfaces
.iter()
.map(|bound| bound.artifact.reference.0.clone())
.collect(),
r#ref: Some(id.0),
validator: self
.implementation
.validator()
.map(|validator| validator.0.clone()),
};
debug_assert!(object.validate().is_ok());
object
@@ -438,14 +447,7 @@ impl<T: WipObject> PublishedObject<T> {
bound
.artifact
.descriptor
.validate_call(&OperationCall {
target: OperationTarget {
object: request.object.clone(),
interface: bound.artifact.descriptor.name.clone(),
operation: request.operation.clone(),
},
arguments: request.arguments.clone(),
})
.validate_arguments(&request.operation, &request.arguments)
.map_err(|error| CallError::new(CallErrorKind::InvalidArguments, error.to_string()))?;
let value = (bound.dispatch)(&self.implementation, &request.operation, request.arguments)
@@ -454,7 +456,7 @@ impl<T: WipObject> PublishedObject<T> {
bound
.artifact
.descriptor
.validate_return(&request.operation, value.as_ref())
.validate_result(&request.operation, &value)
.map_err(|error| CallError::new(CallErrorKind::InvalidResult, error.to_string()))?;
Ok(CallResult {
@@ -512,14 +514,14 @@ pub struct CallRequest {
/// Operation name within the selected interface descriptor.
pub operation: String,
/// Named protocol arguments.
pub arguments: Vec<NamedValue>,
pub arguments: BTreeMap<String, Value>,
}
/// Successful host dispatch result.
#[derive(Debug, Clone, PartialEq)]
pub struct CallResult {
/// Encoded application value, or `None` for a no-return operation.
pub value: Option<Value>,
/// Encoded application result. No-data operations return [`Value::Unit`].
pub value: Value,
/// Object validator observed after the implementation returned.
pub validator: Option<Validator>,
}
@@ -610,20 +612,20 @@ impl CallError {
#[must_use]
pub fn protocol_error(&self) -> ProtocolError {
let category = match self.kind {
CallErrorKind::ObjectNotFound => ProtocolErrorCategory::ObjectNotFound,
CallErrorKind::InterfaceMismatch => ProtocolErrorCategory::InterfaceNotFound,
CallErrorKind::OperationNotFound => ProtocolErrorCategory::OperationNotFound,
CallErrorKind::InvalidArguments => ProtocolErrorCategory::InvalidArguments,
CallErrorKind::ObjectNotFound => ProtocolErrorCode::NotFound,
CallErrorKind::InterfaceMismatch => ProtocolErrorCode::InterfaceMismatch,
CallErrorKind::OperationNotFound => ProtocolErrorCode::OperationNotFound,
CallErrorKind::InvalidArguments => ProtocolErrorCode::InvalidArguments,
CallErrorKind::ValidatorRequired
| CallErrorKind::ValidatorMismatch
| CallErrorKind::InterfaceValidatorRequired
| CallErrorKind::InterfaceValidatorMismatch => ProtocolErrorCategory::InvalidRequest,
| CallErrorKind::InterfaceValidatorMismatch => ProtocolErrorCode::InvalidRequest,
CallErrorKind::InvalidResult | CallErrorKind::Implementation => {
ProtocolErrorCategory::Internal
ProtocolErrorCode::Internal
}
};
ProtocolError {
category,
code: category,
message: self.message.clone(),
}
}