[#784] Support binf.cljc library by adding ByteBuffer and Charset-related classes (#789)

This commit is contained in:
Michiel Borkent 2021-04-14 23:27:31 +02:00 committed by GitHub
parent 0ecee5bf94
commit e0b1c1b01e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 2039 additions and 4 deletions

View file

@ -73,7 +73,8 @@
circleci/bond {:mvn/version "0.4.0"} circleci/bond {:mvn/version "0.4.0"}
version-clj/version-clj {:mvn/version "2.0.1"} version-clj/version-clj {:mvn/version "2.0.1"}
gaka/gaka {:mvn/version "0.3.0"} gaka/gaka {:mvn/version "0.3.0"}
failjure/failjure {:mvn/version "2.1.1"}} failjure/failjure {:mvn/version "2.1.1"}
io.helins/binf {:mvn/version "1.1.0-beta0"}}
:classpath-overrides {org.clojure/clojure nil :classpath-overrides {org.clojure/clojure nil
org.clojure/spec.alpha nil org.clojure/spec.alpha nil
org.clojure/core.specs.alpha nil}} org.clojure/core.specs.alpha nil}}

2
sci

@ -1 +1 @@
Subproject commit d4f656ccfb526ffb4b28285a1867b5195968a67e Subproject commit 1172d1fa98a401b97cfefaddfa30d9b95129a639

View file

@ -95,6 +95,7 @@
java.io.FileFilter java.io.FileFilter
java.io.FilenameFilter java.io.FilenameFilter
java.io.FileNotFoundException java.io.FileNotFoundException
java.io.RandomAccessFile
java.io.InputStream java.io.InputStream
java.io.IOException java.io.IOException
java.io.OutputStream java.io.OutputStream
@ -154,7 +155,19 @@
java.net.URLEncoder java.net.URLEncoder
java.net.URLDecoder java.net.URLDecoder
~@(when features/java-nio? ~@(when features/java-nio?
'[java.nio.file.OpenOption '[java.nio.ByteBuffer
java.nio.ByteOrder
java.nio.CharBuffer
java.nio.DirectByteBuffer
java.nio.DirectByteBufferR
java.nio.MappedByteBuffer
java.nio.file.OpenOption
java.nio.channels.FileChannel
java.nio.channels.FileChannel$MapMode
java.nio.charset.Charset
java.nio.charset.CoderResult
java.nio.charset.CharsetEncoder
java.nio.charset.StandardCharsets
java.nio.file.CopyOption java.nio.file.CopyOption
java.nio.file.DirectoryNotEmptyException java.nio.file.DirectoryNotEmptyException
java.nio.file.FileAlreadyExistsException java.nio.file.FileAlreadyExistsException
@ -344,7 +357,17 @@
(instance? java.nio.file.PathMatcher v) (instance? java.nio.file.PathMatcher v)
java.nio.file.PathMatcher java.nio.file.PathMatcher
(instance? java.util.stream.BaseStream v) (instance? java.util.stream.BaseStream v)
java.util.stream.BaseStream))))) java.util.stream.BaseStream
(instance? java.nio.ByteBuffer v)
java.nio.ByteBuffer
(instance? java.nio.charset.Charset v)
java.nio.charset.Charset
(instance? java.nio.charset.CharsetEncoder v)
java.nio.charset.CharsetEncoder
(instance? java.nio.CharBuffer v)
java.nio.CharBuffer
(instance? java.nio.channels.FileChannel v)
java.nio.channels.FileChannel)))))
(def class-map (gen-class-map)) (def class-map (gen-class-map))

View file

