Skip to content

Feature Request: Add owned version of SerializeAsWrap #827

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Leo1003 opened this issue Mar 18, 2025 · 1 comment
Open

Feature Request: Add owned version of SerializeAsWrap #827

Leo1003 opened this issue Mar 18, 2025 · 1 comment

Comments

@Leo1003
Copy link

Leo1003 commented Mar 18, 2025

SerializeAsWrap is a convenient adapter which provide Serialize implementation over SerializeAs.

However, SerializeAsWrap only store the reference to the data, which makes it not able to return data wrapped with specific SerializeAs impl.

Given an example actix-web api:

#[get("/data")]
pub async fn get_data() -> AppResult<impl Responder> {
    let data = get_data().await?;
    Ok(Json(data))
}

#[get("/data_detailed")]
pub async fn get_data_detailed() -> AppResult<impl Responder> {
    let data = get_data().await?;
    Ok(Json(SerializeAsWrap::<MyData, Detailed>::new(&data)))
}

The above code cannot be compiled since SerializeAsWrap doesn't owns the data.

By adding an owned version of SerializeAsWrap can resolve the above issues:

pub struct SerializeAsWrapOwned<T, U> {
    value: T,
    _phantom: std::marker::PhantomData<U>,
}

impl<T, U> SerializeAsWrapOwned<T, U> {
    pub fn new(value: T) -> Self {
        Self {
            value,
            _phantom: std::marker::PhantomData,
        }
    }

    pub fn into_inner(self) -> T {
        self.value
    }
}

impl<T, U> AsRef<T> for SerializeAsWrapOwned<T, U> {
    fn as_ref(&self) -> &T {
        &self.value
    }
}

impl<T, U> AsMut<T> for SerializeAsWrapOwned<T, U> {
    fn as_mut(&mut self) -> &mut T {
        &mut self.value
    }
}

impl<T, U> serde::Serialize for SerializeAsWrapOwned<T, U>
where
    U: serde_with::SerializeAs<T>,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        U::serialize_as(&self.value, serializer)
    }
}

impl<T, U> From<T> for SerializeAsWrapOwned<T, U> {
    fn from(value: T) -> Self {
        Self::new(value)
    }
}
@Leo1003 Leo1003 changed the title Add owned version of SerializeAsWrap Feature Request: Add owned version of SerializeAsWrap Mar 18, 2025
@jonasbb
Copy link
Owner

jonasbb commented Mar 18, 2025

This looks reasonable overall. The types were only intended to be used as helpers for implementing SerializeAs/DeserializeAs, but a small wrapper doesn't hurt. It does look similar to DeserializeAsWrap now.

I think it could cover the use case of SerializeAsWrap, but the type annotations might be a bit worse. In that case it might make sense to just have one wrapper and implement all the traits (serialization and deserialization) for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants