-- module Encoding.Base62 -- ( enc62 -- , dec62 -- ) where -- import qualified Data.Word.Base62 as B62 -- import Text.Read (readMaybe) -- import Data.Maybe (fromMaybe) -- import Data.ByteString.UTF8 as BSU -- from utf8-string -- import qualified Data.Bytes as Bytes -- import Data.Bytes.Text.Latin1 as Latin1 -- import qualified Data.ByteString.Char8 as C -- import qualified Data.Text as T -- import qualified Data.Text.Encoding as T -- -- import qualified Data.Text.IO as T -- dec62 :: String -> String -- dec62 input = -- let decoded = B62.decode128 (Bytes.fromByteString (BSU.fromString input)) -- in fromMaybe "Error decoding Base62.\n" (show <$> decoded) -- let decoded = BC.unpack $ B62.decode128 -- stringToInt :: String -> Maybe Integer -- stringToInt = readMaybe -- enc62 :: String -> String -- enc62 input = -- let intValue = fromMaybe (error "Error: Unable to convert input string to integer") (stringToInt input) -- encoded = B62.encode64 (fromIntegral intValue) -- encodedText = T.decodeUtf8 (BSU.fromString (Latin1.toString (Bytes.fromByteArray encoded))) -- in T.unpack encodedText module Encoding.Base62 ( enc62 , dec62 ) where import qualified Data.ByteString.Char8 as BC import qualified Data.ByteString as BS import Data.ByteString.Internal (c2w, w2c) import Data.List (elemIndex) import Data.Maybe (fromMaybe) import Numeric (showIntAtBase) import Data.Char (intToDigit) import qualified Data.Text as T import qualified Data.Text.Encoding as T import System.IO.Unsafe (unsafePerformIO) import qualified Data.List as List base62Chars :: String base62Chars = ['0'..'9'] ++ ['A'..'Z'] ++ ['a'..'z'] -- Convert a ByteString to an Integer byteStringToInteger :: BS.ByteString -> Integer byteStringToInteger = BC.foldl' (\acc w -> acc * 256 + fromIntegral (c2w w)) 0 -- Convert an Integer to a ByteString integerToByteString :: Integer -> BS.ByteString integerToByteString 0 = BC.singleton (w2c 0) integerToByteString i = BC.reverse $ BC.unfoldr step i where step 0 = Nothing step x = Just (w2c (fromIntegral (x `mod` 256)), x `div` 256) -- Encode an Integer to a Base62 ByteString encodeBase62 :: Integer -> BS.ByteString encodeBase62 0 = BC.singleton (base62Chars !! 0) encodeBase62 n = BC.reverse $ BC.unfoldr step n where step 0 = Nothing step x = let (q, r) = x `divMod` 62 in Just (base62Chars !! fromIntegral r, q) decodeBase62 :: BS.ByteString -> Integer decodeBase62 = BC.foldl' (\acc w -> acc * 62 + fromIntegral (fromMaybe 0 (elemIndex w base62Chars))) 0 where elemIndex :: Char -> String -> Maybe Int elemIndex c str = List.findIndex (== c) str enc62 :: BC.ByteString -> BC.ByteString enc62 input = let intValue = byteStringToInteger input in encodeBase62 intValue dec62 :: BC.ByteString -> BC.ByteString dec62 input = let decoded = decodeBase62 input in integerToByteString decoded