packages feed

web3-bignum-1.0.0.0: src/Data/BigNum.hs

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings          #-}

-- |
-- Module      :  Data.BigNum
-- Copyright   :  Aleksandr Krupenkin 2016-2021
-- License     :  Apache-2.0
--
-- Maintainer  :  mail@akru.me
-- Stability   :  experimental
-- Portability :  unportable
--
-- Big numbers and codecs for Haskell Web3 library.
--

module Data.BigNum (Word256, Word128, H160, h160, H256, h256, H512, h512) where

import           Codec.Scale                      ()
import           Codec.Scale.Class                (Decode (..), Encode (..))
import           Data.ByteArray                   (ByteArrayAccess, Bytes,
                                                   convert)
import qualified Data.ByteArray                   as A (length)
import           Data.ByteArray.HexString.Convert (FromHex (..), ToHex (..),
                                                   fromBytes)
import           Data.Maybe                       (fromJust)
import           Data.Serialize.Get               (getByteString)
import           Data.Serialize.Put               (putByteString)
import           Data.String                      (IsString (..))
import           Data.WideWord.Word128            (Word128 (..))
import           Data.WideWord.Word256            (Word256 (..))

instance Encode Word128 where
    put (Word128 l h)= put h >> put l

instance Decode Word128 where
    get = flip Word128 <$> get <*> get

instance Encode Word256 where
    put (Word256 lx hx l h) = do
        put h
        put l
        put hx
        put lx

instance Decode Word256 where
    get = do
        h <- get
        l <- get
        hx <- get
        lx <- get
        return (Word256 lx hx l h)

-- | 20 byte of data.
newtype H160 = H160 Bytes
    deriving (Eq, Ord, ByteArrayAccess)

-- | Convert any 20 byte array into H160 type, otherwise returns Nothing.
h160 :: ByteArrayAccess a => a -> Maybe H160
h160 ba
  | A.length ba == 20 = Just $ H160 (convert ba)
  | otherwise = Nothing

instance FromHex H160 where
    fromHex bs
      | A.length bs == 20 = Right $ H160 (convert bs)
      | otherwise = Left ("wrong length: " ++ show (A.length bs))

instance ToHex H160 where
    toHex = fromBytes

instance Show H160 where
    show = show . toHex

instance IsString H160 where
    fromString = either error id . fromHex . fromString

instance Encode H160 where
    put = putByteString . convert

instance Decode H160 where
    get = (fromJust . h160) <$> getByteString 20

-- | 32 byte of data.
newtype H256 = H256 Bytes
    deriving (Eq, Ord, ByteArrayAccess)

-- | Convert any 32 byte array into H256 type, otherwise returns Nothing.
h256 :: ByteArrayAccess a => a -> Maybe H256
h256 ba
  | A.length ba == 32 = Just $ H256 (convert ba)
  | otherwise = Nothing

instance FromHex H256 where
    fromHex bs
      | A.length bs == 32 = Right $ H256 (convert bs)
      | otherwise = Left ("wrong length: " ++ show (A.length bs))

instance ToHex H256 where
    toHex = fromBytes

instance Show H256 where
    show = show . toHex

instance IsString H256 where
    fromString = either error id . fromHex . fromString

instance Encode H256 where
    put = putByteString . convert

instance Decode H256 where
    get = (fromJust . h256) <$> getByteString 32

-- | 64 byte of data.
newtype H512 = H512 Bytes
    deriving (Eq, Ord, ByteArrayAccess)

-- | Convert any 64 byte array into H512 type, otherwise returns Nothing.
h512 :: ByteArrayAccess a => a -> Maybe H512
h512 ba
  | A.length ba == 64 = Just $ H512 (convert ba)
  | otherwise = Nothing

instance FromHex H512 where
    fromHex bs
      | A.length bs == 64 = Right $ H512 (convert bs)
      | otherwise = Left ("wrong length: " ++ show (A.length bs))

instance ToHex H512 where
    toHex = fromBytes

instance Show H512 where
    show = show . toHex

instance IsString H512 where
    fromString = either error id . fromHex . fromString

instance Encode H512 where
    put = putByteString . convert

instance Decode H512 where
    get = (fromJust . h512) <$> getByteString 64