bitcoin-hash-0.1: lib/Bitcoin/Hash/GHCJS.hs
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE JavaScriptFFI #-}
{-# OPTIONS_HADDOCK not-home #-}
-- | Implementation to be used when compiled with GHCJS
module Bitcoin.Hash.GHCJS
( hash160
, hash256
, ripemd160
, sha256
, hmacSHA512
) where
import qualified Data.ByteString as B
import qualified GHCJS.Buffer as Buf
import qualified JavaScript.TypedArray.ArrayBuffer as AB
import qualified JavaScript.TypedArray as TA
--------------------------------------------------------------------------------
-- | @'hash160' == 'ripemd160' . 'sha256'@
hash160
:: B.ByteString -- ^ Data to hash.
-> B.ByteString -- ^ 160-bit long digest.
{-# INLINE hash160 #-}
hash160 = byteStringFromUint8Array
. js_ripemd160
. js_sha256
. byteStringToUint8Array
--------------------------------------------------------------------------------
-- | @'hash256' == 'sha256' . 'sha256'@
hash256
:: B.ByteString -- ^ Data to hash.
-> B.ByteString -- ^ 256-bit long digest.
{-# INLINE hash256 #-}
hash256 = byteStringFromUint8Array
. js_sha256
. js_sha256
. byteStringToUint8Array
--------------------------------------------------------------------------------
-- | RIPEMD-160
ripemd160
:: B.ByteString -- ^ Data to hash.
-> B.ByteString -- ^ 160-bits long digest.
{-# INLINE ripemd160 #-}
ripemd160 = byteStringFromUint8Array . js_ripemd160 . byteStringToUint8Array
foreign import javascript unsafe "h$bitcoin_hash.ripemd160($1)"
js_ripemd160 :: TA.Uint8Array -> TA.Uint8Array
--------------------------------------------------------------------------------
-- | SHA256
sha256
:: B.ByteString -- ^ Data to hash.
-> B.ByteString -- ^ 256-bits long digest.
{-# INLINE sha256 #-}
sha256 = byteStringFromUint8Array . js_sha256 . byteStringToUint8Array
foreign import javascript unsafe "h$bitcoin_hash.sha256($1)"
js_sha256 :: TA.Uint8Array -> TA.Uint8Array
--------------------------------------------------------------------------------
-- | HMAC-SHA512
hmacSHA512
:: B.ByteString -- ^ Arbitrary length key.
-> B.ByteString -- ^ Data to hash.
-> B.ByteString -- ^ 64-byte long digest.
{-# INLINE hmacSHA512 #-}
hmacSHA512 k d =
byteStringFromUint8Array $ js_hmacSHA512 (byteStringToUint8Array k)
(byteStringToUint8Array d)
foreign import javascript unsafe "h$bitcoin_hash.hmacSHA512($1, $2)"
js_hmacSHA512 :: TA.Uint8Array -> TA.Uint8Array -> TA.Uint8Array
--------------------------------------------------------------------------------
byteStringToUint8Array :: B.ByteString -> TA.Uint8Array
{-# INLINE byteStringToUint8Array #-}
byteStringToUint8Array = \x -> case B.length x of
0 -> js_emptyUint8Array
_ -> let (buf, off, len) = Buf.fromByteString x
in js_newUint8Array (Buf.getArrayBuffer buf) off len
foreign import javascript unsafe "new Uint8Array($1, $2, $3)"
js_newUint8Array :: AB.ArrayBuffer -> Int -> Int -> TA.Uint8Array
foreign import javascript unsafe "new Uint8Array(0)"
js_emptyUint8Array :: TA.Uint8Array
--------------------------------------------------------------------------------
byteStringFromUint8Array :: TA.Uint8Array -> B.ByteString
{-# INLINE byteStringFromUint8Array #-}
byteStringFromUint8Array = \x ->
Buf.toByteString (TA.byteOffset x)
(Just (TA.byteLength x))
(Buf.createFromArrayBuffer (TA.buffer x))