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