impl From<sql::Value> for serde_json::Value ()

This commit is contained in:
Rushmore Mushambi 2023-04-29 10:06:02 +02:00 committed by GitHub
parent 141eb091a6
commit 955aea9409
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 221 additions and 90 deletions
lib/src

View file

@ -16,6 +16,7 @@ use crate::sql::Value;
use dmp::Diff;
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json::json;
use serde_json::Map;
use serde_json::Value as JsonValue;
@ -140,38 +141,162 @@ impl PatchOp {
}
}
fn into_json(value: Value) -> serde_json::Result<JsonValue> {
impl From<Value> for serde_json::Value {
fn from(value: Value) -> Self {
into_json(value, true)
}
}
fn into_json(value: Value, simplify: bool) -> JsonValue {
use crate::sql;
use crate::sql::Number;
use serde_json::Error;
#[derive(Serialize)]
struct Array(Vec<JsonValue>);
impl TryFrom<sql::Array> for Array {
type Error = Error;
fn try_from(arr: sql::Array) -> Result<Self, Self::Error> {
impl From<(sql::Array, bool)> for Array {
fn from((arr, simplify): (sql::Array, bool)) -> Self {
let mut vec = Vec::with_capacity(arr.0.len());
for value in arr.0 {
vec.push(into_json(value)?);
vec.push(into_json(value, simplify));
}
Ok(Self(vec))
Self(vec)
}
}
#[derive(Serialize)]
struct Object(Map<String, JsonValue>);
impl TryFrom<sql::Object> for Object {
type Error = Error;
fn try_from(obj: sql::Object) -> Result<Self, Self::Error> {
impl From<(sql::Object, bool)> for Object {
fn from((obj, simplify): (sql::Object, bool)) -> Self {
let mut map = Map::with_capacity(obj.0.len());
for (key, value) in obj.0 {
map.insert(key.to_owned(), into_json(value)?);
map.insert(key.to_owned(), into_json(value, simplify));
}
Ok(Self(map))
Self(map)
}
}
#[derive(Serialize)]
enum CoordinatesType {
Point,
LineString,
Polygon,
MultiPoint,
MultiLineString,
MultiPolygon,
}
#[derive(Serialize)]
struct Coordinates {
#[serde(rename = "type")]
typ: CoordinatesType,
coordinates: JsonValue,
}
#[derive(Serialize)]
struct GeometryCollection;
#[derive(Serialize)]
struct Geometries {
#[serde(rename = "type")]
typ: GeometryCollection,
geometries: Vec<JsonValue>,
}
#[derive(Serialize)]
struct Geometry(JsonValue);
impl From<sql::Geometry> for Geometry {
fn from(geo: sql::Geometry) -> Self {
Self(match geo {
sql::Geometry::Point(v) => json!(Coordinates {
typ: CoordinatesType::Point,
coordinates: vec![json!(v.x()), json!(v.y())].into(),
}),
sql::Geometry::Line(v) => json!(Coordinates {
typ: CoordinatesType::LineString,
coordinates: v
.points()
.map(|p| vec![json!(p.x()), json!(p.y())].into())
.collect::<Vec<JsonValue>>()
.into(),
}),
sql::Geometry::Polygon(v) => json!(Coordinates {
typ: CoordinatesType::Polygon,
coordinates: vec![v
.exterior()
.points()
.map(|p| vec![json!(p.x()), json!(p.y())].into())
.collect::<Vec<JsonValue>>()]
.into_iter()
.chain(
v.interiors()
.iter()
.map(|i| {
i.points()
.map(|p| vec![json!(p.x()), json!(p.y())].into())
.collect::<Vec<JsonValue>>()
})
.collect::<Vec<Vec<JsonValue>>>(),
)
.collect::<Vec<Vec<JsonValue>>>()
.into(),
}),
sql::Geometry::MultiPoint(v) => json!(Coordinates {
typ: CoordinatesType::MultiPoint,
coordinates: v
.0
.iter()
.map(|v| vec![json!(v.x()), json!(v.y())].into())
.collect::<Vec<JsonValue>>()
.into()
}),
sql::Geometry::MultiLine(v) => json!(Coordinates {
typ: CoordinatesType::MultiLineString,
coordinates: v
.0
.iter()
.map(|v| {
v.points()
.map(|v| vec![json!(v.x()), json!(v.y())].into())
.collect::<Vec<JsonValue>>()
})
.collect::<Vec<Vec<JsonValue>>>()
.into()
}),
sql::Geometry::MultiPolygon(v) => json!(Coordinates {
typ: CoordinatesType::MultiPolygon,
coordinates: v
.0
.iter()
.map(|v| {
vec![v
.exterior()
.points()
.map(|p| vec![json!(p.x()), json!(p.y())].into())
.collect::<Vec<JsonValue>>()]
.into_iter()
.chain(
v.interiors()
.iter()
.map(|i| {
i.points()
.map(|p| vec![json!(p.x()), json!(p.y())].into())
.collect::<Vec<JsonValue>>()
})
.collect::<Vec<Vec<JsonValue>>>(),
)
.collect::<Vec<Vec<JsonValue>>>()
})
.collect::<Vec<Vec<Vec<JsonValue>>>>()
.into(),
}),
sql::Geometry::Collection(v) => json!(Geometries {
typ: GeometryCollection,
geometries: v.into_iter().map(Geometry::from).map(|x| x.0).collect(),
}),
})
}
}
@ -183,17 +308,14 @@ fn into_json(value: Value) -> serde_json::Result<JsonValue> {
Object(Object),
}
impl TryFrom<sql::Id> for Id {
type Error = Error;
fn try_from(id: sql::Id) -> Result<Self, Self::Error> {
use sql::Id::*;
Ok(match id {
Number(n) => Id::Number(n),
String(s) => Id::String(s),
Array(arr) => Id::Array(arr.try_into()?),
Object(obj) => Id::Object(obj.try_into()?),
})
impl From<(sql::Id, bool)> for Id {
fn from((id, simplify): (sql::Id, bool)) -> Self {
match id {
sql::Id::Number(n) => Id::Number(n),
sql::Id::String(s) => Id::String(s),
sql::Id::Array(arr) => Id::Array((arr, simplify).into()),
sql::Id::Object(obj) => Id::Object((obj, simplify).into()),
}
}
}
@ -203,46 +325,59 @@ fn into_json(value: Value) -> serde_json::Result<JsonValue> {
id: Id,
}
impl TryFrom<sql::Thing> for Thing {
type Error = Error;
fn try_from(thing: sql::Thing) -> Result<Self, Self::Error> {
Ok(Self {
impl From<(sql::Thing, bool)> for Thing {
fn from((thing, simplify): (sql::Thing, bool)) -> Self {
Self {
tb: thing.tb,
id: thing.id.try_into()?,
})
id: (thing.id, simplify).into(),
}
}
}
match value {
Value::None | Value::Null => Ok(JsonValue::Null),
Value::False => Ok(false.into()),
Value::True => Ok(true.into()),
Value::Number(Number::Int(n)) => Ok(n.into()),
Value::Number(Number::Float(n)) => Ok(n.into()),
Value::Number(Number::Decimal(n)) => serde_json::to_value(n),
Value::Strand(strand) => Ok(strand.0.into()),
Value::Duration(d) => serde_json::to_value(d),
Value::Datetime(d) => serde_json::to_value(d),
Value::Uuid(uuid) => serde_json::to_value(uuid),
Value::Array(arr) => Ok(JsonValue::Array(Array::try_from(arr)?.0)),
Value::Object(obj) => Ok(JsonValue::Object(Object::try_from(obj)?.0)),
Value::Geometry(geometry) => serde_json::to_value(geometry),
Value::Bytes(bytes) => serde_json::to_value(bytes),
Value::Param(param) => serde_json::to_value(param),
Value::Idiom(idiom) => serde_json::to_value(idiom),
Value::Table(table) => serde_json::to_value(table),
Value::Thing(thing) => serde_json::to_value(thing),
Value::Model(model) => serde_json::to_value(model),
Value::Regex(regex) => serde_json::to_value(regex),
Value::Block(block) => serde_json::to_value(block),
Value::Range(range) => serde_json::to_value(range),
Value::Edges(edges) => serde_json::to_value(edges),
Value::Future(future) => serde_json::to_value(future),
Value::Constant(constant) => serde_json::to_value(constant),
Value::Function(function) => serde_json::to_value(function),
Value::Subquery(subquery) => serde_json::to_value(subquery),
Value::Expression(expression) => serde_json::to_value(expression),
Value::None | Value::Null => JsonValue::Null,
Value::False => false.into(),
Value::True => true.into(),
Value::Number(Number::Int(n)) => n.into(),
Value::Number(Number::Float(n)) => n.into(),
Value::Number(Number::Decimal(n)) => json!(n),
Value::Strand(strand) => match simplify {
true => strand.0.into(),
false => json!(strand),
},
Value::Duration(d) => match simplify {
true => d.to_string().into(),
false => json!(d),
},
Value::Datetime(d) => json!(d),
Value::Uuid(uuid) => json!(uuid),
Value::Array(arr) => JsonValue::Array(Array::from((arr, simplify)).0),
Value::Object(obj) => JsonValue::Object(Object::from((obj, simplify)).0),
Value::Geometry(geo) => match simplify {
true => Geometry::from(geo).0,
false => json!(geo),
},
Value::Bytes(bytes) => json!(bytes),
Value::Param(param) => json!(param),
Value::Idiom(idiom) => json!(idiom),
Value::Table(table) => json!(table),
Value::Thing(thing) => match simplify {
true => thing.to_string().into(),
false => json!(thing),
},
Value::Model(model) => json!(model),
Value::Regex(regex) => json!(regex),
Value::Block(block) => json!(block),
Value::Range(range) => json!(range),
Value::Edges(edges) => json!(edges),
Value::Future(future) => json!(future),
Value::Constant(constant) => match simplify {
true => constant.as_f64().into(),
false => json!(constant),
},
Value::Function(function) => json!(function),
Value::Subquery(subquery) => json!(subquery),
Value::Expression(expression) => json!(expression),
}
}
@ -251,15 +386,7 @@ pub(crate) fn from_value<T>(value: Value) -> Result<T, Error>
where
T: DeserializeOwned,
{
let json = match serialize_internal(|| into_json(value.clone())) {
Ok(json) => json,
Err(error) => {
return Err(Error::FromValue {
value,
error: error.to_string(),
})
}
};
let json = serialize_internal(|| into_json(value.clone(), false));
serde_json::from_value(json).map_err(|error| Error::FromValue {
value,
error: error.to_string(),

View file

@ -39,6 +39,30 @@ pub enum Constant {
}
impl Constant {
pub(crate) fn as_f64(&self) -> f64 {
match self {
Self::MathE => std::f64::consts::E,
Self::MathFrac1Pi => std::f64::consts::FRAC_1_PI,
Self::MathFrac1Sqrt2 => std::f64::consts::FRAC_1_SQRT_2,
Self::MathFrac2Pi => std::f64::consts::FRAC_2_PI,
Self::MathFrac2SqrtPi => std::f64::consts::FRAC_2_SQRT_PI,
Self::MathFracPi2 => std::f64::consts::FRAC_PI_2,
Self::MathFracPi3 => std::f64::consts::FRAC_PI_3,
Self::MathFracPi4 => std::f64::consts::FRAC_PI_4,
Self::MathFracPi6 => std::f64::consts::FRAC_PI_6,
Self::MathFracPi8 => std::f64::consts::FRAC_PI_8,
Self::MathLn10 => std::f64::consts::LN_10,
Self::MathLn2 => std::f64::consts::LN_2,
Self::MathLog102 => std::f64::consts::LOG10_2,
Self::MathLog10E => std::f64::consts::LOG10_E,
Self::MathLog210 => std::f64::consts::LOG2_10,
Self::MathLog2E => std::f64::consts::LOG2_E,
Self::MathPi => std::f64::consts::PI,
Self::MathSqrt2 => std::f64::consts::SQRT_2,
Self::MathTau => std::f64::consts::TAU,
}
}
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
@ -46,27 +70,7 @@ impl Constant {
_txn: &Transaction,
_doc: Option<&Value>,
) -> Result<Value, Error> {
Ok(match self {
Self::MathE => std::f64::consts::E.into(),
Self::MathFrac1Pi => std::f64::consts::FRAC_1_PI.into(),
Self::MathFrac1Sqrt2 => std::f64::consts::FRAC_1_SQRT_2.into(),
Self::MathFrac2Pi => std::f64::consts::FRAC_2_PI.into(),
Self::MathFrac2SqrtPi => std::f64::consts::FRAC_2_SQRT_PI.into(),
Self::MathFracPi2 => std::f64::consts::FRAC_PI_2.into(),
Self::MathFracPi3 => std::f64::consts::FRAC_PI_3.into(),
Self::MathFracPi4 => std::f64::consts::FRAC_PI_4.into(),
Self::MathFracPi6 => std::f64::consts::FRAC_PI_6.into(),
Self::MathFracPi8 => std::f64::consts::FRAC_PI_8.into(),
Self::MathLn10 => std::f64::consts::LN_10.into(),
Self::MathLn2 => std::f64::consts::LN_2.into(),
Self::MathLog102 => std::f64::consts::LOG10_2.into(),
Self::MathLog10E => std::f64::consts::LOG10_E.into(),
Self::MathLog210 => std::f64::consts::LOG2_10.into(),
Self::MathLog2E => std::f64::consts::LOG2_E.into(),
Self::MathPi => std::f64::consts::PI.into(),
Self::MathSqrt2 => std::f64::consts::SQRT_2.into(),
Self::MathTau => std::f64::consts::TAU.into(),
})
Ok(self.as_f64().into())
}
}