packages feed

base62 0.1.0.2 → 0.1.0.3

raw patch · 3 files changed

+55/−47 lines, 3 filesdep −word-compatdep ~base

Dependencies removed: word-compat

Dependency ranges changed: base

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for base62 +## 0.1.0.3 -- 2023-07-25++* Support GHC 9.4. Drop support for all versions of GHC before 9.4.+ ## 0.1.0.2 -- 2022-12-07  * Support GHC 9.2.
base62.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: base62-version: 0.1.0.2+version: 0.1.0.3 synopsis: Base62 encoding and decoding description:   Encode and decode using the base62 encoding scheme.@@ -18,13 +18,12 @@   exposed-modules:     Data.Word.Base62   build-depends:-    , base >=4.12 && <5+    , base >=4.17 && <5     , byteslice >=0.2 && <0.3     , natural-arithmetic >=0.1 && <0.2-    , primitive >=0.7 && <0.8+    , primitive >=0.7 && <0.10     , bytebuild >=0.3.4 && <0.4     , wide-word >=0.1.0.8 && <0.2-    , word-compat >=0.0.4   hs-source-dirs: src   default-language: Haskell2010   ghc-options: -Wall -O2
src/Data/Word/Base62.hs view
@@ -34,13 +34,12 @@ import Data.Primitive (ByteArray(..),readByteArray,writeByteArray) import Data.Primitive (MutableByteArray(MutableByteArray)) import Data.WideWord.Word128 (Word128(Word128))-import GHC.Exts (Char(C#),quotRemWord#,indexCharArray#)-import GHC.Exts (ByteArray#,Int#,Int(I#),Word#,(+#),(-#))+import GHC.Exts (Char(C#),Word64#,Word8#,quotRemWord#,indexCharArray#)+import GHC.Exts (ByteArray#,Int#,Int(I#),(+#),(-#)) import GHC.Exts (isTrue#,(>#))-import GHC.Prim.Compat (writeWord8Array#)+import GHC.Exts (wordToWord64#,word64ToWord#) import GHC.ST (ST(ST))-import GHC.Word (Word64(W64#),Word8,Word(W#))-import GHC.Word.Compat (pattern W8#)+import GHC.Word (Word64(W64#),Word8(W8#))  import qualified Arithmetic.Nat as Nat import qualified Data.Bytes as Bytes@@ -79,41 +78,45 @@ {-# inline builder128 #-} builder128 (Word128 (W64# a) (W64# b)) = builder128# a b -builder64# :: Word# -> Builder 11+builder64# :: Word64# -> Builder 11 {-# noinline builder64# #-} builder64# w0 = Builder-  (\marr off0 s0 -> case w0 of-    0## -> case writeWord8Array# marr off0 48## s0 of+  (\marr off0 s0 -> case word64ToWord# w0 of+    0## -> case Exts.writeWord8Array# marr off0 (Exts.wordToWord8# 48##) s0 of       s1 -> (# s1, off0 +# 1# #)-    _ -> let go ix w s1 = case w of+    _ -> let go ix w s1 = case word64ToWord# w of                0## -> case reverseBytes (MutableByteArray marr) (I# off0) (I# (ix -# 1# )) of                  ST f -> case f s1 of                    (# s2, (_ :: ()) #) -> (# s2, ix #)                _ ->-                 let !(# q, r #) = quotRemWord# w 62##-                  in case writeWord8Array# marr ix (unW8 (encodeByte (W# r))) s1 of+                 let !(# q0, r0 #) = quotRemWord# (word64ToWord# w) 62##+                     !q = wordToWord64# q0+                     !r = wordToWord64# r0+                  in case Exts.writeWord8Array# marr ix (unW8 (encodeByte (W64# r))) s1 of                        s2 -> go (ix +# 1#) q s2           in go off0 w0 s0   )  -- Always outputs exactly ten digits. They do not need to be reversed.-builder62pow10# :: Word# -> Builder 10+builder62pow10# :: Word64# -> Builder 10 {-# noinline builder62pow10# #-} builder62pow10# w0 = Builder   (\marr off0 s0 ->      let go ix d w s1 = case d of           0# -> (# s1, ix +# 11# #)            _ ->-            let !(# q, r #) = quotRemWord# w 62##-             in case writeWord8Array# marr ix (unW8 (encodeByte (W# r))) s1 of+            let !(# q0, r0 #) = quotRemWord# (word64ToWord# w) 62##+                !q = wordToWord64# q0+                !r = wordToWord64# r0+             in case Exts.writeWord8Array# marr ix (unW8 (encodeByte (W64# r))) s1 of                   s2 -> go (ix -# 1# ) (d -# 1# ) q s2      in go (off0 +# 9# ) 10# w0 s0   ) -builder128# :: Word# -> Word# -> Builder 22+builder128# :: Word64# -> Word64# -> Builder 22 {-# noinline builder128# #-} builder128# wa wb = Builder-  (\marr off0 s0 -> case wa of+  (\marr off0 s0 -> case word64ToWord# wa of     0## -> case builder64# wb of Builder f -> f marr off0 s0     _ -> case quotRem (Word128 (W64# wa) (W64# wb)) (Word128 0 n62pow10) of       (upper@(Word128 upperHi (W64# upperLo)), (Word128 shouldBeZeroA (W64# lower))) -> case shouldBeZeroA of@@ -123,9 +126,9 @@             (Word128 shouldBeZeroB (W64# x),Word128 shouldBeZeroC (W64# y)) -> case shouldBeZeroB of               0 -> case shouldBeZeroC of                 0 -> case builder64# x `Builder.append` (builder62pow10# y `Builder.append` builder62pow10# lower) of Builder f -> f marr off0 s0-                _ -> error "Data.Word.Base62: logical error c"-              _ -> error "Data.Word.Base62: logical error b"-        _ -> error "Data.Word.Base62: logical error a"+                _ -> errorWithoutStackTrace "Data.Word.Base62: logical error c"+              _ -> errorWithoutStackTrace "Data.Word.Base62: logical error b"+        _ -> errorWithoutStackTrace "Data.Word.Base62: logical error a"   )  -- Reverse the bytes in the designated slice. This takes@@ -143,7 +146,7 @@     else pure ()  -- Precondition: argument is less than 62.-encodeByte :: Word -> Word8+encodeByte :: Word64 -> Word8 encodeByte w   | w < 10 = unsafeW8 (c2w '0' + w)   | w < 36 = unsafeW8 ((c2w 'A' - 10) + w)@@ -151,26 +154,23 @@  -- We use Char here since it produces more readable Core. -- Performance is not impacted in any way.-decodeByte :: Char -> Maybe Word+decodeByte :: Char -> Maybe Word64 decodeByte w   | w >= '0' && w <= '9' = Just (c2w w - c2w '0')   | w >= 'A' && w <= 'Z' = Just (c2w w - (c2w 'A' - 10))   | w >= 'a' && w <= 'z' = Just (c2w w - (c2w 'a' - 36))   | otherwise = Nothing -c2w :: Char -> Word+c2w :: Char -> Word64 c2w = fromIntegral . ord  -- Precondition: the argument is less than 256-unsafeW8 :: Word -> Word8-unsafeW8 (W# w) = W8# w+unsafeW8 :: Word64 -> Word8+unsafeW8 (W64# w) = W8# (Exts.wordToWord8# (word64ToWord# w)) -unW8 :: Word8 -> Word#+unW8 :: Word8 -> Word8# unW8 (W8# w) = w -unW :: Word -> Word#-unW (W# w) = w- -- | Decode a base62-encoded 64-bit word. This rejects the empty -- string rather than decoding it as zero. This also rejects encoded -- numbers greater than or equal to @2^64@.@@ -190,9 +190,9 @@ -- Worker-wrapper will turn this into good code as long as -- we do not put a noinline pragma on it. It is recursive, -- so it cannot inline anywhere.-decode64# :: Word -> Bytes -> (# (# #) | Word# #)-decode64# !acc b@(Bytes arr off len) = case len of-  0 -> (# | unW acc #)+decode64# :: Word64 -> Bytes -> (# (# #) | Word64# #)+decode64# !acc@(W64# acc# ) b@(Bytes arr off len) = case len of+  0 -> (# | acc# #)   _ -> case decodeByte (indexAsciiArray arr off) of     Nothing -> (# (# #) | #)     Just w ->@@ -215,14 +215,14 @@ -- position in the bytearray, @d@ tracks the number of digits -- consumed by this particular function. The caller should always -- set @d@ to 0.-unsafeDecode62pow10# :: Word -> ByteArray -> Int -> Int -> (# (# #) | Word# #)-unsafeDecode62pow10# !acc !arr !off !d = if d < 10+unsafeDecode62pow10# :: Word64 -> ByteArray -> Int -> Int -> (# (# #) | Word64# #)+unsafeDecode62pow10# !acc@(W64# acc# ) !arr !off !d = if d < 10   then case decodeByte (indexAsciiArray arr off) of     Nothing -> (# (# #) | #)     Just w ->       let acc' = acc * 62 + w        in unsafeDecode62pow10# acc' arr (off + 1) (d + 1)-  else (# | unW acc #)+  else (# | acc# #)  -- | Decode a base62-encoded 128-bit word. This rejects the empty -- string rather than decoding it as zero. This also rejects encoded@@ -241,7 +241,7 @@     (# (# #) | #) -> Nothing     (# | (# a, b #) #) -> Just (Word128 (W64# a) (W64# b)) -decode128# :: ByteArray# -> Int# -> Int# -> (# (# #) | (# Word#, Word# #) #)+decode128# :: ByteArray# -> Int# -> Int# -> (# (# #) | (# Word64#, Word64# #) #) {-# noinline decode128# #-} decode128# arr off len   | isTrue# (len ># 22# ) = (# (# #) | #) -- always overflows@@ -269,15 +269,20 @@             Word128 (W64# x) (W64# y) -> (# | (# x, y #) #)   | otherwise = case decode64# 0 (Bytes (ByteArray arr) (I# off) (I# len)) of       (# (# #) | #) -> (# (# #) | #)-      (# | w #) -> (# | (# 0##, w #) #)+      (# | w #) -> (# | (# wordToWord64# 0##, w #) #)  indexAsciiArray :: ByteArray -> Int -> Char indexAsciiArray (ByteArray arr) (I# i) = C# (indexCharArray# arr i) -unsignedPushBase62 :: Word -> Word -> (Bool,Word)-unsignedPushBase62 (W# a) (W# b) = -  let !(# ca, r0 #) = Exts.timesWord2# a 62##-      !r1 = Exts.plusWord# r0 b-      !cb = Exts.int2Word# (Exts.ltWord# r1 r0)-      !c = ca `Exts.or#` cb-   in (case c of { 0## -> False; _ -> True }, W# r1)+unsignedPushBase62 :: Word64 -> Word64 -> (Bool,Word64)+{-# inline unsignedPushBase62 #-}+unsignedPushBase62 (W64# a) (W64# b) = +  let !(# ca, r0 #) = Exts.timesWord2# (word64ToWord# a) 62##+   in case ca of+        0## ->+          let !r0' = wordToWord64# r0+              !r1 = Exts.plusWord64# r0' b+           in case Exts.ltWord64# r1 r0' of+                1# -> (True,0)+                _ -> (False,W64# r1)+        _ -> (True,0)