serde-rs / serde

Serialization framework for Rust
https://serde.rs/
Apache License 2.0
8.82k stars 748 forks source link

Is there plans for allowing async custom serialize function implementations using traits? #2690

Open alexipeck opened 5 months ago

alexipeck commented 5 months ago

I ask this on the tail end of async functions in traits being stabilized.

For context, with tokio::sync::RwLock wrapping a type, I would need the following as a custom serializer for a struct field:

mod arc_rwlock_serde {
    use serde::ser::Serializer;
    use serde::Serialize;
    use std::sync::Arc;
    use tokio::sync::RwLock;

    pub async fn serialize<S, T>(val: &Arc<RwLock<T>>, s: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
        T: Serialize,
    {
        T::serialize(&*val.read().await, s)
    }
}

#[derive(Debug, Clone, Serialize)]
#[serde(bound(serialize = "T: Serialize"))]
pub struct State<T: Clone + Serialize> {
    #[serde(with = "arc_rwlock_serde")]
    pub state: Arc<RwLock<HashMap<Uuid, T>>>,
}

Previously using a sync locking library like parking_lot, I had the following (as you can see, not much changed except for the await and library change):

mod arc_rwlock_serde {
    use serde::ser::Serializer;
    use serde::Serialize;
    use std::sync::Arc;
    use parking_lot::RwLock;

    pub async fn serialize<S, T>(val: &Arc<RwLock<T>>, s: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
        T: Serialize,
    {
        T::serialize(&*val.read(), s)
    }
}

Part of my problem is I can't even do a custom serializer without doing everything manually for the struct as there is currently no support for an async function.

oli-obk commented 5 months ago

This is not possible unless we get an async effect system, which is years off if we'll get it at all.

The workaround for these cases is to write into a buffer and then serialize from the buffer asynchronously.

In your case that is deeply nested, you probably need to use block_on