Optimize CBOR decoding (#3723)
This commit is contained in:
parent
da483716c5
commit
00bc9db496
1 changed files with 54 additions and 53 deletions
|
@ -1,7 +1,6 @@
|
||||||
use ciborium::Value as Data;
|
use ciborium::Value as Data;
|
||||||
use geo::{LineString, Point, Polygon};
|
use geo::{LineString, Point, Polygon};
|
||||||
use geo_types::{MultiLineString, MultiPoint, MultiPolygon};
|
use geo_types::{MultiLineString, MultiPoint, MultiPolygon};
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use surrealdb::sql::Datetime;
|
use surrealdb::sql::Datetime;
|
||||||
|
@ -94,36 +93,31 @@ impl TryFrom<Cbor> for Value {
|
||||||
Ok(v) => Ok(v.into()),
|
Ok(v) => Ok(v.into()),
|
||||||
_ => Err("Expected a valid RecordID value"),
|
_ => Err("Expected a valid RecordID value"),
|
||||||
},
|
},
|
||||||
Data::Array(mut v) if v.len() == 2 => match (v.remove(0), v.remove(0)) {
|
Data::Array(mut v) if v.len() == 2 => {
|
||||||
(Data::Text(tb), Data::Text(id)) => {
|
let tb = match Value::try_from(Cbor(v.remove(0))) {
|
||||||
Ok(Value::from(Thing::from((tb, id))))
|
Ok(Value::Strand(tb)) => tb.0,
|
||||||
}
|
Ok(Value::Table(tb)) => tb.0,
|
||||||
(Data::Text(tb), Data::Integer(id)) => {
|
_ => return Err(
|
||||||
Ok(Value::from(Thing::from((tb, Id::from(i128::from(id) as i64)))))
|
"Expected the tb of a Record Id to be a String or Table value",
|
||||||
}
|
|
||||||
(Data::Text(tb), Data::Array(id)) => Ok(Value::from(Thing::from((
|
|
||||||
tb,
|
|
||||||
Id::from(
|
|
||||||
id.into_iter()
|
|
||||||
.map(|v| Value::try_from(Cbor(v)))
|
|
||||||
.collect::<Result<Vec<Value>, &str>>()?,
|
|
||||||
),
|
),
|
||||||
)))),
|
};
|
||||||
(Data::Text(tb), Data::Map(id)) => Ok(Value::from(Thing::from((
|
|
||||||
tb,
|
match Value::try_from(Cbor(v.remove(0))) {
|
||||||
Id::from(
|
Ok(Value::Strand(id)) => {
|
||||||
id.into_iter()
|
Ok(Value::from(Thing::from((tb, Id::from(id)))))
|
||||||
.map(|(k, v)| {
|
}
|
||||||
let k =
|
Ok(Value::Number(Number::Int(id))) => {
|
||||||
Value::try_from(Cbor(k)).map(|k| k.as_raw_string());
|
Ok(Value::from(Thing::from((tb, Id::from(id)))))
|
||||||
let v = Value::try_from(Cbor(v));
|
}
|
||||||
Ok((k?, v?))
|
Ok(Value::Array(id)) => {
|
||||||
})
|
Ok(Value::from(Thing::from((tb, Id::from(id)))))
|
||||||
.collect::<Result<BTreeMap<String, Value>, &str>>()?,
|
}
|
||||||
),
|
Ok(Value::Object(id)) => {
|
||||||
)))),
|
Ok(Value::from(Thing::from((tb, Id::from(id)))))
|
||||||
_ => Err("Expected a CBOR array with 2 elements, a text data type, and a valid ID type"),
|
}
|
||||||
},
|
_ => Err("Expected the id of a Record Id to be a String, Integer, Array or Object value"),
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => Err("Expected a CBOR text data type, or a CBOR array with 2 elements"),
|
_ => Err("Expected a CBOR text data type, or a CBOR array with 2 elements"),
|
||||||
},
|
},
|
||||||
// A literal table
|
// A literal table
|
||||||
|
@ -131,18 +125,18 @@ impl TryFrom<Cbor> for Value {
|
||||||
Data::Text(v) => Ok(Value::Table(v.into())),
|
Data::Text(v) => Ok(Value::Table(v.into())),
|
||||||
_ => Err("Expected a CBOR text data type"),
|
_ => Err("Expected a CBOR text data type"),
|
||||||
},
|
},
|
||||||
TAG_GEOMETRY_POINT => match v.deref() {
|
TAG_GEOMETRY_POINT => match *v {
|
||||||
Data::Array(v) if v.len() == 2 => {
|
Data::Array(mut v) if v.len() == 2 => {
|
||||||
let x = Value::try_from(Cbor(v.clone().remove(0)))?;
|
let x = Value::try_from(Cbor(v.remove(0)))?;
|
||||||
let y = Value::try_from(Cbor(v.clone().remove(0)))?;
|
let y = Value::try_from(Cbor(v.remove(0)))?;
|
||||||
|
|
||||||
match (x, y) {
|
match (x, y) {
|
||||||
(Value::Number(x), Value::Number(y)) => {
|
(Value::Number(x), Value::Number(y)) => Ok(Value::Geometry(
|
||||||
Ok(Value::Geometry(Geometry::Point((x.as_float(), y.as_float()).into())))
|
Geometry::Point((x.as_float(), y.as_float()).into()),
|
||||||
},
|
)),
|
||||||
_ => Err("Expected a CBOR array with 2 decimal values"),
|
_ => Err("Expected a CBOR array with 2 decimal values"),
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => Err("Expected a CBOR array with 2 decimal values"),
|
_ => Err("Expected a CBOR array with 2 decimal values"),
|
||||||
},
|
},
|
||||||
TAG_GEOMETRY_LINE => match v.deref() {
|
TAG_GEOMETRY_LINE => match v.deref() {
|
||||||
|
@ -151,12 +145,12 @@ impl TryFrom<Cbor> for Value {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| match Value::try_from(Cbor(v.clone()))? {
|
.map(|v| match Value::try_from(Cbor(v.clone()))? {
|
||||||
Value::Geometry(Geometry::Point(v)) => Ok(v),
|
Value::Geometry(Geometry::Point(v)) => Ok(v),
|
||||||
_ => Err("Expected a CBOR array with Geometry Point values")
|
_ => Err("Expected a CBOR array with Geometry Point values"),
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<Point>, &str>>()?;
|
.collect::<Result<Vec<Point>, &str>>()?;
|
||||||
|
|
||||||
Ok(Value::Geometry(Geometry::Line(LineString::from(points))))
|
Ok(Value::Geometry(Geometry::Line(LineString::from(points))))
|
||||||
},
|
}
|
||||||
_ => Err("Expected a CBOR array with Geometry Point values"),
|
_ => Err("Expected a CBOR array with Geometry Point values"),
|
||||||
},
|
},
|
||||||
TAG_GEOMETRY_POLYGON => match v.deref() {
|
TAG_GEOMETRY_POLYGON => match v.deref() {
|
||||||
|
@ -165,17 +159,22 @@ impl TryFrom<Cbor> for Value {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| match Value::try_from(Cbor(v.clone()))? {
|
.map(|v| match Value::try_from(Cbor(v.clone()))? {
|
||||||
Value::Geometry(Geometry::Line(v)) => Ok(v),
|
Value::Geometry(Geometry::Line(v)) => Ok(v),
|
||||||
_ => Err("Expected a CBOR array with Geometry Line values")
|
_ => Err("Expected a CBOR array with Geometry Line values"),
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<LineString>, &str>>()?;
|
.collect::<Result<Vec<LineString>, &str>>()?;
|
||||||
|
|
||||||
let first = match lines.first() {
|
let first = match lines.first() {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
_ => return Err("Expected a CBOR array with at least two Geometry Line values")
|
_ => return Err(
|
||||||
|
"Expected a CBOR array with at least two Geometry Line values",
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Value::Geometry(Geometry::Polygon(Polygon::new(first.clone(), Vec::from(&lines[1..])))))
|
Ok(Value::Geometry(Geometry::Polygon(Polygon::new(
|
||||||
},
|
first.clone(),
|
||||||
|
Vec::from(&lines[1..]),
|
||||||
|
))))
|
||||||
|
}
|
||||||
_ => Err("Expected a CBOR array with at least two Geometry Line values"),
|
_ => Err("Expected a CBOR array with at least two Geometry Line values"),
|
||||||
},
|
},
|
||||||
TAG_GEOMETRY_MULTIPOINT => match v.deref() {
|
TAG_GEOMETRY_MULTIPOINT => match v.deref() {
|
||||||
|
@ -184,12 +183,12 @@ impl TryFrom<Cbor> for Value {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| match Value::try_from(Cbor(v.clone()))? {
|
.map(|v| match Value::try_from(Cbor(v.clone()))? {
|
||||||
Value::Geometry(Geometry::Point(v)) => Ok(v),
|
Value::Geometry(Geometry::Point(v)) => Ok(v),
|
||||||
_ => Err("Expected a CBOR array with Geometry Point values")
|
_ => Err("Expected a CBOR array with Geometry Point values"),
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<Point>, &str>>()?;
|
.collect::<Result<Vec<Point>, &str>>()?;
|
||||||
|
|
||||||
Ok(Value::Geometry(Geometry::MultiPoint(MultiPoint::from(points))))
|
Ok(Value::Geometry(Geometry::MultiPoint(MultiPoint::from(points))))
|
||||||
},
|
}
|
||||||
_ => Err("Expected a CBOR array with Geometry Point values"),
|
_ => Err("Expected a CBOR array with Geometry Point values"),
|
||||||
},
|
},
|
||||||
TAG_GEOMETRY_MULTILINE => match v.deref() {
|
TAG_GEOMETRY_MULTILINE => match v.deref() {
|
||||||
|
@ -198,12 +197,12 @@ impl TryFrom<Cbor> for Value {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| match Value::try_from(Cbor(v.clone()))? {
|
.map(|v| match Value::try_from(Cbor(v.clone()))? {
|
||||||
Value::Geometry(Geometry::Line(v)) => Ok(v),
|
Value::Geometry(Geometry::Line(v)) => Ok(v),
|
||||||
_ => Err("Expected a CBOR array with Geometry Line values")
|
_ => Err("Expected a CBOR array with Geometry Line values"),
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<LineString>, &str>>()?;
|
.collect::<Result<Vec<LineString>, &str>>()?;
|
||||||
|
|
||||||
Ok(Value::Geometry(Geometry::MultiLine(MultiLineString::new(lines))))
|
Ok(Value::Geometry(Geometry::MultiLine(MultiLineString::new(lines))))
|
||||||
},
|
}
|
||||||
_ => Err("Expected a CBOR array with Geometry Point values"),
|
_ => Err("Expected a CBOR array with Geometry Point values"),
|
||||||
},
|
},
|
||||||
TAG_GEOMETRY_MULTIPOLYGON => match v.deref() {
|
TAG_GEOMETRY_MULTIPOLYGON => match v.deref() {
|
||||||
|
@ -212,12 +211,14 @@ impl TryFrom<Cbor> for Value {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| match Value::try_from(Cbor(v.clone()))? {
|
.map(|v| match Value::try_from(Cbor(v.clone()))? {
|
||||||
Value::Geometry(Geometry::Polygon(v)) => Ok(v),
|
Value::Geometry(Geometry::Polygon(v)) => Ok(v),
|
||||||
_ => Err("Expected a CBOR array with Geometry Polygon values")
|
_ => Err("Expected a CBOR array with Geometry Polygon values"),
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<Polygon>, &str>>()?;
|
.collect::<Result<Vec<Polygon>, &str>>()?;
|
||||||
|
|
||||||
Ok(Value::Geometry(Geometry::MultiPolygon(MultiPolygon::from(polygons))))
|
Ok(Value::Geometry(Geometry::MultiPolygon(MultiPolygon::from(
|
||||||
},
|
polygons,
|
||||||
|
))))
|
||||||
|
}
|
||||||
_ => Err("Expected a CBOR array with Geometry Polygon values"),
|
_ => Err("Expected a CBOR array with Geometry Polygon values"),
|
||||||
},
|
},
|
||||||
TAG_GEOMETRY_COLLECTION => match v.deref() {
|
TAG_GEOMETRY_COLLECTION => match v.deref() {
|
||||||
|
@ -226,12 +227,12 @@ impl TryFrom<Cbor> for Value {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| match Value::try_from(Cbor(v.clone()))? {
|
.map(|v| match Value::try_from(Cbor(v.clone()))? {
|
||||||
Value::Geometry(v) => Ok(v),
|
Value::Geometry(v) => Ok(v),
|
||||||
_ => Err("Expected a CBOR array with Geometry values")
|
_ => Err("Expected a CBOR array with Geometry values"),
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<Geometry>, &str>>()?;
|
.collect::<Result<Vec<Geometry>, &str>>()?;
|
||||||
|
|
||||||
Ok(Value::Geometry(Geometry::Collection(geometries)))
|
Ok(Value::Geometry(Geometry::Collection(geometries)))
|
||||||
},
|
}
|
||||||
_ => Err("Expected a CBOR array with Geometry values"),
|
_ => Err("Expected a CBOR array with Geometry values"),
|
||||||
},
|
},
|
||||||
// An unknown tag
|
// An unknown tag
|
||||||
|
|
Loading…
Reference in a new issue