abi_stable/erased_types/
c_functions.rs

1#![allow(non_snake_case)]
2
3use std::{
4    fmt,
5    io::{self, BufRead, Read, Write as IoWrite},
6    mem, ptr,
7};
8
9use super::*;
10
11use crate::{
12    marker_type::ErasedObject,
13    pointer_trait::{GetPointerKind, PK_MutReference, PK_Reference, PK_SmartPointer},
14    sabi_types::{RMut, RRef},
15    std_types::{RIoError, RSeekFrom},
16};
17
18use core_extensions::utils::transmute_ignore_size;
19
20pub(crate) unsafe fn adapt_std_fmt<T>(
21    value: RRef<'_, T>,
22    function: unsafe extern "C" fn(RRef<'_, T>, FormattingMode, &mut RString) -> RResult<(), ()>,
23    formatter: &mut fmt::Formatter<'_>,
24) -> fmt::Result {
25    let mut buf = RString::new();
26    let mode = if formatter.alternate() {
27        FormattingMode::Alternate
28    } else {
29        FormattingMode::Default_
30    };
31
32    unsafe { function(value, mode, &mut buf) }
33        .into_rust()
34        .map_err(|_| fmt::Error)?;
35
36    fmt::Display::fmt(&*buf, formatter)
37}
38
39pub(crate) unsafe extern "C" fn drop_pointer_impl<OrigP, ErasedPtr>(this: RMut<'_, ErasedPtr>) {
40    extern_fn_panic_handling! {no_early_return; unsafe {
41        let this = this.transmute_into_mut::<OrigP>();
42        ptr::drop_in_place(this);
43    }}
44}
45
46pub(crate) unsafe extern "C" fn clone_pointer_impl<OrigP, ErasedPtr>(
47    this: RRef<'_, ErasedPtr>,
48) -> ErasedPtr
49where
50    OrigP: Clone,
51{
52    extern_fn_panic_handling! {no_early_return;
53        let this = unsafe { this.transmute_into_ref::<OrigP>() };
54        let clone = this.clone();
55        unsafe { transmute_ignore_size(clone) }
56    }
57}
58
59////////////////////////////////////////////////////
60
61/*
62I'm implementing DefaultImpl for all pointer kinds,
63only requiring `std::default::Default` for `PK_SmartPointer`
64because it is the only one for which `DynTrait::default` can be called.
65*/
66
67pub trait DefaultImpl<PtrKind> {
68    fn default_impl() -> Self;
69}
70
71impl<This> DefaultImpl<PK_SmartPointer> for This
72where
73    Self: Default,
74{
75    fn default_impl() -> Self {
76        Default::default()
77    }
78}
79
80impl<This> DefaultImpl<PK_Reference> for This {
81    fn default_impl() -> Self {
82        unreachable!("This should not be called in DynTrait::default")
83    }
84}
85
86impl<This> DefaultImpl<PK_MutReference> for This {
87    fn default_impl() -> Self {
88        unreachable!("This should not be called in DynTrait::default")
89    }
90}
91
92pub(crate) unsafe extern "C" fn default_pointer_impl<OrigP, ErasedPtr>() -> ErasedPtr
93where
94    OrigP: GetPointerKind,
95    OrigP: DefaultImpl<<OrigP as GetPointerKind>::Kind>,
96{
97    extern_fn_panic_handling! {no_early_return; unsafe {
98        transmute_ignore_size( OrigP::default_impl() )
99    }}
100}
101
102/////////////
103
104pub(crate) unsafe extern "C" fn display_impl<T>(
105    this: RRef<'_, ErasedObject>,
106    mode: FormattingMode,
107    buf: &mut RString,
108) -> RResult<(), ()>
109where
110    T: Display,
111{
112    extern_fn_panic_handling! {no_early_return;
113        use std::fmt::Write;
114        let this = unsafe { this.transmute_into_ref::<T>() };
115
116        let res = match mode {
117            FormattingMode::Default_ => write!(buf, "{}", this),
118            FormattingMode::Alternate => write!(buf, "{:#}", this),
119        };
120        match res {
121            Ok(_) => ROk(()),
122            Err(_) => RErr(()),
123        }
124    }
125}
126
127pub(crate) unsafe extern "C" fn debug_impl<T>(
128    this: RRef<'_, ErasedObject>,
129    mode: FormattingMode,
130    buf: &mut RString,
131) -> RResult<(), ()>
132where
133    T: Debug,
134{
135    extern_fn_panic_handling! {no_early_return;
136        use std::fmt::Write;
137
138        let this = unsafe { this.transmute_into_ref::<T>() };
139
140        let res = match mode {
141            FormattingMode::Default_ => write!(buf, "{:?}", this),
142            FormattingMode::Alternate => write!(buf, "{:#?}", this),
143        };
144        match res {
145            Ok(_) => ROk(()),
146            Err(_) => RErr(()),
147        }
148    }
149}
150
151pub(crate) unsafe extern "C" fn serialize_impl<'s, T, I>(
152    this: RRef<'s, ErasedObject>,
153) -> RResult<<I as SerializeProxyType<'s>>::Proxy, RBoxError>
154where
155    T: for<'borr> SerializeType<'borr, Interface = I>,
156    I: for<'borr> SerializeProxyType<'borr>,
157{
158    extern_fn_panic_handling! {no_early_return; unsafe {
159        let ret: RResult<<I as SerializeProxyType<'_>>::Proxy, RBoxError> =
160            this
161            .transmute_into_ref::<T>()
162            .serialize_impl()
163            .into_c();
164
165        core_extensions::utils::transmute_ignore_size(ret)
166    }}
167}
168
169pub(crate) unsafe extern "C" fn partial_eq_impl<T>(
170    this: RRef<'_, ErasedObject>,
171    other: RRef<'_, ErasedObject>,
172) -> bool
173where
174    T: PartialEq,
175{
176    extern_fn_panic_handling! {no_early_return;
177        let this = unsafe { this.transmute_into_ref::<T>() };
178        let other = unsafe { other.transmute_into_ref::<T>() };
179        this == other
180    }
181}
182
183pub(crate) unsafe extern "C" fn cmp_ord<T>(
184    this: RRef<'_, ErasedObject>,
185    other: RRef<'_, ErasedObject>,
186) -> RCmpOrdering
187where
188    T: Ord,
189{
190    extern_fn_panic_handling! {no_early_return;
191        let this = unsafe { this.transmute_into_ref::<T>() };
192        let other = unsafe { other.transmute_into_ref::<T>() };
193        this.cmp(other).into_c()
194    }
195}
196
197pub(crate) unsafe extern "C" fn partial_cmp_ord<T>(
198    this: RRef<'_, ErasedObject>,
199    other: RRef<'_, ErasedObject>,
200) -> ROption<RCmpOrdering>
201where
202    T: PartialOrd,
203{
204    extern_fn_panic_handling! {no_early_return;
205        let this = unsafe { this.transmute_into_ref::<T>() };
206        let other = unsafe { other.transmute_into_ref::<T>() };
207
208        this.partial_cmp(other).map(IntoReprC::into_c).into_c()
209    }
210}
211
212//////////////////
213// Hash
214
215pub(crate) unsafe extern "C" fn hash_Hash<T>(
216    this: RRef<'_, ErasedObject>,
217    mut state: trait_objects::HasherObject<'_>,
218) where
219    T: Hash,
220{
221    extern_fn_panic_handling! {no_early_return;
222        let this = unsafe { this.transmute_into_ref::<T>() };
223
224        this.hash(&mut state);
225    }
226}
227
228//////////////////
229// Hasher
230
231pub(crate) unsafe extern "C" fn write_Hasher<T>(this: RMut<'_, ErasedObject>, slic_: RSlice<'_, u8>)
232where
233    T: Hasher,
234{
235    extern_fn_panic_handling! {
236        let this = unsafe { this.transmute_into_mut::<T>() };
237        this.write(slic_.into());
238    }
239}
240
241macro_rules! fn_write {
242    ( $(($ty:ty, $delegated_fn:ident, $new_fn:ident)),* ) => {
243        $(
244            pub(crate) unsafe extern "C" fn $new_fn<T>(
245                this: RMut<'_, ErasedObject>,
246                val: $ty,
247            ) where
248                T: Hasher,
249            {
250                extern_fn_panic_handling! {
251                    let this = unsafe { this.transmute_into_mut::<T>() };
252                    this.$delegated_fn(val);
253                }
254            }
255        )*
256    }
257}
258
259fn_write!(
260    // No c-compatible layout for u128 yet
261    // (i128, write_i128, write_i128_Hasher),
262    (i16, write_i16, write_i16_Hasher),
263    (i32, write_i32, write_i32_Hasher),
264    (i64, write_i64, write_i64_Hasher),
265    (i8, write_i8, write_i8_Hasher),
266    (isize, write_isize, write_isize_Hasher),
267    // No c-compatible layout for u128 yet
268    // (u128, write_u128, write_u128_Hasher),
269    (u16, write_u16, write_u16_Hasher),
270    (u32, write_u32, write_u32_Hasher),
271    (u64, write_u64, write_u64_Hasher),
272    (u8, write_u8, write_u8_Hasher),
273    (usize, write_usize, write_usize_Hasher)
274);
275
276pub(crate) unsafe extern "C" fn finish_Hasher<T>(this: RRef<'_, ErasedObject>) -> u64
277where
278    T: Hasher,
279{
280    extern_fn_panic_handling! {
281        let this = unsafe { this.transmute_into_ref::<T>() };
282
283        this.finish()
284    }
285}
286
287//////////////////////////////////////////////////////////////////////////////////////
288////                        fmt
289//////////////////////////////////////////////////////////////////////////////////////
290
291pub(super) unsafe extern "C" fn write_str_fmt_write<T>(
292    this: RMut<'_, ErasedObject>,
293    data: RStr<'_>,
294) -> RResult<(), ()>
295where
296    T: fmt::Write,
297{
298    extern_fn_panic_handling! {
299        let this = unsafe { this.transmute_into_mut::<T>() };
300        match fmt::Write::write_str(this,data.as_str()) {
301            Ok(())=>ROk(()),
302            Err(_)=>RErr(()),
303        }
304    }
305}
306
307//////////////////////////////////////////////////////////////////////////////////////
308////                         io
309//////////////////////////////////////////////////////////////////////////////////////
310
311#[inline]
312fn convert_io_result<T, U>(res: io::Result<T>) -> RResult<U, RIoError>
313where
314    T: Into<U>,
315{
316    match res {
317        Ok(v) => ROk(v.into()),
318        Err(e) => RErr(RIoError::from(e)),
319    }
320}
321
322///////////////////////////
323
324#[repr(C)]
325#[derive(StableAbi, Copy, Clone)]
326pub struct IoWriteFns {
327    pub(super) write: unsafe extern "C" fn(
328        RMut<'_, ErasedObject>,
329        buf: RSlice<'_, u8>,
330    ) -> RResult<usize, RIoError>,
331
332    pub(super) write_all:
333        unsafe extern "C" fn(RMut<'_, ErasedObject>, buf: RSlice<'_, u8>) -> RResult<(), RIoError>,
334
335    pub(super) flush: unsafe extern "C" fn(RMut<'_, ErasedObject>) -> RResult<(), RIoError>,
336}
337
338pub(super) struct MakeIoWriteFns<W>(W);
339
340impl<W> MakeIoWriteFns<W>
341where
342    W: IoWrite,
343{
344    pub(super) const NEW: IoWriteFns = IoWriteFns {
345        write: io_Write_write::<W>,
346        write_all: io_Write_write_all::<W>,
347        flush: io_Write_flush::<W>,
348    };
349}
350
351pub(super) unsafe extern "C" fn io_Write_write<W>(
352    this: RMut<'_, ErasedObject>,
353    buf: RSlice<'_, u8>,
354) -> RResult<usize, RIoError>
355where
356    W: IoWrite,
357{
358    extern_fn_panic_handling! {no_early_return;
359        let this = unsafe { this.transmute_into_mut::<W>() };
360
361        convert_io_result(this.write(buf.into()))
362    }
363}
364
365pub(super) unsafe extern "C" fn io_Write_write_all<W>(
366    this: RMut<'_, ErasedObject>,
367    buf: RSlice<'_, u8>,
368) -> RResult<(), RIoError>
369where
370    W: IoWrite,
371{
372    extern_fn_panic_handling! {no_early_return;
373        let this = unsafe { this.transmute_into_mut::<W>() };
374
375        convert_io_result(this.write_all(buf.into()))
376    }
377}
378
379pub(super) unsafe extern "C" fn io_Write_flush<W>(
380    this: RMut<'_, ErasedObject>,
381) -> RResult<(), RIoError>
382where
383    W: IoWrite,
384{
385    extern_fn_panic_handling! {no_early_return;
386        let this = unsafe { this.transmute_into_mut::<W>() };
387
388        convert_io_result(this.flush())
389    }
390}
391
392///////////////////////////
393
394#[repr(C)]
395#[derive(StableAbi, Copy, Clone)]
396pub struct IoReadFns {
397    pub(super) read:
398        unsafe extern "C" fn(RMut<'_, ErasedObject>, RSliceMut<'_, u8>) -> RResult<usize, RIoError>,
399
400    pub(super) read_exact:
401        unsafe extern "C" fn(RMut<'_, ErasedObject>, RSliceMut<'_, u8>) -> RResult<(), RIoError>,
402}
403
404pub(super) struct MakeIoReadFns<W>(W);
405
406impl<W> MakeIoReadFns<W>
407where
408    W: io::Read,
409{
410    pub(super) const NEW: IoReadFns = IoReadFns {
411        read: io_Read_read::<W>,
412        read_exact: io_Read_read_exact::<W>,
413    };
414}
415
416pub(super) unsafe extern "C" fn io_Read_read<R>(
417    this: RMut<'_, ErasedObject>,
418    buf: RSliceMut<'_, u8>,
419) -> RResult<usize, RIoError>
420where
421    R: Read,
422{
423    extern_fn_panic_handling! {no_early_return;
424        let this = unsafe { this.transmute_into_mut::<R>() };
425
426        convert_io_result(this.read(buf.into()))
427    }
428}
429
430pub(super) unsafe extern "C" fn io_Read_read_exact<R>(
431    this: RMut<'_, ErasedObject>,
432    buf: RSliceMut<'_, u8>,
433) -> RResult<(), RIoError>
434where
435    R: Read,
436{
437    extern_fn_panic_handling! {no_early_return;
438        let this = unsafe { this.transmute_into_mut::<R>() };
439
440        convert_io_result(this.read_exact(buf.into()))
441    }
442}
443
444///////////////////////////
445
446#[repr(C)]
447#[derive(StableAbi, Copy, Clone)]
448pub struct IoBufReadFns {
449    pub(super) fill_buf:
450        unsafe extern "C" fn(RMut<'_, ErasedObject>) -> RResult<RSlice<'_, u8>, RIoError>,
451
452    pub(super) consume: unsafe extern "C" fn(RMut<'_, ErasedObject>, usize),
453}
454
455pub(super) struct MakeIoBufReadFns<W>(W);
456
457impl<W> MakeIoBufReadFns<W>
458where
459    W: io::BufRead,
460{
461    pub(super) const NEW: IoBufReadFns = IoBufReadFns {
462        fill_buf: io_BufRead_fill_buf::<W>,
463        consume: io_BufRead_consume::<W>,
464    };
465}
466
467pub(super) unsafe extern "C" fn io_BufRead_fill_buf<R>(
468    this: RMut<'_, ErasedObject>,
469) -> RResult<RSlice<'_, u8>, RIoError>
470where
471    R: BufRead,
472{
473    extern_fn_panic_handling! {no_early_return; unsafe {
474        let this = this.transmute_into_mut::<R>();
475
476        // safety: the lifetime is guaranteed correct because the returned lifetime is
477        // the same as the input lifetime,
478        //
479        // This is a workaround to avoid having to write a `R: BufRead + 'a` bound
480        mem::transmute::<
481            RResult<RSlice<'_,u8>,RIoError>,
482            RResult<RSlice<'_,u8>,RIoError>
483        >(convert_io_result(this.fill_buf()))
484    }}
485}
486
487pub(super) unsafe extern "C" fn io_BufRead_consume<R>(this: RMut<'_, ErasedObject>, amount: usize)
488where
489    R: BufRead,
490{
491    extern_fn_panic_handling! {no_early_return;
492        let this = unsafe { this.transmute_into_mut::<R>() };
493
494        this.consume(amount)
495    }
496}
497
498///////////////////////////
499
500pub(super) unsafe extern "C" fn io_Seek_seek<S>(
501    this: RMut<'_, ErasedObject>,
502    seek_from: RSeekFrom,
503) -> RResult<u64, RIoError>
504where
505    S: io::Seek,
506{
507    extern_fn_panic_handling! {no_early_return;
508        let this = unsafe { this.transmute_into_mut::<S>() };
509
510        convert_io_result(this.seek(seek_from.into()))
511    }
512}