From 4856ec516f0733c8aef065166a417a358f12fe62 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Mon, 5 Feb 2024 15:18:01 -0600 Subject: [PATCH] Borsh serialization for HexString --- CHANGELOG.md | 1 + README.md | 5 ---- hexstring.cabal | 3 ++ package.yaml | 3 ++ src/Data/HexString.hs | 64 +++++++++++++++++++++++++++---------------- stack.yaml | 6 ++++ 6 files changed, 53 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e74184..67385b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - CHANGELOG.md - Stack integration +- Borsh serialization for `HexString` ### Changed diff --git a/README.md b/README.md index 45afa52..5bdd5d1 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,4 @@ haskell-hexstring ================= -[![Build Status](https://travis-ci.org/solatis/haskell-hexstring.png?branch=master)](https://travis-ci.org/solatis/haskell-hexstring) -[![Coverage Status](https://coveralls.io/repos/solatis/haskell-hexstring/badge.svg?branch=master)](https://coveralls.io/r/solatis/haskell-hexstring?branch=master) -[![MIT](http://b.repl.ca/v1/license-MIT-blue.png)](http://en.wikipedia.org/wiki/MIT_License) -[![Haskell](http://b.repl.ca/v1/language-haskell-lightgrey.png)](http://haskell.org) - Fast and safe representation of a hex string diff --git a/hexstring.cabal b/hexstring.cabal index 56b5d84..a675077 100644 --- a/hexstring.cabal +++ b/hexstring.cabal @@ -35,7 +35,10 @@ library , base >=4.7 && <5 , base16-bytestring , binary + , borsh >=0.2 , bytestring + , foreign-rust + , generics-sop , text default-language: Haskell2010 diff --git a/package.yaml b/package.yaml index 680f2d2..bee7374 100644 --- a/package.yaml +++ b/package.yaml @@ -27,6 +27,9 @@ library: - bytestring - base16-bytestring - aeson + - generics-sop + - borsh >= 0.2 + - foreign-rust tests: hextring-test: diff --git a/src/Data/HexString.hs b/src/Data/HexString.hs index 3caebcf..d66ae6c 100644 --- a/src/Data/HexString.hs +++ b/src/Data/HexString.hs @@ -1,36 +1,53 @@ -module Data.HexString ( HexString - , hexString - , fromBinary - , toBinary - , fromBytes - , toBytes - , toText ) where +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE OverloadedStrings #-} -import Control.Applicative (pure) +module Data.HexString + ( HexString + , hexString + , fromBinary + , toBinary + , fromBytes + , toBytes + , toText + ) where -import Data.Aeson -import Data.Word (Word8) +import Codec.Borsh +import Control.Applicative (pure) -import qualified Data.ByteString as BS +import Data.Aeson +import Data.Word (Word8) + +import qualified Data.ByteString as BS import qualified Data.ByteString.Base16 as BS16 (decodeLenient, encode) -import qualified Data.ByteString.Lazy as BSL +import qualified Data.ByteString.Lazy as BSL -import qualified Data.Text as T -import qualified Data.Text.Encoding as TE +import Data.Structured +import qualified Data.Text as T +import qualified Data.Text.Encoding as TE -import qualified Data.Binary as B (Binary, decode, encode) +import qualified Data.Binary as B (Binary, decode, encode) + +import qualified GHC.Generics as GHC +import qualified Generics.SOP as SOP -- | Represents a Hex string. Guarantees that all characters it contains -- are valid hex characters. data HexString = HexString BS.ByteString - deriving ( Show, Eq, Ord ) + deriving stock (Prelude.Show, GHC.Generic) + deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo) + deriving anyclass (Data.Structured.Show) + deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct HexString instance FromJSON HexString where parseJSON = withText "HexString" $ pure . hexString . TE.encodeUtf8 instance ToJSON HexString where - toJSON = String . toText + toJSON = Data.Aeson.String . toText -- | Smart constructor which validates that all the text are actually -- hexadecimal characters. @@ -38,16 +55,15 @@ hexString :: BS.ByteString -> HexString hexString bs = let isValidHex :: Word8 -> Bool isValidHex c - | (48 <= c) && (c < 58) = True + | (48 <= c) && (c < 58) = True | (97 <= c) && (c < 103) = True - | otherwise = False - - in if BS.all isValidHex bs - then HexString bs - else error ("Not a valid hex string: " ++ show bs) + | otherwise = False + in if BS.all isValidHex bs + then HexString bs + else error ("Not a valid hex string: " ++ Prelude.show bs) -- | Converts a 'B.Binary' to a 'HexString' value -fromBinary :: B.Binary a => a -> HexString +fromBinary :: B.Binary a => a -> HexString fromBinary = hexString . BS16.encode . BSL.toStrict . B.encode -- | Converts a 'HexString' to a 'B.Binary' value diff --git a/stack.yaml b/stack.yaml index 346aa08..7879a40 100644 --- a/stack.yaml +++ b/stack.yaml @@ -2,3 +2,9 @@ resolver: lts-21.22 packages: - . + +extra-deps: + - git: https://github.com/well-typed/borsh.git + commit: d2fcfa159e0a844b1ec5e8ed3e232d4b380fa831 + - git: https://git.vergara.tech/Vergara_Tech/haskell-foreign-rust.git + commit: 787c2e813eb3a5d16c375d4b37dfefbd2adcdf05