rill_runtime/handler/
mod.rs1pub(crate) mod builtin;
11#[cfg(feature = "wasm")]
12pub(crate) mod wasm;
13
14use serde::Serialize;
15
16#[derive(Debug, Clone, Serialize)]
21pub struct HandlerIdentity {
22 pub handler_id: String,
23 pub handler_version: String,
24 pub handler_api_version: u32,
25 pub effective_capabilities: Vec<String>,
26}
27
28#[derive(Debug, thiserror::Error)]
30#[non_exhaustive]
31pub enum HandlerLoadError {
32 #[error("handler pack error: {0}")]
33 Pack(#[from] crate::handler_package::HandlerPackError),
34 #[error("handler does not cover all model capabilities: missing {missing:?}")]
35 CapabilityMissing { missing: Vec<String> },
36 #[error("handler failed to initialize: {0}")]
37 Init(String),
38 #[error("guest metadata does not match signed manifest: {0}")]
39 MetadataMismatch(String),
40}
41
42pub fn effective_capabilities(
46 model: &[String],
47 handler: &[String],
48) -> Result<Vec<String>, HandlerLoadError> {
49 let mut model_sorted = model.to_vec();
50 model_sorted.sort();
51 let mut handler_sorted = handler.to_vec();
52 handler_sorted.sort();
53
54 let effective: Vec<String> = model_sorted
55 .iter()
56 .filter(|capability| handler_sorted.binary_search(capability).is_ok())
57 .cloned()
58 .collect();
59
60 if effective.len() != model.len() {
61 let missing: Vec<String> = model_sorted
62 .iter()
63 .filter(|capability| handler_sorted.binary_search(capability).is_err())
64 .cloned()
65 .collect();
66 return Err(HandlerLoadError::CapabilityMissing { missing });
67 }
68 Ok(effective)
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn effective_capabilities_intersect() {
77 let model = vec!["a".into(), "b".into()];
78 let handler = vec!["a".into(), "b".into(), "c".into()];
79 let result = effective_capabilities(&model, &handler).unwrap();
80 assert_eq!(result, vec!["a", "b"]);
81 }
82
83 #[test]
84 fn effective_capabilities_reject_missing() {
85 let model = vec!["a".into(), "b".into()];
86 let handler = vec!["a".into()];
87 let error = effective_capabilities(&model, &handler).unwrap_err();
88 assert!(
89 matches!(error, HandlerLoadError::CapabilityMissing { missing } if missing == vec!["b"])
90 );
91 }
92}