module Kewar.Encoding.Data (encodeData, toBitString) where
import Data.Char (ord)
import Kewar.Constants (alphaNumericValue, characterCountIndicator, modeIndicator, totalBits, groupsCodeWords)
import Kewar.Types (BitString, CorrectionLevel, Mode (..), Version, Group)
import Utils (chunksOf, leftPad, leftUnpad, readInt, toBin)
import Data.Foldable (foldl')
encodeData :: String -> Mode -> Version -> CorrectionLevel -> [Group]
encodeData :: String -> Mode -> Version -> CorrectionLevel -> [Group]
encodeData String
i Mode
m Version
v CorrectionLevel
cl = String -> Version -> CorrectionLevel -> [Group]
groups (String
byteString String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> Version -> String
padBytes String
byteString Version
requiredBits) Version
v CorrectionLevel
cl
where
requiredBits :: Version
requiredBits = Version -> CorrectionLevel -> Version
totalBits Version
v CorrectionLevel
cl
encoded :: String
encoded = String -> Mode -> Version -> String
basicEncodeData String
i Mode
m Version
v
byteString :: String
byteString = String -> String
toByteString (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
encoded String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> Version -> String
terminator String
encoded Version
requiredBits
byteToBitString :: String -> BitString
byteToBitString :: String -> String
byteToBitString = (Char -> String) -> String -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Version -> Char -> String -> String
leftPad Version
8 Char
'0' (String -> String) -> (Char -> String) -> Char -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Version -> String
toBin (Version -> String) -> (Char -> Version) -> Char -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Version
ord))
alphaNumericToBitString :: String -> BitString
alphaNumericToBitString :: String -> String
alphaNumericToBitString String
i = do
let sums :: [Version]
sums = ([Version] -> Version) -> [[Version]] -> [Version]
forall a b. (a -> b) -> [a] -> [b]
map (\[Version]
j -> if [Version] -> Version
forall (t :: * -> *) a. Foldable t => t a -> Version
length [Version]
j Version -> Version -> Bool
forall a. Eq a => a -> a -> Bool
== Version
2 then ([Version] -> Version
forall a. [a] -> a
head [Version]
j Version -> Version -> Version
forall a. Num a => a -> a -> a
* Version
45) Version -> Version -> Version
forall a. Num a => a -> a -> a
+ [Version] -> Version
forall a. [a] -> a
last [Version]
j else [Version] -> Version
forall a. [a] -> a
head [Version]
j) (Version -> [Version] -> [[Version]]
forall a. Version -> [a] -> [[a]]
chunksOf Version
2 ([Version] -> [[Version]]) -> [Version] -> [[Version]]
forall a b. (a -> b) -> a -> b
$ (Char -> Version) -> String -> [Version]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Version
alphaNumericValue String
i)
let initial :: String
initial = (Version -> String) -> [Version] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Version -> Char -> String -> String
leftPad Version
11 Char
'0' (String -> String) -> (Version -> String) -> Version -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Version -> String
toBin) ([Version] -> [Version]
forall a. [a] -> [a]
init [Version]
sums)
let finalPad :: Version
finalPad = if Version -> Bool
forall a. Integral a => a -> Bool
odd (Version -> Bool) -> Version -> Bool
forall a b. (a -> b) -> a -> b
$ String -> Version
forall (t :: * -> *) a. Foldable t => t a -> Version
length String
i then Version
6 else Version
11
let final :: String
final = Version -> Char -> String -> String
leftPad Version
finalPad Char
'0' (Version -> String
toBin ([Version] -> Version
forall a. [a] -> a
last [Version]
sums))
String
initial String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
final
numericToBitString :: String -> BitString
numericToBitString :: String -> String
numericToBitString String
i = (String -> String) -> [String] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> String
step (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> String -> String
leftUnpad Char
'0') (Version -> String -> [String]
forall a. Version -> [a] -> [[a]]
chunksOf Version
3 String
i)
where
transform :: String -> String
transform = Version -> String
toBin (Version -> String) -> (String -> Version) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Version
readInt
step :: String -> String
step String
chunk
| String -> Version
forall (t :: * -> *) a. Foldable t => t a -> Version
length String
chunk Version -> Version -> Bool
forall a. Eq a => a -> a -> Bool
== Version
1 = Version -> Char -> String -> String
leftPad Version
4 Char
'0' (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> String
transform String
chunk
| String -> Version
forall (t :: * -> *) a. Foldable t => t a -> Version
length String
chunk Version -> Version -> Bool
forall a. Eq a => a -> a -> Bool
== Version
2 = Version -> Char -> String -> String
leftPad Version
7 Char
'0' (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> String
transform String
chunk
| Bool
otherwise = Version -> Char -> String -> String
leftPad Version
10 Char
'0' (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> String
transform String
chunk
toBitString :: Mode -> String -> BitString
toBitString :: Mode -> String -> String
toBitString Mode
Numeric String
i = String -> String
numericToBitString String
i
toBitString Mode
AlphaNumeric String
i = String -> String
alphaNumericToBitString String
i
toBitString Mode
Byte String
i = String -> String
byteToBitString String
i
basicEncodeData :: String -> Mode -> Version -> BitString
basicEncodeData :: String -> Mode -> Version -> String
basicEncodeData String
i Mode
m Version
v = Mode -> String
modeIndicator Mode
m String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> Mode -> Version -> String
characterCountIndicator String
i Mode
m Version
v String -> String -> String
forall a. [a] -> [a] -> [a]
++ Mode -> String -> String
toBitString Mode
m String
i
toByteString :: BitString -> BitString
toByteString :: String -> String
toByteString String
s
| Version
rest Version -> Version -> Bool
forall a. Eq a => a -> a -> Bool
== Version
0 = String
s
| Bool
otherwise = String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ Version -> Char -> String
forall a. Version -> a -> [a]
replicate (Version
8 Version -> Version -> Version
forall a. Num a => a -> a -> a
- Version
rest) Char
'0'
where
rest :: Version
rest = String -> Version
forall (t :: * -> *) a. Foldable t => t a -> Version
length String
s Version -> Version -> Version
forall a. Integral a => a -> a -> a
`mod` Version
8
terminator :: BitString -> Int -> BitString
terminator :: String -> Version -> String
terminator String
s Version
requiredBits
| Version
delta Version -> Version -> Bool
forall a. Ord a => a -> a -> Bool
>= Version
4 = String
"0000"
| Bool
otherwise = Version -> Char -> String
forall a. Version -> a -> [a]
replicate Version
delta Char
'0'
where
delta :: Version
delta = Version
requiredBits Version -> Version -> Version
forall a. Num a => a -> a -> a
- String -> Version
forall (t :: * -> *) a. Foldable t => t a -> Version
length String
s
padBytes :: BitString -> Int -> BitString
padBytes :: String -> Version -> String
padBytes String
s Version
requiredBits = do
let numberOfPadBytes :: Version
numberOfPadBytes = (Version
requiredBits Version -> Version -> Version
forall a. Num a => a -> a -> a
- String -> Version
forall (t :: * -> *) a. Foldable t => t a -> Version
length String
s) Version -> Version -> Version
forall a. Integral a => a -> a -> a
`div` Version
8
(Version -> String) -> [Version] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\Version
i -> if Version -> Bool
forall a. Integral a => a -> Bool
odd Version
i then String
"11101100" else String
"00010001") [Version
1 .. Version
numberOfPadBytes]
groups :: BitString -> Version -> CorrectionLevel -> [Group]
groups :: String -> Version -> CorrectionLevel -> [Group]
groups String
input Version
version CorrectionLevel
correctionLevel = do
let gcw :: [(Version, Version)]
gcw = Version -> CorrectionLevel -> [(Version, Version)]
groupsCodeWords Version
version CorrectionLevel
correctionLevel
let dataCodewords :: [String]
dataCodewords = Version -> String -> [String]
forall a. Version -> [a] -> [[a]]
chunksOf Version
8 String
input :: [BitString]
([Group], [String]) -> [Group]
forall a b. (a, b) -> a
fst (([Group], [String]) -> [Group]) -> ([Group], [String]) -> [Group]
forall a b. (a -> b) -> a -> b
$ (([Group], [String]) -> (Version, Version) -> ([Group], [String]))
-> ([Group], [String])
-> [(Version, Version)]
-> ([Group], [String])
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\([Group]
acc, [String]
cw) (Version
gs, Version
size) -> ([Group]
acc [Group] -> [Group] -> [Group]
forall a. [a] -> [a] -> [a]
++ [Version -> Group -> Group
forall a. Version -> [a] -> [a]
take Version
gs (Version -> [String] -> Group
forall a. Version -> [a] -> [[a]]
chunksOf Version
size [String]
cw)], Version -> [String] -> [String]
forall a. Version -> [a] -> [a]
drop (Version
gs Version -> Version -> Version
forall a. Num a => a -> a -> a
* Version
size) [String]
cw)) ([], [String]
dataCodewords) [(Version, Version)]
gcw