#[cfg(feature = "mock")]
use torvyn_types::BackpressureSignal;
use torvyn_types::{BufferHandle, ComponentId, ElementMeta};
#[derive(Clone)]
pub struct CompiledComponent {
pub(crate) inner: CompiledComponentInner,
}
#[derive(Clone)]
#[allow(dead_code)]
pub(crate) enum CompiledComponentInner {
#[cfg(feature = "wasmtime-backend")]
Wasmtime(wasmtime::component::Component),
#[cfg(feature = "mock")]
Mock(MockCompiledComponent),
#[allow(dead_code)]
_Placeholder,
}
#[cfg(feature = "mock")]
#[derive(Clone, Debug)]
pub struct MockCompiledComponent {
#[allow(dead_code)]
pub(crate) id: u64,
}
impl std::fmt::Debug for CompiledComponent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "CompiledComponent")
}
}
pub struct ComponentInstance {
pub(crate) component_id: ComponentId,
pub(crate) inner: ComponentInstanceInner,
pub(crate) has_lifecycle: bool,
pub(crate) has_processor: bool,
pub(crate) has_source: bool,
pub(crate) has_sink: bool,
}
pub(crate) enum ComponentInstanceInner {
#[cfg(feature = "wasmtime-backend")]
Wasmtime(WasmtimeInstanceState),
#[cfg(feature = "mock")]
Mock(MockInstanceState),
#[allow(dead_code)]
_Placeholder,
}
#[cfg(feature = "wasmtime-backend")]
pub(crate) struct WasmtimeInstanceState {
pub(crate) store: wasmtime::Store<HostState>,
#[allow(dead_code)]
pub(crate) instance: wasmtime::component::Instance,
pub(crate) func_process: Option<wasmtime::component::Func>,
pub(crate) func_pull: Option<wasmtime::component::Func>,
pub(crate) func_push: Option<wasmtime::component::Func>,
pub(crate) func_init: Option<wasmtime::component::Func>,
pub(crate) func_teardown: Option<wasmtime::component::Func>,
}
#[cfg(feature = "wasmtime-backend")]
pub(crate) struct HostState {
#[allow(dead_code)]
pub(crate) component_id: ComponentId,
pub(crate) limits: wasmtime::StoreLimits,
#[allow(dead_code)]
pub(crate) fuel_budget: u64,
}
#[cfg(feature = "mock")]
pub(crate) struct MockInstanceState {
#[allow(dead_code)]
pub(crate) component_id: ComponentId,
pub(crate) fuel: u64,
pub(crate) memory_bytes: usize,
pub(crate) call_count: u64,
pub(crate) process_response: Option<ProcessResult>,
pub(crate) pull_response: Option<Option<OutputElement>>,
pub(crate) push_response: Option<BackpressureSignal>,
pub(crate) should_trap: bool,
}
impl ComponentInstance {
#[inline]
pub fn component_id(&self) -> ComponentId {
self.component_id
}
#[inline]
pub fn has_lifecycle(&self) -> bool {
self.has_lifecycle
}
#[inline]
pub fn has_processor(&self) -> bool {
self.has_processor
}
#[inline]
pub fn has_source(&self) -> bool {
self.has_source
}
#[inline]
pub fn has_sink(&self) -> bool {
self.has_sink
}
}
impl std::fmt::Debug for ComponentInstance {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ComponentInstance")
.field("component_id", &self.component_id)
.field("has_lifecycle", &self.has_lifecycle)
.field("has_processor", &self.has_processor)
.field("has_source", &self.has_source)
.field("has_sink", &self.has_sink)
.finish()
}
}
pub struct ImportBindings {
pub(crate) inner: ImportBindingsInner,
}
#[allow(dead_code, clippy::large_enum_variant)]
pub(crate) enum ImportBindingsInner {
#[cfg(feature = "wasmtime-backend")]
Wasmtime(wasmtime::component::Linker<HostState>),
#[cfg(feature = "mock")]
Mock,
#[allow(dead_code)]
_Placeholder,
}
impl std::fmt::Debug for ImportBindings {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ImportBindings")
}
}
#[derive(Clone, Debug)]
pub struct StreamElement {
pub meta: ElementMeta,
pub payload: BufferHandle,
}
#[derive(Clone, Debug)]
pub struct OutputElement {
pub meta: ElementMeta,
pub payload: BufferHandle,
}
#[derive(Clone, Debug)]
pub enum ProcessResult {
Output(OutputElement),
Filtered,
Multiple(Vec<OutputElement>),
}
impl ProcessResult {
#[inline]
pub fn has_output(&self) -> bool {
!matches!(self, ProcessResult::Filtered)
}
#[inline]
pub fn output_count(&self) -> usize {
match self {
ProcessResult::Output(_) => 1,
ProcessResult::Filtered => 0,
ProcessResult::Multiple(v) => v.len(),
}
}
}
#[derive(Clone, Debug)]
pub struct InvocationResult {
pub component_id: ComponentId,
pub function_name: &'static str,
pub fuel_consumed: u64,
pub duration_ns: u64,
pub success: bool,
}
#[cfg(test)]
mod tests {
use super::*;
use torvyn_types::{BufferHandle, ElementMeta, ResourceId};
#[test]
fn test_stream_element_creation() {
let meta = ElementMeta::new(0, 1000, "text/plain".into());
let handle = BufferHandle::new(ResourceId::new(1, 0));
let elem = StreamElement {
meta,
payload: handle,
};
assert_eq!(elem.meta.sequence, 0);
assert_eq!(elem.payload.resource_id().index(), 1);
}
#[test]
fn test_process_result_output() {
let meta = ElementMeta::new(1, 2000, "text/plain".into());
let handle = BufferHandle::new(ResourceId::new(2, 0));
let result = ProcessResult::Output(OutputElement {
meta,
payload: handle,
});
assert!(result.has_output());
assert_eq!(result.output_count(), 1);
}
#[test]
fn test_process_result_filtered() {
let result = ProcessResult::Filtered;
assert!(!result.has_output());
assert_eq!(result.output_count(), 0);
}
#[test]
fn test_process_result_multiple() {
let outputs = vec![
OutputElement {
meta: ElementMeta::new(0, 100, "a".into()),
payload: BufferHandle::new(ResourceId::new(0, 0)),
},
OutputElement {
meta: ElementMeta::new(1, 200, "b".into()),
payload: BufferHandle::new(ResourceId::new(1, 0)),
},
];
let result = ProcessResult::Multiple(outputs);
assert!(result.has_output());
assert_eq!(result.output_count(), 2);
}
#[test]
fn test_component_instance_debug() {
let id = ComponentId::new(42);
let debug_str = format!("component_id: {:?}", id);
assert!(debug_str.contains("42"));
}
#[test]
fn test_compiled_component_debug() {
let cc = CompiledComponent {
inner: CompiledComponentInner::_Placeholder,
};
let s = format!("{:?}", cc);
assert!(s.contains("CompiledComponent"));
}
#[test]
fn test_import_bindings_debug() {
let ib = ImportBindings {
inner: ImportBindingsInner::_Placeholder,
};
let s = format!("{:?}", ib);
assert!(s.contains("ImportBindings"));
}
#[test]
fn test_invocation_result() {
let result = InvocationResult {
component_id: ComponentId::new(1),
function_name: "process",
fuel_consumed: 100,
duration_ns: 5000,
success: true,
};
assert!(result.success);
assert_eq!(result.fuel_consumed, 100);
}
}