Add json_from_sql and json_to_sql macros
This commit is contained in:
parent
536c7ecb21
commit
a9504de10d
6 changed files with 51 additions and 38 deletions
|
@ -184,7 +184,7 @@ pub fn get_local_actor(
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
let properties = user.profile.extra_fields.clone()
|
let properties = user.profile.extra_fields.clone()
|
||||||
.unpack().into_iter()
|
.into_inner().into_iter()
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
ActorProperty {
|
ActorProperty {
|
||||||
object_type: PROPERTY_VALUE.to_string(),
|
object_type: PROPERTY_VALUE.to_string(),
|
||||||
|
|
|
@ -19,7 +19,8 @@ macro_rules! int_enum_to_sql {
|
||||||
($t:ty) => {
|
($t:ty) => {
|
||||||
impl postgres_types::ToSql for $t {
|
impl postgres_types::ToSql for $t {
|
||||||
fn to_sql(
|
fn to_sql(
|
||||||
&self, _: &postgres_types::Type,
|
&self,
|
||||||
|
_: &postgres_types::Type,
|
||||||
out: &mut postgres_types::private::BytesMut,
|
out: &mut postgres_types::private::BytesMut,
|
||||||
) -> Result<postgres_types::IsNull, Box<dyn std::error::Error + Sync + Send>> {
|
) -> Result<postgres_types::IsNull, Box<dyn std::error::Error + Sync + Send>> {
|
||||||
let int_value: i16 = self.into();
|
let int_value: i16 = self.into();
|
||||||
|
|
39
src/database/json_macro.rs
Normal file
39
src/database/json_macro.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/// Implements FromSql trait for any de-serializable type
|
||||||
|
macro_rules! json_from_sql {
|
||||||
|
($t:ty) => {
|
||||||
|
impl<'a> postgres_types::FromSql<'a> for $t {
|
||||||
|
fn from_sql(
|
||||||
|
ty: &postgres_types::Type,
|
||||||
|
raw: &'a [u8],
|
||||||
|
) -> Result<$t, Box<dyn std::error::Error + Sync + Send>> {
|
||||||
|
let postgres_types::Json(json_value) =
|
||||||
|
postgres_types::Json::<serde_json::Value>::from_sql(ty, raw)?;
|
||||||
|
let value: $t = serde_json::from_value(json_value)?;
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
postgres_types::accepts!(JSON, JSONB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implements ToSql trait for any serializable type
|
||||||
|
macro_rules! json_to_sql {
|
||||||
|
($t:ty) => {
|
||||||
|
impl postgres_types::ToSql for $t {
|
||||||
|
fn to_sql(
|
||||||
|
&self,
|
||||||
|
ty: &postgres_types::Type,
|
||||||
|
out: &mut postgres_types::private::BytesMut,
|
||||||
|
) -> Result<postgres_types::IsNull, Box<dyn std::error::Error + Sync + Send>> {
|
||||||
|
let value = serde_json::to_value(self)?;
|
||||||
|
postgres_types::Json(value).to_sql(ty, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
postgres_types::accepts!(JSON, JSONB);
|
||||||
|
postgres_types::to_sql_checked!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use {json_from_sql, json_to_sql};
|
|
@ -3,6 +3,7 @@ use tokio_postgres::error::{Error as PgError, SqlState};
|
||||||
use crate::errors::DatabaseError;
|
use crate::errors::DatabaseError;
|
||||||
|
|
||||||
pub mod int_enum;
|
pub mod int_enum;
|
||||||
|
pub mod json_macro;
|
||||||
pub mod migrate;
|
pub mod migrate;
|
||||||
pub mod query_macro;
|
pub mod query_macro;
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ impl Account {
|
||||||
.map(|name| get_file_url(instance_url, name));
|
.map(|name| get_file_url(instance_url, name));
|
||||||
let header_url = profile.banner_file_name.as_ref()
|
let header_url = profile.banner_file_name.as_ref()
|
||||||
.map(|name| get_file_url(instance_url, name));
|
.map(|name| get_file_url(instance_url, name));
|
||||||
let fields = profile.extra_fields.unpack().into_iter()
|
let fields = profile.extra_fields.into_inner().into_iter()
|
||||||
.map(|field| AccountField { name: field.name, value: field.value })
|
.map(|field| AccountField { name: field.name, value: field.value })
|
||||||
.collect();
|
.collect();
|
||||||
Self {
|
Self {
|
||||||
|
@ -83,7 +83,7 @@ impl Account {
|
||||||
|
|
||||||
pub fn from_user(user: User, instance_url: &str) -> Self {
|
pub fn from_user(user: User, instance_url: &str) -> Self {
|
||||||
let fields_sources = user.profile.extra_fields.clone()
|
let fields_sources = user.profile.extra_fields.clone()
|
||||||
.unpack().into_iter()
|
.into_inner().into_iter()
|
||||||
.map(|field| AccountField {
|
.map(|field| AccountField {
|
||||||
name: field.name,
|
name: field.name,
|
||||||
value: field.value_source.unwrap_or(field.value),
|
value: field.value_source.unwrap_or(field.value),
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use postgres_types::{
|
use postgres_types::FromSql;
|
||||||
FromSql, ToSql, IsNull, Type, Json,
|
|
||||||
accepts, to_sql_checked,
|
|
||||||
private::BytesMut,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::activitypub::actor::Actor;
|
use crate::activitypub::actor::Actor;
|
||||||
use crate::activitypub::views::get_actor_url;
|
use crate::activitypub::views::get_actor_url;
|
||||||
|
use crate::database::json_macro::{json_from_sql, json_to_sql};
|
||||||
use crate::errors::ValidationError;
|
use crate::errors::ValidationError;
|
||||||
use super::validators::{
|
use super::validators::{
|
||||||
validate_username,
|
validate_username,
|
||||||
|
@ -29,7 +26,7 @@ pub struct ExtraField {
|
||||||
pub struct ExtraFields(pub Vec<ExtraField>);
|
pub struct ExtraFields(pub Vec<ExtraField>);
|
||||||
|
|
||||||
impl ExtraFields {
|
impl ExtraFields {
|
||||||
pub fn unpack(self) -> Vec<ExtraField> {
|
pub fn into_inner(self) -> Vec<ExtraField> {
|
||||||
let Self(extra_fields) = self;
|
let Self(extra_fields) = self;
|
||||||
extra_fields
|
extra_fields
|
||||||
}
|
}
|
||||||
|
@ -39,35 +36,10 @@ pub fn get_currency_field_name(currency_code: &str) -> String {
|
||||||
format!("${}", currency_code.to_uppercase())
|
format!("${}", currency_code.to_uppercase())
|
||||||
}
|
}
|
||||||
|
|
||||||
type SqlError = Box<dyn std::error::Error + Sync + Send>;
|
json_from_sql!(ExtraFields);
|
||||||
|
json_to_sql!(ExtraFields);
|
||||||
|
|
||||||
impl<'a> FromSql<'a> for ExtraFields {
|
json_from_sql!(Actor);
|
||||||
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, SqlError> {
|
|
||||||
let Json(json_value) = Json::<Value>::from_sql(ty, raw)?;
|
|
||||||
let fields: Self = serde_json::from_value(json_value)?;
|
|
||||||
Ok(fields)
|
|
||||||
}
|
|
||||||
accepts!(JSON, JSONB);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToSql for ExtraFields {
|
|
||||||
fn to_sql(&self, ty: &Type, out: &mut BytesMut) -> Result<IsNull, SqlError> {
|
|
||||||
let value = serde_json::to_value(self)?;
|
|
||||||
Json(value).to_sql(ty, out)
|
|
||||||
}
|
|
||||||
|
|
||||||
accepts!(JSON, JSONB);
|
|
||||||
to_sql_checked!();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> FromSql<'a> for Actor {
|
|
||||||
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, SqlError> {
|
|
||||||
let Json(json_value) = Json::<Value>::from_sql(ty, raw)?;
|
|
||||||
let actor: Self = serde_json::from_value(json_value)?;
|
|
||||||
Ok(actor)
|
|
||||||
}
|
|
||||||
accepts!(JSON, JSONB);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, FromSql)]
|
#[derive(Clone, FromSql)]
|
||||||
#[postgres(name = "actor_profile")]
|
#[postgres(name = "actor_profile")]
|
||||||
|
|
Loading…
Reference in a new issue