1use crate::error::Result;
9use crate::{ActorId, Message};
10
11#[derive(Debug)]
13pub enum ExecutionResult {
14 Success {
16 fuel_consumed: u64,
18 response: Option<Vec<u8>>,
20 },
21 FuelExhausted {
23 requested: u64,
25 },
26 Failed {
28 error: String,
30 },
31 NotReady,
33}
34
35pub trait ActorExecutor: Send + Sync {
40 fn execute(&self, actor_id: &ActorId, message: &Message) -> ExecutionResult;
49
50 fn is_ready(&self, actor_id: &ActorId) -> bool;
52
53 fn get_fuel(&self, actor_id: &ActorId) -> Option<u64>;
55
56 fn reset(&self, actor_id: &ActorId) -> Result<()>;
58}
59
60pub struct NullExecutor {
64 call_count: std::sync::atomic::AtomicU64,
65}
66
67impl NullExecutor {
68 pub fn new() -> Self {
70 Self {
71 call_count: std::sync::atomic::AtomicU64::new(0),
72 }
73 }
74
75 pub fn call_count(&self) -> u64 {
77 self.call_count.load(std::sync::atomic::Ordering::Relaxed)
78 }
79}
80
81impl Default for NullExecutor {
82 fn default() -> Self {
83 Self::new()
84 }
85}
86
87impl ActorExecutor for NullExecutor {
88 fn execute(&self, _actor_id: &ActorId, _message: &Message) -> ExecutionResult {
89 self.call_count
90 .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
91 ExecutionResult::Success {
92 fuel_consumed: 0,
93 response: None,
94 }
95 }
96
97 fn is_ready(&self, _actor_id: &ActorId) -> bool {
98 true
99 }
100
101 fn get_fuel(&self, _actor_id: &ActorId) -> Option<u64> {
102 Some(1_000_000)
103 }
104
105 fn reset(&self, _actor_id: &ActorId) -> Result<()> {
106 Ok(())
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113 use crate::{MessagePayload, Priority};
114
115 #[test]
116 fn test_null_executor() {
117 let executor = NullExecutor::new();
118 let actor_id = ActorId::new();
119 let message = Message {
120 sender: None,
121 payload: MessagePayload::Start,
122 priority: Priority::Normal,
123 };
124
125 let result = executor.execute(&actor_id, &message);
126 assert!(matches!(result, ExecutionResult::Success { .. }));
127 assert_eq!(executor.call_count(), 1);
128 }
129
130 #[test]
131 fn test_null_executor_is_ready() {
132 let executor = NullExecutor::new();
133 let actor_id = ActorId::new();
134 assert!(executor.is_ready(&actor_id));
135 }
136
137 #[test]
138 fn test_execution_result_debug() {
139 let result = ExecutionResult::Success {
140 fuel_consumed: 100,
141 response: Some(vec![1, 2, 3]),
142 };
143 let debug_str = format!("{:?}", result);
144 assert!(debug_str.contains("Success"));
145 }
146}