From eeee025303d060189c4fbfff048008142dd1cf48 Mon Sep 17 00:00:00 2001 From: Joshua Suskalo Date: Thu, 23 Sep 2021 09:33:07 -0500 Subject: [PATCH] Add a very basic struct definition macro --- src/clj/coffi/ffi.clj | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/clj/coffi/ffi.clj b/src/clj/coffi/ffi.clj index 1a412aa..8353507 100644 --- a/src/clj/coffi/ffi.clj +++ b/src/clj/coffi/ffi.clj @@ -1089,3 +1089,36 @@ fun#)))) (s/fdef defcfn :args ::defcfn-args) + +(s/def ::defstruct-args + (s/cat :struct-name qualified-keyword? + ;:layout (s/? keyword?) + :docstring (s/? string?) + :fields (s/* (s/cat :field-name simple-keyword? + :field-type ::type)))) + +(defmacro defstruct + "Defines a type alias for a struct with the given name and fields. + + The fields are provided as keyword args. + + Currently no padding is provided into the structure." + {:arglists '([struct-name docstring? & fields])} + [& args] + ;; TODO(Joshua): Support adding padding to the structure (and make it + ;; extensible?) + (let [args (s/conform ::defstruct-args args)] + `(let [struct-type# [::struct [~@(->> (:fields args) + (partition 2) + (map vector))]]] + (defmethod c-layout ~(:struct-name args) + [_type#] + (c-layout struct-type#)) + (defmethod serialize-into ~(:struct-name args) + [obj# _type# segment# scope#] + (serialize-into obj# struct-type# segment# scope#)) + (defmethod deserialize-from ~(:struct-name args) + [segment# _type#] + (deserialize-from segment# struct-type#))))) +(s/fdef defstruct + :args ::defstruct-args)