rufio 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -0
- data/README.md +74 -3
- data/README_ja.md +71 -2
- data/Rakefile +14 -1
- data/bin/rufio +31 -2
- data/docs/fast_zip_design_ja.md +167 -0
- data/info/help.md +2 -0
- data/info/keybindings.md +3 -1
- data/info/welcome.md +1 -1
- data/lib/rufio/application.rb +12 -1
- data/lib/rufio/archive_controller.rb +211 -0
- data/lib/rufio/background_command_executor.rb +9 -0
- data/lib/rufio/background_status.rb +49 -0
- data/lib/rufio/bookmark_controller.rb +38 -121
- data/lib/rufio/bookmark_manager.rb +77 -331
- data/lib/rufio/command_completion.rb +6 -1
- data/lib/rufio/command_history.rb +5 -2
- data/lib/rufio/command_mode.rb +40 -134
- data/lib/rufio/command_mode_ui.rb +4 -42
- data/lib/rufio/config.rb +88 -136
- data/lib/rufio/config_loader.rb +3 -11
- data/lib/rufio/dialog_renderer.rb +64 -152
- data/lib/rufio/dialog_support.rb +69 -0
- data/lib/rufio/document_text_extractor.rb +167 -0
- data/lib/rufio/file_operation_controller.rb +49 -222
- data/lib/rufio/file_preview.rb +46 -2
- data/lib/rufio/global_search.rb +121 -9
- data/lib/rufio/help_menu.rb +8 -2
- data/lib/rufio/interpreter_resolver.rb +6 -11
- data/lib/rufio/job_manager.rb +2 -5
- data/lib/rufio/key_input.rb +77 -0
- data/lib/rufio/keybind_handler.rb +81 -115
- data/lib/rufio/local_script_scanner.rb +6 -18
- data/lib/rufio/native/aarch64-linux-gnu/librufio_zig.so +0 -0
- data/lib/rufio/native/aarch64-linux-musl/librufio_zig.so +0 -0
- data/lib/rufio/native/aarch64-macos/librufio_zig.dylib +0 -0
- data/lib/rufio/native/aarch64-windows/rufio_zig.dll +0 -0
- data/lib/rufio/native/x86_64-linux-gnu/librufio_zig.so +0 -0
- data/lib/rufio/native/x86_64-linux-musl/librufio_zig.so +0 -0
- data/lib/rufio/native/x86_64-macos/librufio_zig.dylib +0 -0
- data/lib/rufio/native/x86_64-windows/rufio_zig.dll +0 -0
- data/lib/rufio/native_content_search.rb +153 -0
- data/lib/rufio/native_scanner.rb +13 -68
- data/lib/rufio/native_scanner_zig.rb +106 -56
- data/lib/rufio/native_zip.rb +121 -0
- data/lib/rufio/navigation_controller.rb +18 -20
- data/lib/rufio/screen.rb +2 -12
- data/lib/rufio/script_executor.rb +6 -73
- data/lib/rufio/script_file.rb +44 -0
- data/lib/rufio/script_path_manager.rb +9 -43
- data/lib/rufio/script_runner.rb +13 -50
- data/lib/rufio/search_controller.rb +1 -1
- data/lib/rufio/shell_command_completion.rb +1 -5
- data/lib/rufio/shell_init.rb +90 -0
- data/lib/rufio/task_status.rb +5 -1
- data/lib/rufio/terminal_ui.rb +55 -294
- data/lib/rufio/text_utils.rb +26 -3
- data/lib/rufio/ui_renderer.rb +63 -40
- data/lib/rufio/version.rb +1 -1
- data/lib/rufio/zip_archive.rb +314 -0
- data/lib/rufio/zip_extractor.rb +346 -0
- data/lib/rufio/zip_writer.rb +268 -0
- data/lib/rufio/zoxide_integration.rb +5 -43
- data/lib/rufio.rb +5 -0
- data/lib_zig/rufio_native/Makefile +54 -17
- data/lib_zig/rufio_native/bench.sh +36 -0
- data/lib_zig/rufio_native/build.zig +32 -35
- data/lib_zig/rufio_native/src/cli.zig +99 -0
- data/lib_zig/rufio_native/src/main.zig +187 -83
- data/lib_zig/rufio_native/src/os.zig +889 -0
- data/lib_zig/rufio_native/src/search.zig +919 -0
- data/lib_zig/rufio_native/src/search_test.zig +88 -0
- data/lib_zig/rufio_native/src/zip.zig +482 -0
- metadata +125 -3
- data/lib/rufio/native/rufio_zig.bundle +0 -0
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
-
const c =
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
@cInclude("stdlib.h");
|
|
7
|
-
@cInclude("pthread.h");
|
|
8
|
-
});
|
|
2
|
+
const c = std.c;
|
|
3
|
+
const search = @import("search.zig");
|
|
4
|
+
const os = @import("os.zig");
|
|
5
|
+
const zip = @import("zip.zig");
|
|
9
6
|
|
|
10
7
|
/// スキャン状態
|
|
11
8
|
pub const ScanState = enum(u8) {
|
|
@@ -38,11 +35,10 @@ const AsyncScanner = struct {
|
|
|
38
35
|
state: ScanState,
|
|
39
36
|
progress: usize,
|
|
40
37
|
total_estimate: usize,
|
|
41
|
-
mutex:
|
|
38
|
+
mutex: os.Mutex,
|
|
42
39
|
path_copy: ?[*:0]u8,
|
|
43
40
|
max_entries: usize,
|
|
44
|
-
thread:
|
|
45
|
-
thread_started: bool,
|
|
41
|
+
thread: ?std.Thread,
|
|
46
42
|
|
|
47
43
|
fn init() !*AsyncScanner {
|
|
48
44
|
const self = @as(?*AsyncScanner, @ptrCast(@alignCast(c.malloc(@sizeOf(AsyncScanner))))) orelse return error.OutOfMemory;
|
|
@@ -60,19 +56,15 @@ const AsyncScanner = struct {
|
|
|
60
56
|
self.*.total_estimate = 0;
|
|
61
57
|
self.*.path_copy = null;
|
|
62
58
|
self.*.max_entries = 0;
|
|
63
|
-
self.*.
|
|
64
|
-
|
|
65
|
-
// mutex初期化
|
|
66
|
-
_ = c.pthread_mutex_init(&self.*.mutex, null);
|
|
59
|
+
self.*.thread = null;
|
|
60
|
+
self.*.mutex = .{};
|
|
67
61
|
|
|
68
62
|
return self;
|
|
69
63
|
}
|
|
70
64
|
|
|
71
65
|
fn deinit(self: *AsyncScanner) void {
|
|
72
66
|
// スレッドが実行中なら待機
|
|
73
|
-
if (self.
|
|
74
|
-
_ = c.pthread_join(self.thread, null);
|
|
75
|
-
}
|
|
67
|
+
if (self.thread) |thread| thread.join();
|
|
76
68
|
|
|
77
69
|
// 各エントリの名前を解放
|
|
78
70
|
for (self.entries[0..self.count]) |*entry| {
|
|
@@ -87,9 +79,6 @@ const AsyncScanner = struct {
|
|
|
87
79
|
// エントリ配列を解放
|
|
88
80
|
c.free(self.entries.ptr);
|
|
89
81
|
|
|
90
|
-
// mutex破棄
|
|
91
|
-
_ = c.pthread_mutex_destroy(&self.mutex);
|
|
92
|
-
|
|
93
82
|
// 自身を解放
|
|
94
83
|
c.free(self);
|
|
95
84
|
}
|
|
@@ -115,14 +104,14 @@ const AsyncScanner = struct {
|
|
|
115
104
|
}
|
|
116
105
|
|
|
117
106
|
fn isCancelled(self: *AsyncScanner) bool {
|
|
118
|
-
|
|
119
|
-
defer
|
|
107
|
+
self.mutex.lock();
|
|
108
|
+
defer self.mutex.unlock();
|
|
120
109
|
return self.state == .cancelled;
|
|
121
110
|
}
|
|
122
111
|
|
|
123
112
|
fn setState(self: *AsyncScanner, new_state: ScanState) void {
|
|
124
|
-
|
|
125
|
-
defer
|
|
113
|
+
self.mutex.lock();
|
|
114
|
+
defer self.mutex.unlock();
|
|
126
115
|
self.state = new_state;
|
|
127
116
|
}
|
|
128
117
|
|
|
@@ -130,13 +119,13 @@ const AsyncScanner = struct {
|
|
|
130
119
|
// クリア
|
|
131
120
|
self.clear();
|
|
132
121
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
122
|
+
var scratch: os.Scratch = .{};
|
|
123
|
+
try scratch.init();
|
|
124
|
+
defer scratch.deinit();
|
|
125
|
+
var dir = os.Dir.open(std.mem.span(path), &scratch) orelse return error.CannotOpenDir;
|
|
126
|
+
defer dir.close();
|
|
138
127
|
|
|
139
|
-
while (
|
|
128
|
+
while (dir.next() catch return error.ReadFailed) |entry| {
|
|
140
129
|
// キャンセルチェック
|
|
141
130
|
if (self.isCancelled()) {
|
|
142
131
|
return error.Cancelled;
|
|
@@ -145,63 +134,48 @@ const AsyncScanner = struct {
|
|
|
145
134
|
// エントリ数制限チェック
|
|
146
135
|
if (max_entries > 0 and self.count >= max_entries) break;
|
|
147
136
|
|
|
148
|
-
|
|
149
|
-
const
|
|
150
|
-
const name_slice = name_ptr[0..name_len];
|
|
151
|
-
|
|
152
|
-
// "." と ".." をスキップ
|
|
153
|
-
if (std.mem.eql(u8, name_slice, ".") or std.mem.eql(u8, name_slice, "..")) {
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
137
|
+
// ファイル情報を取得(シンボリックリンクは辿らない)
|
|
138
|
+
const info = dir.currentInfo(entry) orelse continue;
|
|
156
139
|
|
|
157
140
|
// 容量確保
|
|
158
141
|
try self.ensureCapacity(self.count + 1);
|
|
159
142
|
|
|
160
|
-
// フルパスを構築
|
|
161
|
-
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
|
162
|
-
const full_path = std.fmt.bufPrintZ(&path_buf, "{s}/{s}", .{ path_slice, name_slice }) catch continue;
|
|
163
|
-
|
|
164
|
-
// ファイル情報を取得
|
|
165
|
-
var stat_buf: c.struct_stat = undefined;
|
|
166
|
-
if (c.lstat(full_path.ptr, &stat_buf) != 0) {
|
|
167
|
-
continue;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
143
|
// 名前をコピー
|
|
144
|
+
const name_len = entry.name.len;
|
|
171
145
|
const name_copy_ptr = c.malloc(name_len + 1) orelse return error.OutOfMemory;
|
|
172
146
|
const name_copy_bytes = @as([*]u8, @ptrCast(@alignCast(name_copy_ptr)));
|
|
173
147
|
const name_copy = name_copy_bytes[0..name_len];
|
|
174
|
-
@memcpy(name_copy,
|
|
148
|
+
@memcpy(name_copy, entry.name);
|
|
175
149
|
name_copy_bytes[name_len] = 0;
|
|
176
150
|
|
|
177
151
|
// エントリを追加
|
|
178
152
|
self.entries[self.count] = DirEntry{
|
|
179
153
|
.name = name_copy,
|
|
180
|
-
.is_dir =
|
|
181
|
-
.size =
|
|
182
|
-
.mtime =
|
|
183
|
-
.executable =
|
|
184
|
-
.hidden =
|
|
154
|
+
.is_dir = info.kind == .dir,
|
|
155
|
+
.size = info.size,
|
|
156
|
+
.mtime = info.mtime_sec,
|
|
157
|
+
.executable = info.executable,
|
|
158
|
+
.hidden = entry.name[0] == '.',
|
|
185
159
|
};
|
|
186
160
|
self.count += 1;
|
|
187
161
|
|
|
188
162
|
// 進捗更新
|
|
189
|
-
|
|
163
|
+
self.mutex.lock();
|
|
190
164
|
self.progress = self.count;
|
|
191
|
-
|
|
165
|
+
self.mutex.unlock();
|
|
192
166
|
}
|
|
193
167
|
}
|
|
194
168
|
|
|
195
169
|
fn scanAsync(self: *AsyncScanner, path: [*:0]const u8, max_entries: usize) !void {
|
|
196
|
-
|
|
197
|
-
defer
|
|
170
|
+
self.mutex.lock();
|
|
171
|
+
defer self.mutex.unlock();
|
|
198
172
|
|
|
199
173
|
if (self.state == .scanning) {
|
|
200
174
|
return error.AlreadyScanning;
|
|
201
175
|
}
|
|
202
176
|
|
|
203
177
|
// パスをコピー
|
|
204
|
-
const path_len =
|
|
178
|
+
const path_len = std.mem.len(path);
|
|
205
179
|
const path_copy_ptr = c.malloc(path_len + 1) orelse return error.OutOfMemory;
|
|
206
180
|
const path_copy_bytes = @as([*:0]u8, @ptrCast(@alignCast(path_copy_ptr)));
|
|
207
181
|
@memcpy(path_copy_bytes[0..path_len], path[0..path_len]);
|
|
@@ -216,13 +190,13 @@ const AsyncScanner = struct {
|
|
|
216
190
|
self.max_entries = max_entries;
|
|
217
191
|
self.state = .scanning;
|
|
218
192
|
|
|
219
|
-
//
|
|
220
|
-
|
|
221
|
-
|
|
193
|
+
// 前回のスキャンスレッドは完了済みなので回収してから開始
|
|
194
|
+
if (self.thread) |thread| thread.join();
|
|
195
|
+
self.thread = std.Thread.spawn(.{}, scanWorker, .{self}) catch {
|
|
196
|
+
self.thread = null;
|
|
222
197
|
self.state = .failed;
|
|
223
198
|
return error.ThreadCreateFailed;
|
|
224
|
-
}
|
|
225
|
-
self.thread_started = true;
|
|
199
|
+
};
|
|
226
200
|
}
|
|
227
201
|
|
|
228
202
|
fn scanWorker(self: *AsyncScanner) void {
|
|
@@ -244,13 +218,6 @@ const AsyncScanner = struct {
|
|
|
244
218
|
}
|
|
245
219
|
};
|
|
246
220
|
|
|
247
|
-
// スレッドエントリポイント
|
|
248
|
-
fn scanWorkerEntry(arg: ?*anyopaque) callconv(.c) ?*anyopaque {
|
|
249
|
-
const scanner = @as(*AsyncScanner, @ptrCast(@alignCast(arg)));
|
|
250
|
-
scanner.scanWorker();
|
|
251
|
-
return null;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
221
|
// ============================================================
|
|
255
222
|
// ABI Boundary: Ruby ABI非依存・ハンドルベース
|
|
256
223
|
// ============================================================
|
|
@@ -284,8 +251,8 @@ export fn core_async_get_state(handle: u64) u8 {
|
|
|
284
251
|
if (handle == 0) return @intFromEnum(ScanState.failed);
|
|
285
252
|
|
|
286
253
|
const scanner = @as(*AsyncScanner, @ptrFromInt(handle));
|
|
287
|
-
|
|
288
|
-
defer
|
|
254
|
+
scanner.mutex.lock();
|
|
255
|
+
defer scanner.mutex.unlock();
|
|
289
256
|
return @intFromEnum(scanner.state);
|
|
290
257
|
}
|
|
291
258
|
|
|
@@ -298,8 +265,8 @@ export fn core_async_get_progress(handle: u64, current: *usize, total: *usize) v
|
|
|
298
265
|
}
|
|
299
266
|
|
|
300
267
|
const scanner = @as(*AsyncScanner, @ptrFromInt(handle));
|
|
301
|
-
|
|
302
|
-
defer
|
|
268
|
+
scanner.mutex.lock();
|
|
269
|
+
defer scanner.mutex.unlock();
|
|
303
270
|
|
|
304
271
|
current.* = scanner.progress;
|
|
305
272
|
total.* = scanner.total_estimate;
|
|
@@ -310,8 +277,8 @@ export fn core_async_cancel(handle: u64) void {
|
|
|
310
277
|
if (handle == 0) return;
|
|
311
278
|
|
|
312
279
|
const scanner = @as(*AsyncScanner, @ptrFromInt(handle));
|
|
313
|
-
|
|
314
|
-
defer
|
|
280
|
+
scanner.mutex.lock();
|
|
281
|
+
defer scanner.mutex.unlock();
|
|
315
282
|
|
|
316
283
|
if (scanner.state == .scanning) {
|
|
317
284
|
scanner.state = .cancelled;
|
|
@@ -323,8 +290,8 @@ export fn core_async_get_count(handle: u64) usize {
|
|
|
323
290
|
if (handle == 0) return 0;
|
|
324
291
|
|
|
325
292
|
const scanner = @as(*AsyncScanner, @ptrFromInt(handle));
|
|
326
|
-
|
|
327
|
-
defer
|
|
293
|
+
scanner.mutex.lock();
|
|
294
|
+
defer scanner.mutex.unlock();
|
|
328
295
|
return scanner.count;
|
|
329
296
|
}
|
|
330
297
|
|
|
@@ -333,8 +300,8 @@ export fn core_async_get_name(handle: u64, index: usize, buf: [*]u8, buf_size: u
|
|
|
333
300
|
if (handle == 0) return 0;
|
|
334
301
|
|
|
335
302
|
const scanner = @as(*AsyncScanner, @ptrFromInt(handle));
|
|
336
|
-
|
|
337
|
-
defer
|
|
303
|
+
scanner.mutex.lock();
|
|
304
|
+
defer scanner.mutex.unlock();
|
|
338
305
|
|
|
339
306
|
if (index >= scanner.count) return 0;
|
|
340
307
|
|
|
@@ -350,8 +317,8 @@ export fn core_async_get_attrs(handle: u64, index: usize, is_dir: *u8, size: *u6
|
|
|
350
317
|
if (handle == 0) return -1;
|
|
351
318
|
|
|
352
319
|
const scanner = @as(*AsyncScanner, @ptrFromInt(handle));
|
|
353
|
-
|
|
354
|
-
defer
|
|
320
|
+
scanner.mutex.lock();
|
|
321
|
+
defer scanner.mutex.unlock();
|
|
355
322
|
|
|
356
323
|
if (index >= scanner.count) return -1;
|
|
357
324
|
|
|
@@ -376,3 +343,140 @@ export fn core_async_destroy(handle: u64) void {
|
|
|
376
343
|
export fn core_async_version() [*:0]const u8 {
|
|
377
344
|
return "4.0.0-async";
|
|
378
345
|
}
|
|
346
|
+
|
|
347
|
+
// ============================================================
|
|
348
|
+
// コンテンツ検索(G mode): NUL 区切りのリストを長さ付きで受け取る
|
|
349
|
+
// ============================================================
|
|
350
|
+
|
|
351
|
+
/// 検索を開始してハンドルを返す(失敗時は 0)。threads=0 で CPU 数
|
|
352
|
+
export fn core_search_create(
|
|
353
|
+
roots: [*]const u8,
|
|
354
|
+
roots_len: usize,
|
|
355
|
+
query: [*]const u8,
|
|
356
|
+
query_len: usize,
|
|
357
|
+
excluded: [*]const u8,
|
|
358
|
+
excluded_len: usize,
|
|
359
|
+
documents: [*]const u8,
|
|
360
|
+
documents_len: usize,
|
|
361
|
+
threads: u32,
|
|
362
|
+
cache_handle: u64,
|
|
363
|
+
) u64 {
|
|
364
|
+
const cache: ?*search.Cache = if (cache_handle == 0) null else @ptrFromInt(cache_handle);
|
|
365
|
+
const s = search.Search.create(
|
|
366
|
+
roots[0..roots_len],
|
|
367
|
+
query[0..query_len],
|
|
368
|
+
excluded[0..excluded_len],
|
|
369
|
+
documents[0..documents_len],
|
|
370
|
+
threads,
|
|
371
|
+
cache,
|
|
372
|
+
) catch return 0;
|
|
373
|
+
return @intFromPtr(s);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export fn core_search_state(handle: u64) u8 {
|
|
377
|
+
if (handle == 0) return @intFromEnum(search.State.failed);
|
|
378
|
+
const s: *search.Search = @ptrFromInt(handle);
|
|
379
|
+
return @intFromEnum(s.getState());
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/// 溜まったレコードを取り出す。返したポインタは次の drain/destroy まで有効
|
|
383
|
+
export fn core_search_drain(handle: u64, out_len: *usize) ?[*]const u8 {
|
|
384
|
+
out_len.* = 0;
|
|
385
|
+
if (handle == 0) return null;
|
|
386
|
+
const s: *search.Search = @ptrFromInt(handle);
|
|
387
|
+
const data = s.drain();
|
|
388
|
+
out_len.* = data.len;
|
|
389
|
+
return if (data.len == 0) null else data.ptr;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
export fn core_search_skipped(handle: u64) u64 {
|
|
393
|
+
if (handle == 0) return 0;
|
|
394
|
+
const s: *search.Search = @ptrFromInt(handle);
|
|
395
|
+
return s.skipped.load(.acquire);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
export fn core_search_cancel(handle: u64) void {
|
|
399
|
+
if (handle == 0) return;
|
|
400
|
+
const s: *search.Search = @ptrFromInt(handle);
|
|
401
|
+
s.cancel();
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
export fn core_search_destroy(handle: u64) void {
|
|
405
|
+
if (handle == 0) return;
|
|
406
|
+
const s: *search.Search = @ptrFromInt(handle);
|
|
407
|
+
s.destroy();
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/// 検索間で共有するファイル内容キャッシュ(max_bytes はキャッシュする内容の上限)
|
|
411
|
+
export fn core_cache_create(max_bytes: u64) u64 {
|
|
412
|
+
const cache = search.Cache.create(max_bytes) catch return 0;
|
|
413
|
+
return @intFromPtr(cache);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export fn core_cache_bytes(handle: u64) u64 {
|
|
417
|
+
if (handle == 0) return 0;
|
|
418
|
+
const cache: *search.Cache = @ptrFromInt(handle);
|
|
419
|
+
return cache.cachedBytes();
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/// 使用中の検索をすべて destroy してから呼ぶこと
|
|
423
|
+
export fn core_cache_destroy(handle: u64) void {
|
|
424
|
+
if (handle == 0) return;
|
|
425
|
+
const cache: *search.Cache = @ptrFromInt(handle);
|
|
426
|
+
cache.destroy();
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// ============================================================
|
|
430
|
+
// ZIP データ処理(展開・圧縮): 検証やパスの決定は Ruby 側で行う
|
|
431
|
+
// ============================================================
|
|
432
|
+
|
|
433
|
+
/// 展開ジョブを開始してハンドルを返す(失敗時は 0)。threads=0 で CPU 数
|
|
434
|
+
export fn core_zip_extract_create(zip_path: [*]const u8, zip_path_len: usize, tasks: [*]const u8, tasks_len: usize, threads: u32) u64 {
|
|
435
|
+
const job = zip.Job.createExtract(zip_path[0..zip_path_len], tasks[0..tasks_len], threads) catch return 0;
|
|
436
|
+
return @intFromPtr(job);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/// 圧縮ジョブを開始してハンドルを返す(失敗時は 0)。level は 1〜9(それ以外は既定)
|
|
440
|
+
export fn core_zip_deflate_create(tasks: [*]const u8, tasks_len: usize, level: i32, threads: u32) u64 {
|
|
441
|
+
const job = zip.Job.createDeflate(tasks[0..tasks_len], level, threads) catch return 0;
|
|
442
|
+
return @intFromPtr(job);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export fn core_zip_state(handle: u64) u8 {
|
|
446
|
+
if (handle == 0) return @intFromEnum(zip.State.failed);
|
|
447
|
+
const job: *zip.Job = @ptrFromInt(handle);
|
|
448
|
+
return @intFromEnum(job.getState());
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export fn core_zip_progress(handle: u64, done: *u64, total: *u64) void {
|
|
452
|
+
done.* = 0;
|
|
453
|
+
total.* = 0;
|
|
454
|
+
if (handle == 0) return;
|
|
455
|
+
const job: *zip.Job = @ptrFromInt(handle);
|
|
456
|
+
job.progress(done, total);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
export fn core_zip_status(handle: u64, index: usize) u8 {
|
|
460
|
+
if (handle == 0) return @intFromEnum(zip.Status.io_error);
|
|
461
|
+
const job: *zip.Job = @ptrFromInt(handle);
|
|
462
|
+
return @intFromEnum(job.status(index));
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
export fn core_zip_deflate_result(handle: u64, index: usize, crc: *u32, compressed: *u64, size: *u64) u8 {
|
|
466
|
+
if (handle == 0) return @intFromEnum(zip.Status.io_error);
|
|
467
|
+
const job: *zip.Job = @ptrFromInt(handle);
|
|
468
|
+
return @intFromEnum(job.deflateResult(index, crc, compressed, size));
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
export fn core_zip_cancel(handle: u64) void {
|
|
472
|
+
if (handle == 0) return;
|
|
473
|
+
const job: *zip.Job = @ptrFromInt(handle);
|
|
474
|
+
job.cancel();
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/// 実行中ならキャンセルしてスレッドの終了を待つ
|
|
478
|
+
export fn core_zip_destroy(handle: u64) void {
|
|
479
|
+
if (handle == 0) return;
|
|
480
|
+
const job: *zip.Job = @ptrFromInt(handle);
|
|
481
|
+
job.destroy();
|
|
482
|
+
}
|