@ -196,6 +196,8 @@
'rewrite-clj.zip.subedit-test 'rewrite-clj.zip.subedit-test
'rewrite-clj.node.coercer-test) 'rewrite-clj.node.coercer-test)
(test-namespaces 'helins.binf.test)
;;;; final exit code ;;;; final exit code
(let [{:keys [:test :fail :error] :as m} @status] (let [{:keys [:test :fail :error] :as m} @status]

View file

@ -0,0 +1,642 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at https://mozilla.org/MPL/2.0/.
(ns helins.binf.test
{:author "Adam Helins"}
(:require [clojure.test :as t]
[helins.binf :as binf]
[helins.binf.buffer :as binf.buffer]
[helins.binf.int :as binf.int]
[helins.binf.int64 :as binf.int64]
#?@(:bb [] :clj [[helins.binf.native :as binf.native]])
[helins.binf.test.buffer :as binf.test.buffer]
[helins.binf.test.string :as binf.test.string]))
#?(:clj (set! *warn-on-reflection*
true))
;;;;;;;;;; Creating views
(def offset
4)
(def size
16)
(def size-2
4)
(def view
(-> (binf.buffer/alloc size)
binf/view
(binf/endian-set :little-endian)))
#?(:bb nil
:clj (def view-native
(binf/endian-set (binf.native/view size)
:little-endian)))
#?(:cljs (def view-shared
(-> (binf.buffer/alloc-shared size)
binf/view
(binf/endian-set :little-endian))))
;; view native not supported in bb
#_(t/deftest buffer->view
;; Without offset nor size
(t/is (= 0
(binf/buffer-offset view)
#?(:cljs (binf/buffer-offset view-shared))))
(t/is (= 0
(binf/position view)
#?(:clj (binf/position view-native))
#?(:cljs (binf/position view-shared))))
(t/is (= size
(binf/limit view)
#?(:clj (binf/limit view-native))
#?(:cljs (binf/limit view-shared))))
(t/is (= size
(binf/remaining view)
#?(:clj (binf/remaining view-native))
#?(:cljs (binf/remaining view-shared))))
;; With offset
(let [v (binf/view (binf.buffer/alloc size)
offset)
#?@(:cljs [v-shared (binf/view (binf.buffer/alloc-shared size)
offset)])]
(t/is (= offset
(binf/buffer-offset v)
#?(:cljs (binf/buffer-offset v-shared))))
(t/is (= 0
(binf/position v)
#?(:cljs (binf/position v-shared))))
(t/is (= (- size
offset)
(binf/limit v)
#?(:cljs (binf/limit v-shared))))
(t/is (= (- size
offset)
(binf/remaining v)
#?(:cljs (binf/remaining v-shared)))))
;; With offset and size
(let [v (binf/view (binf.buffer/alloc size)
offset
size-2)
#?@(:cljs [v-shared (binf/view (binf.buffer/alloc-shared size)
offset
size-2)])]
(t/is (= offset
(binf/buffer-offset v)
#?(:cljs (binf/buffer-offset v-shared))))
(t/is (= 0
(binf/position v)
#?(:cljs (binf/position v-shared))))
(t/is (= size-2
(binf/limit v)
#?(:cljs (binf/limit v-shared))))
(t/is (= size-2
(binf/remaining v)
#?(:cljs (binf/remaining v-shared))))))
(t/deftest view->view
;; Without offset nor size
(let [v (binf/view view)]
(t/is (= :little-endian
(binf/endian-get v))
"Endianess is duplicated")
(t/is (= 0
(binf/buffer-offset v)))
(t/is (= 0
(binf/position v)))
(t/is (= size
(binf/limit v)))
(t/is (= size
(binf/remaining v))))
;; With offset
#_(let [v (binf/view view
offset)
#?@(:clj [v-native (binf/view view-native
offset)])]
(t/is (= :little-endian
(binf/endian-get v))
"Endianess is duplicated")
#?(:clj (t/is (= :little-endian
(binf/endian-get v-native))
"Endianess is duplicated in native view"))
(t/is (= offset
(binf/buffer-offset v)))
(t/is (= 0
(binf/position v)
#?(:clj (binf/position v-native))))
(t/is (= (- size
offset)
(binf/limit v)
#?(:clj (binf/limit v-native))))
(t/is (= (- size
offset)
(binf/remaining v)
#?(:clj (binf/remaining v-native)))))
;; With offset and size
#_(let [v (binf/view view
offset
size-2)
#?@(:clj [v-native (binf/view view-native
offset
size-2)])]
(t/is (= :little-endian
(binf/endian-get v))
"Endianess is duplicated")
#?(:clj (t/is (= :little-endian
(binf/endian-get v-native))
"Endianess is duplicated in native view"))
(t/is (= offset
(binf/buffer-offset v)))
(t/is (= 0
(binf/position v)
#?(:clj (binf/position v-native))))
(t/is (= size-2
(binf/limit v)
#?(:clj (binf/limit v-native))))
(t/is (= size-2
(binf/remaining v)
#?(:clj (binf/remaining v-native))))))
;;;;;;;;; Numerical R/W
(defn view-8
[]
(binf/view (binf.buffer/alloc 8)))
;; #?(:clj (defn view-8-native
;; []
;; (binf.native/view 8)))
#?(:cljs (defn view-8-shared
[]
(binf/view (binf.buffer/alloc-shared 8))))
(defn- -view-uints
[f-view]
(t/are [wa ra wr rr value]
(and (t/is (= value
(-> (f-view)
(wa 0
value)
(ra 0)))
"Absolute uint")
(t/is (= value
(-> (f-view)
(wr value)
(binf/seek 0)
rr))
"Relative uint"))
binf/wa-b8 binf/ra-u8 binf/wr-b8 binf/rr-u8 (binf.int/from-float (dec (Math/pow 2 8)))
binf/wa-b8 binf/ra-i8 binf/wr-b8 binf/rr-i8 -1
binf/wa-b16 binf/ra-u16 binf/wr-b16 binf/rr-u16 (binf.int/from-float (dec (Math/pow 2 16)))
binf/wa-b16 binf/ra-i16 binf/wr-b16 binf/rr-i16 -1
binf/wa-b32 binf/ra-u32 binf/wr-b32 binf/rr-u32 (binf.int/from-float (dec (Math/pow 2 32)))
binf/wa-b32 binf/ra-i32 binf/wr-b32 binf/rr-i32 -1))
(defn- -view-i64
[f-view]
(let [x (binf.int64/i* -9223372036854775808)]
(and (t/is (= x
(-> (f-view)
(binf/wa-b64 0
x)
(binf/ra-i64 0)))
"Absolute i64")
(t/is (= x
(-> (f-view)
(binf/wr-b64 x)
(binf/seek 0)
(binf/rr-i64)))
"Relative i64"))))
#?(:clj (defn- -view-f32
[f-view]
(let [x (float 42.42)]
(and (t/is (= x
(-> (f-view)
(binf/wa-f32 0
x)
(binf/ra-f32 0)))
"Absolute f32")
(t/is (= x
(-> (f-view)
(binf/wr-f32 x)
(binf/seek 0)
binf/rr-f32))
"Relative f32")))))
(defn- -view-f64
[f-view]
(let [x 42.42]
(and (t/is (= x
(-> (f-view)
(binf/wa-f64 0
x)
(binf/ra-f64 0)))
"Absolute f64")
(t/is (= x
(-> (f-view)
(binf/wr-f64 x)
(binf/seek 0)
binf/rr-f64))
"Relative f64"))))
(t/deftest view-uints
(-view-uints view-8))
#?(:clj (t/deftest view-uints-native
#_(-view-uints view-8-native)))
#?(:cljs (t/deftest view-uints-shared
(-view-uints view-8-shared)))
(t/deftest view-i64
(-view-i64 view-8))
#?(:clj (t/deftest view-i64-native
#_(-view-i64 view-8-native)))
#?(:cljs (t/deftest view-i64-shared
(-view-i64 view-8-shared)))
#?(:clj (t/deftest view-f32
(-view-f32 view-8)))
#?(:clj (t/deftest view-f32-native
#_(-view-f32 view-8-native)))
(t/deftest view-f64
(-view-f64 view-8))
#?(:clj (t/deftest view-f64-native
#_(-view-f64 view-8-native)))
#?(:cljs (t/deftest view-f64-shared
(-view-f64 view-8-shared)))
;;;;;;;;;; Copying from/to buffers
(def copy-size
10)
(defn- -rwa-buffer
[view]
(t/is (= (take 7
binf.test.buffer/copy-target)
(seq (binf/ra-buffer (binf/wa-buffer view
5
(binf/backing-buffer (binf.test.buffer/make-view))
2
2)
0
7)))
"Absolute writing")
(t/is (= (take 5
(drop 2
binf.test.buffer/copy-target))
(seq (binf/ra-buffer view
2
5)))
"Absolute reading")
(t/is (zero? (binf/position view))
"Position is unchanged"))
(defn- -rwr-buffer
[view]
(binf/seek view
5)
(t/is (= (take 7
binf.test.buffer/copy-target)
(seq (binf/ra-buffer (binf/wr-buffer view
(binf/backing-buffer (binf.test.buffer/make-view))
2
2)
0
7)))
"Relative writing")
(t/is (= (binf/position view)
7)
"Writing is relative")
(binf/seek view
0)
(t/is (= (take 7
binf.test.buffer/copy-target)
(seq (binf/rr-buffer view
7)))
"Relative reading")
(t/is (= (binf/position view)
7)
"Reading is relative"))
(t/deftest rwa-buffer
(-rwa-buffer (binf/view (binf.buffer/alloc copy-size))))
#?(:bb nil
:clj (t/deftest rwa-buffer-native
(-rwa-buffer (binf.native/view copy-size))))
#?(:cljs (t/deftest rwa-buffer-shared
(-rwa-buffer (binf/view (binf.buffer/alloc-shared copy-size)))))
(t/deftest rwr-buffer
(-rwr-buffer (binf/view (binf.buffer/alloc copy-size))))
#?(:bb nil
:clj (t/deftest rwr-buffer-shared
(-rwr-buffer (binf.native/view copy-size))))
#?(:cljs (t/deftest rwr-buffer-shared
(-rwr-buffer (binf/view (binf.buffer/alloc-shared copy-size)))))
;;;;;;;;;; Encoding and decoding strings
(defn -string
[string res]
(t/is (first res)
"Enough bytes for writing strings")
(t/is (= (count string)
(res 2))
"Char count is accurate")
(t/is (<= (res 2)
(res 1))
"Cannot write more chars than bytes"))
(defn- -a-string
[f-view]
(t/is (false? (first (binf/wa-string (binf/view (binf.buffer/alloc 10))
0
binf.test.string/string)))
"Not enough bytes to write everything")
(let [view (f-view)
res (binf/wa-string view
0
binf.test.string/string)]
(-string binf.test.string/string
res)
(t/is (zero? (binf/position view))
"Write was absolute")
(t/is (= binf.test.string/string
(binf/ra-string view
0
(res 1)))
"Properly decoding encoded string")
(t/is (zero? (binf/position view))
"Read was absolute")))
(defn- -r-string
[f-view]
(t/is (false? (first (binf/wr-string (binf/view (binf.buffer/alloc 10))
binf.test.string/string)))
"Not enough bytes to write everything")
(let [view (f-view)
res (binf/wr-string view
binf.test.string/string)]
(-string binf.test.string/string
res)
(t/is (= (res 1)
(binf/position view))
"Write was relative")
(binf/seek view
0)
(t/is (= binf.test.string/string
(binf/rr-string view
(res 1)))
"Properly decoding encoded string")
(t/is (= (res 1)
(binf/position view))
"Read was relative")))
(t/deftest a-string
(-a-string #(binf/view (binf.buffer/alloc 1024))))
#?(:bb nil
:clj (t/deftest a-string-native
(-a-string #(binf.native/view 1024))))
#_(t/deftest r-string
(-r-string #(binf/view (binf.buffer/alloc 1024))))
#?(:bb nil
:clj (t/deftest r-string-native
(-r-string #(binf.native/view 1024))))
;;;;;;;;;; Reallocating views
(t/deftest grow
(t/is (= [1 2 42 0 0 0]
(seq (binf/backing-buffer (binf/grow (-> (binf.buffer/alloc 4)
binf/view
(binf/wr-b8 1)
(binf/wr-b8 2)
(binf/wr-b8 42))
2)))
#?(:cljs (seq (binf/backing-buffer (binf/grow (-> (binf.buffer/alloc-shared 4)
binf/view
(binf/wr-b8 1)
(binf/wr-b8 2)
(binf/wr-b8 42))
2))))))
(let [view (-> (binf/view (binf.buffer/alloc 100))
(binf/seek 42))]
(t/is (= 42
(binf/position view)
(-> view
(binf/grow 200)
binf/position))
"Position is the same than in the original view"))
(t/is (= :little-endian
(-> (binf.buffer/alloc 42)
binf/view
(binf/endian-set :little-endian)
(binf/grow 24)
binf/endian-get))
"Endianess is duplicated"))
;;;;;;;;;; Additional types / Boolean
(t/deftest bool
(let [view (binf/view (binf.buffer/alloc 2))]
(t/is (= true
(-> view
(binf/wr-bool true)
(binf/seek 0)
binf/rr-bool))
"Relative")
(t/is (= true
(-> view
(binf/wa-bool 1
true)
(binf/ra-bool 1)))
"Absolute")))

View file

@ -0,0 +1,80 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at https://mozilla.org/MPL/2.0/.
(ns helins.binf.test.base64
{:author "Adam Helins"}
(:require [clojure.test :as t]
[clojure.test.check.clojure-test :as tc.ct]
[clojure.test.check.generators :as tc.gen]
[clojure.test.check.properties :as tc.prop]
[helins.binf :as binf]
[helins.binf.base64 :as binf.base64]
[helins.binf.buffer :as binf.buffer]
[helins.binf.gen :as binf.gen]))
;;;;;;;;;;
(t/deftest main
(let [buffer (binf.buffer/alloc 64)
view (binf/view buffer)
#?@(:cljs [buffer-shared (binf.buffer/alloc-shared 64)
view-shared (binf/view buffer-shared)])]
(dotimes [i 64]
(binf/wr-b8 view
i)
#?(:cljs (binf/wr-b8 view-shared
i)))
(t/is (= (seq buffer)
(seq (-> buffer
binf.base64/encode
binf.base64/decode
binf/backing-buffer))
#?(:cljs (seq (-> buffer-shared
binf.base64/encode
(binf.base64/decode binf.buffer/alloc-shared)
binf/backing-buffer))))
"Without offset nor lenght")
(t/is (= (drop 5
(seq buffer))
(seq (-> buffer
(binf.base64/encode 5)
binf.base64/decode
binf/backing-buffer))
#?(:cljs (seq (-> buffer-shared
(binf.base64/encode 5)
(binf.base64/decode binf.buffer/alloc-shared)
binf/backing-buffer))))
"With offset without length")
(t/is (= (->> (seq buffer)
(drop 5)
(take 20))
(seq (-> buffer
(binf.base64/encode 5
20)
binf.base64/decode
binf/backing-buffer))
#?(:cljs (seq (-> buffer-shared
(binf.base64/encode 5
20)
(binf.base64/decode binf.buffer/alloc-shared)
binf/backing-buffer))))
"With offset and length")))
(tc.ct/defspec gen
(tc.prop/for-all [buffer binf.gen/buffer]
(= (seq buffer)
(let [view (-> buffer
binf.base64/encode
binf.base64/decode)]
(seq (binf/rr-buffer view
(binf/limit view)))))))

