1- use core:: slice;
2- use std:: { ffi:: c_void, path:: Path , ptr:: NonNull } ;
1+ use std:: { mem:: MaybeUninit , path:: Path } ;
32
43use libloading:: { Library , Symbol } ;
54
65const COLLECT_SCHEMA_FUNC : & str = "__cargo_casper_collect_schema" ;
76
8- type CollectSchema = unsafe extern "C" fn (
9- callback : unsafe extern "C" fn ( * const u8 , usize , * mut c_void ) ,
10- ctx : * mut c_void ,
11- ) ;
7+ type CollectSchema = unsafe extern "C" fn ( size_ptr : * mut u64 ) -> * mut u8 ;
128
139pub ( crate ) struct Artifact {
1410 library : Library ,
1511}
1612
17- unsafe extern "C" fn collect_schema_cb < T : FnOnce ( & [ u8 ] ) > (
18- data_ptr : * const u8 ,
19- data_len : usize ,
20- ctx : * mut c_void ,
21- ) {
22- let ptr: * mut Option < T > = ctx as _ ;
23- let data = slice:: from_raw_parts ( data_ptr, data_len) ;
24- let ptr = ( * ptr) . take ( ) . unwrap ( ) ;
25- ptr ( data) ;
26- }
27-
28- fn collect_schema_helper < T > ( library : & Library , cb : T )
29- where
30- T : for < ' a > FnOnce ( & ' a [ u8 ] ) ,
31- {
32- let collect_schema: Symbol < CollectSchema > =
33- unsafe { library. get ( COLLECT_SCHEMA_FUNC . as_bytes ( ) ) . unwrap ( ) } ;
34-
35- let ptr = NonNull :: from ( & Some ( cb) ) ;
36- unsafe { collect_schema ( collect_schema_cb :: < T > , ptr. as_ptr ( ) as * mut _ ) } ;
37- }
38-
3913impl Artifact {
4014 pub ( crate ) fn from_path < P : AsRef < Path > > (
4115 artifact_path : P ,
@@ -50,12 +24,17 @@ impl Artifact {
5024 /// This returns a [`serde_json::Value`] to skip validation of a `Schema` object structure which
5125 /// (in theory) can differ.
5226 pub ( crate ) fn collect_schema ( & self ) -> serde_json:: Result < serde_json:: Value > {
53- let mut value = None ;
54-
55- collect_schema_helper ( & self . library , |data| {
56- value = Some ( serde_json:: from_slice ( data) ) ;
57- } ) ;
58-
59- value. expect ( "Callback called" )
27+ let collect_schema: Symbol < CollectSchema > =
28+ unsafe { self . library . get ( COLLECT_SCHEMA_FUNC . as_bytes ( ) ) . unwrap ( ) } ;
29+
30+ let json_bytes = {
31+ let mut value = MaybeUninit :: uninit ( ) ;
32+ let leaked_json_bytes = unsafe { collect_schema ( value. as_mut_ptr ( ) ) } ;
33+ let size = unsafe { value. assume_init ( ) } ;
34+ let length: usize = size. try_into ( ) . unwrap ( ) ;
35+ unsafe { Vec :: from_raw_parts ( leaked_json_bytes, length, length) }
36+ } ;
37+
38+ serde_json:: from_slice ( & json_bytes)
6039 }
6140}
0 commit comments