Adding supported key/path types (updated in version 1.3)
June 16, 2018 ยท View on GitHub
defpathtype
If you want to support additional types in paths you can use the defpathtype macro.
It takes the following parameters:
hex-code- a number used for type identification in the database0x0is used internally and off limits- built-in codes which should not be overwritten are:
0x10,0x20,0x21,0x24,0x25,0x30,0x31,0x32,0x68,0x69,0x70,0xa0. Attempts to overwrite them (or generally change encodings) should print a warning.
types- the types to be encoded (generally there should only be one)encoder- a function which takes elements of the types specified intypesand returns a string representationdecoder- a function which takes the string reprensentations generated by the encoder and reconstructs a value of the appropriate type
You can see which types and hex-codes are already assigned by calling the path-encoding-assignments function
check-encoding
Additionally, you should use the check-encoding function to test that your encoding and decodings match.
It returns a map with four keys:
:equal- indicates if the decoded value is equal to the initial value:initial- the supplied value before encoding:decoded- the value after it has been decoded:encoded- the encoded (string) representation of the value
Example
;; setup namespace
(require '(clojure [string :as str]))
(use 'codax.core)
;; create a record type
(defrecord Point [x y])
;; find an unused hex-code
(path-encoding-assignments) ;{:hex-codes ("0x20" "0xa0" "0x21" "0x24" "0x25" "0x68" "0x69" "0x10" "0x30" "0x70" "0x31" "0x32"),
; :types (nil java.time.Instant java.lang.Double clojure.lang.Symbol java.lang.String ...}
;; define a path type using 0x50 as the identifier code.
;; 0x50 is chosen arbitrarily, because it is unassigned.
(defpathtype [0x50 Point]
(fn point-encoder [pt]
(str (:x pt) "x" (:y pt))) ;; e.g. path-type-demo.Point{:x 10 :y 20} becomes "10x20"
(fn point-decoder [encoded-pt]
(let [[x y] (str/split encoded-pt #"x")] ;; split the str representation on "x"
(Point. (read-string x) (read-string y))))) ;; read the x and y values and use them to reconstruct the point
;; test the encoder/decoder pair
(check-path-encoding (Point. 10 20)) ;{:equal true,
; :initial #path_type_demo.Point{:x 10, :y 20},
; :decoded #path_type_demo.Point{:x 10, :y 20},
; :encoded "10x20"}
;; now the type can be used in any path
;; e.g. (assoc-at! some-database [:points (Point. 10 20)] true)
Notes
- Creating custom path types is advanced functionality which is not required for the vast majority of applications.
- A database using custom pathtypes will (probably) be unreadable in any program which does not define the exact same pathtype
- If you believe that a custom pathtype you have defined has generally applicable utility, please submit a PR or open an issue!