use rexie::{ObjectStore, Rexie, TransactionMode}; use js_sys::Uint8Array; use wasm_bindgen::JsValue; const DB_NAME: &str = "kipina_qwen_db"; const STORE_NAME: &str = "weights_store"; /// Kytketään yhteys IndexedDB:hen (tai luodaan store jos sitä ei ole) pub async fn get_db() -> Result { Rexie::builder(DB_NAME) .version(1) .add_object_store(ObjectStore::new(STORE_NAME)) .build() .await } /// Tallennetaan binääridata (esim. .safetensors lohko tai tokenizer.json string) IndexedDB-välimuistiin pub async fn save_to_idb(key: &str, data: &[u8]) -> Result<(), String> { let db = get_db().await.map_err(|e| format!("DB Error: {}", e))?; let transaction = db .transaction(&[STORE_NAME], TransactionMode::ReadWrite) .map_err(|e| format!("Tx Error: {}", e))?; let store = transaction.store(STORE_NAME).map_err(|e| format!("Store Error: {}", e))?; // Konvertoidaan Rust u8-taulukko JS Uint8Array:ksi, joka on turvallisin blob IDB:lle let js_data = Uint8Array::from(data); store.put(&js_data, Some(&JsValue::from_str(key))) .await .map_err(|e| format!("Put Error: {:?}", e))?; transaction.done().await.map_err(|e| format!("Done Error: {}", e))?; Ok(()) } /// Haetaan tallennettu data IndexedDB:stä key-arvon perusteella pub async fn load_from_idb(key: &str) -> Result>, String> { let db = get_db().await.map_err(|e| format!("DB Error: {}", e))?; let transaction = db .transaction(&[STORE_NAME], TransactionMode::ReadOnly) .map_err(|e| format!("Tx Error: {}", e))?; let store = transaction.store(STORE_NAME).map_err(|e| format!("Store Error: {}", e))?; let js_val_req = store.get(JsValue::from_str(key)).await.map_err(|e| format!("Get Error: {:?}", e))?; let js_val = match js_val_req { Some(val) => val, None => return Ok(None), }; if js_val.is_undefined() || js_val.is_null() { return Ok(None); } // Ladataan JS muisti-blockista suoraan Rustin Veg:giksi let arr = Uint8Array::new(&js_val); let mut vec = vec![0; arr.length() as usize]; arr.copy_to(&mut vec); Ok(Some(vec)) }