Created
December 10, 2025 20:52
-
-
Save daily3014/fc25ae3165387a3bccc2b530b04e3143 to your computer and use it in GitHub Desktop.
Ever wanted to encode a string in Base64? Can't be bothered with those bloated Text to Base64 websites? Too elegant for those overrated "terminals" or whatever? Now you can encode strings in Base64 straight in luau with TYPES!
This file contains hidden or 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
| --!strict | |
| --!optimize 2 | |
| --!native | |
| type function Base64(user_type) | |
| if not user_type:is("singleton") then | |
| error(`provided type is not a singleton: {user_type.tag}`) | |
| end | |
| local value = tostring(user_type:value() :: string) | |
| local buff = buffer.fromstring(value) | |
| local PADDING_CHARACTER = 61 | |
| local ALPHABET_INDEX = buffer.create(64) do | |
| local Characters = { | |
| 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, | |
| 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, | |
| 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, | |
| 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, | |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, | |
| 43, 47 | |
| } | |
| for Index = 0, 63 do | |
| buffer.writeu8(ALPHABET_INDEX, Index, Characters[Index + 1]) | |
| end | |
| end | |
| local DIRECT_LOOKUP = buffer.create(256) do | |
| for Index = 0, 255 do | |
| buffer.writeu8(DIRECT_LOOKUP, Index, buffer.readu8(ALPHABET_INDEX, bit32.band(Index, 63))) | |
| end | |
| end | |
| local DECODE_TABLE = buffer.create(256) do | |
| for Index = 0, 255 do | |
| buffer.writeu8(DECODE_TABLE, Index, 255) | |
| end | |
| for Index = 65, 90 do | |
| buffer.writeu8(DECODE_TABLE, Index, Index - 65) | |
| end | |
| for Index = 97, 122 do | |
| buffer.writeu8(DECODE_TABLE, Index, Index - 97 + 26) | |
| end | |
| for Index = 48, 57 do | |
| buffer.writeu8(DECODE_TABLE, Index, Index - 48 + 52) | |
| end | |
| buffer.writeu8(DECODE_TABLE, 43, 62) | |
| buffer.writeu8(DECODE_TABLE, 47, 63) | |
| end | |
| local Padding = PADDING_CHARACTER | |
| local InputLength = buffer.len(buff) | |
| local Chunks = math.ceil(InputLength / 3) | |
| local OutputLength = Chunks * 4 | |
| local Output = buffer.create(OutputLength) | |
| local Lookup = DIRECT_LOOKUP | |
| local DoubleChunks = math.floor((Chunks - 1) / 2) | |
| for ChunkIndex = 1, DoubleChunks do | |
| local InputIndex = (ChunkIndex - 1) * 6 | |
| local OutputIndex = (ChunkIndex - 1) * 8 | |
| local Word1 = bit32.byteswap(buffer.readu32(buff, InputIndex)) | |
| local Octet1_1 = bit32.rshift(Word1, 26) | |
| local Octet1_2 = bit32.rshift(Word1, 20) | |
| local Octet1_3 = bit32.rshift(Word1, 14) | |
| local Octet1_4 = bit32.rshift(Word1, 8) | |
| local Word2 = bit32.byteswap(buffer.readu32(buff, InputIndex + 3)) | |
| local Octet2_1 = bit32.rshift(Word2, 26) | |
| local Octet2_2 = bit32.rshift(Word2, 20) | |
| local Octet2_3 = bit32.rshift(Word2, 14) | |
| local Octet2_4 = bit32.rshift(Word2, 8) | |
| buffer.writeu32(Output, OutputIndex, bit32.bor( | |
| buffer.readu8(Lookup, bit32.band(Octet1_1, 255)), | |
| buffer.readu8(Lookup, bit32.band(Octet1_2, 255)) * 256, | |
| buffer.readu8(Lookup, bit32.band(Octet1_3, 255)) * 65536, | |
| buffer.readu8(Lookup, bit32.band(Octet1_4, 255)) * 16777216 | |
| )) | |
| buffer.writeu32(Output, OutputIndex + 4, bit32.bor( | |
| buffer.readu8(Lookup, bit32.band(Octet2_1, 255)), | |
| buffer.readu8(Lookup, bit32.band(Octet2_2, 255)) * 256, | |
| buffer.readu8(Lookup, bit32.band(Octet2_3, 255)) * 65536, | |
| buffer.readu8(Lookup, bit32.band(Octet2_4, 255)) * 16777216 | |
| )) | |
| end | |
| local ProcessedChunks = DoubleChunks * 2 | |
| if ProcessedChunks < Chunks - 1 then | |
| local InputIndex = ProcessedChunks * 3 | |
| local OutputIndex = ProcessedChunks * 4 | |
| local Word = bit32.byteswap(buffer.readu32(buff, InputIndex)) | |
| local Octet1 = bit32.rshift(Word, 26) | |
| local Octet2 = bit32.rshift(Word, 20) | |
| local Octet3 = bit32.rshift(Word, 14) | |
| local Octet4 = bit32.rshift(Word, 8) | |
| buffer.writeu32(Output, OutputIndex, bit32.bor( | |
| buffer.readu8(Lookup, bit32.band(Octet1, 255)), | |
| buffer.readu8(Lookup, bit32.band(Octet2, 255)) * 256, | |
| buffer.readu8(Lookup, bit32.band(Octet3, 255)) * 65536, | |
| buffer.readu8(Lookup, bit32.band(Octet4, 255)) * 16777216 | |
| )) | |
| end | |
| if InputLength > 0 then | |
| local TotalProcessedChunks = DoubleChunks * 2 + (ProcessedChunks < Chunks - 1 and 1 or 0) | |
| local ProcessedBytes = TotalProcessedChunks * 3 | |
| local RemainingBytes = InputLength - ProcessedBytes | |
| local LastOutputIndex = OutputLength - 4 | |
| if RemainingBytes == 3 then | |
| if ProcessedBytes + 4 <= InputLength then | |
| local Word = bit32.byteswap(buffer.readu32(buff, ProcessedBytes)) | |
| local Octet1 = bit32.rshift(Word, 26) | |
| local Octet2 = bit32.rshift(Word, 20) | |
| local Octet3 = bit32.rshift(Word, 14) | |
| local Octet4 = bit32.rshift(Word, 8) | |
| buffer.writeu32(Output, LastOutputIndex, bit32.bor( | |
| buffer.readu8(Lookup, bit32.band(Octet1, 255)), | |
| buffer.readu8(Lookup, bit32.band(Octet2, 255)) * 256, | |
| buffer.readu8(Lookup, bit32.band(Octet3, 255)) * 65536, | |
| buffer.readu8(Lookup, bit32.band(Octet4, 255)) * 16777216 | |
| )) | |
| else | |
| local Byte1 = buffer.readu8(buff, ProcessedBytes) | |
| local Byte2 = buffer.readu8(buff, ProcessedBytes + 1) | |
| local Byte3 = buffer.readu8(buff, ProcessedBytes + 2) | |
| local Combined = bit32.bor(bit32.lshift(Byte1, 16), bit32.lshift(Byte2, 8), Byte3) | |
| local Octet1 = bit32.rshift(Combined, 18) | |
| local Octet2 = bit32.band(bit32.rshift(Combined, 12), 63) | |
| local Octet3 = bit32.band(bit32.rshift(Combined, 6), 63) | |
| local Octet4 = bit32.band(Combined, 63) | |
| buffer.writeu32(Output, LastOutputIndex, bit32.bor( | |
| buffer.readu8(Lookup, Octet1), | |
| buffer.readu8(Lookup, Octet2) * 256, | |
| buffer.readu8(Lookup, Octet3) * 65536, | |
| buffer.readu8(Lookup, Octet4) * 16777216 | |
| )) | |
| end | |
| elseif RemainingBytes == 2 then | |
| local Byte1 = buffer.readu8(buff, ProcessedBytes) | |
| local Byte2 = buffer.readu8(buff, ProcessedBytes + 1) | |
| local Combined = bit32.bor(bit32.lshift(Byte1, 16), bit32.lshift(Byte2, 8)) | |
| local Octet1 = bit32.rshift(Combined, 18) | |
| local Octet2 = bit32.rshift(Combined, 12) | |
| local Octet3 = bit32.rshift(Combined, 6) | |
| buffer.writeu32(Output, LastOutputIndex, bit32.bor( | |
| buffer.readu8(Lookup, bit32.band(Octet1, 255)), | |
| buffer.readu8(Lookup, bit32.band(Octet2, 255)) * 256, | |
| buffer.readu8(Lookup, bit32.band(Octet3, 255)) * 65536, | |
| Padding * 16777216 | |
| )) | |
| elseif RemainingBytes == 1 then | |
| local Byte1 = buffer.readu8(buff, ProcessedBytes) | |
| local Combined = bit32.lshift(Byte1, 16) | |
| local Octet1 = bit32.rshift(Combined, 18) | |
| local Octet2 = bit32.rshift(Combined, 12) | |
| buffer.writeu32(Output, LastOutputIndex, bit32.bor( | |
| buffer.readu8(Lookup, bit32.band(Octet1, 255)), | |
| buffer.readu8(Lookup, bit32.band(Octet2, 255)) * 256, | |
| Padding * 65536, | |
| Padding * 16777216 | |
| )) | |
| end | |
| end | |
| return types.singleton(buffer.tostring(Output)) | |
| end | |
| -- Example Usage: | |
| local Encoded: Base64<"This is a test string"> = "" -- Press tab for autocompletion! | |
| -- Do note that autocompletion will *not* work with Fragment Autocomplete |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Awesome!