Created
October 24, 2018 01:59
-
-
Save IGJoshua/2d71822bb9ce5d62ca84f30847b9d1d2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(s/def :entry/endian #{:endian/little :endian/big}) | |
(s/def :entry/type keyword?) | |
(s/def :entry/id keyword?) | |
(s/def ::entry (s/keys :req [:entry/id :entry/type] | |
:opt [:entry/endian])) | |
(s/def :entry/size pos-int?) | |
(s/def :string/encoding #{:utf8 :utf16 :ascii :latin1}) | |
(s/def :string/delimiter string?) | |
(s/def :entry.type/string (s/merge ::entry | |
(s/keys :req [:string/encoding | |
(or :entry/size | |
:string/delimiter)]))) | |
(s/def :integer/unsigned boolean?) | |
(s/def :entry.type/int (s/merge ::entry | |
(s/keys :req [:entry/size] | |
:opt [:integer/unsigned]))) | |
(s/def ::block (s/coll-of ::entry)) | |
(s/def ::root-block ::block) | |
(s/def ::spec (s/keys :req [::root-block])) | |
(defn endian-abbrev | |
[endian] | |
(case endian | |
:endian/little :le | |
:endian/big :be)) | |
(defmulti parse-entry | |
(fn [reader parsed-structure entry] | |
(:entry/type entry))) | |
(s/fdef parse-entry | |
:args (s/cat :reader (partial instance? BitReader) | |
:parsed-structure any? | |
:entry ::entry)) | |
(defmethod parse-entry :entry.type/string | |
[^BitReader reader parsed-structure entry] | |
(read-string reader {:size (:entry/size entry) | |
:endian (endian-abbrev (:entry/endian entry)) | |
:delimiter (:string/delimiter entry) | |
:encoding (:string/encoding entry)})) | |
(defmethod parse-entry :entry.type/int | |
[^BitReader reader parsed-structure entry] | |
(let [bytes (read-bytes reader {:size (:entry/size entry) | |
:endian (endian-abbrev (:entry/endian entry))})]) | |
(if (:integer/unsigned entry) | |
(tr/bytes->uint bytes) | |
(tr/bytes->int bytes))) | |
(defn parse-spec | |
[spec file] | |
(let [file (io/open-file file) | |
reader (:reader file)] | |
(reduce (fn [structure entry] | |
(conj structure | |
(parse-entry reader | |
structure | |
entry))) | |
[] | |
(::root-block spec)))) | |
(s/fdef parse-spec | |
:args (s/cat :spec ::spec | |
:file string?)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment