moved all encodings to bytestring, updated tests accordingly
This commit is contained in:
parent
1889691259
commit
82aed9340c
14
app/Main.hs
14
app/Main.hs
|
@ -17,7 +17,7 @@ import Encoding.Base16 (enc16, dec16)
|
||||||
import Encoding.Base32 (enc32, dec32)
|
import Encoding.Base32 (enc32, dec32)
|
||||||
import Encoding.Base45 (enc45, dec45)
|
import Encoding.Base45 (enc45, dec45)
|
||||||
import Encoding.Base58 (enc58, dec58)
|
import Encoding.Base58 (enc58, dec58)
|
||||||
--import Encoding.Base62 (enc62, dec62)
|
import Encoding.Base62 (enc62, dec62)
|
||||||
import Encoding.Base64 (enc64, dec64, enc64url, dec64url)
|
import Encoding.Base64 (enc64, dec64, enc64url, dec64url)
|
||||||
import Encoding.Base85 (enc85, dec85)
|
import Encoding.Base85 (enc85, dec85)
|
||||||
import Encoding.Base91 (enc91, dec91)
|
import Encoding.Base91 (enc91, dec91)
|
||||||
|
@ -35,7 +35,7 @@ data Based = Decode {
|
||||||
b64 :: Bool,
|
b64 :: Bool,
|
||||||
b64url :: Bool,
|
b64url :: Bool,
|
||||||
url :: Bool,
|
url :: Bool,
|
||||||
-- b62 :: Bool,
|
b62 :: Bool,
|
||||||
b58 :: Bool,
|
b58 :: Bool,
|
||||||
b45 :: Bool,
|
b45 :: Bool,
|
||||||
b32 :: Bool,
|
b32 :: Bool,
|
||||||
|
@ -56,7 +56,7 @@ data Based = Decode {
|
||||||
b64 :: Bool,
|
b64 :: Bool,
|
||||||
b64url :: Bool,
|
b64url :: Bool,
|
||||||
url :: Bool,
|
url :: Bool,
|
||||||
-- b62 :: Bool,
|
b62 :: Bool,
|
||||||
b58 :: Bool,
|
b58 :: Bool,
|
||||||
b45 :: Bool,
|
b45 :: Bool,
|
||||||
b32 :: Bool,
|
b32 :: Bool,
|
||||||
|
@ -161,8 +161,8 @@ optionHandler Decode{b64url=True} = dec64url
|
||||||
optionHandler Encode{b64url=True} = enc64url
|
optionHandler Encode{b64url=True} = enc64url
|
||||||
optionHandler Decode{url=True} = decurl
|
optionHandler Decode{url=True} = decurl
|
||||||
optionHandler Encode{url=True} = encurl
|
optionHandler Encode{url=True} = encurl
|
||||||
--optionHandler Decode{b62=True} = dec62
|
optionHandler Decode{b62=True} = dec62
|
||||||
--optionHandler Encode{b62=True} = enc62
|
optionHandler Encode{b62=True} = enc62
|
||||||
optionHandler Decode{b58=True} = dec58
|
optionHandler Decode{b58=True} = dec58
|
||||||
optionHandler Encode{b58=True} = enc58
|
optionHandler Encode{b58=True} = enc58
|
||||||
optionHandler Decode{b45=True} = dec45
|
optionHandler Decode{b45=True} = dec45
|
||||||
|
@ -196,7 +196,7 @@ decodeMode = Decode {
|
||||||
b64 = def &= help "decode base64",
|
b64 = def &= help "decode base64",
|
||||||
b64url = def &= help "decode base64Url",
|
b64url = def &= help "decode base64Url",
|
||||||
url = def &= help "decode URI",
|
url = def &= help "decode URI",
|
||||||
-- b62 = def &= help "decode base62",
|
b62 = def &= help "decode base62",
|
||||||
b58 = def &= help "decode base58",
|
b58 = def &= help "decode base58",
|
||||||
b45 = def &= help "decode base45",
|
b45 = def &= help "decode base45",
|
||||||
b32 = def &= help "decode base32",
|
b32 = def &= help "decode base32",
|
||||||
|
@ -219,7 +219,7 @@ encodeMode = Encode {
|
||||||
b64 = def &= help "encode base64",
|
b64 = def &= help "encode base64",
|
||||||
b64url = def &= help "encode base64Url",
|
b64url = def &= help "encode base64Url",
|
||||||
url = def &= help "encode URI",
|
url = def &= help "encode URI",
|
||||||
-- b62 = def &= help "encode base62",
|
b62 = def &= help "encode base62",
|
||||||
b58 = def &= help "encode base58",
|
b58 = def &= help "encode base58",
|
||||||
b45 = def &= help "encode base45",
|
b45 = def &= help "encode base45",
|
||||||
b32 = def &= help "encode base32",
|
b32 = def &= help "encode base32",
|
||||||
|
|
|
@ -41,6 +41,7 @@ library
|
||||||
hxt,
|
hxt,
|
||||||
haskoin-core,
|
haskoin-core,
|
||||||
text,
|
text,
|
||||||
|
primitive,
|
||||||
base64-bytestring
|
base64-bytestring
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,91 @@
|
||||||
|
-- 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
|
module Encoding.Base62
|
||||||
( enc62
|
( enc62
|
||||||
, dec62
|
, dec62
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import qualified Data.ByteString.Char8 as BC
|
||||||
import qualified Data.Word.Base62 as B62
|
import qualified Data.ByteString as BS
|
||||||
import Text.Read (readMaybe)
|
import Data.ByteString.Internal (c2w, w2c)
|
||||||
|
import Data.List (elemIndex)
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
import Data.ByteString.UTF8 as BSU -- from utf8-string
|
import Numeric (showIntAtBase)
|
||||||
import qualified Data.Bytes as Bytes
|
import Data.Char (intToDigit)
|
||||||
import Data.Bytes.Text.Latin1 as Latin1
|
|
||||||
import qualified Data.ByteString.Char8 as C
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding as T
|
import qualified Data.Text.Encoding as T
|
||||||
-- import qualified Data.Text.IO as T
|
import System.IO.Unsafe (unsafePerformIO)
|
||||||
|
import qualified Data.List as List
|
||||||
|
|
||||||
|
base62Chars :: String
|
||||||
|
base62Chars = ['0'..'9'] ++ ['A'..'Z'] ++ ['a'..'z']
|
||||||
|
|
||||||
dec62 :: String -> String
|
-- Convert a ByteString to an Integer
|
||||||
dec62 input =
|
byteStringToInteger :: BS.ByteString -> Integer
|
||||||
let decoded = B62.decode128 (Bytes.fromByteString (BSU.fromString input))
|
byteStringToInteger = BC.foldl' (\acc w -> acc * 256 + fromIntegral (c2w w)) 0
|
||||||
in fromMaybe "Error decoding Base62.\n" (show <$> decoded)
|
|
||||||
|
|
||||||
stringToInt :: String -> Maybe Integer
|
-- Convert an Integer to a ByteString
|
||||||
stringToInt = readMaybe
|
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)
|
||||||
|
|
||||||
enc62 :: String -> String
|
-- 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 =
|
enc62 input =
|
||||||
let intValue = fromMaybe (error "Error: Unable to convert input string to integer") (stringToInt input)
|
let intValue = byteStringToInteger input
|
||||||
encoded = B62.encode64 (fromIntegral intValue)
|
in encodeBase62 intValue
|
||||||
encodedText = T.decodeUtf8 (BSU.fromString (Latin1.toString (Bytes.fromByteArray encoded)))
|
|
||||||
in T.unpack encodedText
|
dec62 :: BC.ByteString -> BC.ByteString
|
||||||
|
dec62 input =
|
||||||
|
let decoded = decodeBase62 input
|
||||||
|
in integerToByteString decoded
|
||||||
|
|
||||||
|
|
17
test/Main.hs
17
test/Main.hs
|
@ -6,6 +6,7 @@ import Data.ByteString.UTF8 as BSU
|
||||||
import Encoding.Base91 (enc91, dec91)
|
import Encoding.Base91 (enc91, dec91)
|
||||||
import Encoding.Base85 (enc85, dec85)
|
import Encoding.Base85 (enc85, dec85)
|
||||||
import Encoding.Base64 (enc64, dec64)
|
import Encoding.Base64 (enc64, dec64)
|
||||||
|
import Encoding.Base62 (enc62, dec62)
|
||||||
import Encoding.Base45 (enc45, dec45)
|
import Encoding.Base45 (enc45, dec45)
|
||||||
import Encoding.Base32 (enc32, dec32)
|
import Encoding.Base32 (enc32, dec32)
|
||||||
import Encoding.Base16 (enc16, dec16)
|
import Encoding.Base16 (enc16, dec16)
|
||||||
|
@ -63,6 +64,18 @@ testDec64 = TestCase $ do
|
||||||
assertEqual "for (dec64 \"AAEC\")," (BSU.fromString "\x00\x01\x02") (dec64 $ BSU.fromString "AAEC")
|
assertEqual "for (dec64 \"AAEC\")," (BSU.fromString "\x00\x01\x02") (dec64 $ BSU.fromString "AAEC")
|
||||||
assertEqual "for (dec64 \"8J+Ygg==\")," (BSU.fromString "😂") (dec64 $ BSU.fromString "8J+Ygg==")
|
assertEqual "for (dec64 \"8J+Ygg==\")," (BSU.fromString "😂") (dec64 $ BSU.fromString "8J+Ygg==")
|
||||||
|
|
||||||
|
testEnc62 :: Test
|
||||||
|
testEnc62 = TestCase $ do
|
||||||
|
assertEqual "for (enc62 \"Hello, World!\")," (BSU.fromString "1wJfrzvdbtXUOlUjUf") (enc62 helloWorldBS)
|
||||||
|
assertEqual "for (enc62 \"Haskell\")," (BSU.fromString "1VJEByfMCK") (enc62 haskellBS)
|
||||||
|
assertEqual "for (enc62 \"😂\")," (BSU.fromString "4PCnnm") (enc62 emojiBS)
|
||||||
|
|
||||||
|
testDec62 :: Test
|
||||||
|
testDec62 = TestCase $ do
|
||||||
|
assertEqual "for (dec62 \"1wJfrzvdbtXUOlUjUf\")," helloWorldBS (dec62 $ BSU.fromString "1wJfrzvdbtXUOlUjUf")
|
||||||
|
assertEqual "for (dec62 \"1VJEByfMCK\")," haskellBS (dec62 $ BSU.fromString "1VJEByfMCK")
|
||||||
|
assertEqual "for (dec62 \"4PCnnm\")," emojiBS (dec62 $ BSU.fromString "4PCnnm")
|
||||||
|
|
||||||
testEnc45 :: Test
|
testEnc45 :: Test
|
||||||
testEnc45 = TestCase $ do
|
testEnc45 = TestCase $ do
|
||||||
assertEqual "for (enc45 \"Hello, World!\")," (BSU.fromString "%69 VDK2E:3404ESVDX0") (enc45 helloWorldBS)
|
assertEqual "for (enc45 \"Hello, World!\")," (BSU.fromString "%69 VDK2E:3404ESVDX0") (enc45 helloWorldBS)
|
||||||
|
@ -133,7 +146,7 @@ testEncQp = TestCase $ do
|
||||||
testDecQp :: Test
|
testDecQp :: Test
|
||||||
testDecQp = TestCase $ do
|
testDecQp = TestCase $ do
|
||||||
assertEqual "for (decqp \"Hello,=20World!\")," helloWorldBS (decqp $ BSU.fromString "Hello,=20World!")
|
assertEqual "for (decqp \"Hello,=20World!\")," helloWorldBS (decqp $ BSU.fromString "Hello,=20World!")
|
||||||
assertEqual "for (decqp \"QP=20works=20by=20using=20the=20equals=20sign=20=3D=20as=20an=20escape=20=\r\ncharacter.=20It=20also=20limits=20line=20length=20to=2076,=20as=20some=20=\r\nsoftware=20has=20limits=20on=20line=20length.\")," (BSU.fromString "QP works by using the equals sign = as an escape character. It also limits line length to 76, as some software has limits on line length.") (decqp $ BSU.fromString "QP=20works=20by=20using=20the=20equals=20sign=20=3D=20as=20an=20escape=20=\ncharacter.=20It=20also=20limits=20line=20length=20to=2076,=20as=20some=20=\nsoftware=20has=20limits=20on=20line=20length.")
|
assertEqual "for (decqp \"QP=20works=20by=20using=20the=20equals=20sign=20=3D=20as=20an=20escape=20=\r\ncharacter.=20It=20also=20limits=20line=20length=20to=2076,=20as=20some=20=\r\nsoftware=20has=20limits=20on=20line=20length.\")," (BSU.fromString "QP works by using the equals sign = as an escape character. It also limits line length to 76, as some software has limits on line length.") (decqp $ BSU.fromString "QP=20works=20by=20using=20the=20equals=20sign=20=3D=20as=20an=20escape=20=\r\ncharacter.=20It=20also=20limits=20line=20length=20to=2076,=20as=20some=20=\r\nsoftware=20has=20limits=20on=20line=20length.")
|
||||||
assertEqual "for (decqp \"=F0=9F=98=82\")," emojiBS (decqp $ BSU.fromString "=F0=9F=98=82")
|
assertEqual "for (decqp \"=F0=9F=98=82\")," emojiBS (decqp $ BSU.fromString "=F0=9F=98=82")
|
||||||
|
|
||||||
-- testEnUu :: Test
|
-- testEnUu :: Test
|
||||||
|
@ -156,6 +169,8 @@ tests = TestList [TestLabel "Test enc91" testEnc91,
|
||||||
TestLabel "Test dec85" testDec85,
|
TestLabel "Test dec85" testDec85,
|
||||||
TestLabel "Test enc64" testEnc64,
|
TestLabel "Test enc64" testEnc64,
|
||||||
TestLabel "Test dec64" testDec64,
|
TestLabel "Test dec64" testDec64,
|
||||||
|
TestLabel "Test enc62" testEnc62,
|
||||||
|
TestLabel "Test dec62" testDec62,
|
||||||
TestLabel "Test enc45" testEnc45,
|
TestLabel "Test enc45" testEnc45,
|
||||||
TestLabel "Test dec45" testDec45,
|
TestLabel "Test dec45" testDec45,
|
||||||
TestLabel "Test enc32" testEnc32,
|
TestLabel "Test enc32" testEnc32,
|
||||||
|
|
Loading…
Reference in New Issue