Skip to content

Commit

Permalink
feat: serde support for a basic structs (#344)
Browse files Browse the repository at this point in the history
* feat: serde support for a basic structs

* cleanup
  • Loading branch information
QuantumExplorer authored Oct 4, 2024
1 parent 208b382 commit 7f900ea
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 29 deletions.
2 changes: 2 additions & 0 deletions grovedb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ tokio-util = { version = "0.7.12", optional = true }
tokio = { version = "1.40.0", features = ["rt-multi-thread", "net"], optional = true }
tower-http = { version = "0.5.2", features = ["fs"], optional = true }
zip-extensions = { version ="0.6.2", optional = true }
serde = { version = "1.0.210", features = ["derive"], optional = true }

[dev-dependencies]
grovedb-epoch-based-storage-flags = { version = "2.1.0", path = "../grovedb-epoch-based-storage-flags" }
Expand All @@ -52,6 +53,7 @@ harness = false
[features]
default = ["full"]
proof_debug = ["grovedb-merk/proof_debug"]
serde = ["dep:serde", "grovedb-merk/serde", "indexmap/serde"]
full = [
"grovedb-merk/full",
"thiserror",
Expand Down
3 changes: 2 additions & 1 deletion grovedb/src/debugger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ where
let now = Instant::now();
let mut lock = state.sessions.write().await;
let to_delete: Vec<SessionId> = lock.iter().filter_map(
|(id, session)| (session.last_access < now - SESSION_TIMEOUT).then_some(*id)
|(id, session)|
(session.last_access < now - SESSION_TIMEOUT).then_some(*id)
).collect();

to_delete.into_iter().for_each(|id| { lock.remove(&id); });
Expand Down
1 change: 1 addition & 0 deletions grovedb/src/element/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ pub type SumValue = i64;
/// of how serialization works.
#[derive(Clone, Encode, Decode, PartialEq, Eq, Hash)]
#[cfg_attr(not(any(feature = "full", feature = "visualize")), derive(Debug))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Element {
/// An ordinary value
Item(Vec<u8>, Option<ElementFlags>),
Expand Down
2 changes: 2 additions & 0 deletions grovedb/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::Error;

#[cfg(any(feature = "full", feature = "verify"))]
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// Path query
///
/// Represents a path to a specific GroveDB tree and a corresponding query to
Expand Down Expand Up @@ -50,6 +51,7 @@ impl fmt::Display for PathQuery {

#[cfg(any(feature = "full", feature = "verify"))]
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// Holds a query to apply to a tree and an optional limit/offset value.
/// Limit and offset values affect the size of the result set.
pub struct SizedQuery {
Expand Down
29 changes: 1 addition & 28 deletions grovedb/src/reference_path.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,3 @@
// MIT LICENSE
//
// Copyright (c) 2021 Dash Core Group
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the
// Software without restriction, including without
// limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//! Space efficient methods for referencing other elements in GroveDB

#[cfg(any(feature = "full", feature = "verify"))]
Expand All @@ -42,6 +14,7 @@ use crate::Error;

#[cfg(any(feature = "full", feature = "verify"))]
#[cfg_attr(not(any(feature = "full", feature = "visualize")), derive(Debug))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// Reference path variants
#[derive(Hash, Eq, PartialEq, Encode, Decode, Clone)]
pub enum ReferencePathType {
Expand Down
2 changes: 2 additions & 0 deletions merk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ hex = "0.4.3"
indexmap = "2.2.6"
integer-encoding = "4.0.0"
thiserror = "1.0.58"
serde = { version = "1.0.210", features = ["derive"], optional = true }

[dependencies.time]
version = "0.3.34"
Expand Down Expand Up @@ -56,6 +57,7 @@ optional = true
[features]
default = ["full"]
proof_debug = []
serde = ["dep:serde", "indexmap/serde"]
full = ["rand",
"time",
"colored",
Expand Down
2 changes: 2 additions & 0 deletions merk/src/proofs/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub type PathKey = (Path, Key);

#[cfg(any(feature = "full", feature = "verify"))]
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// Subquery branch
pub struct SubqueryBranch {
/// Subquery path
Expand Down Expand Up @@ -111,6 +112,7 @@ impl SubqueryBranch {
/// `Query` represents one or more keys or ranges of keys, which can be used to
/// resolve a proof which will include all the requested values.
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Query {
/// Items
pub items: Vec<QueryItem>,
Expand Down
147 changes: 147 additions & 0 deletions merk/src/proofs/query/query_item/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ use bincode::{enc::write::Writer, error::DecodeError, BorrowDecode, Decode, Enco
use grovedb_costs::{CostContext, CostsExt, OperationCost};
#[cfg(feature = "full")]
use grovedb_storage::RawIterator;
#[cfg(feature = "serde")]
use serde::de::VariantAccess;
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};

#[cfg(any(feature = "full", feature = "verify"))]
use crate::error::Error;
Expand All @@ -36,6 +40,149 @@ pub enum QueryItem {
RangeAfterToInclusive(RangeInclusive<Vec<u8>>),
}

#[cfg(feature = "serde")]
impl Serialize for QueryItem {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
QueryItem::Key(key) => serializer.serialize_newtype_variant("QueryItem", 0, "Key", key),
QueryItem::Range(range) => {
serializer.serialize_newtype_variant("QueryItem", 1, "Range", &range)
}
QueryItem::RangeInclusive(range) => {
serializer.serialize_newtype_variant("QueryItem", 2, "RangeInclusive", range)
}
QueryItem::RangeFull(_) => {
serializer.serialize_unit_variant("QueryItem", 3, "RangeFull")
}
QueryItem::RangeFrom(range_from) => {
serializer.serialize_newtype_variant("QueryItem", 4, "RangeFrom", range_from)
}
QueryItem::RangeTo(range_to) => {
serializer.serialize_newtype_variant("QueryItem", 5, "RangeTo", range_to)
}
QueryItem::RangeToInclusive(range_to_inclusive) => serializer
.serialize_newtype_variant(
"QueryItem",
6,
"RangeToInclusive",
&range_to_inclusive.end,
),
QueryItem::RangeAfter(range_after) => {
serializer.serialize_newtype_variant("QueryItem", 7, "RangeAfter", range_after)
}
QueryItem::RangeAfterTo(range_after_to) => {
serializer.serialize_newtype_variant("QueryItem", 8, "RangeAfterTo", range_after_to)
}
QueryItem::RangeAfterToInclusive(range_after_to_inclusive) => serializer
.serialize_newtype_variant(
"QueryItem",
9,
"RangeAfterToInclusive",
range_after_to_inclusive,
),
}
}
}

#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for QueryItem {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(field_identifier, rename_all = "snake_case")]
enum Field {
Key,
Range,
RangeInclusive,
RangeFull,
RangeFrom,
RangeTo,
RangeToInclusive,
RangeAfter,
RangeAfterTo,
RangeAfterToInclusive,
}

struct QueryItemVisitor;

impl<'de> serde::de::Visitor<'de> for QueryItemVisitor {
type Value = QueryItem;

fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("enum QueryItem")
}

fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: serde::de::EnumAccess<'de>,
{
let (variant, variant_access) = data.variant()?;

match variant {
Field::Key => {
let key = variant_access.newtype_variant()?;
Ok(QueryItem::Key(key))
}
Field::Range => {
let range = variant_access.newtype_variant()?;
Ok(QueryItem::Range(range))
}
Field::RangeInclusive => {
let range_inclusive = variant_access.newtype_variant()?;
Ok(QueryItem::RangeInclusive(range_inclusive))
}
Field::RangeFull => Ok(QueryItem::RangeFull(RangeFull)),
Field::RangeFrom => {
let range_from = variant_access.newtype_variant()?;
Ok(QueryItem::RangeFrom(range_from))
}
Field::RangeTo => {
let range_to = variant_access.newtype_variant()?;
Ok(QueryItem::RangeTo(range_to))
}
Field::RangeToInclusive => {
// Deserialize the `Vec<u8>` for the `end` of the range
let end = variant_access.newtype_variant()?;
Ok(QueryItem::RangeToInclusive(..=end))
}
Field::RangeAfter => {
let range_after = variant_access.newtype_variant()?;
Ok(QueryItem::RangeAfter(range_after))
}
Field::RangeAfterTo => {
let range_after_to = variant_access.newtype_variant()?;
Ok(QueryItem::RangeAfterTo(range_after_to))
}
Field::RangeAfterToInclusive => {
let range_after_to_inclusive = variant_access.newtype_variant()?;
Ok(QueryItem::RangeAfterToInclusive(range_after_to_inclusive))
}
}
}
}

const VARIANTS: &[&str] = &[
"Key",
"Range",
"RangeInclusive",
"RangeFull",
"RangeFrom",
"RangeTo",
"RangeToInclusive",
"RangeAfter",
"RangeAfterTo",
"RangeAfterToInclusive",
];

deserializer.deserialize_enum("QueryItem", VARIANTS, QueryItemVisitor)
}
}

#[cfg(any(feature = "full", feature = "verify"))]
impl Encode for QueryItem {
fn encode<E: bincode::enc::Encoder>(
Expand Down

0 comments on commit 7f900ea

Please sign in to comment.