uniffi-rs icon indicating copy to clipboard operation
uniffi-rs copied to clipboard

`uniffi::custom_type!` should have `try_lower` instead of just `lower`

Open kriswuollett opened this issue 8 months ago • 2 comments

A possible common use case could be serializing a complex value instead of using Uniffi for everything like a structured record like a JSON type. For example I'd expect to be able to have a failure when lowering:

#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
pub struct Metadata(serde_json::Value);

uniffi::custom_type!(Metadata, String, {
    try_lower: |s| serde_json::to_string(&s).context("Metadata serialization failed"),
    try_lift: |s| serde_json::from_str(&s).context("Metadata deserialization failed"),
});

I assumed that was possible, but found out only lower that doesn't return an error is available. A generic structure like a serde_json::Value may be invalid if non-string keys are used:

/// Serialize the given data structure as a String of JSON.
///
/// # Errors
///
/// Serialization can fail if `T`'s implementation of `Serialize` decides to
/// fail, or if `T` contains a map with non-string keys.
#[inline]
pub fn to_string<T>(value: &T) -> Result<String>
where
    T: ?Sized + Serialize,
{
    let vec = tri!(to_vec(value));
    let string = unsafe {
        // We do not emit invalid UTF-8.
        String::from_utf8_unchecked(vec)
    };
    Ok(string)
}

kriswuollett avatar Feb 03 '25 16:02 kriswuollett