// Base64 (RFC 4648) for `-bin` metadata. gRPC carries binary metadata under keys
// suffixed `-bin`, base64-encoded on the wire; a call surfaces the decoded bytes and
// re-encodes on the way out. Pure and all-backend, like the rest of the engine.
///|
let b64_alphabet : Bytes = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
///|
/// Standard base64 encode with `=` padding.
pub fn base64_encode(data : Bytes) -> Bytes {
let out = @buffer.Buffer()
let n = data.length()
let mut i = 0
while i + 3 <= n {
let x = (data[i].to_int() << 16) |
(data[i + 1].to_int() << 8) |
data[i + 2].to_int()
out.write_byte(b64_alphabet[(x >> 18) & 0x3f])
out.write_byte(b64_alphabet[(x >> 12) & 0x3f])
out.write_byte(b64_alphabet[(x >> 6) & 0x3f])
out.write_byte(b64_alphabet[x & 0x3f])
i = i + 3
}
let rem = n - i
if rem == 1 {
let x = data[i].to_int() << 16
out.write_byte(b64_alphabet[(x >> 18) & 0x3f])
out.write_byte(b64_alphabet[(x >> 12) & 0x3f])
out.write_byte(b'=')
out.write_byte(b'=')
} else if rem == 2 {
let x = (data[i].to_int() << 16) | (data[i + 1].to_int() << 8)
out.write_byte(b64_alphabet[(x >> 18) & 0x3f])
out.write_byte(b64_alphabet[(x >> 12) & 0x3f])
out.write_byte(b64_alphabet[(x >> 6) & 0x3f])
out.write_byte(b'=')
}
out.to_bytes()
}
///|
fn b64_val(c : Int) -> Int {
if c >= 65 && c <= 90 {
c - 65
} else if c >= 97 && c <= 122 {
c - 97 + 26
} else if c >= 48 && c <= 57 {
c - 48 + 52
} else if c == 43 {
62
} else if c == 47 {
63
} else {
-1
}
}
///|
/// Standard base64 decode. Non-alphabet bytes (padding, whitespace) are skipped, so
/// both padded and unpadded input decode.
pub fn base64_decode(data : Bytes) -> Bytes {
let vals : Array[Int] = []
for i = 0; i < data.length(); i = i + 1 {
let v = b64_val(data[i].to_int())
if v >= 0 {
vals.push(v)
}
}
let out = @buffer.Buffer()
let mut i = 0
while i + 2 <= vals.length() {
out.write_byte(((vals[i] << 2) | (vals[i + 1] >> 4)).to_byte())
if i + 3 <= vals.length() {
out.write_byte(
(((vals[i + 1] & 0xf) << 4) | (vals[i + 2] >> 2)).to_byte(),
)
if i + 4 <= vals.length() {
out.write_byte((((vals[i + 2] & 0x3) << 6) | vals[i + 3]).to_byte())
}
}
i = i + 4
}
out.to_bytes()
}
///|
/// Whether a metadata key names binary content: it ends in `-bin` (gRPC's convention
/// for base64-on-the-wire values).
pub fn is_binary_metadata(name : Bytes) -> Bool {
let n = name.length()
n >= 4 &&
name[n - 4] == b'-' &&
name[n - 3] == b'b' &&
name[n - 2] == b'i' &&
name[n - 1] == b'n'
}
///|
/// Decode a metadata value coming off the wire: base64-decoded for a `-bin` key,
/// verbatim otherwise.
pub fn metadata_value_from_wire(name : Bytes, value : Bytes) -> Bytes {
if is_binary_metadata(name) {
base64_decode(value)
} else {
value
}
}
///|
/// Encode a metadata value for the wire: base64-encoded for a `-bin` key, verbatim
/// otherwise.
pub fn metadata_value_to_wire(name : Bytes, value : Bytes) -> Bytes {
if is_binary_metadata(name) {
base64_encode(value)
} else {
value
}
}