added base45 encoding/decoding
This commit is contained in:
parent
5d1bd6abc2
commit
87089a314b
|
@ -13,6 +13,7 @@ import Encoding.Base8 (enc8, dec8)
|
||||||
import Encoding.Base10 (enc10, dec10)
|
import Encoding.Base10 (enc10, dec10)
|
||||||
import Encoding.Base16 (enc16, dec16)
|
import Encoding.Base16 (enc16, dec16)
|
||||||
import Encoding.Base32 (enc32, dec32)
|
import Encoding.Base32 (enc32, dec32)
|
||||||
|
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)
|
||||||
|
@ -34,6 +35,7 @@ data Based = Decode {
|
||||||
url :: Bool,
|
url :: Bool,
|
||||||
b62 :: Bool,
|
b62 :: Bool,
|
||||||
b58 :: Bool,
|
b58 :: Bool,
|
||||||
|
b45 :: Bool,
|
||||||
b32 :: Bool,
|
b32 :: Bool,
|
||||||
b16 :: Bool,
|
b16 :: Bool,
|
||||||
b10 :: Bool,
|
b10 :: Bool,
|
||||||
|
@ -54,6 +56,7 @@ data Based = Decode {
|
||||||
url :: Bool,
|
url :: Bool,
|
||||||
b62 :: Bool,
|
b62 :: Bool,
|
||||||
b58 :: Bool,
|
b58 :: Bool,
|
||||||
|
b45 :: Bool,
|
||||||
b32 :: Bool,
|
b32 :: Bool,
|
||||||
b16 :: Bool,
|
b16 :: Bool,
|
||||||
b10 :: Bool,
|
b10 :: Bool,
|
||||||
|
@ -160,6 +163,8 @@ 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 Encode{b45=True} = enc45
|
||||||
optionHandler Decode{b32=True} = dec32
|
optionHandler Decode{b32=True} = dec32
|
||||||
optionHandler Encode{b32=True} = enc32
|
optionHandler Encode{b32=True} = enc32
|
||||||
optionHandler Decode{b16=True} = dec16
|
optionHandler Decode{b16=True} = dec16
|
||||||
|
@ -191,6 +196,7 @@ decodeMode = Decode {
|
||||||
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",
|
||||||
b32 = def &= help "decode base32",
|
b32 = def &= help "decode base32",
|
||||||
b16 = def &= help "decode base16",
|
b16 = def &= help "decode base16",
|
||||||
b10 = def &= help "decode decimal from hex",
|
b10 = def &= help "decode decimal from hex",
|
||||||
|
@ -213,6 +219,7 @@ encodeMode = Encode {
|
||||||
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",
|
||||||
b32 = def &= help "encode base32",
|
b32 = def &= help "encode base32",
|
||||||
b16 = def &= help "encode base16",
|
b16 = def &= help "encode base16",
|
||||||
b10 = def &= help "encode base10 to hex",
|
b10 = def &= help "encode base10 to hex",
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
./dist-newstyle/build/aarch64-linux/ghc-9.4.8/based-0.4.3.0/x/based/build/based/based
|
|
@ -13,6 +13,7 @@ library
|
||||||
Encoding.Base10
|
Encoding.Base10
|
||||||
Encoding.Base16
|
Encoding.Base16
|
||||||
Encoding.Base32
|
Encoding.Base32
|
||||||
|
Encoding.Base45
|
||||||
Encoding.Base58
|
Encoding.Base58
|
||||||
Encoding.Base62
|
Encoding.Base62
|
||||||
Encoding.Base64
|
Encoding.Base64
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
module Encoding.Base45
|
||||||
|
( enc45
|
||||||
|
, dec45
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Data.Char (chr, ord)
|
||||||
|
import Data.List (elemIndex)
|
||||||
|
import Data.Maybe (fromJust)
|
||||||
|
|
||||||
|
base45Alphabet :: String
|
||||||
|
base45Alphabet = ['0'..'9'] ++ ['A'..'Z'] ++ " " ++ "$%*+-./:"
|
||||||
|
|
||||||
|
enc45 :: String -> String
|
||||||
|
enc45 = concatMap (reverse . encodeChunk) . chunkBy 2 . map ord
|
||||||
|
|
||||||
|
chunkBy :: Int -> [a] -> [[a]]
|
||||||
|
chunkBy _ [] = []
|
||||||
|
chunkBy n xs = take n xs : chunkBy n (drop n xs)
|
||||||
|
|
||||||
|
encodeChunk :: [Int] -> String
|
||||||
|
encodeChunk [x1, x2] = map (base45Alphabet !!) [c, b, a]
|
||||||
|
where
|
||||||
|
n = x1 * 256 + x2
|
||||||
|
a = n `mod` 45
|
||||||
|
b = (n `div` 45) `mod` 45
|
||||||
|
c = n `div` 2025
|
||||||
|
encodeChunk [x1] = map (base45Alphabet !!) [b, a]
|
||||||
|
where
|
||||||
|
a = x1 `mod` 45
|
||||||
|
b = x1 `div` 45
|
||||||
|
encodeChunk _ = error "Invalid chunk length"
|
||||||
|
|
||||||
|
-- Decode
|
||||||
|
dec45 :: String -> String
|
||||||
|
dec45 encoded = bytesToChars decodedBytes
|
||||||
|
where
|
||||||
|
numericValues = map charToNumeric encoded
|
||||||
|
groups = groupIntoThrees numericValues
|
||||||
|
base45Values = map toBase45 groups
|
||||||
|
decodedBytes = concatMap fromBase45 base45Values
|
||||||
|
|
||||||
|
charToNumeric :: Char -> Int
|
||||||
|
charToNumeric c = case c of
|
||||||
|
'0' -> 0
|
||||||
|
'1' -> 1
|
||||||
|
'2' -> 2
|
||||||
|
'3' -> 3
|
||||||
|
'4' -> 4
|
||||||
|
'5' -> 5
|
||||||
|
'6' -> 6
|
||||||
|
'7' -> 7
|
||||||
|
'8' -> 8
|
||||||
|
'9' -> 9
|
||||||
|
'A' -> 10
|
||||||
|
'B' -> 11
|
||||||
|
'C' -> 12
|
||||||
|
'D' -> 13
|
||||||
|
'E' -> 14
|
||||||
|
'F' -> 15
|
||||||
|
'G' -> 16
|
||||||
|
'H' -> 17
|
||||||
|
'I' -> 18
|
||||||
|
'J' -> 19
|
||||||
|
'K' -> 20
|
||||||
|
'L' -> 21
|
||||||
|
'M' -> 22
|
||||||
|
'N' -> 23
|
||||||
|
'O' -> 24
|
||||||
|
'P' -> 25
|
||||||
|
'Q' -> 26
|
||||||
|
'R' -> 27
|
||||||
|
'S' -> 28
|
||||||
|
'T' -> 29
|
||||||
|
'U' -> 30
|
||||||
|
'V' -> 31
|
||||||
|
'W' -> 32
|
||||||
|
'X' -> 33
|
||||||
|
'Y' -> 34
|
||||||
|
'Z' -> 35
|
||||||
|
' ' -> 36
|
||||||
|
'$' -> 37
|
||||||
|
'%' -> 38
|
||||||
|
'*' -> 39
|
||||||
|
'+' -> 40
|
||||||
|
'-' -> 41
|
||||||
|
'.' -> 42
|
||||||
|
'/' -> 43
|
||||||
|
':' -> 44
|
||||||
|
_ -> error "Invalid Base45 character"
|
||||||
|
|
||||||
|
groupIntoThrees :: [Int] -> [[Int]]
|
||||||
|
groupIntoThrees [] = []
|
||||||
|
groupIntoThrees xs
|
||||||
|
| length xs < 3 = [xs ++ replicate (3 - length xs) 0]
|
||||||
|
| otherwise = take 3 xs : groupIntoThrees (drop 3 xs)
|
||||||
|
|
||||||
|
toBase45 :: [Int] -> Int
|
||||||
|
toBase45 [c, d, e] = c + d * 45 + e * (45 * 45)
|
||||||
|
|
||||||
|
fromBase45 :: Int -> [Int]
|
||||||
|
fromBase45 n
|
||||||
|
| n >= 256 = fromBase45 (n `div` 256) ++ [n `mod` 256]
|
||||||
|
| otherwise = [n]
|
||||||
|
|
||||||
|
bytesToChars :: [Int] -> String
|
||||||
|
bytesToChars = map chr
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue