Skip to content

Commit

Permalink
stdlib: add Base64 encoder
Browse files Browse the repository at this point in the history
  • Loading branch information
soc committed Nov 8, 2024
1 parent f0b06ef commit 46f99c3
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 1 deletion.
43 changes: 43 additions & 0 deletions core/stdlib/base64.core
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use std.string.StringBuffer

let STANDARD: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
let STANDARD_URL_SAFE: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
let ORDERED: String = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"

@pub
fun encodeStandard(src: Array[UInt8]): String = encode(src, STANDARD)

@pub
fun encodeUrlSafe(src: Array[UInt8]): String = encode(src, STANDARD_URL_SAFE)

@pub
fun encodeOrdered(src: Array[UInt8]): String = encode(src, ORDERED)

fun encode(src: Array[UInt8], alphabet: String): String {
let buffer = StringBuffer::new()
var srcSize = src.size()
let remainder = srcSize.remainder(3)
srcSize = srcSize - remainder
var i = 0
while (i < srcSize) {
let bits = src(i).toInt32().shiftLeft(16i32) | src(i+1).toInt32().shiftLeft(8i32) | src(i+2).toInt32()
i = i + 3
buffer.appendChar(alphabet.getByte(bits.shiftRight(18i32).asInt64() & 0b111111).toChar())
buffer.appendChar(alphabet.getByte(bits.shiftRight(12i32).asInt64() & 0b111111).toChar())
buffer.appendChar(alphabet.getByte(bits.shiftRight( 6i32).asInt64() & 0b111111).toChar())
buffer.appendChar(alphabet.getByte(bits .asInt64() & 0b111111).toChar())
}
if remainder
... == 2 {
let bits = src(i).toInt32().shiftLeft(16i32) | src(i+1).toInt32().shiftLeft(8i32)
buffer.appendChar(alphabet.getByte(bits.shiftRight(18i32).asInt64() & 0b111111).toChar())
buffer.appendChar(alphabet.getByte(bits.shiftRight(12i32).asInt64() & 0b111111).toChar())
buffer.appendChar(alphabet.getByte(bits.shiftRight( 6i32).asInt64() & 0b111111).toChar())
}
... == 1 {
let bits = src(i).toInt32().shiftLeft(16i32)
buffer.appendChar(alphabet.getByte(bits.shiftRight(18i32).asInt64() & 0b111111).toChar())
buffer.appendChar(alphabet.getByte(bits.shiftRight(12i32).asInt64() & 0b111111).toChar())
}
buffer.toString()
}
1 change: 1 addition & 0 deletions core/stdlib/stdlib.core
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@pub use thread.{AtomicInt32, AtomicInt64, Condition, Mutex, Thread};

@pub mod annotations;
@pub mod base64;
@pub mod collections;
@pub mod primitives
@pub mod rand
Expand Down
44 changes: 44 additions & 0 deletions tests/base64/base64_ordered.core
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
fun main(): Unit {
bytes0()
bytes1()
bytes2()
bytes3()
bytes13()
bytes15()
}

fun bytes0(): Unit {
let bytes = Array[UInt8]::new()
let string = std::base64::encodeOrdered(bytes)
assert(string == "")
}

fun bytes1(): Unit {
let bytes = Array[UInt8]::new(0u8)
let string = std::base64::encodeOrdered(bytes)
assert(string == "--")
}

fun bytes2(): Unit {
let bytes = Array[UInt8]::new(0u8, 12u8)
let string = std::base64::encodeOrdered(bytes)
assert(string == "--k")
}

fun bytes3(): Unit {
let bytes = Array[UInt8]::new(0u8, 12u8, 23u8)
let string = std::base64::encodeOrdered(bytes)
assert(string == "--kM")
}

fun bytes13(): Unit {
let bytes = Array[UInt8]::new(255u8, 234u8, 23u8, 45u8, 238u8, 78u8, 89u8, 23u8, 45u8, 67u8, 78u8, 89u8, 91u8)
let string = std::base64::encodeOrdered(bytes)
assert(string == "zycMATtDLGRhFotOLk")
}

