use std::{
borrow::Cow,
ops::{Deref, DerefMut},
};
use indexmap::IndexMap;
use mysql_async::{prelude::FromRow, Column, FromRowError, Row};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
pub struct StringValues(pub IndexMap<String, String>);
impl StringValues {
const NO_ESCAPE_BACKSLASH: bool = true;
}
impl FromRow for StringValues {
#[allow(clippy::needless_collect)]
fn from_row_opt(row: Row) -> Result<Self, FromRowError> {
let column_names_lossy = row
.columns_ref()
.iter()
.map(Column::name_str)
.map(Cow::into_owned)
.collect::<Vec<String>>();
let values = row
.unwrap()
.into_iter()
.map(|value| value.as_sql(Self::NO_ESCAPE_BACKSLASH))
.map(|value| {
value
.strip_prefix('\'')
.and_then(|value| value.strip_suffix('\''))
.map(str::to_string)
.unwrap_or(value)
});
let values = column_names_lossy
.into_iter()
.zip(values)
.collect::<IndexMap<String, String>>();
Ok(StringValues(values))
}
}
impl Deref for StringValues {
type Target = IndexMap<String, String>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for StringValues {
fn deref_mut(self: &mut StringValues) -> &mut Self::Target {
&mut self.0
}
}