base58-bytestring 0.0.3 → 0.1.0
raw patch · 4 files changed
+123/−55 lines, 4 filesdep +criterionPVP ok
version bump matches the API change (PVP)
Dependencies added: criterion
API changes (from Hackage documentation)
- Data.ByteString.Base58: instance Constructor C1_0Alphabet
- Data.ByteString.Base58: instance Datatype D1Alphabet
- Data.ByteString.Base58: instance Eq Alphabet
- Data.ByteString.Base58: instance Generic Alphabet
- Data.ByteString.Base58: instance IsString Alphabet
- Data.ByteString.Base58: instance Ord Alphabet
- Data.ByteString.Base58: instance Selector S1_0_0Alphabet
- Data.ByteString.Base58: instance Show Alphabet
- Data.ByteString.Base58: instance Typeable Alphabet
+ Data.ByteString.Base58.Internal: Alphabet :: ByteString -> Alphabet
+ Data.ByteString.Base58.Internal: b58 :: Alphabet -> Int -> Word8
+ Data.ByteString.Base58.Internal: b58' :: Alphabet -> Word8 -> Maybe Int
+ Data.ByteString.Base58.Internal: bitcoinAlphabet :: Alphabet
+ Data.ByteString.Base58.Internal: bsToInteger :: ByteString -> Integer
+ Data.ByteString.Base58.Internal: flickrAlphabet :: Alphabet
+ Data.ByteString.Base58.Internal: instance Constructor C1_0Alphabet
+ Data.ByteString.Base58.Internal: instance Datatype D1Alphabet
+ Data.ByteString.Base58.Internal: instance Eq Alphabet
+ Data.ByteString.Base58.Internal: instance Generic Alphabet
+ Data.ByteString.Base58.Internal: instance IsString Alphabet
+ Data.ByteString.Base58.Internal: instance Ord Alphabet
+ Data.ByteString.Base58.Internal: instance Selector S1_0_0Alphabet
+ Data.ByteString.Base58.Internal: instance Show Alphabet
+ Data.ByteString.Base58.Internal: instance Typeable Alphabet
+ Data.ByteString.Base58.Internal: integerToBS :: Integer -> ByteString
+ Data.ByteString.Base58.Internal: newtype Alphabet
+ Data.ByteString.Base58.Internal: rippleAlphabet :: Alphabet
+ Data.ByteString.Base58.Internal: unAlphabet :: Alphabet -> ByteString
Files
- base58-bytestring.cabal +19/−1
- bench/Main.hs +41/−0
- src/Data/ByteString/Base58.hs +8/−54
- src/Data/ByteString/Base58/Internal.hs +55/−0
base58-bytestring.cabal view
@@ -1,5 +1,5 @@ name: base58-bytestring-version: 0.0.3+version: 0.1.0 synopsis: Implementation of BASE58 transcoding for ByteStrings description: Implementation of BASE58 transcoding copy-pasted from@@ -20,6 +20,7 @@ library exposed-modules: Data.ByteString.Base58+ , Data.ByteString.Base58.Internal default-extensions: OverloadedStrings , DeriveDataTypeable@@ -40,6 +41,7 @@ hs-source-dirs: test ghc-options: -Wall -rtsopts -threaded+ default-language: Haskell2010 build-depends: base >=4.6 && < 5 , base58-bytestring@@ -48,3 +50,19 @@ , quickcheck-instances , tasty , tasty-quickcheck+++benchmark bench+ type: exitcode-stdio-1.0+ main-is: Main.hs++ default-extensions: OverloadedStrings++ hs-source-dirs: bench+ ghc-options: -Wall -rtsopts -threaded+ default-language: Haskell2010++ build-depends: base >=4.6 && < 5+ , base58-bytestring+ , bytestring+ , criterion
+ bench/Main.hs view
@@ -0,0 +1,41 @@+module Main where++import Data.Word+import Criterion.Main+import Data.ByteString ( ByteString )+import Data.ByteString.Base58++import qualified Data.ByteString as BS++symChars :: [Word8]+symChars = cycle+ $ BS.unpack+ $ unAlphabet bitcoinAlphabet++symN :: Int -> ByteString+symN n = BS.pack+ $ take n+ $ symChars++nameVal :: [(String, Int)]+nameVal = [ ("10 bytes", 10)+ , ("42 bytes", 100)+ , ("100 bytes", 1000) ]++main :: IO ()+main = defaultMain+ [ bgroup "encodeBase58I"+ [ bench "approx 10 bytes (1e24)" $ nf (encodeBase58I bitcoinAlphabet) 1000000000000000000000000+ , bench "approx 42 bytes (1e100)" $ nf (encodeBase58I bitcoinAlphabet) 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+ , bench "approx 100 bytes (1e240)" $ nf (encodeBase58I bitcoinAlphabet) 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+ ]++ , bgroup "decodeBase58I"+ $ map (\(name, val) -> bench name $ nf (decodeBase58I bitcoinAlphabet) $ symN val) nameVal++ , bgroup "encodeBase58"+ $ map (\(name, val) -> bench name $ nf (encodeBase58 bitcoinAlphabet) $ symN val) nameVal++ , bgroup "decodeBase58"+ $ map (\(name, val) -> bench name $ nf (decodeBase58 bitcoinAlphabet) $ symN val) nameVal+ ]
src/Data/ByteString/Base58.hs view
@@ -13,45 +13,16 @@ ) where import Control.Applicative-import Data.Bits import Data.ByteString ( ByteString )+import Data.ByteString.Base58.Internal import Data.Char (chr, ord) import Data.Maybe-import Data.String-import Data.Typeable ( Typeable )-import Data.Word-import GHC.Generics ( Generic ) import Numeric import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as BC-import qualified Data.List as L -newtype Alphabet =- Alphabet- { unAlphabet :: ByteString- } deriving (Ord, Eq, Show, Typeable, Generic, IsString) -bitcoinAlphabet :: Alphabet-bitcoinAlphabet =- "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"--rippleAlphabet :: Alphabet-rippleAlphabet =- "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"--flickrAlphabet :: Alphabet-flickrAlphabet =- "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"---- | Take 'i' byte from alphabet-b58 :: Alphabet -> Int -> Word8-b58 a i = BS.index (unAlphabet a) i---- | Lookup position of byte 'w' in alphabet-b58' :: Alphabet -> Word8 -> Maybe Int-b58' a w = BS.elemIndex w (unAlphabet a)- encodeBase58I :: Alphabet -> Integer -> ByteString encodeBase58I alpha i = BC.pack $ showIntAtBase 58 f i ""@@ -60,14 +31,13 @@ f = chr . fromIntegral . b58 alpha . fromIntegral decodeBase58I :: Alphabet -> ByteString -> Maybe Integer-decodeBase58I alpha s = case go of- Just (r,[]) -> Just r- _ -> Nothing- where- c = b58' alpha . fromIntegral . ord- p = isJust . c- f = fromIntegral . fromJust . c- go = listToMaybe $ readInt 58 p f (BC.unpack s)+decodeBase58I alpha s =+ let c = b58' alpha . fromIntegral . ord+ p = isJust . c+ f = fromIntegral . fromJust . c+ in case readInt 58 p f (BC.unpack s) of+ [(r,[])] -> Just r+ _ -> Nothing -- | Encode a bytestring to a base 58 representation. encodeBase58 :: Alphabet -> ByteString -> ByteString@@ -91,19 +61,3 @@ r | BS.null b = Just BS.empty | otherwise = integerToBS <$> decodeBase58I alpha b in BS.append prefix <$> r---- | Decode a big endian Integer from a bytestring-bsToInteger :: ByteString -> Integer-bsToInteger = (L.foldl' f 0) . BS.unpack- where- f n w = (toInteger w) .|. shiftL n 8---- | Encode an Integer to a bytestring as big endian-integerToBS :: Integer -> ByteString-integerToBS 0 = BS.pack [0]-integerToBS i- | i > 0 = BS.pack $ reverse $ L.unfoldr f i- | otherwise = error "integerToBS not defined for negative values"- where- f 0 = Nothing- f x = Just $ (fromInteger x :: Word8, x `shiftR` 8)
+ src/Data/ByteString/Base58/Internal.hs view
@@ -0,0 +1,55 @@+module Data.ByteString.Base58.Internal where++import Data.Bits+import Data.ByteString ( ByteString )+import Data.String+import Data.Typeable ( Typeable )+import Data.Word+import GHC.Generics ( Generic )++import qualified Data.ByteString as BS+import qualified Data.List as L+++newtype Alphabet =+ Alphabet+ { unAlphabet :: ByteString+ } deriving (Ord, Eq, Show, Typeable, Generic, IsString)+++bitcoinAlphabet :: Alphabet+bitcoinAlphabet =+ "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"++rippleAlphabet :: Alphabet+rippleAlphabet =+ "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"++flickrAlphabet :: Alphabet+flickrAlphabet =+ "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"++-- | Take 'i' byte from alphabet+b58 :: Alphabet -> Int -> Word8+b58 a i = BS.index (unAlphabet a) i++-- | Lookup position of byte 'w' in alphabet+b58' :: Alphabet -> Word8 -> Maybe Int+b58' a w = BS.elemIndex w (unAlphabet a)+++-- | Decode a big endian Integer from a bytestring+bsToInteger :: ByteString -> Integer+bsToInteger = (L.foldl' f 0) . BS.unpack+ where+ f n w = (toInteger w) .|. shiftL n 8++-- | Encode an Integer to a bytestring as big endian+integerToBS :: Integer -> ByteString+integerToBS 0 = BS.pack [0]+integerToBS i+ | i > 0 = BS.pack $ reverse $ L.unfoldr f i+ | otherwise = error "integerToBS not defined for negative values"+ where+ f 0 = Nothing+ f x = Just $ (fromInteger x :: Word8, x `shiftR` 8)