Repository: diesel-rs/diesel
File: diesel/src/deserialize.rs (Rust)

Code before:
    DB: Backend,
    T::Row: FromStaticSqlRow<ST, DB>,
{
    // This inline(always) attribute is here as benchmarks have shown
    // up to 5% reduction in instruction count of having it here
    //
    // A plain inline attribute does not show similar improvements
    #[inline(always)]
    fn build_from_row<'a>(row: &impl Row<'a, DB>) -> Result<Self> {
        let row = <T::Row as FromStaticSqlRow<ST, DB>>::build_from_row(row)?;
        T::build(row)
    }
}

impl<T, ST, DB> FromStaticSqlRow<ST, DB> for T
where
    DB: Backend,
    T: FromSql<ST, DB>,
    ST: SingleValue,
{
    fn build_from_row<'a>(row: &impl Row<'a, DB>) -> Result<Self> {
        use crate::row::Field;

        let field = row.get(0).ok_or(crate::result::UnexpectedEndOfRow)?;
        T::from_nullable_sql(field.value()).map_err(|e| {
            format!("Error for field '{}': {:?}", field.field_name().unwrap(), e).into()
        })
    }
}

// We cannot have this impl because rustc
// then complains in third party crates that
// diesel may implement `SingleValue` for tuples
// in the future. While that is theoretically true,
// that will likely not happen in practice.
// If we get negative trait impls at some point in time
// it should be possible to make this work.
/*impl<T, ST, DB> Queryable<ST, DB> for T
where
    DB: Backend,
    T: FromStaticSqlRow<ST, DB>,
    ST: SingleValue,
{
    type Row = Self;

    fn build(row: Self::Row) -> Self {
        row
    }
}*/

impl<T, ST, DB> StaticallySizedRow<ST, DB> for T

Review comment (suggestion):
Given that this might contain a completely user defined error (as `FromSql` can be implemented by third party crates for custom types) I wouldn't want to just convert that error to a string. Rather I would prefer having an error type that wraps the inner error. So something like 

```rust
// part of `src/result.rs

#[non_exhaustive]
pub struct DeserializeFieldError {
    // use an option to not require unwrapping
    pub field_name: Option<String>,
    pub error: Box<dyn Error + …>
}

impl Error for DeserializeFieldError {
 // … (forward the inner error as source)
}
```

Afterwards we can change this line to use the new error type instead. 



Code after:
    //
    // A plain inline attribute does not show similar improvements
    #[inline(always)]
    fn build_from_row<'a>(row: &impl Row<'a, DB>) -> Result<Self> {
        let row = <T::Row as FromStaticSqlRow<ST, DB>>::build_from_row(row)?;
        T::build(row)
    }
}

impl<T, ST, DB> FromStaticSqlRow<ST, DB> for T
where
    DB: Backend,
    T: FromSql<ST, DB>,
    ST: SingleValue,
{
    fn build_from_row<'a>(row: &impl Row<'a, DB>) -> Result<Self> {
        use crate::row::Field;

        let field = row.get(0).ok_or(crate::result::UnexpectedEndOfRow)?;
        T::from_nullable_sql(field.value()).map_err(|e| {
            if e.is::<crate::result::UnexpectedNullError>() {
                e
            } else {
                Box::new(crate::result::DeserializeFieldError::new(field, e))
            }
        })
    }
}

// We cannot have this impl because rustc
// then complains in third party crates that
// diesel may implement `SingleValue` for tuples
// in the future. While that is theoretically true,
// that will likely not happen in practice.
// If we get negative trait impls at some point in time
// it should be possible to make this work.
/*impl<T, ST, DB> Queryable<ST, DB> for T
where
    DB: Backend,
    T: FromStaticSqlRow<ST, DB>,
    ST: SingleValue,
{
    type Row = Self;

    fn build(row: Self::Row) -> Self {
        row
    }
}*/

impl<T, ST, DB> StaticallySizedRow<ST, DB> for T
where