phlow-ffi 3.0.0

Provides C-like api to the phlow crates
Documentation
use phlow::{AnySendObject, ObjectRef, PhlowVTable, PhlowView};
use string_box::StringBox;
use value_box::{BorrowedPtr, ErasedBorrowedPtr, OwnedPtr, ReturnBoxerResult};

#[unsafe(no_mangle)]
pub extern "C" fn phlow_vtable_supports_type_name(phlow_vtable: BorrowedPtr<PhlowVTable>) -> bool {
    phlow_vtable
        .with_ref_ok(|phlow_vtable| phlow_vtable.supports_type_name())
        .or_log(false)
}

#[unsafe(no_mangle)]
pub extern "C" fn phlow_vtable_get_type_name(
    phlow_vtable: BorrowedPtr<PhlowVTable>,
    mut type_name: BorrowedPtr<StringBox>,
) {
    phlow_vtable
        .with_ref(|phlow_vtable| {
            let vtable_type_name = phlow_vtable.type_name().unwrap_or_default();
            type_name.with_mut_ok(|type_name| type_name.set_string(vtable_type_name.to_string()))
        })
        .log();
}

#[unsafe(no_mangle)]
pub extern "C" fn phlow_vtable_supports_to_string(phlow_vtable: BorrowedPtr<PhlowVTable>) -> bool {
    phlow_vtable
        .with_ref_ok(|phlow_vtable| phlow_vtable.supports_to_string())
        .or_log(false)
}

#[unsafe(no_mangle)]
pub extern "C" fn phlow_vtable_to_string_for_typed_object(
    phlow_vtable: BorrowedPtr<PhlowVTable>,
    object: ErasedBorrowedPtr,
    string: BorrowedPtr<StringBox>,
) {
    vtable_to_string_for_object(phlow_vtable, string, |phlow_vtable| {
        object
            .with_ptr_ok(|ptr| unsafe {
                ObjectRef::with_erased_ptr(ptr, |object| phlow_vtable.to_string(object))
            })
            .or_log(None)
            .unwrap_or_default()
    });
}

#[unsafe(no_mangle)]
pub extern "C" fn phlow_vtable_to_string_for_any_object(
    phlow_vtable: BorrowedPtr<PhlowVTable>,
    object: BorrowedPtr<AnySendObject>,
    string: BorrowedPtr<StringBox>,
) {
    vtable_to_string_for_object(phlow_vtable, string, |phlow_vtable| {
        object
            .with_ref_ok(|object| {
                ObjectRef::with_any(object.as_any(), |object| phlow_vtable.to_string(object))
            })
            .or_log(None)
            .unwrap_or_default()
    });
}

#[unsafe(no_mangle)]
pub extern "C" fn phlow_vtable_get_views_for_typed_object(
    phlow_vtable: BorrowedPtr<PhlowVTable>,
    object: ErasedBorrowedPtr,
) -> OwnedPtr<Vec<Box<dyn PhlowView>>> {
    vtable_get_views_for_object(phlow_vtable, |phlow_vtable| {
        object
            .with_ptr_ok(|ptr| unsafe {
                ObjectRef::with_erased_ptr(ptr, |object| phlow_vtable.views(object))
            })
            .or_log(Vec::new())
    })
}

#[unsafe(no_mangle)]
pub extern "C" fn phlow_vtable_get_views_for_any_object(
    phlow_vtable: BorrowedPtr<PhlowVTable>,
    object: BorrowedPtr<AnySendObject>,
) -> OwnedPtr<Vec<Box<dyn PhlowView>>> {
    vtable_get_views_for_object(phlow_vtable, |phlow_vtable| {
        object
            .with_ref_ok(|object| {
                ObjectRef::with_any(object.as_any(), |object| phlow_vtable.views(object))
            })
            .or_log(Vec::new())
    })
}

#[unsafe(no_mangle)]
pub extern "C" fn phlow_vtable_drop(phlow_vtable: OwnedPtr<PhlowVTable>) {
    drop(phlow_vtable);
}

fn vtable_to_string_for_object(
    phlow_vtable: BorrowedPtr<PhlowVTable>,
    mut string: BorrowedPtr<StringBox>,
    with_object: impl FnOnce(&PhlowVTable) -> String,
) {
    phlow_vtable
        .with_ref(|phlow_vtable| {
            let object_string = with_object(phlow_vtable);
            string.with_mut_ok(|string| string.set_string(object_string))
        })
        .log();
}

fn vtable_get_views_for_object(
    phlow_vtable: BorrowedPtr<PhlowVTable>,
    with_object: impl FnOnce(&PhlowVTable) -> Vec<Box<dyn PhlowView>>,
) -> OwnedPtr<Vec<Box<dyn PhlowView>>> {
    phlow_vtable
        .with_ref_ok(|phlow_vtable| OwnedPtr::new(with_object(phlow_vtable)))
        .or_log(OwnedPtr::null())
}