[feature] add varint encoding/decoding

Signed-off-by: yenda <eric@status.im>
This commit is contained in:
yenda 2019-05-02 10:47:49 +02:00
parent b542c7de26
commit 9b18f1d261
No known key found for this signature in database
GPG Key ID: 0095623C0069DCE6
2 changed files with 82 additions and 0 deletions

View File

@ -0,0 +1,54 @@
(ns ^{:doc "Implementation of varint based on https://github.com/chrisdickinson/varint"}
status-im.utils.varint
(:require [status-im.utils.ethereum.abi-spec :as abi-spec]
[status-im.js-dependencies :as dependencies]))
(def utils dependencies/web3-utils)
(def most-significant-bit 0x80)
(def biggest-int-per-byte 0x7F)
(def biggest-int 2147483648) ;; 2^31
(defn encode [num]
(loop [num num
out []]
(if (>= num 128)
(recur (if (>= num biggest-int)
(/ num 128)
(bit-shift-right num 7))
(conj out (bit-or (bit-and num 0xFF)
most-significant-bit)))
(conj out (bit-or num 0)))))
(defn encode-hex [num]
(reduce (fn [hex current-bit]
(str hex
(.leftPad utils
(abi-spec/number-to-hex current-bit)
2)))
""
(encode num)))
(defn add-b-to-res
[res b shift]
(+ res (if (< shift 28)
(bit-shift-left (bit-and b biggest-int-per-byte)
shift)
(* (bit-and b biggest-int-per-byte)
shift shift))))
(defn decode [buf]
(loop [res 0
shift 0
[b & rest-buf] buf]
(if (>= b most-significant-bit)
(recur (add-b-to-res res b shift)
(+ shift 7)
rest-buf)
(add-b-to-res res b shift))))
(defn decode-hex [hex]
(->> hex
(partition 2)
(mapv #(abi-spec/hex-to-number (apply str %)))
decode))

View File

@ -0,0 +1,28 @@
(ns status-im.test.utils.varint
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.utils.varint :as varint]))
(deftest encode
(is (= (varint/encode-hex 0x0)
"0"))
(is (= (varint/encode-hex 0x70)
"70"))
(is (= (varint/encode-hex 0xe3)
"e301")))
(deftest decode
(is (= (varint/decode-hex "0")
0x0))
(is (= (varint/decode-hex "70")
0x70))
(is (= (varint/decode-hex "e301")
0xe301)))
(defn test-roundtrip [n]
(= (varint/decode-hex (varint/encode-hex n))
n))
(deftest roundtrip
(is (test-roundtrip 0))
(is (test-roundtrip 23948))
(is (test-roundtrip 2684453)))