fun bytes15(): Unit {
let bytes = Array[UInt8]::new(0u8, 12u8, 23u8, 45u8, 67u8, 78u8, 89u8, 91u8, 12u8, 23u8, 45u8, 67u8, 78u8, 89u8, 91u8);
let string = std::base64::encodeOrdered(bytes);
assert(string == "--kMAJCDLKgB4mp2I__Q");
}
44 changes: 44 additions & 0 deletions tests/base64/base64_standard.core
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
fun main(): Unit {
bytes0()
bytes1()
bytes2()
bytes3()
bytes13()
bytes15()
}

fun bytes0(): Unit {
let bytes = Array[UInt8]::new()
let string = std::base64::encodeStandard(bytes)
assert(string == "")
}

fun bytes1(): Unit {
let bytes = Array[UInt8]::new(0u8)
let string = std::base64::encodeStandard(bytes)
assert(string == "AA")
}

fun bytes2(): Unit {
let bytes = Array[UInt8]::new(0u8, 12u8)
let string = std::base64::encodeStandard(bytes)
assert(string == "AAw")
}

fun bytes3(): Unit {
let bytes = Array[UInt8]::new(0u8, 12u8, 23u8);
let string = std::base64::encodeStandard(bytes);
assert(string == "AAwX");
}

fun bytes13(): Unit {
let bytes = Array[UInt8]::new(255u8, 234u8, 23u8, 45u8, 238u8, 78u8, 89u8, 23u8, 45u8, 67u8, 78u8, 89u8, 91u8);
let string = std::base64::encodeStandard(bytes);
assert(string == "/+oXLe5OWRctQ05ZWw");
}

fun bytes15(): Unit {
let bytes = Array[UInt8]::new(0u8, 12u8, 23u8, 45u8, 67u8, 78u8, 89u8, 91u8, 12u8, 23u8, 45u8, 67u8, 78u8, 89u8, 91u8);
let string = std::base64::encodeStandard(bytes);
assert(string == "AAwXLUNOWVsMFy1DTllb");
}
44 changes: 44 additions & 0 deletions tests/base64/base64_urlsafe.core
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
fun main(): Unit {
bytes0();
bytes1();
bytes2();
bytes3();
bytes13();
bytes15();
}

fun bytes0(): Unit {
let bytes = Array[UInt8]::new();
let string = std::base64::encodeUrlSafe(bytes);
assert(string == "");
}

fun bytes1(): Unit {
let bytes = Array[UInt8]::new(0u8)
let string = std::base64::encodeUrlSafe(bytes)
assert(string == "AA")
}

fun bytes2(): Unit {
let bytes = Array[UInt8]::new(0u8, 12u8)
let string = std::base64::encodeUrlSafe(bytes)
assert(string == "AAw")
}

fun bytes3(): Unit {
let bytes = Array[UInt8]::new(0u8, 12u8, 23u8)
let string = std::base64::encodeUrlSafe(bytes)
assert(string == "AAwX")
}

fun bytes13(): Unit {
let bytes = Array[UInt8]::new(255u8, 234u8, 23u8, 45u8, 238u8, 78u8, 89u8, 23u8, 45u8, 67u8, 78u8, 89u8, 91u8)
let string = std::base64::encodeUrlSafe(bytes)
assert(string == "_-oXLe5OWRctQ05ZWw")
}

fun bytes15(): Unit {
let bytes = Array[UInt8]::new(0u8, 12u8, 23u8, 45u8, 67u8, 78u8, 89u8, 91u8, 12u8, 23u8, 45u8, 67u8, 78u8, 89u8, 91u8)
let string = std::base64::encodeUrlSafe(bytes)
assert(string == "AAwXLUNOWVsMFy1DTllb")
}
2 changes: 1 addition & 1 deletion tests/fatal1.core
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//= error code 1
//= stderr "fatal error: bla\n std::fatalError (stdlib/stdlib.core:16)\n main (tests/fatal1.core:5)\n"
//= stderr "fatal error: bla\n std::fatalError (stdlib/stdlib.core:17)\n main (tests/fatal1.core:5)\n"

fun main(): Unit {
std::fatalError("bla");
Expand Down

0 comments on commit 46f99c3

Please sign in to comment.