Macro ocaml::custom[][src]

macro_rules! custom {
    ($name:ident $(<$t:tt>)? $({$($k:ident : $v:expr),* $(,)? })?) => { ... };
    {name : $name:expr $(, fixed_length: $fl:expr)? $(, $($k:ident : $v:expr),*)? $(,)? } => { ... };
}

Create a custom OCaml type from an existing Rust type

See the struct custom_operations section in the OCaml manual for more information about each field

struct MyType {
    s: String,
    i: i32,
}

extern "C" fn mytype_finalizer(_: ocaml::Value) {
    println!("This runs when the value gets garbage collected");
}

extern "C" fn mytype_compare(a: ocaml::Value, b: ocaml::Value) -> i32 {
    let a: ocaml::Pointer::<MyType> = ocaml::FromValue::from_value(a);
    let b: ocaml::Pointer::<MyType> = ocaml::FromValue::from_value(b);

    let a_i = a.as_ref().i;
    let b_i = b.as_ref().i;

    if a_i == b_i {
        return 0
    }

    if a_i < b_i {
        return -1;
    }

    1
}

ocaml::custom!(MyType {
    finalize: mytype_finalizer,
    compare: mytype_compare,
});

// This is equivalent to
struct MyType2 {
    s: String,
    i: i32,
}

impl ocaml::Custom for MyType2 {
    const NAME: &'static str = "rust.MyType\0";

    const OPS: ocaml::custom::CustomOps = ocaml::custom::CustomOps {
        identifier: Self::NAME.as_ptr() as *mut ocaml::sys::Char,
        finalize: Some(mytype_finalizer),
        compare: Some(mytype_compare),
        .. ocaml::custom::DEFAULT_CUSTOM_OPS
    };
}

Additionally, custom can be used inside the impl block:

extern "C" fn implexample_finalizer(_: ocaml::Value) {
    println!("This runs when the value gets garbage collected");
}

struct ImplExample<'a>(&'a str);

impl<'a> ocaml::Custom for ImplExample<'a> {
    ocaml::custom! {
        name: "rust.ImplExample",
        finalize: implexample_finalizer
    }
}

// This is equivalent to:

struct ImplExample2<'a>(&'a str);

ocaml::custom!(ImplExample2<'a> {
    finalize: implexample_finalizer,
});