1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//! # FFI compatible callbacks
//!
//! The essence of them is to be simple, reliable, and flexible. Thus, every callback accepts a C
//! function that takes 2 arguments: `context`, and `argument`.
//!
//! `context` is any type of context. We take a sized pointer to it. It can hold anything like a
//! closure that we then wrap for callback functionality.
//!
//! `argument` is the actual argument that gets produced and passed over. This will be variable,
//! and it is passed as value.
//!
//! `OpaqueCallback`, as the name suggests, marks the `context` as opaque, casts it to `c_void`
//! pointer. It allows the code not to care about what's behind the context, it just knows that it
//! needs to pass it over to the callback.

use crate::trait_group::c_void;
use std::prelude::v1::*;

// C style callbacks that are needed so that C code can easily use callback like functions
#[repr(transparent)]
#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
pub struct OpaqueCallback<'a, T: 'a>(Callback<'a, c_void, T>);

impl<'a, T> OpaqueCallback<'a, T> {
    #[must_use = "this value is the stopping condition"]
    pub fn call(&mut self, arg: T) -> bool {
        (self.0.func)(self.0.context, arg)
    }
}

#[repr(C)]
#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
pub struct Callback<'a, T: 'a, F> {
    context: &'a mut T,
    func: extern "C" fn(&mut T, F) -> bool,
}

impl<'a, T, F> From<Callback<'a, T, F>> for OpaqueCallback<'a, F> {
    fn from(callback: Callback<'a, T, F>) -> Self {
        Self(callback.into_opaque())
    }
}

impl<'a, T, F> Callback<'a, T, F> {
    pub fn into_opaque(self) -> Callback<'a, c_void, F> {
        unsafe {
            Callback {
                context: &mut *(self.context as *mut T as *mut c_void),
                func: std::mem::transmute(self.func),
            }
        }
    }

    pub fn new(context: &'a mut T, func: extern "C" fn(&mut T, F) -> bool) -> Self {
        Self { context, func }
    }
}

impl<'a, T: FnMut(F) -> bool, F> From<&'a mut T> for OpaqueCallback<'a, F> {
    fn from(func: &'a mut T) -> Self {
        extern "C" fn callback<T: FnMut(F) -> bool, F>(func: &mut T, context: F) -> bool {
            func(context)
        }

        Callback {
            context: func,
            func: callback::<T, F>,
        }
        .into()
    }
}

impl<'a, T> From<&'a mut Vec<T>> for OpaqueCallback<'a, T> {
    fn from(vec: &'a mut Vec<T>) -> Self {
        extern "C" fn callback<T>(v: &mut Vec<T>, context: T) -> bool {
            v.push(context);
            true
        }

        Callback {
            context: vec,
            func: callback::<T>,
        }
        .into()
    }
}

impl<'a, T> std::iter::Extend<T> for OpaqueCallback<'a, T> {
    fn extend<F: IntoIterator<Item = T>>(&mut self, iter: F) {
        for item in iter {
            if !self.call(item) {
                break;
            }
        }
    }
}

pub trait FeedCallback<T> {
    fn feed_into_mut(self, callback: &mut OpaqueCallback<T>) -> usize;

    fn feed_into(self, mut callback: OpaqueCallback<T>) -> usize
    where
        Self: Sized,
    {
        self.feed_into_mut(&mut callback)
    }
}

impl<I: std::iter::IntoIterator<Item = T>, T> FeedCallback<T> for I {
    fn feed_into_mut(self, callback: &mut OpaqueCallback<T>) -> usize {
        let mut cnt = 0;
        for v in self {
            cnt += 1;
            if !callback.call(v) {
                break;
            }
        }
        cnt
    }
}

pub trait FromExtend<T>: Extend<T> + Sized {
    #[allow(clippy::wrong_self_convention)]
    fn from_extend(&mut self) -> OpaqueCallback<T> {
        extern "C" fn callback<C: Extend<T>, T>(v: &mut C, context: T) -> bool {
            v.extend(Some(context));
            true
        }

        Callback {
            context: self,
            func: callback::<Self, T>,
        }
        .into()
    }
}

impl<C: Extend<T>, T> FromExtend<T> for C {}

pub trait Callbackable<T> {
    fn call(&mut self, data: T) -> bool;
}

impl<T> Callbackable<T> for &mut OpaqueCallback<'_, T> {
    fn call(&mut self, data: T) -> bool {
        (*self).call(data)
    }
}

impl<T> Callbackable<T> for OpaqueCallback<'_, T> {
    fn call(&mut self, data: T) -> bool {
        (self.0.func)(self.0.context, data)
    }
}

impl<T, F: FnMut(T) -> bool> Callbackable<T> for F {
    fn call(&mut self, data: T) -> bool {
        (*self)(data)
    }
}