View file

@ -0,0 +1,95 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at https://mozilla.org/MPL/2.0/.
(ns helins.binf.test.buffer
{:author "Adam Helinski"}
(:require [clojure.test :as t]
[helins.binf :as binf]
[helins.binf.buffer :as binf.buffer]))
;;;;;;;;;;
(defn make-view
([]
(make-view binf.buffer/alloc))
([make-buffer]
(let [view (binf/view (make-buffer 5))]
(dotimes [_ 5]
(binf/wr-b8 view
1))
view)))
(def copy-target
(concat (repeat 5
0)
(repeat 2
1)
(repeat 3
0)))
(t/deftest copy-buffer
(t/is (= (seq (binf/backing-buffer (make-view)))
(seq (binf.buffer/copy (binf/backing-buffer (make-view))))
#?(:cljs (seq (binf/backing-buffer (make-view binf.buffer/alloc-shared))))
#?(:cljs (seq (binf.buffer/copy (binf/backing-buffer (make-view binf.buffer/alloc-shared))))))
"Cloning")
(t/is (= (concat (repeat 5
0)
(repeat 5
1))
(seq (binf.buffer/copy (binf.buffer/alloc 10)
5
(binf/backing-buffer (make-view))))
#?(:cljs (seq (binf.buffer/copy (binf.buffer/alloc-shared 10)
5
(binf/backing-buffer (make-view binf.buffer/alloc-shared))))))
"Without offset nor length")
(t/is (= (concat (repeat 5
0)
(repeat 3
1)
(repeat 2
0))
(seq (binf.buffer/copy (binf.buffer/alloc 10)
5
(binf/backing-buffer (make-view))
2))
#?(:cljs (seq (binf.buffer/copy (binf.buffer/alloc-shared 10)
5
(binf/backing-buffer (make-view binf.buffer/alloc-shared))
2))))
"With offset")
(t/is (= copy-target
(seq (binf.buffer/copy (binf.buffer/alloc 10)
5
(binf/backing-buffer (make-view))
2
2))
#?(:cljs (seq (binf.buffer/copy (binf.buffer/alloc-shared 10)
5
(binf/backing-buffer (make-view binf.buffer/alloc-shared))
2
2))))
"With offset and length"))

