Skip to content

impl Decode, Encode and Type for smart pointer types like Cow Β #3100

Open
@JoHaHu

Description

@JoHaHu

Currently this code doesn't work since Decode isn't implemented for Cow<T> but for Cow<str>.

This leads to the problem that I have to implement two different structs for the types if I don't want to clone the fields for every query (one using owned types to retrieve data and one using references to bind in query).
Cow<T> can be used in this case to allow treating a field like a pointer or like a owned value as needed.
The same is true for other smart pointer types like Arc and Rc.

#[derive(sqlx::FromRow, Clone)]
pub(super) struct A<'a> {
  pub(super) content: Cow<'a, MaybeBig>, 
  ...
}

Describe the solution you'd like

impl<DB, T> Type<DB> for Cow<'_, T>
where
  T: Type<DB>,
  DB: Database,
{
  fn type_info() -> DB::TypeInfo {
    T::type_info()
  }

  fn compatible(ty: &DB::TypeInfo) -> bool {
    T::compatible(ty)
  }
}

// Maybe this is unnecessary since smart pointers implement Deref for T
impl<'q, DB, T> Encode<'q, DB> for Cow<'q, T>
where
  T: Encode<'q, DB>,
  DB: Database,
{
 //  encode() omitted since it requires an additional ToOwned<Owned=T> bound on T 

  fn encode_by_ref(&self, buf: &mut <DB as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
    T::encode_by_ref(self, buf)
  }

  fn produces(&self) -> Option<DB::TypeInfo> {
    T::produces(self)
  }

  fn size_hint(&self) -> usize {
    T::size_hint(self)
  }
}

impl<'r, DB, T> Decode<'r, DB> for Cow<'static, T>
where
  T: Decode<'r, DB> + ToOwned<Owned = T>,
  DB: Database,
{
  fn decode(value: <DB as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
    T::decode(value).map(|t| t.to_owned()).map(Cow::Owned)
  }
}

Describe alternatives you've considered
I've considered using a extension trait for a short time, but couldn't get it done, because of dyn object safety.
And i believe this should be part of the library.

Another alternative is to have two different structs. One for querying (uses references) and one for retrieving (uses owned Types)

Create a wrapper around Cow from standard library that delegates to the inner and implement the trait on this wrapper.

If this seems useful to you I would like to start working on a PR for this.


This is related to #1904

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions