//! Provides [`Decode`] for decoding values from the database. use crate::database::{Database, HasValueRef}; use crate::error::BoxDynError; use crate::value::ValueRef; /// A type that can be decoded from the database. /// /// ## How can I implement `Decode`? /// /// A manual implementation of `Decode` can be useful when adding support for /// types externally to SQLx. /// /// The following showcases how to implement `Decode` to be generic over [`Database`]. The /// implementation can be marginally simpler if you remove the `DB` type parameter and explicitly /// use the concrete [`ValueRef`](HasValueRef::ValueRef) and [`TypeInfo`](Database::TypeInfo) types. /// /// ```rust /// # use sqlx_core::database::{Database, HasValueRef}; /// # use sqlx_core::decode::Decode; /// # use sqlx_core::types::Type; /// # use std::error::Error; /// # /// struct MyType; /// /// # impl Type for MyType { /// # fn type_info() -> DB::TypeInfo { todo!() } /// # } /// # /// # impl std::str::FromStr for MyType { /// # type Err = sqlx_core::error::Error; /// # fn from_str(s: &str) -> Result { todo!() } /// # } /// # /// // DB is the database driver /// // `'r` is the lifetime of the `Row` being decoded /// impl<'r, DB: Database> Decode<'r, DB> for MyType /// where /// // we want to delegate some of the work to string decoding so let's make sure strings /// // are supported by the database /// &'r str: Decode<'r, DB> /// { /// fn decode( /// value: >::ValueRef, /// ) -> Result> { /// // the interface of ValueRef is largely unstable at the moment /// // so this is not directly implementable /// /// // however, you can delegate to a type that matches the format of the type you want /// // to decode (such as a UTF-8 string) /// /// let value = <&str as Decode>::decode(value)?; /// /// // now you can parse this into your type (assuming there is a `FromStr`) /// /// Ok(value.parse()?) /// } /// } /// ``` pub trait Decode<'r, DB: Database>: Sized { /// Decode a new value of this type using a raw value from the database. fn decode(value: >::ValueRef) -> Result; } // implement `Decode` for Option for all SQL types impl<'r, DB, T> Decode<'r, DB> for Option where DB: Database, T: Decode<'r, DB>, { fn decode(value: >::ValueRef) -> Result { if value.is_null() { Ok(None) } else { Ok(Some(T::decode(value)?)) } } }