Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: serde support for a basic structs #344

Merged
merged 2 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion 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 @@ -50,8 +51,9 @@ name = "insertion_benchmark"
harness = false

[features]
default = ["full"]
default = ["full", "serde-support"]
proof_debug = ["grovedb-merk/proof_debug"]
serde-support = ["serde", "grovedb-merk/serde-support", "indexmap/serde"]
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved
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
6 changes: 6 additions & 0 deletions grovedb/src/element/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
use grovedb_merk::estimated_costs::{LAYER_COST_SIZE, SUM_LAYER_COST_SIZE};
#[cfg(feature = "full")]
use grovedb_visualize::visualize_to_vec;
#[cfg(feature = "serde-support")]
use serde::{Deserialize, Serialize};

Check warning on line 34 in grovedb/src/element/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `Serialize`

warning: unused import: `Serialize` --> grovedb/src/element/mod.rs:34:26 | 34 | use serde::{Deserialize, Serialize}; | ^^^^^^^^^

Check warning on line 34 in grovedb/src/element/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `Deserialize`

warning: unused import: `Deserialize` --> grovedb/src/element/mod.rs:34:13 | 34 | use serde::{Deserialize, Serialize}; | ^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

use crate::operations::proof::util::hex_to_ascii;
#[cfg(any(feature = "full", feature = "verify"))]
Expand Down Expand Up @@ -71,6 +73,10 @@
/// 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-support",
derive(serde::Serialize, serde::Deserialize)
)]
pub enum Element {
/// An ordinary value
Item(Vec<u8>, Option<ElementFlags>),
Expand Down
10 changes: 10 additions & 0 deletions grovedb/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
use grovedb_merk::proofs::Query;
use grovedb_version::{check_grovedb_v0, error::GroveVersionError, version::GroveVersion};
use indexmap::IndexMap;
#[cfg(feature = "serde-support")]
use serde::{Deserialize, Serialize};

Check warning on line 18 in grovedb/src/query/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unused imports: `Deserialize` and `Serialize`

warning: unused imports: `Deserialize` and `Serialize` --> grovedb/src/query/mod.rs:18:13 | 18 | use serde::{Deserialize, Serialize}; | ^^^^^^^^^^^ ^^^^^^^^^

use crate::operations::proof::util::hex_to_ascii;
#[cfg(any(feature = "full", feature = "verify"))]
Expand All @@ -23,6 +25,10 @@

#[cfg(any(feature = "full", feature = "verify"))]
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(
feature = "serde-support",
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 +56,10 @@

#[cfg(any(feature = "full", feature = "verify"))]
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(
feature = "serde-support",
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
32 changes: 4 additions & 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,10 @@ use crate::Error;

#[cfg(any(feature = "full", feature = "verify"))]
#[cfg_attr(not(any(feature = "full", feature = "visualize")), derive(Debug))]
#[cfg_attr(
feature = "serde-support",
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-support = ["serde", "indexmap/serde"]
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved
full = ["rand",
"time",
"colored",
Expand Down
8 changes: 8 additions & 0 deletions merk/src/proofs/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ pub type PathKey = (Path, Key);

#[cfg(any(feature = "full", feature = "verify"))]
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(
feature = "serde-support",
derive(serde::Serialize, serde::Deserialize)
)]
/// Subquery branch
pub struct SubqueryBranch {
/// Subquery path
Expand Down Expand Up @@ -111,6 +115,10 @@ 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-support",
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,
),
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved
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,
),
}
}
}
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved

#[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))
}
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved
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
Loading