Improve default serialization of vector and optional in LCP

Summary:
This change should preclude the need to specify `:capnp-save` and
`:capnp-load` functions for regularly saved elements of `std::vector<T>`
and `std::optional<T>`. Regular saving in this context means saving
primitive types or compound types which have a `Save(capnp::Builder *)`
method.

Reviewers: mtomic, msantl

Reviewed By: mtomic

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1497
This commit is contained in:
Teon Banek 2018-07-18 13:09:50 +02:00
parent 4f417e1f5d
commit 3ac749caea
5 changed files with 78 additions and 40 deletions

View File

@ -25,11 +25,7 @@ cpp<#
(:response
((registration-successful :bool)
(recovery-info "std::experimental::optional<durability::RecoveryInfo>"
:capnp-type "Utils.Optional(Dur.RecoveryInfo)"
:capnp-save (lcp:capnp-save-optional "durability::capnp::RecoveryInfo"
"durability::RecoveryInfo")
:capnp-load (lcp:capnp-load-optional "durability::capnp::RecoveryInfo"
"durability::RecoveryInfo"))
:capnp-type "Utils.Optional(Dur.RecoveryInfo)")
(workers "std::unordered_map<int, io::network::Endpoint>"
:capnp-type "Utils.Map(Utils.BoxInt16, Io.Endpoint)"
:capnp-save

View File

@ -485,10 +485,7 @@ void PullResData::LoadGraphElement(
${member}.Add(entry_reader.getKey().getValue(), value);
}
cpp<#))
(symbols "std::vector<query::Symbol>"
:capnp-type "List(Sem.Symbol)"
:capnp-save (lcp:capnp-save-vector "query::capnp::Symbol" "query::Symbol")
:capnp-load (lcp:capnp-load-vector "query::capnp::Symbol" "query::Symbol"))
(symbols "std::vector<query::Symbol>" :capnp-type "List(Sem.Symbol)")
(timestamp :int64_t)
(accumulate :bool)
(batch-size :int64_t)

View File

@ -875,20 +875,57 @@ used for outside definition."
:virtual (and (not parents) (capnp-union-subclasses cpp-class))
:const t :override parents :inline inline)))
(defun capnp-cpp-type<-cpp-type (cpp-type &key boxp)
(declare (type cpp-type cpp-type))
(when (cpp-type-type-params cpp-type)
(error "Don't know how to convert '~A' to capnp equivalent"
(cpp-type-decl cpp-type)))
(let ((name (cpp-type-base-name cpp-type))
(namespace (cpp-type-namespace cpp-type)))
(cond
((and boxp (typep cpp-type 'cpp-primitive-type))
(setf name (concatenate 'string "Box" (capnp-type<-cpp-type cpp-type))
namespace '("utils" "capnp")))
((string= "string" (cpp-type-base-name cpp-type))
(setf name "Text"
namespace '("capnp")))
(t ;; Just append capnp as final namespace
(setf namespace (append namespace '("capnp")))))
(make-instance 'cpp-type :name name :namespace namespace)))
(defun capnp-save-default (member-name member-type member-builder)
"Generate the default call to save for member."
(declare (type string member-name member-type member-builder))
(let* ((type (parse-cpp-type-declaration member-type))
(type-name (cpp-type-base-name type)))
(when (member type-name '("unique_ptr" "shared_ptr" "vector") :test #'string=)
(error "Use a custom :capnp-save function for ~A ~A" type-name member-name))
(let* ((cpp-class (find-cpp-class type-name)) ;; TODO: full type-name search
(extra-args (when cpp-class
(mapcar (lambda (name-and-type)
(cpp-variable-name (first name-and-type)))
(capnp-extra-args cpp-class :save)))))
(format nil "~A.Save(&~A~{, ~A~});"
member-name member-builder extra-args))))
(cond
((string= "vector" type-name)
(let* ((elem-type (car (cpp-type-type-args type)))
(capnp-cpp-type (capnp-cpp-type<-cpp-type elem-type)))
(if (capnp-primitive-type-p (capnp-type<-cpp-type (cpp-type-base-name elem-type)))
(raw-cpp-string
#>cpp
utils::SaveVector(${member-name}, &${member-builder});
cpp<#)
(raw-cpp-string
(funcall (capnp-save-vector (cpp-type-decl capnp-cpp-type) (cpp-type-decl elem-type))
member-builder member-name)))))
((string= "optional" type-name)
(let* ((elem-type (car (cpp-type-type-args type)))
(capnp-cpp-type (capnp-cpp-type<-cpp-type elem-type :boxp t)))
(raw-cpp-string
(funcall (capnp-save-optional (cpp-type-decl capnp-cpp-type) (cpp-type-decl elem-type))
member-builder member-name))))
((member type-name '("unique_ptr" "shared_ptr" "vector") :test #'string=)
(error "Use a custom :capnp-save function for ~A ~A" type-name member-name))
(t
(let* ((cpp-class (find-cpp-class type-name)) ;; TODO: full type-name search
(extra-args (when cpp-class
(mapcar (lambda (name-and-type)
(cpp-variable-name (first name-and-type)))
(capnp-extra-args cpp-class :save)))))
(format nil "~A.Save(&~A~{, ~A~});"
member-name member-builder extra-args))))))
(defun capnp-save-code (cpp-class)
"Generate Cap'n Proto saving code for CPP-CLASS"
@ -1046,15 +1083,34 @@ used for outside definition."
(declare (type string member-name member-type member-reader))
(let* ((type (parse-cpp-type-declaration member-type))
(type-name (cpp-type-base-name type)))
(when (member type-name '("unique_ptr" "shared_ptr" "vector") :test #'string=)
(error "Use a custom :capnp-load function for ~A ~A" type-name member-name))
(let* ((cpp-class (find-cpp-class type-name)) ;; TODO: full type-name search
(extra-args (when cpp-class
(mapcar (lambda (name-and-type)
(cpp-variable-name (first name-and-type)))
(capnp-extra-args cpp-class :load)))))
(format nil "~A.Load(~A~{, ~A~});"
member-name member-reader extra-args))))
(cond
((string= "vector" type-name)
(let* ((elem-type (car (cpp-type-type-args type)))
(capnp-cpp-type (capnp-cpp-type<-cpp-type elem-type)))
(if (capnp-primitive-type-p (capnp-type<-cpp-type (cpp-type-base-name elem-type)))
(raw-cpp-string
#>cpp
utils::LoadVector(&${member-name}, ${member-reader});
cpp<#)
(raw-cpp-string
(funcall (capnp-load-vector (cpp-type-decl capnp-cpp-type) (cpp-type-decl elem-type))
member-reader member-name)))))
((string= "optional" type-name)
(let* ((elem-type (car (cpp-type-type-args type)))
(capnp-cpp-type (capnp-cpp-type<-cpp-type elem-type :boxp t)))
(raw-cpp-string
(funcall (capnp-load-optional (cpp-type-decl capnp-cpp-type) (cpp-type-decl elem-type))
member-reader member-name))))
((member type-name '("unique_ptr" "shared_ptr" "vector") :test #'string=)
(error "Use a custom :capnp-load function for ~A ~A" type-name member-name))
(t
(let* ((cpp-class (find-cpp-class type-name)) ;; TODO: full type-name search
(extra-args (when cpp-class
(mapcar (lambda (name-and-type)
(cpp-variable-name (first name-and-type)))
(capnp-extra-args cpp-class :load)))))
(format nil "~A.Load(~A~{, ~A~});"
member-name member-reader extra-args))))))
(defun capnp-load-declaration (cpp-class &key (inline t))
"Generate Cap'n Proto load function declaration for CPP-CLASS. If

View File

@ -2484,15 +2484,7 @@ by having only one result from each worker.")
((input "std::shared_ptr<LogicalOperator>"
:capnp-save #'save-operator-pointer
:capnp-load #'load-operator-pointer)
(usernames "std::vector<std::string>" :reader t
:capnp-save (lambda (builder member-name)
#>cpp
utils::SaveVector(${member-name}, &${builder});
cpp<#)
:capnp-load (lambda (reader member-name)
#>cpp
utils::LoadVector(&${member-name}, ${reader});
cpp<#)))
(usernames "std::vector<std::string>" :reader t))
(:documentation
"Operator that deletes one or more existing database users.")
(:public

View File

@ -42,10 +42,7 @@ cpp<#
(lcp:define-rpc batch-stats
(:request
((requests "std::vector<StatsReq>"
:capnp-type "List(StatsReq)"
:capnp-save (lcp:capnp-save-vector "capnp::StatsReq" "StatsReq")
:capnp-load (lcp:capnp-load-vector "capnp::StatsReq" "StatsReq"))))
((requests "std::vector<StatsReq>")))
(:response ()))
(lcp:pop-namespace) ;; stats