1#ifndef YAZE_APP_PLATFORM_WASM_STORAGE_QUOTA_H_
2#define YAZE_APP_PLATFORM_WASM_STORAGE_QUOTA_H_
7#include <emscripten/val.h>
55class WasmStorageQuota {
85 void GetStorageInfo(std::function<
void(
const StorageInfo&)> callback);
98 const std::vector<uint8_t>& data,
99 std::function<
void(
bool success)> callback);
110 std::function<
void(std::vector<uint8_t>)> callback);
120 void EvictOldest(
int count, std::function<
void(
int evicted)> callback);
131 std::function<
void(
int evicted)> callback);
151 std::function<
void(std::vector<StorageItem>)> callback);
159 std::function<
void(
bool success)> callback);
167 void ClearAll(std::function<
void()> callback);
179 static WasmStorageQuota&
Get();
188 WasmStorageQuota() =
default;
191 void CompressData(
const std::vector<uint8_t>& input,
192 std::function<
void(std::vector<uint8_t>)> callback);
193 void DecompressData(
const std::vector<uint8_t>& input,
194 std::function<
void(std::vector<uint8_t>)> callback);
197 void StoreCompressedData(
const std::string& key,
198 const std::vector<uint8_t>& compressed_data,
199 size_t original_size,
200 std::function<
void(
bool)> callback);
201 void LoadCompressedData(
const std::string& key,
202 std::function<
void(std::vector<uint8_t>,
size_t)> callback);
205 void UpdateMetadata(
const std::string& key,
size_t compressed_size,
206 size_t original_size);
208 void SaveMetadata(std::function<
void()> callback);
211 void CheckQuotaAndEvict(
size_t new_size_bytes,
212 std::function<
void(
bool)> callback);
215 mutable std::mutex mutex_;
218 std::map<std::string, double> access_times_;
219 std::map<std::string, StorageItem> item_metadata_;
220 std::atomic<bool> metadata_loaded_{
false};
223 StorageInfo last_storage_info_;
224 std::atomic<double> last_quota_check_time_{0.0};
230EM_JS(
void, wasm_storage_quota_estimate, (
int callback_id), {
231 if (!navigator.storage || !navigator.storage.estimate) {
233 Module.ccall(
'wasm_storage_quota_estimate_callback',
234 null, [
'number',
'number',
'number',
'number'],
235 [callback_id, 0, 0, 0]);
239 navigator.storage.estimate().then(function(estimate) {
240 var used = estimate.usage || 0;
241 var quota = estimate.quota || 0;
242 var persistent = estimate.persistent ? 1 : 0;
243 Module.ccall(
'wasm_storage_quota_estimate_callback',
244 null, [
'number',
'number',
'number',
'number'],
245 [callback_id, used, quota, persistent]);
246 }).
catch(function(error) {
247 console.error(
'[StorageQuota] Error estimating storage:', error);
248 Module.ccall(
'wasm_storage_quota_estimate_callback',
249 null, [
'number',
'number',
'number',
'number'],
250 [callback_id, 0, 0, 0]);
255EM_JS(
void, wasm_compress_data, (
const uint8_t* data,
size_t size,
int callback_id), {
256 var input =
new Uint8Array(Module.HEAPU8.buffer, data, size);
259 if (typeof CompressionStream !==
'undefined') {
260 var stream =
new CompressionStream(
'deflate');
261 var writer = stream.writable.getWriter();
263 writer.write(input).then(function() {
264 return writer.close();
266 return new Response(stream.readable).arrayBuffer();
267 }).then(function(compressed) {
268 var compressedArray =
new Uint8Array(compressed);
269 var ptr = Module._malloc(compressedArray.length);
270 Module.HEAPU8.set(compressedArray, ptr);
271 Module.ccall(
'wasm_compress_callback',
272 null, [
'number',
'number',
'number'],
273 [callback_id, ptr, compressedArray.length]);
274 }).
catch(function(error) {
275 console.error(
'[StorageQuota] Compression error:', error);
276 Module.ccall(
'wasm_compress_callback',
277 null, [
'number',
'number',
'number'],
278 [callback_id, 0, 0]);
282 console.warn(
'[StorageQuota] CompressionStream not available, storing uncompressed');
283 var ptr = Module._malloc(size);
284 Module.HEAPU8.set(input, ptr);
285 Module.ccall(
'wasm_compress_callback',
286 null, [
'number',
'number',
'number'],
287 [callback_id, ptr, size]);
291EM_JS(
void, wasm_decompress_data, (
const uint8_t* data,
size_t size,
int callback_id), {
292 var input =
new Uint8Array(Module.HEAPU8.buffer, data, size);
294 if (typeof DecompressionStream !==
'undefined') {
295 var stream =
new DecompressionStream(
'deflate');
296 var writer = stream.writable.getWriter();
298 writer.write(input).then(function() {
299 return writer.close();
301 return new Response(stream.readable).arrayBuffer();
302 }).then(function(decompressed) {
303 var decompressedArray =
new Uint8Array(decompressed);
304 var ptr = Module._malloc(decompressedArray.length);
305 Module.HEAPU8.set(decompressedArray, ptr);
306 Module.ccall(
'wasm_decompress_callback',
307 null, [
'number',
'number',
'number'],
308 [callback_id, ptr, decompressedArray.length]);
309 }).
catch(function(error) {
310 console.error(
'[StorageQuota] Decompression error:', error);
311 Module.ccall(
'wasm_decompress_callback',
312 null, [
'number',
'number',
'number'],
313 [callback_id, 0, 0]);
317 var ptr = Module._malloc(size);
318 Module.HEAPU8.set(input, ptr);
319 Module.ccall(
'wasm_decompress_callback',
320 null, [
'number',
'number',
'number'],
321 [callback_id, ptr, size]);
326EM_JS(
double, wasm_get_timestamp_ms, (), {
331EM_JS(
int, wasm_compression_available, (), {
332 return (typeof CompressionStream !==
'undefined' &&
333 typeof DecompressionStream !==
'undefined') ? 1 : 0;
376 const std::vector<uint8_t>& data,
377 std::function<
void(
bool success)> callback) {
382 std::function<
void(std::vector<uint8_t>)> callback) {
383 callback(std::vector<uint8_t>());
386 void EvictOldest(
int count, std::function<
void(
int evicted)> callback) {
391 std::function<
void(
int evicted)> callback) {
398 std::function<
void(std::vector<StorageItem>)> callback) {
399 callback(std::vector<StorageItem>());
403 std::function<
void(
bool success)> callback) {
407 void ClearAll(std::function<
void()> callback) { callback(); }
EM_JS(void, CallJsAiDriver,(const char *history_json), { if(window.yaze &&window.yaze.ai &&window.yaze.ai.processAgentRequest) { window.yaze.ai.processAgentRequest(UTF8ToString(history_json));} else { console.error("AI Driver not found in window.yaze.ai.processAgentRequest");} })
absl::Status LoadMetadata(const Rom &rom, GameData &data)