1- use mbn :: { decode:: RecordDecoder , record_ref :: RecordRef , records :: RecordHeader } ;
1+ use mbinary :: decode:: RecordDecoder ;
22use std:: ffi:: CStr ;
33use std:: fs:: File ;
44use std:: io:: { BufReader , Cursor , Read } ;
55use std:: ptr;
66use std:: slice;
77
8- use crate :: records:: RecordData ;
8+ use crate :: records:: CRecordEnum ;
99
1010/// C-compatible wrapper around RecordDecoder
1111pub struct CRecordDecoder {
@@ -19,77 +19,72 @@ pub extern "C" fn create_buffer_decoder(
1919 source_size : usize ,
2020) -> * mut CRecordDecoder {
2121 if source. is_null ( ) || source_size == 0 {
22- return ptr:: null_mut ( ) ; // Return null pointer for invalid input
22+ return ptr:: null_mut ( ) ;
2323 }
2424
25- // Safety: Convert the raw pointer and size to a Vec<u8>
25+ // Convert the raw pointer and size to a Vec<u8>
2626 let source_slice = unsafe { slice:: from_raw_parts ( source, source_size) } ;
2727 let source_buffer = Cursor :: new ( source_slice. to_vec ( ) ) ;
2828
2929 let decoder = CRecordDecoder {
3030 decoder : RecordDecoder :: new ( Box :: new ( source_buffer) ) ,
3131 } ;
3232
33- Box :: into_raw ( Box :: new ( decoder) ) // Return a raw pointer for FFI
33+ Box :: into_raw ( Box :: new ( decoder) )
3434}
3535
3636/// Create a new `CRecordDecoder` with a file as the source.
3737#[ no_mangle]
3838pub extern "C" fn create_file_decoder ( file_path : * const libc:: c_char ) -> * mut CRecordDecoder {
3939 if file_path. is_null ( ) {
40- return ptr:: null_mut ( ) ; // Return null pointer for invalid input
40+ return ptr:: null_mut ( ) ;
4141 }
4242
4343 // Convert C string to Rust Path
4444 let c_str = unsafe { CStr :: from_ptr ( file_path) } ;
4545 let path = match c_str. to_str ( ) {
4646 Ok ( path) => path,
47- Err ( _) => return ptr:: null_mut ( ) , // Invalid UTF-8
47+ Err ( _) => return ptr:: null_mut ( ) ,
4848 } ;
4949
5050 let decoder = match create_decoder_from_file ( path) {
5151 Ok ( f) => f,
52- Err ( _) => return ptr:: null_mut ( ) , // Failed to open file
52+ Err ( _) => return ptr:: null_mut ( ) ,
5353 } ;
5454
5555 let c_decoder = CRecordDecoder { decoder } ;
5656
57- Box :: into_raw ( Box :: new ( c_decoder) ) // Return a raw pointer for FFI
57+ Box :: into_raw ( Box :: new ( c_decoder) )
5858}
5959
60+ // Helper function, not exposed to C directly.
61+ fn create_decoder_from_file (
62+ file_path : & str ,
63+ ) -> Result < RecordDecoder < Box < dyn Read > > , std:: io:: Error > {
64+ let file = File :: open ( file_path) ?;
65+ let buf_reader = BufReader :: new ( file) ;
66+ let boxed_reader: Box < dyn Read > = Box :: new ( buf_reader) ;
67+ Ok ( RecordDecoder :: new ( boxed_reader) )
68+ }
69+
70+ /// Iteratively decodes records, returning false when all records are decoded.
6071#[ no_mangle]
61- pub extern "C" fn decode_records (
62- decoder : * mut CRecordDecoder ,
63- output_size : * mut usize ,
64- ) -> * mut RecordData {
65- if decoder. is_null ( ) || output_size. is_null ( ) {
66- return std:: ptr:: null_mut ( ) ; // Invalid pointers
72+ pub extern "C" fn decoder_iter ( decoder : * mut CRecordDecoder , output : * mut CRecordEnum ) -> bool {
73+ if decoder. is_null ( ) || output. is_null ( ) {
74+ return false ;
6775 }
6876
6977 let decoder = unsafe { & mut * decoder } ;
70-
71- // Decode records into a Vec<TestRecord>
72- let records = match decoder. decoder . decode_to_owned ( ) {
73- Ok ( records) => records,
74- Err ( _) => return std:: ptr:: null_mut ( ) , // Decoding error
75- } ;
76-
77- // Map RecordEnum to RecordData
78- let records_data: Vec < RecordData > = records
79- . into_iter ( )
80- . map ( |record_enum| record_enum. into ( ) )
81- . collect ( ) ;
82-
83- // println!("{:?}", &records);
84-
85- // Return the number of records
86- unsafe {
87- * output_size = records_data. len ( ) ;
78+ let mut iterator = decoder. decoder . decode_iterator ( ) ;
79+
80+ match iterator. next ( ) {
81+ Some ( Ok ( record_enum) ) => {
82+ let c_record: CRecordEnum = record_enum. into ( ) ;
83+ unsafe { ptr:: write ( output, c_record) } ;
84+ true
85+ }
86+ _ => false ,
8887 }
89-
90- // Allocate memory for the records on the heap and pass ownership to the caller
91- let records_box = records_data. into_boxed_slice ( ) ;
92- Box :: into_raw ( records_box) as * mut RecordData
9388}
9489
9590/// Destroy the `CRecordDecoder`
@@ -100,15 +95,6 @@ pub extern "C" fn destroy_record_decoder(decoder: *mut CRecordDecoder) {
10095 }
10196
10297 unsafe {
103- let _ = Box :: from_raw ( decoder) ; // Drop the decoder
98+ let _ = Box :: from_raw ( decoder) ;
10499 }
105100}
106-
107- fn create_decoder_from_file (
108- file_path : & str ,
109- ) -> Result < RecordDecoder < Box < dyn Read > > , std:: io:: Error > {
110- let file = File :: open ( file_path) ?;
111- let buf_reader = BufReader :: new ( file) ;
112- let boxed_reader: Box < dyn Read > = Box :: new ( buf_reader) ;
113- Ok ( RecordDecoder :: new ( boxed_reader) )
114- }
0 commit comments