-
-
Save sayurin/a452e4c2b7e6a283cbd73945cdf4a6e8 to your computer and use it in GitHub Desktop.
Tiny Base64 Decoder in F#
This file contains 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 tinyBase64Decoder | |
open System | |
open System.Collections.Generic | |
// Declare fundamental functions | |
// Generate n length Integer List (0 upto n - 1) | |
let iota n = [0..n-1] | |
// Generate n length List of x | |
let repeat n x = List.replicate n x | |
// 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 |> String | |
// Convert int List (corresponding with char) into String | |
let intListToString intList = | |
intList | |
|> List.map char | |
|> charSeqToString | |
// BASE64 Decoder and Subsets | |
// Base64 Charactors | |
let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" |> Seq.toList | |
// Conversion table, Base64 Char to Binary number string | |
let table = | |
charset | |
|> List.mapi (fun i c -> | |
let e = decToBin i | |
let s = String.replicate (6 - e.Length) "0" + e | |
c, s) | |
|> Map.ofList | |
// Convert Base64 strings into Binary String(by replacing with the above table) | |
let convert data = | |
data | |
|> Seq.choose (fun e -> Map.tryFind e table) // omit invalid char, for example '=' | |
|> String.concat "" | |
// Create List by 4 bits List from convted string | |
let getQuotients (converted:string) = | |
let cLen = converted.Length | |
List.init (cLen / 4) (fun i -> converted.[(i * 4)..((i + 1) * 4 - 1)]) | |
// Create List by two bits List from ```quotients``` (require it from result of the above function) | |
let getBuffers quotients = | |
let quotients = List.toArray quotients | |
let qLen = quotients.Length | |
List.init (qLen / 2) (fun i -> quotients.[(i * 2)..((i + 1) * 2 - 1)]) | |
// Generating Binaries with buffers from the above function | |
let finalize buf = | |
buf |> List.map (fun (b:string[]) -> | |
let b0 = b.[0] |> binToDec | |
let b1 = b.[1] |> binToDec | |
((b0 <<< 4) ||| b1) &&& 0xff) | |
// Decode base64 String into Unsinged Bytes | |
let decode64 (data:string) = | |
data | |
|> convert | |
|> getQuotients | |
|> getBuffers | |
|> finalize | |
//Decode Test. The below codes are test for decoding | |
let encoded = "QUJDREVGRw==" // <- encoded string of "ABCDEFG" | |
assert ("ABCDEFG" = (decode64 encoded |> intListToString)) | |
printfn "%s -> %A" encoded <| (decode64 encoded |> intListToString) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment