- var chars_in_last_step = length % 3
- var result_length = steps*4
- if chars_in_last_step > 0 then result_length += 4
- var result = (padding.to_s*result_length).to_cstring
+ var bytes_in_last_step = length % 3
+ var result_length = steps * 4
+ if bytes_in_last_step > 0 then result_length += 4
+ var result = new Bytes.with_capacity(result_length)
+
+ var in_off = 0
+ for s in [0 .. steps[ do
+ var ind = ((self[in_off] & 0b1111_1100u8) >> 2).to_i
+ result.add base64_bytes[ind]
+ ind = ((self[in_off] & 0b0000_0011u8) << 4).to_i | ((self[in_off + 1] & 0b1111_0000u8) >> 4).to_i
+ result.add base64_bytes[ind]
+ ind = ((self[in_off + 1] & 0b0000_1111u8) << 2).to_i | ((self[in_off + 2] & 0b1100_0000u8) >> 6).to_i
+ result.add base64_bytes[ind]
+ ind = (self[in_off + 2] & 0b0011_1111u8).to_i
+ result.add base64_bytes[ind]
+ in_off += 3
+ end
+ if bytes_in_last_step == 1 then
+ result.add base64_bytes[((self[in_off] & 0b1111_1100u8) >> 2).to_i]
+ result.add base64_bytes[((self[in_off] & 0b0000_0011u8) << 4).to_i]
+ else if bytes_in_last_step == 2 then
+ result.add base64_bytes[((self[in_off] & 0b1111_1100u8) >> 2).to_i]
+ result.add base64_bytes[(((self[in_off] & 0b0000_0011u8) << 4) | ((self[in_off + 1] & 0b1111_0000u8) >> 4)).to_i]
+ result.add base64_bytes[((self[in_off + 1] & 0b0000_1111u8) << 2).to_i]
+ end
+ var rempad = if bytes_in_last_step > 0 then 3 - bytes_in_last_step else 0
+ for i in [0 .. rempad[ do result.add b'='