Skip to content

Commit f50ecc5

Browse files
committed
Fix pack/theater API compatibility - use local ConversionError and FromValue
1 parent 485d966 commit f50ecc5

File tree

2 files changed

+148
-24
lines changed

2 files changed

+148
-24
lines changed

Cargo.lock

Lines changed: 1 addition & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/theater/src/pack_bridge.rs

Lines changed: 147 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,134 @@ use std::sync::Arc;
1717
// Re-export Pack types for convenient use throughout Theater
1818
// Note: We use composite's internal abi module, not composite_abi crate directly,
1919
// because that's what the runtime functions return.
20-
pub use pack::abi::{FromValue, FromValueError, Value, ValueType};
20+
pub use pack::abi::{Value, ValueType};
21+
22+
// ============================================================================
23+
// Value Conversion Types
24+
// ============================================================================
25+
26+
/// Error type for Value conversions
27+
#[derive(Debug, Clone)]
28+
pub enum ConversionError {
29+
/// Type mismatch during conversion
30+
TypeMismatch { expected: String, got: String },
31+
/// Missing field in record
32+
MissingField(String),
33+
/// Missing index in tuple/list
34+
MissingIndex(usize),
35+
/// Missing payload for variant
36+
MissingPayload,
37+
/// Field conversion error
38+
FieldError(String, Box<ConversionError>),
39+
/// Index conversion error
40+
IndexError(usize, Box<ConversionError>),
41+
}
42+
43+
impl std::fmt::Display for ConversionError {
44+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45+
match self {
46+
Self::TypeMismatch { expected, got } => {
47+
write!(f, "type mismatch: expected {}, got {}", expected, got)
48+
}
49+
Self::MissingField(name) => write!(f, "missing field: {}", name),
50+
Self::MissingIndex(idx) => write!(f, "missing index: {}", idx),
51+
Self::MissingPayload => write!(f, "missing payload for variant"),
52+
Self::FieldError(name, e) => write!(f, "field '{}': {}", name, e),
53+
Self::IndexError(idx, e) => write!(f, "index {}: {}", idx, e),
54+
}
55+
}
56+
}
57+
58+
impl std::error::Error for ConversionError {}
59+
60+
/// Trait for converting from a Pack Value.
61+
///
62+
/// This is Theater's local version that works with pack::abi::Value.
63+
pub trait FromValue: Sized {
64+
fn from_value(v: Value) -> std::result::Result<Self, ConversionError>;
65+
}
66+
67+
// Basic FromValue implementations
68+
69+
impl FromValue for () {
70+
fn from_value(v: Value) -> std::result::Result<Self, ConversionError> {
71+
match v {
72+
Value::Tuple(items) if items.is_empty() => Ok(()),
73+
other => Err(ConversionError::TypeMismatch {
74+
expected: String::from("()"),
75+
got: format!("{:?}", other),
76+
}),
77+
}
78+
}
79+
}
80+
81+
impl FromValue for String {
82+
fn from_value(v: Value) -> std::result::Result<Self, ConversionError> {
83+
match v {
84+
Value::String(s) => Ok(s),
85+
other => Err(ConversionError::TypeMismatch {
86+
expected: String::from("String"),
87+
got: format!("{:?}", other),
88+
}),
89+
}
90+
}
91+
}
92+
93+
impl FromValue for i64 {
94+
fn from_value(v: Value) -> std::result::Result<Self, ConversionError> {
95+
match v {
96+
Value::S64(n) => Ok(n),
97+
other => Err(ConversionError::TypeMismatch {
98+
expected: String::from("i64"),
99+
got: format!("{:?}", other),
100+
}),
101+
}
102+
}
103+
}
104+
105+
impl FromValue for i32 {
106+
fn from_value(v: Value) -> std::result::Result<Self, ConversionError> {
107+
match v {
108+
Value::S32(n) => Ok(n),
109+
other => Err(ConversionError::TypeMismatch {
110+
expected: String::from("i32"),
111+
got: format!("{:?}", other),
112+
}),
113+
}
114+
}
115+
}
116+
117+
impl FromValue for bool {
118+
fn from_value(v: Value) -> std::result::Result<Self, ConversionError> {
119+
match v {
120+
Value::Bool(b) => Ok(b),
121+
other => Err(ConversionError::TypeMismatch {
122+
expected: String::from("bool"),
123+
got: format!("{:?}", other),
124+
}),
125+
}
126+
}
127+
}
128+
129+
impl<T: FromValue> FromValue for Vec<T> {
130+
fn from_value(v: Value) -> std::result::Result<Self, ConversionError> {
131+
match v {
132+
Value::List { items, .. } => {
133+
items.into_iter()
134+
.enumerate()
135+
.map(|(i, item)| {
136+
T::from_value(item).map_err(|e| ConversionError::IndexError(i, Box::new(e)))
137+
})
138+
.collect()
139+
}
140+
other => Err(ConversionError::TypeMismatch {
141+
expected: String::from("List"),
142+
got: format!("{:?}", other),
143+
}),
144+
}
145+
}
146+
}
147+
21148
pub use pack::{
22149
AsyncCtx, AsyncInstance, AsyncRuntime, CallInterceptor, Ctx, HostFunctionProvider,
23150
HostLinkerBuilder, InterfaceBuilder, LinkerError,
@@ -529,7 +656,7 @@ pub struct ActorResult<T> {
529656
}
530657

531658
impl<T: FromValue> FromValue for ActorResult<T> {
532-
fn from_value(value: Value) -> std::result::Result<Self, FromValueError> {
659+
fn from_value(value: Value) -> std::result::Result<Self, ConversionError> {
533660
match value {
534661
// Handle Value::Result (Pack's native result type)
535662
Value::Result { value: Ok(inner), .. } => {
@@ -540,14 +667,17 @@ impl<T: FromValue> FromValue for ActorResult<T> {
540667
Value::String(s) => s,
541668
other => format!("{:?}", other),
542669
};
543-
Err(FromValueError::Custom(format!("Actor error: {}", error_msg)))
670+
Err(ConversionError::TypeMismatch {
671+
expected: String::from("Ok result"),
672+
got: format!("Actor error: {}", error_msg),
673+
})
544674
}
545675
// Handle Value::Variant (alternative encoding)
546676
Value::Variant { tag: 0, payload, .. } if !payload.is_empty() => {
547677
decode_actor_ok_payload(payload.into_iter().next().unwrap())
548678
}
549679
Value::Variant { tag: 0, .. } => {
550-
Err(FromValueError::Custom("Ok variant with empty payload".to_string()))
680+
Err(ConversionError::MissingPayload)
551681
}
552682
Value::Variant { tag: 1, payload, .. } => {
553683
let error_msg = payload.into_iter().next()
@@ -556,11 +686,14 @@ impl<T: FromValue> FromValue for ActorResult<T> {
556686
other => format!("{:?}", other),
557687
})
558688
.unwrap_or_else(|| "Unknown error".to_string());
559-
Err(FromValueError::Custom(format!("Actor error: {}", error_msg)))
689+
Err(ConversionError::TypeMismatch {
690+
expected: String::from("Ok result"),
691+
got: format!("Actor error: {}", error_msg),
692+
})
560693
}
561694
other => {
562-
Err(FromValueError::TypeMismatch {
563-
expected: "Result or Variant",
695+
Err(ConversionError::TypeMismatch {
696+
expected: String::from("Result or Variant"),
564697
got: format!("{:?}", other),
565698
})
566699
}
@@ -569,7 +702,7 @@ impl<T: FromValue> FromValue for ActorResult<T> {
569702
}
570703

571704
/// Helper to decode the Ok payload of an actor result.
572-
fn decode_actor_ok_payload<T: FromValue>(value: Value) -> std::result::Result<ActorResult<T>, FromValueError> {
705+
fn decode_actor_ok_payload<T: FromValue>(value: Value) -> std::result::Result<ActorResult<T>, ConversionError> {
573706
match value {
574707
Value::Tuple(mut items) if !items.is_empty() => {
575708
// First element is state: option<list<u8>>
@@ -580,23 +713,23 @@ fn decode_actor_ok_payload<T: FromValue>(value: Value) -> std::result::Result<Ac
580713
let bytes: std::result::Result<Vec<u8>, _> = items.into_iter()
581714
.map(|v| match v {
582715
Value::U8(b) => Ok(b),
583-
other => Err(FromValueError::TypeMismatch {
584-
expected: "U8",
716+
other => Err(ConversionError::TypeMismatch {
717+
expected: String::from("U8"),
585718
got: format!("{:?}", other),
586719
}),
587720
})
588721
.collect();
589722
Some(bytes?)
590723
}
591-
other => return Err(FromValueError::TypeMismatch {
592-
expected: "List<u8>",
724+
other => return Err(ConversionError::TypeMismatch {
725+
expected: String::from("List<u8>"),
593726
got: format!("{:?}", other),
594727
}),
595728
}
596729
}
597730
Value::Option { value: None, .. } => None,
598-
other => return Err(FromValueError::TypeMismatch {
599-
expected: "Option",
731+
other => return Err(ConversionError::TypeMismatch {
732+
expected: String::from("Option"),
600733
got: format!("{:?}", other),
601734
}),
602735
};

0 commit comments

Comments
 (0)