co3 0.4.0

Build C API from Rust
Documentation
use co3::ffi;

ffi! {
    #![unsafe(extern("C"))]
    #![symbol_prefix = "import_opaque"]

    pub type Value;
    pub type OpaqueStruct;

    impl Drop for Value {
        fn drop(&mut self);
    }

    impl Drop for OpaqueStruct {
        fn drop(&mut self);
    }

    impl Value {
        move fn new(move input: String) -> OwnedValue;
        fn len(&self) -> usize;
    }

    impl Clone for OwnedValue {
        #[symbol_name = "import_opaque_value_clone"]
        move fn clone(&self) -> Self;
    }

    impl OpaqueStruct {
        move fn new(name: u8) -> OwnedOpaqueStruct;
        fn name(&self) -> u8;
        fn identity(&self) -> &Self;
        fn value_len(&self, value: &Value) -> usize;
    }
}

mod provider {
    use co3::ffi;

    #[derive(Debug, Clone, PartialEq, Eq)]
    pub struct Value(String);

    #[derive(Debug, PartialEq, Eq)]
    pub struct OpaqueStruct {
        name: u8,
    }

    impl Drop for Value {
        fn drop(&mut self) {}
    }

    impl Drop for OpaqueStruct {
        fn drop(&mut self) {}
    }

    ffi! {
        #![unsafe(export("C"))]
        #![symbol_prefix = "import_opaque"]

        type Value;
        type OpaqueStruct;

        impl Drop for Value {
            fn drop(&mut self);
        }

        impl Drop for OpaqueStruct {
            fn drop(&mut self);
        }

        impl Value {
            move fn new(move input: String) -> Box<Self>;
            fn len(&self) -> usize;
        }

        impl Clone for Box<Value> {
            #[symbol_name = "import_opaque_value_clone"]
            move fn clone(&self) -> Self;
        }

        impl OpaqueStruct {
            move fn new(name: u8) -> Box<Self>;
            fn name(&self) -> u8;
            fn identity(&self) -> &Self;
            fn value_len(&self, value: &Value) -> usize;
        }
    }

    impl Value {
        fn new(input: String) -> Box<Self> {
            Box::new(Self(input))
        }

        fn len(&self) -> usize {
            self.0.len()
        }
    }

    impl OpaqueStruct {
        fn new(name: u8) -> Box<Self> {
            Box::new(Self { name })
        }

        fn name(&self) -> u8 {
            self.name
        }

        fn identity(&self) -> &Self {
            self
        }

        fn value_len(&self, value: &Value) -> usize {
            value.0.len()
        }
    }
}

#[test]
fn constructs_and_uses_imported_opaque_handles() {
    let value = Value::new(String::from("opaque value"));
    let cloned = value.clone();
    assert_eq!(12, value.len());
    assert_eq!(12, cloned.len());

    let opaque = OpaqueStruct::new(42);
    assert_eq!(42, opaque.name());
    assert_eq!(12, opaque.value_len(&value));
}

#[test]
fn imported_opaque_borrow_preserves_identity() {
    let opaque = OpaqueStruct::new(7);
    let identity = opaque.identity();

    assert!(core::ptr::eq::<OpaqueStruct>(&*opaque, identity));
}