abi_stable/erased_types/
iterator.rs

1use crate::{
2    marker_type::{ErasedObject, NonOwningPhantom},
3    sabi_types::{RMut, RRef},
4    std_types::{RNone, ROption, RSome, RVec, Tuple2},
5    traits::IntoReprC,
6    utils::Transmuter,
7};
8
9///////////////////////////////////////////////////////////////////////////////////
10
11#[repr(C)]
12#[derive(StableAbi)]
13pub struct IteratorFns<Item> {
14    pub(super) next: unsafe extern "C" fn(RMut<'_, ErasedObject>) -> ROption<Item>,
15    pub(super) extending_rvec:
16        unsafe extern "C" fn(RMut<'_, ErasedObject>, &mut RVec<Item>, ROption<usize>),
17    pub(super) size_hint:
18        unsafe extern "C" fn(RRef<'_, ErasedObject>) -> Tuple2<usize, ROption<usize>>,
19    pub(super) count: unsafe extern "C" fn(RMut<'_, ErasedObject>) -> usize,
20    pub(super) last: unsafe extern "C" fn(RMut<'_, ErasedObject>) -> ROption<Item>,
21    pub(super) nth: unsafe extern "C" fn(RMut<'_, ErasedObject>, usize) -> ROption<Item>,
22    pub(super) skip_eager: unsafe extern "C" fn(RMut<'_, ErasedObject>, usize),
23}
24
25impl<Item> Copy for IteratorFns<Item> {}
26impl<Item> Clone for IteratorFns<Item> {
27    fn clone(&self) -> Self {
28        *self
29    }
30}
31
32///////////////////////////////////////////////////////////////////////////////////
33
34pub struct MakeIteratorFns<I>(NonOwningPhantom<I>);
35
36impl<I> MakeIteratorFns<I>
37where
38    I: Iterator,
39{
40    const ITER: IteratorFns<I::Item> = IteratorFns {
41        next: next::<I>,
42        extending_rvec: extending_rvec::<I>,
43        size_hint: size_hint::<I>,
44        count: count::<I>,
45        last: last::<I>,
46        nth: nth::<I>,
47        skip_eager: skip_eager::<I>,
48    };
49
50    pub(super) const NEW: IteratorFns<()> = unsafe { Transmuter { from: Self::ITER }.to };
51}
52
53///////////////////////////////////////////////////////////////////////////////////
54
55pub(super) unsafe extern "C" fn next<I>(this: RMut<'_, ErasedObject>) -> ROption<I::Item>
56where
57    I: Iterator,
58{
59    extern_fn_panic_handling! {no_early_return;
60        let this = unsafe { this.transmute_into_mut::<I>() };
61        this.next().into_c()
62    }
63}
64
65pub(super) unsafe extern "C" fn extending_rvec<I>(
66    this: RMut<'_, ErasedObject>,
67    vec: &mut RVec<I::Item>,
68    taking: ROption<usize>,
69) where
70    I: Iterator,
71{
72    extern_fn_panic_handling! {no_early_return;
73        let this = unsafe { this.transmute_into_mut::<I>() };
74
75        vec.extend(
76            this.take(taking.unwrap_or(!0))
77        );
78    }
79}
80
81pub(super) unsafe extern "C" fn size_hint<I>(
82    this: RRef<'_, ErasedObject>,
83) -> Tuple2<usize, ROption<usize>>
84where
85    I: Iterator,
86{
87    extern_fn_panic_handling! {no_early_return;
88        let this = unsafe { this.transmute_into_ref::<I>() };
89        let (l,r)=this.size_hint();
90
91        Tuple2(l,r.into_c())
92    }
93}
94
95pub(super) unsafe extern "C" fn count<I>(this: RMut<'_, ErasedObject>) -> usize
96where
97    I: Iterator,
98{
99    extern_fn_panic_handling! {no_early_return;
100        let this = unsafe { this.transmute_into_mut::<I>() };
101        this.count()
102    }
103}
104
105pub(super) unsafe extern "C" fn last<I>(this: RMut<'_, ErasedObject>) -> ROption<I::Item>
106where
107    I: Iterator,
108{
109    extern_fn_panic_handling! {no_early_return;
110        let this = unsafe { this.transmute_into_mut::<I>() };
111        this.last().into_c()
112    }
113}
114
115pub(super) unsafe extern "C" fn nth<I>(this: RMut<'_, ErasedObject>, at: usize) -> ROption<I::Item>
116where
117    I: Iterator,
118{
119    extern_fn_panic_handling! {no_early_return;
120        let this = unsafe { this.transmute_into_mut::<I>() };
121        this.nth(at).into_c()
122    }
123}
124
125pub(super) unsafe extern "C" fn skip_eager<I>(this: RMut<'_, ErasedObject>, skipping: usize)
126where
127    I: Iterator,
128{
129    extern_fn_panic_handling! {no_early_return;
130        let this = unsafe { this.transmute_into_mut::<I>() };
131
132        if skipping!=0 {
133            let _=this.nth(skipping-1);
134        }
135    }
136}
137
138////////////////////////////////////////////////////////////////////////////////
139////////////////////////////////////////////////////////////////////////////////
140////////////////////////////////////////////////////////////////////////////////
141
142#[repr(C)]
143#[derive(StableAbi)]
144pub struct DoubleEndedIteratorFns<Item> {
145    pub(super) next_back: unsafe extern "C" fn(RMut<'_, ErasedObject>) -> ROption<Item>,
146    pub(super) extending_rvec_back:
147        unsafe extern "C" fn(RMut<'_, ErasedObject>, &mut RVec<Item>, ROption<usize>),
148    pub(super) nth_back: unsafe extern "C" fn(RMut<'_, ErasedObject>, usize) -> ROption<Item>,
149}
150
151impl<Item> Copy for DoubleEndedIteratorFns<Item> {}
152impl<Item> Clone for DoubleEndedIteratorFns<Item> {
153    fn clone(&self) -> Self {
154        *self
155    }
156}
157
158///////////////////////////////////////////////////////////////////////////////////
159
160pub struct MakeDoubleEndedIteratorFns<I>(NonOwningPhantom<I>);
161
162impl<I> MakeDoubleEndedIteratorFns<I>
163where
164    I: DoubleEndedIterator,
165{
166    pub(super) const ITER: DoubleEndedIteratorFns<I::Item> = DoubleEndedIteratorFns {
167        next_back: next_back::<I>,
168        extending_rvec_back: extending_rvec_back::<I>,
169        nth_back: nth_back::<I>,
170    };
171
172    pub(super) const NEW: DoubleEndedIteratorFns<()> =
173        unsafe { Transmuter { from: Self::ITER }.to };
174}
175
176///////////////////////////////////////////////////////////////////////////////////
177
178pub(super) unsafe extern "C" fn next_back<I>(this: RMut<'_, ErasedObject>) -> ROption<I::Item>
179where
180    I: DoubleEndedIterator,
181{
182    extern_fn_panic_handling! {no_early_return;
183        let this = unsafe { this.transmute_into_mut::<I>() };
184        this.next_back().into_c()
185    }
186}
187
188pub(super) unsafe extern "C" fn extending_rvec_back<I>(
189    this: RMut<'_, ErasedObject>,
190    vec: &mut RVec<I::Item>,
191    taking: ROption<usize>,
192) where
193    I: DoubleEndedIterator,
194{
195    extern_fn_panic_handling! {no_early_return;
196        let this = unsafe { this.transmute_into_mut::<I>() };
197
198        vec.extend(
199            this.rev().take(taking.unwrap_or(!0))
200        );
201    }
202}
203
204pub(super) unsafe extern "C" fn nth_back<I>(
205    this: RMut<'_, ErasedObject>,
206    mut at: usize,
207) -> ROption<I::Item>
208where
209    I: DoubleEndedIterator,
210{
211    extern_fn_panic_handling! { // returns early
212        let this = unsafe { this.transmute_into_mut::<I>() };
213        for x in this.rev() {
214            if at == 0 {
215                return RSome(x)
216            }
217            at -= 1;
218        }
219        RNone
220    }
221}