View file

@ -0,0 +1,324 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at https://mozilla.org/MPL/2.0/.
(ns helins.binf.test.cabi
{:author "Adam Helins"}
(:require [clojure.test :as t]
[helins.binf.cabi :as binf.cabi])
(:refer-clojure :exclude [array]))
;;;;;;;;;;
(def w32
4)
(def w64
8)
(def env32
(binf.cabi/env w32))
(def env64
(binf.cabi/env w64))
(defn member
""
[f-member offset env]
(assoc (f-member env)
:binf.cabi/offset
offset))
;;;;;;;;;; Enums
(t/deftest enum
(t/is (= {:binf.cabi/align w32
:binf.cabi/n-byte 4
:binf.cabi/type :enum
:binf.cabi.enum/constant+ {:a 0
:b 1
:c 1000
:d 1001
:e 42
:f 43}
:binf.cabi.enum/type :foo}
((binf.cabi/enum :foo
[:a
:b
[:c 1000]
:d
[:e 42]
:f])
env64))))
;;;;;;;;;; Unnested structs
(t/deftest struct-unnested
(t/is (= {:binf.cabi/align w32
:binf.cabi/n-byte 12
:binf.cabi/type :struct
:binf.cabi.struct/layout [:a
:b
:c
:d]
:binf.cabi.struct/member+ {:a (member binf.cabi/u8
0
env32)
:b (member binf.cabi/i16
2
env32)
:c (member binf.cabi/u32
4
env32)
:d (member binf.cabi/i8
8
env32)}
:binf.cabi.struct/type :foo}
((binf.cabi/struct :foo
[[:a binf.cabi/u8]
[:b binf.cabi/i16]
[:c binf.cabi/u32]
[:d binf.cabi/i8]])
env32)))
(t/is (= {:binf.cabi/align w64
:binf.cabi/n-byte 24
:binf.cabi/type :struct
:binf.cabi.struct/layout [:a
:b
:c]
:binf.cabi.struct/member+ {:a (member binf.cabi/u8
0
env64)
:b (member binf.cabi/f64
8
env64)
:c (member binf.cabi/i16
16
env64)}
:binf.cabi.struct/type :foo}
((binf.cabi/struct :foo
[[:a binf.cabi/u8]
[:b binf.cabi/f64]
[:c binf.cabi/i16]])
env64)))
(t/is (= {:binf.cabi/align w32
:binf.cabi/n-byte 16
:binf.cabi/type :struct
:binf.cabi.struct/layout [:a
:b
:c
:d]
:binf.cabi.struct/member+ {:a (member binf.cabi/bool
0
env32)
:b (member binf.cabi/u16
2
env32)
:c (member binf.cabi/i64
4
env32)
:d (member binf.cabi/u8
12
env32)}
:binf.cabi.struct/type :foo}
((binf.cabi/struct :foo
[[:a binf.cabi/bool]
[:b binf.cabi/u16]
[:c binf.cabi/i64]
[:d binf.cabi/u8]])
env32))))
;;;;;;;;;; Pointers
(t/deftest ptr
(t/is (= {:binf.cabi/align 4
:binf.cabi/n-byte w32
:binf.cabi/type :ptr
:binf.cabi.pointer/target ((binf.cabi/struct :foo
[[:a binf.cabi/u64]])
env32)}
((binf.cabi/ptr (binf.cabi/struct :foo
[[:a binf.cabi/u64]]))
(assoc env32
:binf.cabi.pointer/n-byte
w32)))))
;;;;;;;;;; Arrays
(t/deftest array-primitive
(t/is (= {:binf.cabi/align 4
:binf.cabi/n-byte 40
:binf.cabi/type :array
:binf.cabi.array/element (binf.cabi/f32 env64)
:binf.cabi.array/n-element 10}
((binf.cabi/array binf.cabi/f32
10)
env64))
"1D")
(t/is (= {:binf.cabi/align 4
:binf.cabi/n-byte 160
:binf.cabi/type :array
:binf.cabi.array/element {:binf.cabi/align 4
:binf.cabi/n-byte 80
:binf.cabi/type :array
:binf.cabi.array/element (binf.cabi/f64 env32)
:binf.cabi.array/n-element 10}
:binf.cabi.array/n-element 2}
((-> binf.cabi/f64
(binf.cabi/array 10)
(binf.cabi/array 2))
env32))
"2D"))
(t/deftest struct-with-array
(t/is (= {:binf.cabi/align 2
:binf.cabi/n-byte 22
:binf.cabi/type :struct
:binf.cabi.struct/member+ {:a (member binf.cabi/u8
0
env64)
:b (member (fn [env]
((binf.cabi/array binf.cabi/u16
10)
env))
2
env64)}
:binf.cabi.struct/layout [:a
:b]
:binf.cabi.struct/type :foo}
((binf.cabi/struct :foo
[[:a binf.cabi/u8]
[:b (binf.cabi/array binf.cabi/u16
10)]])
env64))
"1D")
(t/is (= {:binf.cabi/align 2
:binf.cabi/n-byte 102
:binf.cabi/type :struct
:binf.cabi.struct/layout [:a
:b]
:binf.cabi.struct/member+ {:a (member binf.cabi/bool
0
env64)
:b (member (fn [env]
((-> binf.cabi/u16
(binf.cabi/array 10)
(binf.cabi/array 5))
env))
2
env64)}
:binf.cabi.struct/type :foo}
((binf.cabi/struct :foo
[[:a binf.cabi/bool]
[:b (-> binf.cabi/u16
(binf.cabi/array 10)
(binf.cabi/array 5))]])
env64))
"2D"))
(t/deftest array-struct
(t/is (= {:binf.cabi/align 4
:binf.cabi/n-byte 40
:binf.cabi/type :array
:binf.cabi.array/element ((binf.cabi/struct :foo
[[:a binf.cabi/u32]])
env64)
:binf.cabi.array/n-element 10}
((binf.cabi/array (binf.cabi/struct :foo
[[:a binf.cabi/u32]])
10)
env64))))
;;;;;;;;;; Nested structs
(def struct-inner
(binf.cabi/struct :bar
[[:c binf.cabi/i8]
[:d binf.cabi/f64]]))
(t/deftest struct-nested
(t/is (= {:binf.cabi/align w32
:binf.cabi/n-byte 16
:binf.cabi/type :struct
:binf.cabi.struct/layout [:a
:b]
:binf.cabi.struct/member+ {:a (member binf.cabi/u16
0
env32)
:b (member struct-inner
4
env32)}
:binf.cabi.struct/type :foo}
((binf.cabi/struct :foo
[[:a binf.cabi/u16]
[:b struct-inner]])
env32))))
;;;;;;;;;; Unions
(t/deftest union
(t/is (= {:binf.cabi/align 8
:binf.cabi/n-byte 16
:binf.cabi/type :union
:binf.cabi.union/member+ {:a (binf.cabi/i8 env64)
:b ((binf.cabi/struct :bar
[[:c binf.cabi/u16]
[:d binf.cabi/f64]])
env64)}
:binf.cabi.union/type :foo}
((binf.cabi/union :foo
{:a binf.cabi/i8
:b (binf.cabi/struct :bar
[[:c binf.cabi/u16]
[:d binf.cabi/f64]])})
env64))))

