Last active
June 29, 2016 23:15
-
-
Save alphaKAI/208bc43d0d3efe69d80c5377ec7c70a3 to your computer and use it in GitHub Desktop.
Tiny Base64 Encoder in F#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module tinyBase64Encoder | |
open System | |
open System.Collections.Generic | |
// Declare fundamental functions | |
// Convert binary string into decimal | |
let binToDec binStr = Convert.ToInt32 (binStr, 2) | |
// Convert decimal into binary string | |
let decToBin dec = Convert.ToString (dec &&& 0xff, 2) | |
// Convert Char Sequence into String | |
let charSeqToString charSeq = Array.ofSeq charSeq |> Seq.map string |> String.concat "" | |
// Convert int List (corresponding with char) into String | |
let intListToString intList = | |
intList | |
|> List.map char | |
|> charSeqToString | |
let stringToIntList str = | |
str |> Seq.toList |> List.map int | |
// BASE64 Encoder and Subsets | |
// Base64 Charactors | |
let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" |> Seq.toList | |
// Conversion table, Binary number string into Base64 Char | |
let table = | |
charset | |
|> List.mapi (fun i c -> | |
let e = decToBin i | |
let s = String.replicate (6 - e.Length) "0" + e | |
s, c) | |
|> Map.ofList | |
// Convert data to BinaryString | |
let convert data = | |
data | |
|> List.map (decToBin >> (fun e -> | |
if e.Length = 8 then e | |
else String.replicate (8 - e.Length) "0" + e)) | |
// Create List of six bit List and padding last list if the length of last list is shortan than 6 | |
let prepare converted = | |
let binaries = converted |> String.concat "" | |
let bLen = binaries.Length | |
let quotients = List.init (bLen / 6) (fun i -> binaries.[(i * 6)..((i + 1) * 6 - 1)]) | |
in | |
if bLen % 6 = 0 then quotients | |
else | |
let appends = | |
let remainds = binaries.[(bLen - (bLen % 6))..(bLen - 1)] | |
remainds + String.replicate (6 - remainds.Length) "0" | |
List.append quotients [appends] | |
// Convert binarie string into Base64 Char by four Charactors | |
let preEncode1 prepared = | |
let prepared = prepared |> List.toArray | |
let pLen = prepared.Length | |
List.init (pLen / 4) (fun i -> i * 4) | |
|> List.map (fun j -> | |
List.init 4 (fun k -> table.[prepared.[j + k]]) | |
|> List.map string | |
|> List.toArray | |
|> String.concat "") | |
|> String.concat "" | |
// If the last list which retunred by prepared function is shortan than 4, padding by '=' | |
let preEncode2 prepared preEncoded = | |
let prepared = prepared |> List.toArray | |
let pLen = prepared.Length | |
if pLen % 4 = 0 then preEncoded | |
else | |
let padding = String.replicate (4 - (pLen % 4)) "=" | |
let appends = prepared.[(pLen - (pLen % 4))..(pLen - 1)] | |
|> Array.map (fun remain -> string table.[remain]) | |
|> String.concat "" | |
preEncoded + appends + padding | |
// Base64 Encoder | |
let encode64 data = | |
let prepared = data | |
|> convert | |
|> prepare | |
preEncode2 prepared <| preEncode1 prepared | |
printfn "%A" <| ("ABCDEFG" |> Seq.toList |> List.map int |> encode64) | |
assert(encode64 ("ABCDEFG" |> stringToIntList )= "QUJDREVGRw==") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment