Skip to content
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

feat: impl Encode, Decode and Type for Cow<T> where T: Encode + Decode + Type #3102

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

JoHaHu
Copy link

@JoHaHu JoHaHu commented Mar 9, 2024

This allows to use Cow for every T that implements Encode, Decode, and Type.
The motivation for this is that I can use the same struct to decode and encode without having unnecessary copies of data. This is especially helpful in situations where you a have struct for all db tables, since then you would need clone the participating keys of each relation into those structs.

This allows to write this

pub(super) struct TableA<'a> {
  pub(super) id: Cow<'a, Uuid>,
  pub(super) content: Cow<'a, str>,
  ...
}

, instead of this.

// Cannot be used to receive data since decoding into a pointer is not possible, since the Uuid needs to live somewhere
pub(super) struct TableARef<'a> {
  pub(super) id:  &'a Uuid,
  pub(super) content: &'a str,
  ...
}

// Can be used to decode, but encoding requires cloning the data or taking ownership 
pub(super) struct TableA {
  pub(super) id:  Uuid,
  pub(super) content: String,
  ...
}

The implementation for Encode and Type will just delegate to the implementation of T.

The Decode trait is implemented by creating an owned Cow.
The owned variant is used here, because

  1. e.g. the query_as function has the bound for<'r> FromRow<'r, DB::Row>.
    This can only be implemented if the lifetime of the type is arbitrary/static, which necessitate the owned variant.
  2. the expansion of the query_as! won't work with an object with the same lifetime as the row, which also leads to the owned variant.

I believe that the current impl<'r, DB> Decode<'r, DB> for Cow<'r, str> is broken/ useless, but maybe i've miss the use case for the borrowed variant while decoding.

This implementation currently does not work with the derive macro for FromRow, because the macro implements
impl<'r, R> FromRow<'r, R> for TableA<'r> instead of impl<'r,'a, R> FromRow<'r, R> for TableA<'a>.
But manually implementing FromRow works.

fixed #3100

when the sqlx_macros_unstable cfg is activated path would have moved otherwise.
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

Successfully merging this pull request may close these issues.

impl Decode, Encode and Type for smart pointer types like Cow
1 participant