View file

@ -0,0 +1,71 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at https://mozilla.org/MPL/2.0/.
(ns helins.binf.test.endian
""
{:author "Adam Helinski"}
(:require [clojure.test :as t]
[clojure.test.check.clojure-test :as tc.ct]
[clojure.test.check.properties :as tc.prop]
[helins.binf.int :as binf.int]
[helins.binf.int64 :as binf.int64]
[helins.binf.endian :as binf.endian]
[helins.binf.gen :as binf.gen]))
;;;;;;;;;;
(t/deftest main
(t/is (= 0x01234
(binf.endian/b16 0x3412))
"16-bit")
(t/is (= 0x11223344
(binf.endian/b32 0x44332211))
"32-bit")
(t/is (= (binf.int64/u* 0x1122334455667788)
(binf.endian/b64 (binf.int64/u* 0x8877665544332211)))
"64-bit"))
;;;;;;;;;; Generative
(tc.ct/defspec b16
(tc.prop/for-all [u16 binf.gen/u16]
(= u16
(-> u16
binf.endian/b16
binf.endian/b16
binf.int/u16))))
(tc.ct/defspec b32
(tc.prop/for-all [u32 binf.gen/u32]
(= u32
(-> u32
binf.endian/b32
binf.endian/b32
binf.int/u32))))
(tc.ct/defspec b64
(tc.prop/for-all [u64 binf.gen/u64]
(= u64
(-> u64
binf.endian/b64
binf.endian/b64
binf.int64/u*))))

