[#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"}
version-clj/version-clj {:mvn/version "2.0.1"}
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
org.clojure/spec.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.FilenameFilter
java.io.FileNotFoundException
java.io.RandomAccessFile
java.io.InputStream
java.io.IOException
java.io.OutputStream
@ -154,7 +155,19 @@
java.net.URLEncoder
java.net.URLDecoder
~@(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.DirectoryNotEmptyException
java.nio.file.FileAlreadyExistsException
@ -344,7 +357,17 @@
(instance? java.nio.file.PathMatcher v)
java.nio.file.PathMatcher
(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))

View file

@ -196,6 +196,8 @@
'rewrite-clj.zip.subedit-test
'rewrite-clj.node.coercer-test)
(test-namespaces 'helins.binf.test)
;;;; final exit code
(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?
(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
(comment