|
1 | 1 | use std::sync::LazyLock; |
2 | 2 |
|
3 | | -use lean_ffi::include; |
4 | | -use lean_ffi::object::{ExternalClass, LeanByteArray, LeanExternal, LeanObject, LeanString}; |
| 3 | +use lean_ffi::object::{ |
| 4 | + ExternalClass, LeanBorrowed, LeanByteArray, LeanExternal, LeanOwned, LeanString, |
| 5 | +}; |
5 | 6 |
|
6 | 7 | static HASHER_CLASS: LazyLock<ExternalClass> = |
7 | 8 | LazyLock::new(ExternalClass::register_with_drop::<blake3::Hasher>); |
8 | 9 |
|
9 | 10 | #[unsafe(no_mangle)] |
10 | | -pub extern "C" fn rs_blake3_version() -> LeanString { |
| 11 | +pub extern "C" fn rs_blake3_version() -> LeanString<LeanOwned> { |
11 | 12 | LeanString::new("1.8.3") |
12 | 13 | } |
13 | 14 |
|
14 | 15 | #[unsafe(no_mangle)] |
15 | | -pub extern "C" fn rs_blake3_init() -> LeanObject { |
16 | | - LeanExternal::alloc(&HASHER_CLASS, blake3::Hasher::new()).into() |
| 16 | +pub extern "C" fn rs_blake3_init() -> LeanExternal<blake3::Hasher, LeanOwned> { |
| 17 | + LeanExternal::alloc(&HASHER_CLASS, blake3::Hasher::new()) |
17 | 18 | } |
18 | 19 |
|
19 | 20 | #[unsafe(no_mangle)] |
20 | | -pub extern "C" fn rs_blake3_init_keyed(key: LeanByteArray) -> LeanObject { |
| 21 | +pub extern "C" fn rs_blake3_init_keyed( |
| 22 | + key: LeanByteArray<LeanBorrowed<'_>>, |
| 23 | +) -> LeanExternal<blake3::Hasher, LeanOwned> { |
21 | 24 | let bytes = key.as_bytes(); |
22 | 25 | let key_array: &[u8; 32] = bytes.try_into().expect("key must be 32 bytes"); |
23 | | - LeanExternal::alloc(&HASHER_CLASS, blake3::Hasher::new_keyed(key_array)).into() |
| 26 | + LeanExternal::alloc(&HASHER_CLASS, blake3::Hasher::new_keyed(key_array)) |
24 | 27 | } |
25 | 28 |
|
26 | 29 | #[unsafe(no_mangle)] |
27 | | -pub extern "C" fn rs_blake3_init_derive_key(context: LeanByteArray) -> LeanObject { |
| 30 | +pub extern "C" fn rs_blake3_init_derive_key( |
| 31 | + context: LeanByteArray<LeanBorrowed<'_>>, |
| 32 | +) -> LeanExternal<blake3::Hasher, LeanOwned> { |
28 | 33 | let bytes = context.as_bytes(); |
29 | 34 | let ctx_str = std::str::from_utf8(bytes).expect("context must be valid UTF-8"); |
30 | | - LeanExternal::alloc(&HASHER_CLASS, blake3::Hasher::new_derive_key(ctx_str)).into() |
31 | | -} |
32 | | - |
33 | | -/// Ensure copy-on-write: if the object is shared, clone the hasher into a new |
34 | | -/// external object; otherwise return it as-is for in-place mutation. |
35 | | -unsafe fn ensure_exclusive(obj: LeanObject) -> LeanObject { |
36 | | - if unsafe { include::lean_is_exclusive(obj.as_ptr() as *mut _) } { |
37 | | - obj |
38 | | - } else { |
39 | | - let ext = unsafe { LeanExternal::<blake3::Hasher>::from_raw(obj.as_ptr()) }; |
40 | | - let cloned = ext.get().clone(); |
41 | | - obj.dec_ref(); |
42 | | - LeanExternal::alloc(&HASHER_CLASS, cloned).into() |
43 | | - } |
| 35 | + LeanExternal::alloc(&HASHER_CLASS, blake3::Hasher::new_derive_key(ctx_str)) |
44 | 36 | } |
45 | 37 |
|
46 | 38 | #[unsafe(no_mangle)] |
47 | 39 | pub extern "C" fn rs_blake3_hasher_update( |
48 | | - self_: LeanObject, |
49 | | - input: LeanByteArray, |
50 | | -) -> LeanObject { |
51 | | - let obj = unsafe { ensure_exclusive(self_) }; |
52 | | - let hasher_ptr = |
53 | | - unsafe { include::lean_get_external_data(obj.as_ptr() as *mut _) as *mut blake3::Hasher }; |
54 | | - unsafe { (*hasher_ptr).update(input.as_bytes()) }; |
55 | | - obj |
| 40 | + mut hasher: LeanExternal<blake3::Hasher, LeanOwned>, |
| 41 | + input: LeanByteArray<LeanBorrowed<'_>>, |
| 42 | +) -> LeanExternal<blake3::Hasher, LeanOwned> { |
| 43 | + if let Some(h) = hasher.get_mut() { |
| 44 | + h.update(input.as_bytes()); |
| 45 | + hasher |
| 46 | + } else { |
| 47 | + let mut new_hasher = hasher.get().clone(); |
| 48 | + new_hasher.update(input.as_bytes()); |
| 49 | + LeanExternal::alloc(&HASHER_CLASS, new_hasher) |
| 50 | + } |
56 | 51 | } |
57 | 52 |
|
58 | 53 | #[unsafe(no_mangle)] |
59 | | -pub extern "C" fn rs_blake3_hasher_finalize(self_: LeanObject, len: usize) -> LeanObject { |
60 | | - let ext = unsafe { LeanExternal::<blake3::Hasher>::from_raw(self_.as_ptr()) }; |
61 | | - let hasher = ext.get(); |
62 | | - let out = LeanByteArray::alloc(len); |
63 | | - let buf = unsafe { |
64 | | - let cptr = include::lean_sarray_cptr(out.as_ptr() as *mut _); |
65 | | - std::slice::from_raw_parts_mut(cptr, len) |
66 | | - }; |
67 | | - hasher.finalize_xof().fill(buf); |
68 | | - self_.dec_ref(); |
69 | | - out.into() |
| 54 | +pub extern "C" fn rs_blake3_hasher_finalize( |
| 55 | + hasher: LeanExternal<blake3::Hasher, LeanOwned>, |
| 56 | + len: usize, |
| 57 | +) -> LeanByteArray<LeanOwned> { |
| 58 | + let mut buf = vec![0u8; len]; |
| 59 | + hasher.get().finalize_xof().fill(&mut buf); |
| 60 | + LeanByteArray::from_bytes(&buf) |
70 | 61 | } |
0 commit comments