xref: /third_party/rust/crates/cxx/tests/ffi/lib.rs (revision 33d722a9)
1#![allow(
2    clippy::boxed_local,
3    clippy::derive_partial_eq_without_eq,
4    clippy::just_underscores_and_digits,
5    clippy::missing_safety_doc,
6    clippy::must_use_candidate,
7    clippy::needless_lifetimes,
8    clippy::needless_pass_by_value,
9    clippy::ptr_arg,
10    clippy::trivially_copy_pass_by_ref,
11    clippy::unnecessary_wraps,
12    clippy::unused_self
13)]
14
15pub mod cast;
16pub mod module;
17
18use cxx::{type_id, CxxString, CxxVector, ExternType, SharedPtr, UniquePtr};
19use std::fmt::{self, Display};
20use std::mem::MaybeUninit;
21use std::os::raw::c_char;
22
23#[cxx::bridge(namespace = "tests")]
24pub mod ffi {
25    #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
26    struct Shared {
27        z: usize,
28    }
29
30    #[derive(PartialEq, PartialOrd)]
31    struct SharedString {
32        msg: String,
33    }
34
35    #[derive(Debug, Hash, PartialOrd, Ord)]
36    enum Enum {
37        AVal,
38        BVal = 2020,
39        #[cxx_name = "CVal"]
40        LastVal,
41    }
42
43    #[namespace = "A"]
44    #[derive(Copy, Clone, Default)]
45    struct AShared {
46        #[cxx_name = "type"]
47        z: usize,
48    }
49
50    #[namespace = "A"]
51    enum AEnum {
52        AAVal,
53        ABVal = 2020,
54        ACVal,
55    }
56
57    #[namespace = "A::B"]
58    enum ABEnum {
59        ABAVal,
60        ABBVal = 2020,
61        ABCVal,
62    }
63
64    #[namespace = "A::B"]
65    #[derive(Clone)]
66    struct ABShared {
67        z: usize,
68    }
69
70    #[namespace = "first"]
71    struct First {
72        second: Box<Second>,
73    }
74
75    #[namespace = "second"]
76    #[derive(Hash)]
77    struct Second {
78        i: i32,
79        e: COwnedEnum,
80    }
81
82    pub struct Array {
83        a: [i32; 4],
84        b: Buffer,
85    }
86
87    #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
88    pub struct StructWithLifetime<'a> {
89        s: &'a str,
90    }
91
92    unsafe extern "C++" {
93        include!("tests/ffi/tests.h");
94
95        type C;
96
97        fn c_return_primitive() -> usize;
98        fn c_return_shared() -> Shared;
99        fn c_return_box() -> Box<R>;
100        fn c_return_unique_ptr() -> UniquePtr<C>;
101        fn c_return_shared_ptr() -> SharedPtr<C>;
102        fn c_return_ref(shared: &Shared) -> &usize;
103        fn c_return_mut(shared: &mut Shared) -> &mut usize;
104        fn c_return_str(shared: &Shared) -> &str;
105        fn c_return_slice_char(shared: &Shared) -> &[c_char];
106        fn c_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8];
107        fn c_return_rust_string() -> String;
108        fn c_return_rust_string_lossy() -> String;
109        fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
110        fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
111        fn c_return_unique_ptr_vector_f64() -> UniquePtr<CxxVector<f64>>;
112        fn c_return_unique_ptr_vector_string() -> UniquePtr<CxxVector<CxxString>>;
113        fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
114        fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
115        fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
116        fn c_return_mut_vector(c: Pin<&mut C>) -> Pin<&mut CxxVector<u8>>;
117        fn c_return_rust_vec_u8() -> Vec<u8>;
118        fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
119        fn c_return_mut_rust_vec(c: Pin<&mut C>) -> &mut Vec<u8>;
120        fn c_return_rust_vec_string() -> Vec<String>;
121        fn c_return_rust_vec_bool() -> Vec<bool>;
122        fn c_return_identity(_: usize) -> usize;
123        fn c_return_sum(_: usize, _: usize) -> usize;
124        fn c_return_enum(n: u16) -> Enum;
125        fn c_return_ns_ref(shared: &AShared) -> &usize;
126        fn c_return_nested_ns_ref(shared: &ABShared) -> &usize;
127        fn c_return_ns_enum(n: u16) -> AEnum;
128        fn c_return_nested_ns_enum(n: u16) -> ABEnum;
129        fn c_return_const_ptr(n: usize) -> *const C;
130        fn c_return_mut_ptr(n: usize) -> *mut C;
131
132        fn c_take_primitive(n: usize);
133        fn c_take_shared(shared: Shared);
134        fn c_take_box(r: Box<R>);
135        fn c_take_ref_r(r: &R);
136        fn c_take_ref_c(c: &C);
137        fn c_take_str(s: &str);
138        fn c_take_slice_char(s: &[c_char]);
139        fn c_take_slice_shared(s: &[Shared]);
140        fn c_take_slice_shared_sort(s: &mut [Shared]);
141        fn c_take_slice_r(s: &[R]);
142        fn c_take_slice_r_sort(s: &mut [R]);
143        fn c_take_rust_string(s: String);
144        fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
145        fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
146        fn c_take_unique_ptr_vector_f64(v: UniquePtr<CxxVector<f64>>);
147        fn c_take_unique_ptr_vector_string(v: UniquePtr<CxxVector<CxxString>>);
148        fn c_take_unique_ptr_vector_shared(v: UniquePtr<CxxVector<Shared>>);
149        fn c_take_ref_vector(v: &CxxVector<u8>);
150        fn c_take_rust_vec(v: Vec<u8>);
151        fn c_take_rust_vec_shared(v: Vec<Shared>);
152        fn c_take_rust_vec_string(v: Vec<String>);
153        fn c_take_rust_vec_index(v: Vec<u8>);
154        fn c_take_rust_vec_shared_index(v: Vec<Shared>);
155        fn c_take_rust_vec_shared_push(v: Vec<Shared>);
156        fn c_take_rust_vec_shared_truncate(v: Vec<Shared>);
157        fn c_take_rust_vec_shared_clear(v: Vec<Shared>);
158        fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
159        fn c_take_rust_vec_shared_sort(v: Vec<Shared>);
160        fn c_take_ref_rust_vec(v: &Vec<u8>);
161        fn c_take_ref_rust_vec_string(v: &Vec<String>);
162        fn c_take_ref_rust_vec_index(v: &Vec<u8>);
163        fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
164        fn c_take_ref_shared_string(s: &SharedString) -> &SharedString;
165        fn c_take_callback(callback: fn(String) -> usize);
166        fn c_take_callback_ref(callback: fn(&String));
167        #[cxx_name = "c_take_callback_ref"]
168        fn c_take_callback_ref_lifetime<'a>(callback: fn(&'a String));
169        fn c_take_callback_mut(callback: fn(&mut String));
170        fn c_take_enum(e: Enum);
171        fn c_take_ns_enum(e: AEnum);
172        fn c_take_nested_ns_enum(e: ABEnum);
173        fn c_take_ns_shared(shared: AShared);
174        fn c_take_nested_ns_shared(shared: ABShared);
175        fn c_take_rust_vec_ns_shared(v: Vec<AShared>);
176        fn c_take_rust_vec_nested_ns_shared(v: Vec<ABShared>);
177        unsafe fn c_take_const_ptr(c: *const C) -> usize;
178        unsafe fn c_take_mut_ptr(c: *mut C) -> usize;
179
180        fn c_try_return_void() -> Result<()>;
181        fn c_try_return_primitive() -> Result<usize>;
182        fn c_fail_return_primitive() -> Result<usize>;
183        fn c_try_return_box() -> Result<Box<R>>;
184        fn c_try_return_ref(s: &String) -> Result<&String>;
185        fn c_try_return_str(s: &str) -> Result<&str>;
186        fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
187        fn c_try_return_mutsliceu8(s: &mut [u8]) -> Result<&mut [u8]>;
188        fn c_try_return_rust_string() -> Result<String>;
189        fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
190        fn c_try_return_rust_vec() -> Result<Vec<u8>>;
191        fn c_try_return_rust_vec_string() -> Result<Vec<String>>;
192        fn c_try_return_ref_rust_vec(c: &C) -> Result<&Vec<u8>>;
193
194        fn get(self: &C) -> usize;
195        fn set(self: Pin<&mut C>, n: usize) -> usize;
196        fn get2(&self) -> usize;
197        fn getRef(self: &C) -> &usize;
198        fn getMut(self: Pin<&mut C>) -> &mut usize;
199        fn set_succeed(self: Pin<&mut C>, n: usize) -> Result<usize>;
200        fn get_fail(self: Pin<&mut C>) -> Result<usize>;
201        fn c_method_on_shared(self: &Shared) -> usize;
202        fn c_method_ref_on_shared(self: &Shared) -> &usize;
203        fn c_method_mut_on_shared(self: &mut Shared) -> &mut usize;
204        fn c_set_array(self: &mut Array, value: i32);
205
206        fn c_get_use_count(weak: &WeakPtr<C>) -> usize;
207
208        #[rust_name = "i32_overloaded_method"]
209        fn cOverloadedMethod(&self, x: i32) -> String;
210        #[rust_name = "str_overloaded_method"]
211        fn cOverloadedMethod(&self, x: &str) -> String;
212        #[rust_name = "i32_overloaded_function"]
213        fn cOverloadedFunction(x: i32) -> String;
214        #[rust_name = "str_overloaded_function"]
215        fn cOverloadedFunction(x: &str) -> String;
216
217        #[namespace = "other"]
218        fn ns_c_take_ns_shared(shared: AShared);
219    }
220
221    extern "C++" {
222        include!("tests/ffi/module.rs.h");
223
224        type COwnedEnum;
225        type Job = crate::module::ffi::Job;
226    }
227
228    extern "Rust" {
229        #[derive(ExternType)]
230        type Reference<'a>;
231    }
232
233    unsafe extern "C++" {
234        type Borrow<'a>;
235
236        fn c_return_borrow<'a>(s: &'a CxxString) -> UniquePtr<Borrow<'a>>;
237
238        #[rust_name = "c_return_borrow_elided"]
239        fn c_return_borrow(s: &CxxString) -> UniquePtr<Borrow>;
240
241        fn const_member(self: &Borrow);
242        fn nonconst_member(self: Pin<&mut Borrow>);
243    }
244
245    #[repr(u32)]
246    #[derive(Hash)]
247    enum COwnedEnum {
248        #[cxx_name = "CVAL1"]
249        CVal1,
250        #[cxx_name = "CVAL2"]
251        CVal2,
252    }
253
254    extern "C++" {
255        type Buffer = crate::Buffer;
256    }
257
258    extern "Rust" {
259        type R;
260
261        fn r_return_primitive() -> usize;
262        fn r_return_shared() -> Shared;
263        fn r_return_box() -> Box<R>;
264        fn r_return_unique_ptr() -> UniquePtr<C>;
265        fn r_return_shared_ptr() -> SharedPtr<C>;
266        fn r_return_ref(shared: &Shared) -> &usize;
267        fn r_return_mut(shared: &mut Shared) -> &mut usize;
268        fn r_return_str(shared: &Shared) -> &str;
269        fn r_return_sliceu8(shared: &Shared) -> &[u8];
270        fn r_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8];
271        fn r_return_rust_string() -> String;
272        fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
273        fn r_return_rust_vec() -> Vec<u8>;
274        fn r_return_rust_vec_string() -> Vec<String>;
275        fn r_return_rust_vec_extern_struct() -> Vec<Job>;
276        fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
277        fn r_return_mut_rust_vec(shared: &mut Shared) -> &mut Vec<u8>;
278        fn r_return_identity(_: usize) -> usize;
279        fn r_return_sum(_: usize, _: usize) -> usize;
280        fn r_return_enum(n: u32) -> Enum;
281
282        fn r_take_primitive(n: usize);
283        fn r_take_shared(shared: Shared);
284        fn r_take_box(r: Box<R>);
285        fn r_take_unique_ptr(c: UniquePtr<C>);
286        fn r_take_shared_ptr(c: SharedPtr<C>);
287        fn r_take_ref_r(r: &R);
288        fn r_take_ref_c(c: &C);
289        fn r_take_str(s: &str);
290        fn r_take_slice_char(s: &[c_char]);
291        fn r_take_rust_string(s: String);
292        fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
293        fn r_take_ref_vector(v: &CxxVector<u8>);
294        fn r_take_ref_empty_vector(v: &CxxVector<u64>);
295        fn r_take_rust_vec(v: Vec<u8>);
296        fn r_take_rust_vec_string(v: Vec<String>);
297        fn r_take_ref_rust_vec(v: &Vec<u8>);
298        fn r_take_ref_rust_vec_string(v: &Vec<String>);
299        fn r_take_enum(e: Enum);
300
301        fn r_try_return_void() -> Result<()>;
302        fn r_try_return_primitive() -> Result<usize>;
303        fn r_try_return_box() -> Result<Box<R>>;
304        fn r_fail_return_primitive() -> Result<usize>;
305        fn r_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
306        fn r_try_return_mutsliceu8(s: &mut [u8]) -> Result<&mut [u8]>;
307
308        fn get(self: &R) -> usize;
309        fn set(self: &mut R, n: usize) -> usize;
310        fn r_method_on_shared(self: &Shared) -> String;
311        fn r_get_array_sum(self: &Array) -> i32;
312
313        #[cxx_name = "rAliasedFunction"]
314        fn r_aliased_function(x: i32) -> String;
315    }
316
317    struct Dag0 {
318        i: i32,
319    }
320
321    struct Dag1 {
322        dag2: Dag2,
323        vec: Vec<Dag3>,
324    }
325
326    struct Dag2 {
327        dag4: Dag4,
328    }
329
330    struct Dag3 {
331        dag1: Dag1,
332    }
333
334    struct Dag4 {
335        dag0: Dag0,
336    }
337
338    impl Box<Shared> {}
339    impl CxxVector<SharedString> {}
340}
341
342mod other {
343    use cxx::kind::{Opaque, Trivial};
344    use cxx::{type_id, CxxString, ExternType};
345
346    #[repr(C)]
347    pub struct D {
348        pub d: u64,
349    }
350
351    #[repr(C)]
352    pub struct E {
353        e: u64,
354        e_str: CxxString,
355    }
356
357    pub mod f {
358        use cxx::kind::Opaque;
359        use cxx::{type_id, CxxString, ExternType};
360
361        #[repr(C)]
362        pub struct F {
363            e: u64,
364            e_str: CxxString,
365        }
366
367        unsafe impl ExternType for F {
368            type Id = type_id!("F::F");
369            type Kind = Opaque;
370        }
371    }
372
373    #[repr(C)]
374    pub struct G {
375        pub g: u64,
376    }
377
378    unsafe impl ExternType for G {
379        type Id = type_id!("G::G");
380        type Kind = Trivial;
381    }
382
383    unsafe impl ExternType for D {
384        type Id = type_id!("tests::D");
385        type Kind = Trivial;
386    }
387
388    unsafe impl ExternType for E {
389        type Id = type_id!("tests::E");
390        type Kind = Opaque;
391    }
392}
393
394#[derive(PartialEq, Debug)]
395pub struct R(pub usize);
396
397impl R {
398    fn get(&self) -> usize {
399        self.0
400    }
401
402    fn set(&mut self, n: usize) -> usize {
403        self.0 = n;
404        n
405    }
406}
407
408pub struct Reference<'a>(&'a String);
409
410impl ffi::Shared {
411    fn r_method_on_shared(&self) -> String {
412        "2020".to_owned()
413    }
414}
415
416impl ffi::Array {
417    pub fn r_get_array_sum(&self) -> i32 {
418        self.a.iter().sum()
419    }
420}
421
422#[derive(Default)]
423#[repr(C)]
424pub struct Buffer([c_char; 12]);
425
426unsafe impl ExternType for Buffer {
427    type Id = type_id!("tests::Buffer");
428    type Kind = cxx::kind::Trivial;
429}
430
431#[derive(Debug)]
432struct Error;
433
434impl std::error::Error for Error {}
435
436impl Display for Error {
437    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
438        f.write_str("rust error")
439    }
440}
441
442fn r_return_primitive() -> usize {
443    2020
444}
445
446fn r_return_shared() -> ffi::Shared {
447    ffi::Shared { z: 2020 }
448}
449
450fn r_return_box() -> Box<R> {
451    Box::new(R(2020))
452}
453
454fn r_return_unique_ptr() -> UniquePtr<ffi::C> {
455    extern "C" {
456        fn cxx_test_suite_get_unique_ptr() -> *mut ffi::C;
457    }
458    unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr()) }
459}
460
461fn r_return_shared_ptr() -> SharedPtr<ffi::C> {
462    extern "C" {
463        fn cxx_test_suite_get_shared_ptr(repr: *mut SharedPtr<ffi::C>);
464    }
465    let mut shared_ptr = MaybeUninit::<SharedPtr<ffi::C>>::uninit();
466    let repr = shared_ptr.as_mut_ptr();
467    unsafe {
468        cxx_test_suite_get_shared_ptr(repr);
469        shared_ptr.assume_init()
470    }
471}
472
473fn r_return_ref(shared: &ffi::Shared) -> &usize {
474    &shared.z
475}
476
477fn r_return_mut(shared: &mut ffi::Shared) -> &mut usize {
478    &mut shared.z
479}
480
481fn r_return_str(shared: &ffi::Shared) -> &str {
482    let _ = shared;
483    "2020"
484}
485
486fn r_return_sliceu8(shared: &ffi::Shared) -> &[u8] {
487    let _ = shared;
488    b"2020"
489}
490
491fn r_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8] {
492    slice
493}
494
495fn r_return_rust_string() -> String {
496    "2020".to_owned()
497}
498
499fn r_return_unique_ptr_string() -> UniquePtr<CxxString> {
500    extern "C" {
501        fn cxx_test_suite_get_unique_ptr_string() -> *mut CxxString;
502    }
503    unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr_string()) }
504}
505
506fn r_return_rust_vec() -> Vec<u8> {
507    Vec::new()
508}
509
510fn r_return_rust_vec_string() -> Vec<String> {
511    Vec::new()
512}
513
514fn r_return_rust_vec_extern_struct() -> Vec<ffi::Job> {
515    Vec::new()
516}
517
518fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
519    let _ = shared;
520    unimplemented!()
521}
522
523fn r_return_mut_rust_vec(shared: &mut ffi::Shared) -> &mut Vec<u8> {
524    let _ = shared;
525    unimplemented!()
526}
527
528fn r_return_identity(n: usize) -> usize {
529    n
530}
531
532fn r_return_sum(n1: usize, n2: usize) -> usize {
533    n1 + n2
534}
535
536fn r_return_enum(n: u32) -> ffi::Enum {
537    if n == 0 {
538        ffi::Enum::AVal
539    } else if n <= 2020 {
540        ffi::Enum::BVal
541    } else {
542        ffi::Enum::LastVal
543    }
544}
545
546fn r_take_primitive(n: usize) {
547    assert_eq!(n, 2020);
548}
549
550fn r_take_shared(shared: ffi::Shared) {
551    assert_eq!(shared.z, 2020);
552}
553
554fn r_take_box(r: Box<R>) {
555    let _ = r;
556}
557
558fn r_take_unique_ptr(c: UniquePtr<ffi::C>) {
559    let _ = c;
560}
561
562fn r_take_shared_ptr(c: SharedPtr<ffi::C>) {
563    let _ = c;
564}
565
566fn r_take_ref_r(r: &R) {
567    let _ = r;
568}
569
570fn r_take_ref_c(c: &ffi::C) {
571    let _ = c;
572}
573
574fn r_take_str(s: &str) {
575    assert_eq!(s, "2020");
576}
577
578fn r_take_rust_string(s: String) {
579    assert_eq!(s, "2020");
580}
581
582fn r_take_slice_char(s: &[c_char]) {
583    assert_eq!(s.len(), 5);
584    let s = cast::c_char_to_unsigned(s);
585    assert_eq!(std::str::from_utf8(s).unwrap(), "2020\0");
586}
587
588fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
589    assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
590}
591
592fn r_take_ref_vector(v: &CxxVector<u8>) {
593    let slice = v.as_slice();
594    assert_eq!(slice, [20, 2, 0]);
595}
596
597fn r_take_ref_empty_vector(v: &CxxVector<u64>) {
598    assert!(v.as_slice().is_empty());
599    assert!(v.is_empty());
600}
601
602fn r_take_rust_vec(v: Vec<u8>) {
603    let _ = v;
604}
605
606fn r_take_rust_vec_string(v: Vec<String>) {
607    let _ = v;
608}
609
610fn r_take_ref_rust_vec(v: &Vec<u8>) {
611    let _ = v;
612}
613
614fn r_take_ref_rust_vec_string(v: &Vec<String>) {
615    let _ = v;
616}
617
618fn r_take_enum(e: ffi::Enum) {
619    let _ = e;
620}
621
622fn r_try_return_void() -> Result<(), Error> {
623    Ok(())
624}
625
626fn r_try_return_primitive() -> Result<usize, Error> {
627    Ok(2020)
628}
629
630fn r_try_return_box() -> Result<Box<R>, Error> {
631    Ok(Box::new(R(2020)))
632}
633
634fn r_fail_return_primitive() -> Result<usize, Error> {
635    Err(Error)
636}
637
638fn r_try_return_sliceu8(slice: &[u8]) -> Result<&[u8], Error> {
639    Ok(slice)
640}
641
642fn r_try_return_mutsliceu8(slice: &mut [u8]) -> Result<&mut [u8], Error> {
643    Ok(slice)
644}
645
646fn r_aliased_function(x: i32) -> String {
647    x.to_string()
648}
649