module Network.Ethereum.Web3.Encoding.Bytes (
BytesN(..)
, BytesD(..)
) where
import qualified Data.ByteString.Base16 as BS16 (decode, encode)
import qualified Data.Attoparsec.Text as P
import qualified Data.Text.Lazy.Builder as B
import qualified Data.Text.Encoding as T
import qualified Data.Text as T
import qualified Data.ByteArray as BA
import Network.Ethereum.Web3.Encoding.Internal
import Network.Ethereum.Web3.Encoding
import GHC.TypeLits (KnownNat, Nat, natVal)
import Data.Monoid (Monoid(..), (<>))
import Data.ByteArray (Bytes)
import Debug.Trace
newtype BytesN (n :: Nat) = BytesN { unBytesN :: Bytes }
deriving (Eq, Ord)
update :: BytesN a -> Bytes -> BytesN a
update _ = BytesN
instance KnownNat n => EncodingType (BytesN n) where
typeName = const "bytes[N]"
isDynamic = const False
instance KnownNat n => ABIEncoding (BytesN n) where
toDataBuilder (BytesN bytes) = bytesBuilder bytes
fromDataParser = do
let result = undefined :: KnownNat n => BytesN n
len = fromIntegral (natVal result)
bytesString <- T.take (len * 2) <$> P.take 64
return (update result (bytesDecode bytesString))
instance KnownNat n => Show (BytesN n) where
show = show . BS16.encode . BA.convert . unBytesN
bytesBuilder :: Bytes -> B.Builder
bytesBuilder = alignL . B.fromText . T.decodeUtf8
. BS16.encode . BA.convert
bytesDecode :: T.Text -> Bytes
bytesDecode = BA.convert . fst . BS16.decode . T.encodeUtf8
newtype BytesD = BytesD { unBytesD :: Bytes }
deriving (Eq, Ord)
instance Monoid BytesD where
mempty = BytesD mempty
mappend (BytesD a) (BytesD b) = BytesD (mappend a b)
instance EncodingType BytesD where
typeName = const "bytes[]"
isDynamic = const True
instance ABIEncoding BytesD where
toDataBuilder (BytesD bytes) = int256HexBuilder (BA.length bytes)
<> bytesBuilder bytes
fromDataParser = do
len <- int256HexParser
if (len :: Integer) > fromIntegral (maxBound :: Int)
then fail "Bytes length over bound!"
else (BytesD . bytesDecode) <$> P.take (fromIntegral len * 2)
instance Show BytesD where
show = show . BS16.encode . BA.convert . unBytesD