-- | Implementation of base-62 encoding, which we use when computing hashes
-- for fully instantiated unit ids.
module Distribution.Utils.Base62 (hashToBase62) where

import GHC.Fingerprint ( Fingerprint(..), fingerprintString )
import Numeric ( showIntAtBase )
import Data.Char ( chr )

-- | Hash a string using GHC's fingerprinting algorithm (a 128-bit
-- MD5 hash) and then encode the resulting hash in base 62.
hashToBase62 :: String -> String
hashToBase62 :: String -> String
hashToBase62 String
s = Fingerprint -> String
showFingerprint forall a b. (a -> b) -> a -> b
$ String -> Fingerprint
fingerprintString String
s
  where
    showIntAtBase62 :: a -> String
showIntAtBase62 a
x = forall a.
(Integral a, Show a) =>
a -> (Int -> Char) -> a -> String -> String
showIntAtBase a
62 Int -> Char
representBase62 a
x String
""
    representBase62 :: Int -> Char
representBase62 Int
x
        | Int
x forall a. Ord a => a -> a -> Bool
< Int
10 = Int -> Char
chr (Int
48 forall a. Num a => a -> a -> a
+ Int
x)
        | Int
x forall a. Ord a => a -> a -> Bool
< Int
36 = Int -> Char
chr (Int
65 forall a. Num a => a -> a -> a
+ Int
x forall a. Num a => a -> a -> a
- Int
10)
        | Int
x forall a. Ord a => a -> a -> Bool
< Int
62 = Int -> Char
chr (Int
97 forall a. Num a => a -> a -> a
+ Int
x forall a. Num a => a -> a -> a
- Int
36)
        | Bool
otherwise = Char
'@'
    showFingerprint :: Fingerprint -> String
showFingerprint (Fingerprint Word64
a Word64
b) = forall {a}. (Integral a, Show a) => a -> String
showIntAtBase62 Word64
a forall a. [a] -> [a] -> [a]
++ forall {a}. (Integral a, Show a) => a -> String
showIntAtBase62 Word64
b