Skip to content

Instantly share code, notes, and snippets.

@alphaKAI
Last active June 29, 2016 23:15
Show Gist options
  • Save alphaKAI/208bc43d0d3efe69d80c5377ec7c70a3 to your computer and use it in GitHub Desktop.
Save alphaKAI/208bc43d0d3efe69d80c5377ec7c70a3 to your computer and use it in GitHub Desktop.
Tiny Base64 Encoder in F#
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