View file

@ -0,0 +1,58 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at https://mozilla.org/MPL/2.0/.
(ns helins.binf.test.float
{:author "Adam Helins"}
(:require [clojure.test.check.clojure-test :as tc.ct]
[clojure.test.check.generators :as tc.gen]
[clojure.test.check.properties :as tc.prop]
[helins.binf.float :as binf.float]))
;;;;;;;;;;
(defn nan?
""
[x]
#?(:clj (Double/isNaN x)
:cljs (js/isNaN x)))
(defn f=
""
[x-1 x-2]
(if (nan? x-1)
(nan? x-2)
(= x-1
x-2)))
;;;;;;;;;;
#?(:clj (tc.ct/defspec f32
(tc.prop/for-all [x (tc.gen/fmap unchecked-float
tc.gen/double)]
(f= x
(binf.float/from-b32 (binf.float/b32 x))))))
(tc.ct/defspec f64
(tc.prop/for-all [x tc.gen/double]
(f= x
(binf.float/from-b64 (binf.float/b64 x)))))

View file

@ -0,0 +1,92 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at https://mozilla.org/MPL/2.0/.
(ns helins.binf.test.int
{:author "Adam Helins"}
(:require [clojure.test :as t]
[helins.binf.int :as binf.int]
[helins.binf.int64 :as binf.int64]))
;;;;;;;;;;
(t/deftest casting
(t/are [n-bit fi fu]
(let [value (dec (binf.int/from-float (Math/pow 2
n-bit)))]
(t/is (= value
(-> value
fu
fi
fu
fi
fu))))
8 binf.int/i8 binf.int/u8
16 binf.int/i16 binf.int/u16
32 binf.int/i32 binf.int/u32))
(t/deftest byte-combining
(t/is (= 0x1122
(binf.int/i16 0x11
0x22)
(binf.int/u16 0x11
0x22))
"16-bits")
(t/is (= 0x11223344
(binf.int/i32 0x11
0x22
0x33
0x44)
(binf.int/i32 0x1122
0x3344)
(binf.int/u32 0x11
0x22
0x33
0x44)
(binf.int/u32 0x1122
0x3344))
"32-bit")
(t/is (= (binf.int64/i* 0x1122334455667788)
(binf.int/i64 0x11
0x22
0x33
0x44
0x55
0x66
0x77
0x88)
(binf.int/i64 0x1122
0x3344
0x5566
0x7788)
(binf.int/i64 0x11223344
0x55667788))
"Signed 64-bit")
(t/is (= (binf.int64/u* 0x1122334455667788)
(binf.int/u64 0x11
0x22
0x33
0x44
0x55
0x66
0x77
0x88)
(binf.int/u64 0x1122
0x3344
0x5566
0x7788)
(binf.int/u64 0x11223344
0x55667788))
"Unsigned 64-bit"))

View file

@ -0,0 +1,158 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at https://mozilla.org/MPL/2.0/.
(ns helins.binf.test.int64
{:author "Adam Helins"}
(:require [clojure.test :as t]
[helins.binf.int64 :as binf.int64])
(:refer-clojure :exclude [bit-clear
bit-flip
bit-set
bit-test]))
;;;;;;;;;; Casting to ints <= 32-bits
(t/deftest casting-smaller
(let [n (binf.int64/i* -42)]
(t/is (= -42
(binf.int64/i8 n)
(binf.int64/i16 n)
(binf.int64/i32 n))
"Signed"))
(let [n (binf.int64/u* 42)]
(t/is (= 42
(binf.int64/u8 n)
(binf.int64/u16 n)
(binf.int64/u32 n))
"Unsigned")))
;;;;;;;;;; Bitwise operations from standard lib which does not work with js/BigInt
(t/deftest bit-clear
(t/is (zero? (binf.int64/u32 (binf.int64/bit-clear (binf.int64/u* 2r10)
(binf.int64/u* 1)))))
(t/is (zero? (binf.int64/u32 (binf.int64/bit-clear (binf.int64/u* 0)
(binf.int64/u* 1))))))
(t/deftest bit-flip
(t/is (zero? (binf.int64/u32 (binf.int64/bit-flip (binf.int64/u* 2r10)
(binf.int64/u* 1)))))
(t/is (= (binf.int64/u* 2)
(binf.int64/bit-flip (binf.int64/u* 2r00)
(binf.int64/u* 1)))))
(t/deftest bit-set
(t/is (= (binf.int64/u* 2)
(binf.int64/bit-set (binf.int64/u* 2r00)
(binf.int64/u* 1)))))
(t/deftest bit-test
(t/is (true? (binf.int64/bit-test (binf.int64/u* 2r10)
(binf.int64/u* 1))))
(t/is (false? (binf.int64/bit-test (binf.int64/u* 0)
(binf.int64/u* 1)))))
;;;;;;;;;; Unsigned logic tests
(def u64-max
(binf.int64/u* 0xffffffffffffffff))
(def u64-min
(binf.int64/u* 0))
(t/deftest u<
(t/is (binf.int64/u< u64-min
u64-max))
(t/is (false? (binf.int64/u< u64-max
u64-min)))
(t/is (false? (binf.int64/u< u64-max
u64-max))))
(t/deftest u<=
(t/is (binf.int64/u<= u64-min
u64-max))
(t/is (false? (binf.int64/u<= u64-max
u64-min)))
(t/is (binf.int64/u<= u64-max
u64-max)))
(t/deftest u>
(t/is (binf.int64/u> u64-max
u64-min))
(t/is (false? (binf.int64/u> u64-min
u64-max)))
(t/is (false? (binf.int64/u> u64-max
u64-max))))
(t/deftest u>=
(t/is (binf.int64/u>= u64-max
u64-min))
(t/is (false? (binf.int64/u>= u64-min
u64-max)))
(t/is (binf.int64/u>= u64-max
u64-max)))
;;;;;;;;;; Unsigned maths
(t/deftest udiv
(t/is (= (binf.int64/u* 0x7fffffffffffffff)
(binf.int64/udiv u64-max
(binf.int64/u* 2)))))
(t/deftest urem
(t/is (= (binf.int64/u* 1)
(binf.int64/urem (binf.int64/u* 10)
(binf.int64/u* 3)))))

