cglue/
callback.rs

1//! # FFI compatible callbacks
2//!
3//! The essence of them is to be simple, reliable, and flexible. Thus, every callback accepts a C
4//! function that takes 2 arguments: `context`, and `argument`.
5//!
6//! `context` is any type of context. We take a sized pointer to it. It can hold anything like a
7//! closure that we then wrap for callback functionality.
8//!
9//! `argument` is the actual argument that gets produced and passed over. This will be variable,
10//! and it is passed as value.
11//!
12//! `OpaqueCallback`, as the name suggests, marks the `context` as opaque, casts it to `c_void`
13//! pointer. It allows the code not to care about what's behind the context, it just knows that it
14//! needs to pass it over to the callback.
15
16use crate::trait_group::c_void;
17use std::prelude::v1::*;
18
19// C style callbacks that are needed so that C code can easily use callback like functions
20#[repr(transparent)]
21#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
22pub struct OpaqueCallback<'a, T: 'a>(Callback<'a, c_void, T>);
23
24impl<'a, T> OpaqueCallback<'a, T> {
25    #[must_use = "this value is the stopping condition"]
26    pub fn call(&mut self, arg: T) -> bool {
27        (self.0.func)(self.0.context, arg)
28    }
29}
30
31#[repr(C)]
32#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
33pub struct Callback<'a, T: 'a, F> {
34    context: &'a mut T,
35    func: extern "C" fn(&mut T, F) -> bool,
36}
37
38impl<'a, T, F> From<Callback<'a, T, F>> for OpaqueCallback<'a, F> {
39    fn from(callback: Callback<'a, T, F>) -> Self {
40        Self(callback.into_opaque())
41    }
42}
43
44impl<'a, T, F> Callback<'a, T, F> {
45    pub fn into_opaque(self) -> Callback<'a, c_void, F> {
46        unsafe {
47            Callback {
48                context: &mut *(self.context as *mut T as *mut c_void),
49                func: std::mem::transmute(self.func),
50            }
51        }
52    }
53
54    pub fn new(context: &'a mut T, func: extern "C" fn(&mut T, F) -> bool) -> Self {
55        Self { context, func }
56    }
57}
58
59impl<'a, T: FnMut(F) -> bool, F> From<&'a mut T> for OpaqueCallback<'a, F> {
60    fn from(func: &'a mut T) -> Self {
61        extern "C" fn callback<T: FnMut(F) -> bool, F>(func: &mut T, context: F) -> bool {
62            func(context)
63        }
64
65        Callback {
66            context: func,
67            func: callback::<T, F>,
68        }
69        .into()
70    }
71}
72
73impl<'a, T> From<&'a mut Vec<T>> for OpaqueCallback<'a, T> {
74    fn from(vec: &'a mut Vec<T>) -> Self {
75        extern "C" fn callback<T>(v: &mut Vec<T>, context: T) -> bool {
76            v.push(context);
77            true
78        }
79
80        Callback {
81            context: vec,
82            func: callback::<T>,
83        }
84        .into()
85    }
86}
87
88impl<'a, T> std::iter::Extend<T> for OpaqueCallback<'a, T> {
89    fn extend<F: IntoIterator<Item = T>>(&mut self, iter: F) {
90        for item in iter {
91            if !self.call(item) {
92                break;
93            }
94        }
95    }
96}
97
98pub trait FeedCallback<T> {
99    fn feed_into_mut(self, callback: &mut OpaqueCallback<T>) -> usize;
100
101    fn feed_into(self, mut callback: OpaqueCallback<T>) -> usize
102    where
103        Self: Sized,
104    {
105        self.feed_into_mut(&mut callback)
106    }
107}
108
109impl<I: std::iter::IntoIterator<Item = T>, T> FeedCallback<T> for I {
110    fn feed_into_mut(self, callback: &mut OpaqueCallback<T>) -> usize {
111        let mut cnt = 0;
112        for v in self {
113            cnt += 1;
114            if !callback.call(v) {
115                break;
116            }
117        }
118        cnt
119    }
120}
121
122pub trait FromExtend<T>: Extend<T> + Sized {
123    #[allow(clippy::wrong_self_convention)]
124    fn from_extend(&mut self) -> OpaqueCallback<T> {
125        extern "C" fn callback<C: Extend<T>, T>(v: &mut C, context: T) -> bool {
126            v.extend(Some(context));
127            true
128        }
129
130        Callback {
131            context: self,
132            func: callback::<Self, T>,
133        }
134        .into()
135    }
136}
137
138impl<C: Extend<T>, T> FromExtend<T> for C {}
139
140pub trait Callbackable<T> {
141    fn call(&mut self, data: T) -> bool;
142}
143
144impl<T> Callbackable<T> for &mut OpaqueCallback<'_, T> {
145    fn call(&mut self, data: T) -> bool {
146        (*self).call(data)
147    }
148}
149
150impl<T> Callbackable<T> for OpaqueCallback<'_, T> {
151    fn call(&mut self, data: T) -> bool {
152        (self.0.func)(self.0.context, data)
153    }
154}
155
156impl<T, F: FnMut(T) -> bool> Callbackable<T> for F {
157    fn call(&mut self, data: T) -> bool {
158        (*self)(data)
159    }
160}