savefile_abi/
bytes.rs

1use bytes::buf::UninitSlice;
2use bytes::BufMut;
3use core::slice;
4
5extern crate savefile;
6extern crate savefile_derive;
7use crate::{
8    abi_entry_light, parse_return_value_impl, AbiConnection, AbiConnectionMethod, AbiErrorMsg, AbiExportable,
9    AbiProtocol, FlexBuffer, RawAbiCallResult, TraitObject,
10};
11use savefile::prelude::{
12    get_schema, AbiMethod, AbiMethodArgument, AbiMethodInfo, AbiTraitDefinition, Deserialize, Deserializer,
13    LittleEndian, ReadBytesExt, ReceiverType, SavefileError, Schema, Serialize, Serializer,
14};
15use std::collections::HashMap;
16use std::io::Cursor;
17use std::mem::MaybeUninit;
18unsafe extern "C" fn abi_entry_light_buf_mut(flag: AbiProtocol) {
19    unsafe {
20        abi_entry_light::<dyn BufMut>(flag);
21    }
22}
23
24unsafe impl AbiExportable for dyn BufMut {
25    const ABI_ENTRY: unsafe extern "C" fn(flag: AbiProtocol) = abi_entry_light_buf_mut;
26    fn get_definition(version: u32) -> AbiTraitDefinition {
27        AbiTraitDefinition {
28            name: "BufMut".to_string(),
29            methods: vec![
30                AbiMethod {
31                    name: "remaining_mut".to_string(),
32                    info: AbiMethodInfo {
33                        return_value: { get_schema::<usize>(version) },
34                        receiver: ReceiverType::Shared,
35                        arguments: vec![],
36                        async_trait_heuristic: false,
37                    },
38                },
39                AbiMethod {
40                    name: "advance_mut".to_string(),
41                    info: AbiMethodInfo {
42                        return_value: { get_schema::<()>(0) },
43                        receiver: ReceiverType::Mut,
44                        arguments: vec![AbiMethodArgument {
45                            schema: { get_schema::<usize>(version) },
46                        }],
47                        async_trait_heuristic: false,
48                    },
49                },
50                AbiMethod {
51                    name: "chunk_mut".to_string(),
52                    info: AbiMethodInfo {
53                        return_value: Schema::UninitSlice,
54                        receiver: ReceiverType::Mut,
55                        arguments: vec![],
56                        async_trait_heuristic: false,
57                    },
58                },
59            ],
60            sync: false,
61            send: false,
62        }
63    }
64    fn get_latest_version() -> u32 {
65        0u32
66    }
67
68    // TODO: This method should be marked unsafe!
69    #[allow(clippy::not_unsafe_ptr_arg_deref)]
70    fn call(
71        trait_object: TraitObject,
72        method_number: u16,
73        effective_version: u32,
74        _compatibility_mask: u64,
75        data: &[u8],
76        abi_result: *mut (),
77        __savefile_internal_receiver: unsafe extern "C" fn(outcome: *const RawAbiCallResult, result_receiver: *mut ()),
78    ) -> Result<(), SavefileError> {
79        let mut cursor = Cursor::new(data);
80        let mut deserializer = Deserializer {
81            file_version: cursor.read_u32::<LittleEndian>()?,
82            reader: &mut cursor,
83            ephemeral_state: HashMap::new(),
84        };
85        match method_number {
86            0u16 => {
87                let ret = unsafe { &*trait_object.as_const_ptr::<dyn BufMut>() }.remaining_mut();
88                let mut __savefile_internal_data = FlexBuffer::new();
89                let mut serializer = Serializer {
90                    writer: &mut __savefile_internal_data,
91                    file_version: 0u32,
92                };
93                serializer.write_u32(effective_version)?;
94                match ret.serialize(&mut serializer) {
95                    Ok(()) => {
96                        let outcome = RawAbiCallResult::Success {
97                            data: __savefile_internal_data.as_ptr() as *const u8,
98                            len: __savefile_internal_data.len(),
99                        };
100                        unsafe { __savefile_internal_receiver(&outcome as *const _, abi_result) }
101                    }
102                    Err(err) => {
103                        let err_str = format!("{:?}", err);
104                        let outcome = RawAbiCallResult::AbiError(AbiErrorMsg {
105                            error_msg_utf8: err_str.as_ptr(),
106                            len: err_str.len(),
107                        });
108                        unsafe { __savefile_internal_receiver(&outcome as *const _, abi_result) }
109                    }
110                }
111            }
112            1u16 => {
113                let arg_cnt;
114                arg_cnt = <usize as Deserialize>::deserialize(&mut deserializer)?;
115                unsafe { (&mut *trait_object.as_mut_ptr::<dyn BufMut>()).advance_mut(arg_cnt) };
116            }
117            2u16 => {
118                let ret = unsafe { &mut *trait_object.as_mut_ptr::<dyn BufMut>() }.chunk_mut();
119                let mut __savefile_internal_data = FlexBuffer::new();
120                let mut serializer = Serializer {
121                    writer: &mut __savefile_internal_data,
122                    file_version: 0u32,
123                };
124                serializer.write_u32(effective_version)?;
125
126                match unsafe { serializer.write_raw_ptr_size(ret.as_mut_ptr(), ret.len()) } {
127                    Ok(()) => {
128                        let outcome = RawAbiCallResult::Success {
129                            data: __savefile_internal_data.as_ptr() as *const u8,
130                            len: __savefile_internal_data.len(),
131                        };
132                        unsafe { __savefile_internal_receiver(&outcome as *const _, abi_result) }
133                    }
134                    Err(err) => {
135                        let err_str = format!("{:?}", err);
136                        let outcome = RawAbiCallResult::AbiError(AbiErrorMsg {
137                            error_msg_utf8: err_str.as_ptr(),
138                            len: err_str.len(),
139                        });
140                        unsafe { __savefile_internal_receiver(&outcome as *const _, abi_result) }
141                    }
142                }
143            }
144            _ => {
145                return Err(SavefileError::general("Unknown method number"));
146            }
147        }
148        Ok(())
149    }
150}
151unsafe impl BufMut for AbiConnection<dyn BufMut> {
152    #[inline]
153    fn remaining_mut(&self) -> usize {
154        let info: &AbiConnectionMethod = &self.template.methods[0u16 as usize];
155        let Some(callee_method_number) = info.callee_method_number else {
156            panic!("Method \'{0}\' does not exist in implementation.", info.method_name,);
157        };
158        let mut result_buffer = MaybeUninit::<Result<usize, SavefileError>>::uninit();
159        let compatibility_mask = info.compatibility_mask;
160        let mut __savefile_internal_datarawdata = [0u8; 4usize];
161        let mut __savefile_internal_data = Cursor::new(&mut __savefile_internal_datarawdata[..]);
162        let mut serializer = Serializer {
163            writer: &mut __savefile_internal_data,
164            file_version: self.template.effective_version,
165        };
166        serializer.write_u32(self.template.effective_version).unwrap();
167        unsafe {
168            unsafe extern "C" fn abi_result_receiver(outcome: *const RawAbiCallResult, result_receiver: *mut ()) {
169                let outcome = unsafe { &*outcome };
170                let result_receiver =
171                    unsafe { &mut *(result_receiver as *mut std::mem::MaybeUninit<Result<usize, SavefileError>>) };
172                result_receiver.write(parse_return_value_impl(
173                    outcome,
174                    |deserializer| -> Result<usize, SavefileError> {
175                        <usize as Deserialize>::deserialize(deserializer)
176                    },
177                ));
178            }
179            (self.template.entry)(AbiProtocol::RegularCall {
180                trait_object: self.trait_object,
181                compatibility_mask,
182                method_number: callee_method_number,
183                effective_version: self.template.effective_version,
184                data: __savefile_internal_datarawdata[..].as_ptr(),
185                data_length: 4usize,
186                abi_result: &mut result_buffer as *mut _ as *mut (),
187                receiver: abi_result_receiver,
188            });
189        }
190        let resval = unsafe { result_buffer.assume_init() };
191        resval.expect("Unexpected panic in invocation target")
192    }
193    #[inline]
194    unsafe fn advance_mut(&mut self, arg_cnt: usize) {
195        let info: &AbiConnectionMethod = &self.template.methods[1u16 as usize];
196        let Some(callee_method_number) = info.callee_method_number else {
197            panic!("Method \'{0}\' does not exist in implementation.", info.method_name,);
198        };
199        let mut result_buffer = MaybeUninit::<Result<(), SavefileError>>::new(Ok(()));
200        let compatibility_mask = info.compatibility_mask;
201        let mut __savefile_internal_datarawdata = [0u8; 12usize];
202        let mut __savefile_internal_data = Cursor::new(&mut __savefile_internal_datarawdata[..]);
203        let mut serializer = Serializer {
204            writer: &mut __savefile_internal_data,
205            file_version: self.template.effective_version,
206        };
207        serializer.write_u32(self.template.effective_version).unwrap();
208        arg_cnt.serialize(&mut serializer).expect("Failed while serializing");
209        debug_assert_eq!(std::mem::size_of_val(&arg_cnt), 8);
210        unsafe {
211            unsafe extern "C" fn abi_result_receiver(outcome: *const RawAbiCallResult, result_receiver: *mut ()) {
212                let outcome = unsafe { &*outcome };
213                let result_receiver =
214                    unsafe { &mut *(result_receiver as *mut std::mem::MaybeUninit<Result<(), SavefileError>>) };
215                result_receiver.write(parse_return_value_impl(outcome, |_| -> Result<(), SavefileError> {
216                    Ok(())
217                }));
218            }
219            (self.template.entry)(AbiProtocol::RegularCall {
220                trait_object: self.trait_object,
221                compatibility_mask,
222                method_number: callee_method_number,
223                effective_version: self.template.effective_version,
224                data: __savefile_internal_datarawdata.as_ptr() as *const u8,
225                data_length: 12,
226                abi_result: &mut result_buffer as *mut _ as *mut (),
227                receiver: abi_result_receiver,
228            });
229        }
230        let resval = unsafe { result_buffer.assume_init() };
231        resval.expect("Unexpected panic in invocation target")
232    }
233    #[inline]
234    fn chunk_mut(&mut self) -> &mut UninitSlice {
235        let info: &AbiConnectionMethod = &self.template.methods[2u16 as usize];
236        let Some(callee_method_number) = info.callee_method_number else {
237            panic!("Method \'{0}\' does not exist in implementation.", info.method_name,);
238        };
239        let mut result_buffer = MaybeUninit::<Result<&mut UninitSlice, SavefileError>>::uninit();
240        let compatibility_mask = info.compatibility_mask;
241        let mut __savefile_internal_datarawdata = [0u8; 4usize];
242        let mut __savefile_internal_data = Cursor::new(&mut __savefile_internal_datarawdata[..]);
243        let mut serializer = Serializer {
244            writer: &mut __savefile_internal_data,
245            file_version: self.template.effective_version,
246        };
247        serializer.write_u32(self.template.effective_version).unwrap();
248        unsafe {
249            unsafe extern "C" fn abi_result_receiver(outcome: *const RawAbiCallResult, result_receiver: *mut ()) {
250                let outcome = unsafe { &*outcome };
251                let result_receiver = unsafe {
252                    &mut *(result_receiver as *mut std::mem::MaybeUninit<Result<&mut UninitSlice, SavefileError>>)
253                };
254                result_receiver.write(parse_return_value_impl(
255                    outcome,
256                    |deserializer| -> Result<&mut UninitSlice, SavefileError> {
257                        let iptr: *mut u8 = deserializer.read_raw_ptr_mut()?;
258                        let len = deserializer.read_usize()?;
259                        let bytes = slice::from_raw_parts_mut(iptr, len);
260                        Ok(UninitSlice::new(bytes))
261                    },
262                ));
263            }
264            (self.template.entry)(AbiProtocol::RegularCall {
265                trait_object: self.trait_object,
266                compatibility_mask,
267                method_number: callee_method_number,
268                effective_version: self.template.effective_version,
269                data: __savefile_internal_datarawdata[..].as_ptr(),
270                data_length: 4usize,
271                abi_result: &mut result_buffer as *mut _ as *mut (),
272                receiver: abi_result_receiver,
273            });
274        }
275        let resval = unsafe { result_buffer.assume_init() };
276        resval.expect("Unexpected panic in invocation target")
277    }
278}