1use std::sync::Mutex;
12
13use crate::blocks::EncryptionAlgorithm;
14use crate::crypto::KeyRing;
15use crate::engine::Emoji;
16use crate::error::MeshError;
17use crate::render::{CpuRenderer, Renderer};
18
19#[derive(Debug, thiserror::Error)]
21pub enum EngineError {
22 #[error("engine not initialized")]
24 NotInitialized,
25 #[error("crypto error: {0}")]
27 Crypto(String),
28 #[error("render error: {0}")]
30 Render(String),
31 #[error("unsupported: {0}")]
34 Unsupported(String),
35 #[error(transparent)]
37 Mesh(#[from] MeshError),
38}
39
40pub trait CombsEngineCore: Send + Sync {
42 fn init(&self, key: &[u8]) -> Result<(), EngineError>;
44
45 fn infer(&self, prompt: &str) -> Result<String, EngineError>;
47
48 fn encrypt_memory(&self, data: &[u8]) -> Result<Vec<u8>, EngineError>;
50
51 fn decrypt_memory(&self, data: &[u8]) -> Result<Vec<u8>, EngineError>;
53
54 fn render_sprite(&self, emoji: &Emoji, frame_index: u32) -> Result<Vec<u8>, EngineError>;
57
58 fn shutdown(&self) -> Result<(), EngineError>;
60}
61
62pub struct DefaultEngine {
66 keyring: Mutex<Option<KeyRing>>,
67 renderer: CpuRenderer,
68}
69
70impl DefaultEngine {
71 #[must_use]
73 pub fn new() -> Self {
74 DefaultEngine {
75 keyring: Mutex::new(None),
76 renderer: CpuRenderer::new(),
77 }
78 }
79}
80
81impl Default for DefaultEngine {
82 fn default() -> Self {
83 Self::new()
84 }
85}
86
87impl CombsEngineCore for DefaultEngine {
88 fn init(&self, key: &[u8]) -> Result<(), EngineError> {
89 let mut guard = self
90 .keyring
91 .lock()
92 .map_err(|_| EngineError::Crypto("keyring lock poisoned".into()))?;
93 *guard = Some(KeyRing::new(Some(key)));
94 Ok(())
95 }
96
97 fn infer(&self, _prompt: &str) -> Result<String, EngineError> {
98 Err(EngineError::Unsupported(
99 "inference requires the `engine` feature".into(),
100 ))
101 }
102
103 fn encrypt_memory(&self, data: &[u8]) -> Result<Vec<u8>, EngineError> {
104 let guard = self
105 .keyring
106 .lock()
107 .map_err(|_| EngineError::Crypto("keyring lock poisoned".into()))?;
108 let keyring = guard.as_ref().ok_or(EngineError::NotInitialized)?;
109 Ok(keyring.encrypt(data, EncryptionAlgorithm::Aes256Gcm)?)
110 }
111
112 fn decrypt_memory(&self, data: &[u8]) -> Result<Vec<u8>, EngineError> {
113 let guard = self
114 .keyring
115 .lock()
116 .map_err(|_| EngineError::Crypto("keyring lock poisoned".into()))?;
117 let keyring = guard.as_ref().ok_or(EngineError::NotInitialized)?;
118 Ok(keyring.decrypt(data, EncryptionAlgorithm::Aes256Gcm)?)
119 }
120
121 fn render_sprite(&self, emoji: &Emoji, frame_index: u32) -> Result<Vec<u8>, EngineError> {
122 let image = emoji.get_image().ok_or(EngineError::Render(
123 "emoji has no image block".into(),
124 ))?;
125 Ok(self.renderer.render_frame(&image.atlas, frame_index)?)
126 }
127
128 fn shutdown(&self) -> Result<(), EngineError> {
129 let mut guard = self
130 .keyring
131 .lock()
132 .map_err(|_| EngineError::Crypto("keyring lock poisoned".into()))?;
133 *guard = None;
134 Ok(())
135 }
136}