From c68097c4e6a4ec6186c9dc22b72d81043ed318d5 Mon Sep 17 00:00:00 2001 From: Leon Mergen Date: Mon, 20 Apr 2015 09:39:58 +0700 Subject: [PATCH] Initial check in of first version, including tests --- .gitignore | 8 ++--- .travis.yml | 60 ++++++++++++++++++++++++++++++++++++++ README.md | 12 ++++++-- Setup.hs | 3 ++ hexstring.cabal | 56 +++++++++++++++++++++++++++++++++++ src/Data/HexString.hs | 45 ++++++++++++++++++++++++++++ test/Data/HexStringSpec.hs | 23 +++++++++++++++ test/Main.hs | 8 +++++ test/Spec.hs | 1 + 9 files changed, 208 insertions(+), 8 deletions(-) create mode 100644 .travis.yml create mode 100644 Setup.hs create mode 100644 hexstring.cabal create mode 100644 src/Data/HexString.hs create mode 100644 test/Data/HexStringSpec.hs create mode 100644 test/Main.hs create mode 100644 test/Spec.hs diff --git a/.gitignore b/.gitignore index 3f4aa15..eefe19f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,13 +4,9 @@ cabal-dev *.hi *.chi *.chs.h -*.dyn_o -*.dyn_hi +*.tix .virtualenv -.hpc .hsenv .cabal-sandbox/ cabal.sandbox.config -*.prof -*.aux -*.hp +cabal.config diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..cedf6ac --- /dev/null +++ b/.travis.yml @@ -0,0 +1,60 @@ +language: c +env: + - CABALVER=1.22 GHCVER=7.8.4 + - CABALVER=1.22 GHCVER=7.10.1 + - CABALVER=1.22 GHCVER=head + +matrix: + allow_failures: + - env: CABALVER=1.22 GHCVER=7.10.1 + - env: CABALVER=1.22 GHCVER=head + +before_install: +# Installing cabal and ghc + - travis_retry sudo add-apt-repository -y ppa:hvr/ghc + - travis_retry sudo apt-get update + - travis_retry sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER # see note about happy/alex + - export PATH=$HOME/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH + - travis_retry cabal update + + - | + if [ $GHCVER = "head" ] || [ ${GHCVER%.*} = "7.8" ] || [ ${GHCVER%.*} = "7.10" ]; then + travis_retry sudo apt-get install happy-1.19.4 alex-3.1.3 + export PATH=/opt/alex/3.1.3/bin:/opt/happy/1.19.4/bin:$PATH + else + travis_retry sudo apt-get install happy alex + fi + + - cabal install hlint + +# Install hpc-coveralls + - travis_retry cabal sandbox init + - cabal install hpc-coveralls -j --bindir=$HOME/.cabal/bin/ --constraint='aeson >= 0.7' + - cabal sandbox delete + +install: + - cabal --version + - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]" + - travis_retry cabal install --only-dependencies --enable-tests --enable-benchmarks -j + +script: + - hlint src --ignore="Parse error" + - cabal configure --enable-tests --enable-benchmarks --enable-library-coverage + - cabal build -j + - run-cabal-test --cabal-name=cabal --show-details=always + - cabal check + - cabal sdist + +# The following scriptlet checks that the resulting source distribution can be built & installed + - export SRC_TGZ=$(cabal info . | awk '{print $2 ".tar.gz";exit}') ; + cd dist/; + if [ -f "$SRC_TGZ" ]; then + cabal install --force-reinstalls "$SRC_TGZ"; + else + echo "expected '$SRC_TGZ' not found"; + exit 1; + fi ; + cd ../ + +after_script: + - hpc-coveralls test-suite --exclude-dir=test --display-report diff --git a/README.md b/README.md index 696d49c..a063140 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ -# haskell-hexstring -Fast and safe representation of hex string +haskell-bitcoin-script +================== + +[![Build Status](https://travis-ci.org/solatis/haskell-bitcoin-script.png?branch=master)](https://travis-ci.org/solatis/haskell-bitcoin-script) +[![Coverage Status](https://coveralls.io/repos/solatis/haskell-bitcoin-script/badge.svg?branch=master)](https://coveralls.io/r/solatis/haskell-bitcoin-script?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) + +This library provides utilities for compiling, manipulation and decompiling of +Bitcoin scripts. diff --git a/Setup.hs b/Setup.hs new file mode 100644 index 0000000..e8ef27d --- /dev/null +++ b/Setup.hs @@ -0,0 +1,3 @@ +import Distribution.Simple + +main = defaultMain diff --git a/hexstring.cabal b/hexstring.cabal new file mode 100644 index 0000000..305203f --- /dev/null +++ b/hexstring.cabal @@ -0,0 +1,56 @@ +name: hexstring +category: Network, Finance +version: 0.1.0 +license: MIT +license-file: LICENSE +copyright: (c) 2015 Leon Mergen +author: Leon Mergen +maintainer: leon@solatis.com +homepage: http://www.leonmergen.com/opensource.html +bug-reports: http://github.com/solatis/haskell-hexstring/issues +stability: experimental +synopsis: Fast and safe representation of a hex string +description: + Provides an interface for representing a HexString. It uses fast conversion + functions to convert to-and-from String or Text formats. Internally, the + HexString is represented by a ByteString. + +build-type: Simple +data-files: LICENSE, README.md +cabal-version: >= 1.10 +tested-with: GHC == 7.6, GHC == 7.8, GHC == 7.10 + +library + hs-source-dirs: src + ghc-options: -Wall -ferror-spans + default-language: Haskell2010 + + exposed-modules: Data.HexString + + build-depends: base >= 4.3 && < 5 + , text + , bytestring + , base16-bytestring + +test-suite test-suite + type: exitcode-stdio-1.0 + ghc-options: -Wall -ferror-spans -threaded -auto-all -caf-all -fno-warn-type-defaults + default-language: Haskell2010 + hs-source-dirs: test + main-is: Main.hs + + other-modules: Data.HexStringSpec + Spec + Main + + build-depends: base >= 4.3 && < 5 + , hspec + , text + + , bytestring + , hexstring + +source-repository head + type: git + location: git://github.com/solatis/haskell-bitcoin-script.git + branch: master diff --git a/src/Data/HexString.hs b/src/Data/HexString.hs new file mode 100644 index 0000000..2d9d88f --- /dev/null +++ b/src/Data/HexString.hs @@ -0,0 +1,45 @@ +module Data.HexString where + +import qualified Data.ByteString as BS +import qualified Data.ByteString.Char8 as BS8 +import qualified Data.ByteString.Base16 as BS16 + +import qualified Data.Text as T +import qualified Data.Text.Encoding as TE + +-- | Data type representing a HexString. +data HexString + = HexString !BS.ByteString + deriving ( Show, Eq, Ord ) + +-- | Access to the raw binary data this HexString represents +getBinary :: HexString -> BS.ByteString +getBinary (HexString bs) = bs + +-- | Create new HexString based on raw binary data +setBinary :: BS.ByteString -> HexString +setBinary = HexString + +-- | Converts `BS.ByteString` to a `HexString` +decodeByteString :: BS.ByteString -> HexString +decodeByteString = HexString . fst . BS16.decode + +-- | Converts a `T.Text` representation to a `HexString` +decodeText :: T.Text -> HexString +decodeText = decodeByteString . TE.encodeUtf8 + +-- | Converts a `String` representation to a `HexString` +decodeString :: String -> HexString +decodeString = decodeByteString . BS8.pack + +-- | Converts a `HexString` to a `BS.ByteString` +encodeByteString :: HexString -> BS.ByteString +encodeByteString = BS16.encode . getBinary + +-- | Converts a `HexString` to a `T.Text` representation +encodeText :: HexString -> T.Text +encodeText = TE.decodeUtf8 . encodeByteString + +-- | Converts a `HexString` to a `String` representation +encodeString :: HexString -> String +encodeString = BS8.unpack . encodeByteString diff --git a/test/Data/HexStringSpec.hs b/test/Data/HexStringSpec.hs new file mode 100644 index 0000000..c3614b0 --- /dev/null +++ b/test/Data/HexStringSpec.hs @@ -0,0 +1,23 @@ +module Data.HexStringSpec where + +import Data.HexString + +import qualified Data.ByteString.Char8 as BS8 +import qualified Data.Text as T + +import Test.Hspec + +spec :: Spec +spec = do + describe "when decoding hex data" $ do + it "should be able to parse basic hex data" $ do + (getBinary . decodeByteString) (BS8.pack "ffff") `shouldBe` BS8.pack "\255\255" + (getBinary . decodeString) "ffff" `shouldBe` BS8.pack "\255\255" + (getBinary . decodeText) (T.pack "ffff") `shouldBe` BS8.pack "\255\255" + + it "should be able to recode basic hex data to different formats" $ + let hex = BS8.pack "ffff" + in do + (encodeText . decodeByteString) hex `shouldBe` T.pack "ffff" + (encodeString . decodeByteString) hex `shouldBe` "ffff" + (encodeByteString . decodeByteString) hex `shouldBe` BS8.pack "ffff" diff --git a/test/Main.hs b/test/Main.hs new file mode 100644 index 0000000..7e63552 --- /dev/null +++ b/test/Main.hs @@ -0,0 +1,8 @@ +module Main where + +import Test.Hspec.Runner +import qualified Spec + +main :: IO () +main = + hspecWith defaultConfig Spec.spec diff --git a/test/Spec.hs b/test/Spec.hs new file mode 100644 index 0000000..5416ef6 --- /dev/null +++ b/test/Spec.hs @@ -0,0 +1 @@ +{-# OPTIONS_GHC -F -pgmF hspec-discover -optF --module-name=Spec #-}