View file

@ -0,0 +1,284 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at https://mozilla.org/MPL/2.0/.
(ns helins.binf.test.leb128
{:author "Adam Helins"}
(:require [clojure.test :as t]
[clojure.test.check.clojure-test :as tc.ct]
[clojure.test.check.properties :as tc.prop]
[helins.binf :as binf]
[helins.binf.buffer :as binf.buffer]
[helins.binf.gen :as binf.gen]
[helins.binf.int64 :as binf.int64]
[helins.binf.leb128 :as binf.leb128]))
;;;;;;;;;; int32
(t/deftest u32
(let [v (binf/view (binf.buffer/alloc 32))]
(-> v
(binf/seek 0)
(binf.leb128/wr-u32 0))
(t/is (= 1
(binf/position v)
(binf.leb128/n-byte-u32 0)))
(t/is (= 0
(-> v
(binf/seek 0)
(binf.leb128/rr-u32))))
(-> v
(binf/seek 0)
(binf.leb128/wr-u32 4294967295))
(t/is (= (binf.leb128/n-byte-max 32)
(binf/position v)
(binf.leb128/n-byte-u32 4294967295)))
(t/is (= 4294967295
(-> v
(binf/seek 0)
(binf.leb128/rr-u32))))))
(t/deftest i32
(let [v (binf/view (binf.buffer/alloc 32))]
(-> v
(binf/seek 0)
(binf.leb128/wr-i32 0))
(t/is (= 1
(binf/position v)
(binf.leb128/n-byte-i32 0)))
(t/is (= 0
(-> v
(binf/seek 0)
(binf.leb128/rr-i32))))
(-> v
(binf/seek 0)
(binf.leb128/wr-i32 2147483647))
(t/is (= (binf.leb128/n-byte-max 32)
(binf/position v)
(binf.leb128/n-byte-i32 2147483647)))
(t/is (= 2147483647
(-> v
(binf/seek 0)
(binf.leb128/rr-i32))))
(-> v
(binf/seek 0)
(binf.leb128/wr-i32 -2147483648))
(t/is (= (binf.leb128/n-byte-max 32)
(binf/position v)
(binf.leb128/n-byte-i32 -2147483648)))
(t/is (= -2147483648
(-> v
(binf/seek 0)
(binf.leb128/rr-i32))))
(-> v
(binf/seek 0)
(binf.leb128/wr-i32 -42))
(t/is (= 1
(binf/position v)
(binf.leb128/n-byte-i32 0)))
(t/is (= -42
(-> v
(binf/seek 0)
(binf.leb128/rr-i32))))
(-> v
(binf/seek 0)
(binf/wr-b8 0x7F))
(t/is (= 1
(binf/position v)
(binf.leb128/n-byte-i32 0)))
(t/is (= -1
(-> v
(binf/seek 0)
(binf.leb128/rr-i32))))))
;;;;;;;;;; int64
(t/deftest u64
(let [v (binf/view (binf.buffer/alloc 32))]
(-> v
(binf/seek 0)
(binf.leb128/wr-u64 (binf.int64/u* 0)))
(t/is (= 1
(binf/position v)
(binf.leb128/n-byte-u64 (binf.int64/u* 0))))
(t/is (= (binf.int64/u* 0)
(-> v
(binf/seek 0)
(binf.leb128/rr-u64))))
(-> v
(binf/seek 0)
(binf.leb128/wr-u64 (binf.int64/u* 18446744073709551615)))
(t/is (= (binf.leb128/n-byte-max 64)
(binf/position v)
(binf.leb128/n-byte-u64 (binf.int64/u* 18446744073709551615))))
(t/is (= (binf.int64/u* 18446744073709551615)
(-> v
(binf/seek 0)
(binf.leb128/rr-u64))))))
(t/deftest i64
(let [v (binf/view (binf.buffer/alloc 32))]
(-> v
(binf/seek 0)
(binf.leb128/wr-i64 (binf.int64/i* 0)))
(t/is (= 1
(binf/position v)
(binf.leb128/n-byte-i64 (binf.int64/i* 0))))
(t/is (= (binf.int64/i* 0)
(-> v
(binf/seek 0)
(binf.leb128/rr-i64))))
(-> v
(binf/seek 0)
(binf.leb128/wr-i64 (binf.int64/i* 9223372036854775807)))
(t/is (= (binf.leb128/n-byte-max 64)
(binf/position v)
(binf.leb128/n-byte-i64 (binf.int64/i* 9223372036854775807))))
(t/is (= (binf.int64/i* 9223372036854775807)
(-> v
(binf/seek 0)
(binf.leb128/rr-i64))))
(-> v
(binf/seek 0)
(binf.leb128/wr-i64 (binf.int64/i* -9223372036854775808)))
(t/is (= (binf.leb128/n-byte-max 64)
(binf/position v)
(binf.leb128/n-byte-i64 (binf.int64/i* -9223372036854775808))))
(t/is (= (binf.int64/i* -9223372036854775808)
(-> v
(binf/seek 0)
(binf.leb128/rr-i64))))
(-> v
(binf/seek 0)
(binf.leb128/wr-i64 (binf.int64/i* -42)))
(t/is (= 1
(binf/position v)
(binf.leb128/n-byte-i64 (binf.int64/i* -42))))
(t/is (= (binf.int64/i* -42)
(-> v
(binf/seek 0)
(binf.leb128/rr-i64))))
(-> v
(binf/seek 0)
(binf/wr-b8 0x7F))
(t/is (= 1
(binf/position v)
(binf.leb128/n-byte-i64 (binf.int64/i* -1))))
(t/is (= (binf.int64/i* -1)
(-> v
(binf/seek 0)
(binf.leb128/rr-i64))))))
;;;;;;;;;; Generative testing
(def view-gen
(-> (binf.leb128/n-byte-max 64)
binf.buffer/alloc
binf/view))
(tc.ct/defspec gen-i32
(tc.prop/for-all [i32 binf.gen/i32]
(= i32
(-> view-gen
(binf/seek 0)
(binf.leb128/wr-i32 i32)
(binf/seek 0)
binf.leb128/rr-i32))))
(tc.ct/defspec gen-u32
(tc.prop/for-all [u32 binf.gen/u32]
(= u32
(-> view-gen
(binf/seek 0)
(binf.leb128/wr-u32 u32)
(binf/seek 0)
binf.leb128/rr-u32))))
(tc.ct/defspec gen-i64
(tc.prop/for-all [i64 binf.gen/i64]
(= i64
(-> view-gen
(binf/seek 0)
(binf.leb128/wr-i64 i64)
(binf/seek 0)
binf.leb128/rr-i64))))
(tc.ct/defspec gen-u64
(tc.prop/for-all [u64 binf.gen/u64]
(= u64
(-> view-gen
(binf/seek 0)
(binf.leb128/wr-u64 u64)
(binf/seek 0)
binf.leb128/rr-u64))))

