ppad-bech32 0.2.0 → 0.2.1
raw patch · 4 files changed
+47/−7 lines, 4 filesdep −primitivePVP ok
version bump matches the API change (PVP)
Dependencies removed: primitive
API changes (from Hackage documentation)
Files
- CHANGELOG +3/−0
- lib/Data/ByteString/Bech32/Internal.hs +10/−5
- ppad-bech32.cabal +1/−2
- test/Main.hs +33/−0
CHANGELOG view
@@ -1,5 +1,8 @@ # Changelog +- 0.2.1 (2025-01-07)+ * Removes the 'primitive' dependency.+ - 0.2.0 (2025-01-04) * Adds bech32/bech32m/base32 decoding. * Fixes a bug in which mixed-case HRP's would result in encodings with
lib/Data/ByteString/Bech32/Internal.hs view
@@ -1,6 +1,7 @@ {-# OPTIONS_HADDOCK hide, prune #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE BinaryLiterals #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ViewPatterns #-} @@ -20,7 +21,6 @@ import qualified Data.ByteString.Builder.Extra as BE import qualified Data.ByteString.Internal as BI import qualified Data.ByteString.Unsafe as BU-import qualified Data.Primitive.PrimArray as PA import Data.Word (Word32) fi :: (Integral a, Num b) => a -> b@@ -52,8 +52,14 @@ polymod :: BS.ByteString -> Word32 polymod = BS.foldl' alg 1 where- generator = PA.primArrayFromListN 5- [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]+ generator :: Int -> Word32+ generator = \case+ 0 -> 0x3b6a57b2+ 1 -> 0x26508e6d+ 2 -> 0x1ea119fa+ 3 -> 0x3d4233dd+ 4 -> 0x2a1462b3+ _ -> error "ppad-bech32: internal error (please report this as a bug!)" alg !chk v = let !b = chk `B.shiftR` 25@@ -63,8 +69,7 @@ loop_gen i b !chk | i > 4 = chk | otherwise =- let sor | B.testBit (b `B.shiftR` i) 0 =- PA.indexPrimArray generator i+ let sor | B.testBit (b `B.shiftR` i) 0 = generator i | otherwise = 0 in loop_gen (succ i) b (chk `B.xor` sor)
ppad-bech32.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: ppad-bech32-version: 0.2.0+version: 0.2.1 synopsis: bech32 and bech32m encoding/decoding, per BIPs 173 & 350. license: MIT license-file: LICENSE@@ -31,7 +31,6 @@ build-depends: base >= 4.9 && < 5 , bytestring >= 0.9 && < 0.13- , primitive >= 0.8 && < 0.10 test-suite bech32-tests type: exitcode-stdio-1.0
test/Main.hs view
@@ -16,6 +16,9 @@ data ValidInput = ValidInput BS.ByteString BS.ByteString deriving (Eq, Show) +data InvalidInput = InvalidInput BS.ByteString BS.ByteString+ deriving (Eq, Show)+ instance Q.Arbitrary ValidInput where arbitrary = do h <- hrp@@ -24,6 +27,14 @@ b <- bytes a pure (ValidInput h b) +instance Q.Arbitrary InvalidInput where+ arbitrary = do+ h <- invalid_hrp+ let l = 83 - BS.length h+ a = l * 5 `quot` 8+ b <- bytes a+ pure (InvalidInput h b)+ instance Q.Arbitrary BS where arbitrary = do b <- bytes 1024@@ -35,6 +46,12 @@ v <- Q.vectorOf l (Q.choose (33, 126)) pure (B8.map C.toLower (BS.pack v)) +invalid_hrp :: Q.Gen BS.ByteString+invalid_hrp = do+ l <- Q.oneof [pure 0, Q.chooseInt (84, 100)]+ v <- Q.vectorOf l (Q.oneof [Q.choose (0, 32), Q.choose (127, 255)])+ pure (B8.map C.toLower (BS.pack v))+ bytes :: Int -> Q.Gen BS.ByteString bytes k = do l <- Q.chooseInt (0, k)@@ -66,6 +83,18 @@ Nothing -> False Just b -> b == bs +bech32_invalid_input_fails_encode :: InvalidInput -> Bool+bech32_invalid_input_fails_encode (InvalidInput h b) =+ case Bech32.encode h b of+ Nothing -> True+ Just _ -> False++bech32m_invalid_input_fails_encode :: InvalidInput -> Bool+bech32m_invalid_input_fails_encode (InvalidInput h b) =+ case Bech32m.encode h b of+ Nothing -> True+ Just _ -> False+ main :: IO () main = defaultMain $ testGroup "ppad-bech32" [ testGroup "base32" [@@ -77,10 +106,14 @@ Q.withMaxSuccess 1000 matches_reference , Q.testProperty "decode . encode ~ id" $ Q.withMaxSuccess 1000 bech32_decode_inverts_encode+ , Q.testProperty "invalid bech32 input fails to encode" $+ Q.withMaxSuccess 1000 bech32_invalid_input_fails_encode ] , testGroup "bech32m" [ Q.testProperty "decode . encode ~ id" $ Q.withMaxSuccess 1000 bech32m_decode_inverts_encode+ , Q.testProperty "invalid bech32m input fails to encode" $+ Q.withMaxSuccess 1000 bech32_invalid_input_fails_encode ] ]