Skip to content

Commit

Permalink
Feature-gate dynamic deserialization.
Browse files Browse the repository at this point in the history
We generate a `AnyDeserialize` implementation that allows
deserializing into instances of `Any` given relation id.
This impl is not used by most applications, but causes massive
code bloat.  The reason is that is uses erased_serde, which
forces all `Deserialize` impls to get specialized for
`erased_serde::Deserializer`.  We feature-gate this impl, so only
clients who want to use it can enable it.

Signed-off-by: Leonid Ryzhyk <lryzhyk@vmware.com>
  • Loading branch information
ryzhyk committed Nov 12, 2021
1 parent 68e980d commit 6ad6d96
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 7 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased]

- Feature-gate `AnyDeserialize` impl. The DDlog compiler generates an
implementation of the `AnyDeserialize` trait, which allows clients to
deserialize instances of `ddlog_std::Any` provided they know relation id of
the value being deserialized. This feature is not used by most applications,
but can cause significant code bloat and slow down compilation. We
feature-gate this impl, so that only users who require this functionality
have to pay the price.

## [1.0.0] - Nov 9, 2021

### Self-profiler revamp.
Expand Down
1 change: 1 addition & 0 deletions rust/template/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ command-line = ["cmd_parser", "rustop"]
nested_ts_32 = ["differential_datalog/nested_ts_32"]
c_api = ["differential_datalog/c_api"]
checked_weights = ["differential_datalog/checked_weights"]
deserialize_any = []

[dependencies]
abomonation = "0.7"
Expand Down
4 changes: 2 additions & 2 deletions rust/template/differential_datalog/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub struct HDDlog {
pub print_err: Option<extern "C" fn(msg: *const c_char)>,
pub inventory: BoxedInventory,
pub d3log_localizer: BoxedLocalizer,
pub any_deserialize: BoxedDeserialize,
pub any_deserialize: Option<BoxedDeserialize>,
pub flatbuf_converter: BoxedFlatbufConverter,
/// When set, all commands sent to the program are recorded in
/// the specified `.dat` file so that they can be replayed later.
Expand All @@ -60,7 +60,7 @@ impl HDDlog {
print_err: Option<extern "C" fn(msg: *const c_char)>,
init_ddlog: fn(Arc<dyn RelationCallback>) -> Program,
inventory: BoxedInventory,
any_deserialize: BoxedDeserialize,
any_deserialize: Option<BoxedDeserialize>,
d3log_localizer: BoxedLocalizer,
flatbuf_converter: BoxedFlatbufConverter,
) -> Result<(Self, DeltaMap<DDValue>), String> {
Expand Down
26 changes: 23 additions & 3 deletions rust/template/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ pub struct RelValDeserialize;
#[macro_export]
macro_rules! decl_any_deserialize {
( $(($rel:expr, $typ:ty)),* ) => {
#[cfg(feature = "deserialize_any")]
static DDANY_DESERIALIZE_FUNC_MAP: phf::Map<u64, ::differential_datalog::AnyDeserializeFunc> = phf_map! {
$(
$rel => {
Expand All @@ -85,6 +86,7 @@ macro_rules! decl_any_deserialize {
)*
};

#[cfg(feature = "deserialize_any")]
impl ::differential_datalog::AnyDeserialize for RelValDeserialize {
fn get_deserialize(&self, relid: ::differential_datalog::program::RelId) -> ::std::option::Option<::differential_datalog::AnyDeserializeFunc> {
DDANY_DESERIALIZE_FUNC_MAP.get(&(relid as u64)).cloned()
Expand Down Expand Up @@ -211,14 +213,20 @@ pub fn run_with_config(
#[cfg(not(feature = "flatbuf"))]
let flatbuf_converter = Box::new(differential_datalog::flatbuf::UnimplementedFlatbufConverter);

#[cfg(feature = "deserialize_any")]
let deserialize_any = Some(Box::new(RelValDeserialize)
as Box<dyn ::differential_datalog::AnyDeserialize + Send + Sync + 'static>);
#[cfg(not(feature = "deserialize_any"))]
let deserialize_any = None;

::differential_datalog::api::HDDlog::new(
config,
&SOURCE_CODE,
do_store,
None,
crate::prog,
Box::new(crate::Inventory),
Box::new(RelValDeserialize),
deserialize_any,
Box::new(crate::D3logInventory),
flatbuf_converter,
)
Expand Down Expand Up @@ -251,14 +259,20 @@ pub fn run(
#[cfg(not(feature = "flatbuf"))]
let flatbuf_converter = Box::new(differential_datalog::flatbuf::UnimplementedFlatbufConverter);

#[cfg(feature = "deserialize_any")]
let deserialize_any = Some(Box::new(RelValDeserialize)
as Box<dyn ::differential_datalog::AnyDeserialize + Send + Sync + 'static>);
#[cfg(not(feature = "deserialize_any"))]
let deserialize_any = None;

::differential_datalog::api::HDDlog::new(
config,
&SOURCE_CODE,
do_store,
None,
crate::prog,
Box::new(crate::Inventory),
Box::new(RelValDeserialize),
deserialize_any,
Box::new(crate::D3logInventory),
flatbuf_converter,
)
Expand Down Expand Up @@ -299,14 +313,20 @@ pub unsafe extern "C" fn ddlog_run_with_config(
#[cfg(not(feature = "flatbuf"))]
let flatbuf_converter = Box::new(differential_datalog::flatbuf::UnimplementedFlatbufConverter);

#[cfg(feature = "deserialize_any")]
let deserialize_any = Some(Box::new(RelValDeserialize)
as Box<dyn ::differential_datalog::AnyDeserialize + Send + Sync + 'static>);
#[cfg(not(feature = "deserialize_any"))]
let deserialize_any = None;

let result = HDDlog::new(
config,
&SOURCE_CODE,
do_store,
print_err,
crate::prog,
Box::new(crate::Inventory),
Box::new(RelValDeserialize),
deserialize_any,
Box::new(crate::D3logInventory),
flatbuf_converter,
);
Expand Down
2 changes: 1 addition & 1 deletion test/datalog_tests/rust_api_test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ serde = "1.0"
# The generated Rust project contains several crates that must be imported
# by the client program.
differential_datalog = { path = "../tutorial_ddlog/differential_datalog" }
tutorial = { path = "../tutorial_ddlog" }
tutorial = { path = "../tutorial_ddlog", features = ["deserialize_any"] }
ddlog_rt = { path = "../tutorial_ddlog/types/ddlog_rt" }
types = { path = "../tutorial_ddlog/types" }
2 changes: 1 addition & 1 deletion test/datalog_tests/rust_api_test/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ fn ddval_deserialize_test(ddlog: &HDDlog) {
let json_string = serde_json::to_string(&val).unwrap();

// Deserialize using AnyDeserializeSeed.
let seed = AnyDeserializeSeed::from_relid(&*ddlog.any_deserialize, Relations::Word1 as RelId).unwrap();
let seed = AnyDeserializeSeed::from_relid(&**ddlog.any_deserialize.as_ref().unwrap(), Relations::Word1 as RelId).unwrap();
let val_deserialized = seed.deserialize(&mut serde_json::Deserializer::from_str(json_string.as_str())).unwrap();

assert_eq!(val, val_deserialized);
Expand Down

0 comments on commit 6ad6d96

Please sign in to comment.