View file

@ -0,0 +1,137 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at https://mozilla.org/MPL/2.0/.
(ns helins.binf.test.native
""
{:author "Adam Helinski"}
(:require [clojure.test :as t]
[helins.binf.native :as binf.native]))
;;;;;;;;;;
(def n-byte
64)
(def ptr
(binf.native/alloc n-byte))
;;;;;
(t/deftest copy
(let [ptr (binf.native/alloc 64)]
(binf.native/w-b64 ptr
42)
(binf.native/copy (+ ptr
8)
ptr
8)
(t/is (= 42
(binf.native/r-b64 (+ ptr
8)))
"From low address to high")
(binf.native/w-b64 (+ ptr
8)
100)
(binf.native/copy ptr
(+ ptr
8)
8)
(t/is (= 100
(binf.native/r-b64 ptr))
"From high address to low")
(binf.native/copy (inc ptr)
ptr
24)
(t/is (= 100
(binf.native/r-b64 (inc ptr)))
"No corruption when dest address overlaps src address")))
(t/deftest free
(t/is (nil? (binf.native/free (binf.native/alloc 4)))))
(t/deftest realloc
(t/is (not (zero? (binf.native/realloc (binf.native/alloc 4)
8)))))
(t/deftest rw
(t/is (= -42
(do
(binf.native/w-b8 ptr
-42)
(binf.native/r-i8 ptr))
(do
(binf.native/w-b16 ptr
-42)
(binf.native/r-i16 ptr))
(do
(binf.native/w-b32 ptr
-42)
(binf.native/r-i32 ptr))
(do
(binf.native/w-b64 ptr
-42)
(binf.native/r-b64 ptr)))
"Signed")
(t/is (= 42
(do
(binf.native/w-b8 ptr
42)
(binf.native/r-u8 ptr))
(do
(binf.native/w-b16 ptr
42)
(binf.native/r-u16 ptr))
(do
(binf.native/w-b32 ptr
42)
(binf.native/r-u32 ptr))
(do
(binf.native/w-b64 ptr
42)
(binf.native/r-b64 ptr)))
"Unsigned")
(t/is (= (float 42.24)
(do
(binf.native/w-f32 ptr
42.24)
(binf.native/r-f32 ptr)))
"f32")
(t/is (= 42.24
(do
(binf.native/w-f64 ptr
42.24)
(binf.native/r-f64 ptr)))
"f64")
(t/is (= 0xffffffff
(do
(binf.native/w-ptr ptr
0xffffffff)
(binf.native/r-ptr ptr)))
"ptr"))

View file

@ -0,0 +1,42 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at https://mozilla.org/MPL/2.0/.
(ns helins.binf.test.string
""
{:author "Adam Helinski"}
(:require [clojure.test :as t]
#?@(:bb [] :clj [clojure.test.check.clojure-test :as tc.ct])
[clojure.test.check.generators :as tc.gen]
[clojure.test.check.properties :as tc.prop]
[helins.binf.string :as binf.string]))
;;;;;;;;;;
(def string
"²é&\"'(§è!çà)-aertyuiopqsdfhgklmwcvbnùµ,;:=")
(t/deftest main
(t/is (= string
(-> string
binf.string/encode
binf.string/decode))))
#_(tc.ct/defspec gen
(tc.prop/for-all [string tc.gen/string]
(= string
(-> string
binf.string/encode
binf.string/decode))))

View file

@ -561,6 +561,32 @@
(when test-utils/native? (when test-utils/native?
(is (= 'Something (bb nil "(.print (System/out) \"Something\")"))))) (is (= 'Something (bb nil "(.print (System/out) \"Something\")")))))
(deftest byte-buffer-test
(testing "interop with HeapByteBuffer"
(is (= 42 (bb nil "(count (.array (java.nio.ByteBuffer/allocate 42)))"))))
(testing "interop with HeapByteByfferR"
(is (bb nil "(.hasRemaining (.asReadOnlyBuffer (java.nio.ByteBuffer/allocate 42)))")))
(is (bb nil "
(import 'java.io.RandomAccessFile)
(import 'java.nio.channels.FileChannel$MapMode)
(def raf (RandomAccessFile. \"/tmp/binf-example.dat\" \"rw\"))
;; DirectByteBuffer
(def view (-> raf .getChannel (.map FileChannel$MapMode/READ_WRITE 0 4)))
;; interop with DirectByteBuffer
(.load view)
(.force view)
true"))
(is (bb nil "
(import 'java.io.RandomAccessFile)
(import 'java.nio.channels.FileChannel$MapMode)
(def raf (RandomAccessFile. \"/tmp/binf-example.dat\" \"r\"))
;; DirectByteBuffer
(def view (-> raf .getChannel (.map FileChannel$MapMode/READ_ONLY 0 4)))
;; interop with DirectByteBufferR
(.load view)
(.force view)
true")))
;;;; Scratch ;;;; Scratch
(comment (comment