Compare commits
No commits in common. "fb22e14524b059379caadcde3566e5d7e62c30dc" and "5b69ce554ce0d7ab8ecf325564e0aa4a999c6c24" have entirely different histories.
fb22e14524
...
5b69ce554c
@ -25,4 +25,3 @@ luna_app(mkdir.cpp mkdir OFF)
|
|||||||
luna_app(rm.cpp rm OFF)
|
luna_app(rm.cpp rm OFF)
|
||||||
luna_app(stat.cpp stat OFF)
|
luna_app(stat.cpp stat OFF)
|
||||||
luna_app(uname.cpp uname OFF)
|
luna_app(uname.cpp uname OFF)
|
||||||
luna_app(base64.cpp base64 OFF)
|
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
#include <luna/Base64.h>
|
|
||||||
#include <os/ArgumentParser.h>
|
|
||||||
#include <os/File.h>
|
|
||||||
|
|
||||||
Result<int> luna_main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
StringView path;
|
|
||||||
bool decode { false };
|
|
||||||
bool allow_garbage { false };
|
|
||||||
|
|
||||||
os::ArgumentParser parser;
|
|
||||||
parser.add_description("Encode or decode Base64 data. If not given a file, reads from standard input.");
|
|
||||||
parser.add_positional_argument(path, "file", "-"_sv);
|
|
||||||
parser.add_switch_argument(decode, 'd', "decode", "decode data");
|
|
||||||
parser.add_switch_argument(allow_garbage, ' ', "allow-garbage", "ignore non-base64 characters");
|
|
||||||
parser.parse(argc, argv);
|
|
||||||
|
|
||||||
auto file = TRY(os::File::open_input_file(path));
|
|
||||||
|
|
||||||
auto output = os::File::standard_output();
|
|
||||||
|
|
||||||
if (!decode)
|
|
||||||
{
|
|
||||||
auto data = TRY(file->read_all());
|
|
||||||
|
|
||||||
auto encoded = TRY(Base64::encode(data));
|
|
||||||
|
|
||||||
output->write(encoded.view());
|
|
||||||
output->write("\n"_sv);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto data = TRY(file->read_all_as_string());
|
|
||||||
|
|
||||||
auto decoded = TRY(Base64::decode(data.view(), allow_garbage));
|
|
||||||
|
|
||||||
output->write(decoded);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -6,10 +6,14 @@ using os::File;
|
|||||||
|
|
||||||
static Result<void> do_cat(StringView path)
|
static Result<void> do_cat(StringView path)
|
||||||
{
|
{
|
||||||
SharedPtr<File> f = TRY(File::open_input_file(path));
|
SharedPtr<File> f;
|
||||||
|
|
||||||
auto out = File::standard_output();
|
auto out = File::standard_output();
|
||||||
|
|
||||||
|
if (path == "-") f = File::standard_input();
|
||||||
|
else
|
||||||
|
f = TRY(File::open(path, File::ReadOnly));
|
||||||
|
|
||||||
auto buf = TRY(Buffer::create_sized(4096));
|
auto buf = TRY(Buffer::create_sized(4096));
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
@ -59,7 +59,7 @@ void ConsoleDevice::did_press_key(char key)
|
|||||||
// Ctrl+D
|
// Ctrl+D
|
||||||
if (key == 'd' && (Keyboard::modifiers() & Keyboard::LeftControl))
|
if (key == 'd' && (Keyboard::modifiers() & Keyboard::LeftControl))
|
||||||
{
|
{
|
||||||
if (g_temp_input.size() == 0) g_eof = true;
|
g_eof = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include "boot/bootboot.h"
|
#include "boot/bootboot.h"
|
||||||
#include "video/Framebuffer.h"
|
#include "video/Framebuffer.h"
|
||||||
#include <luna/CString.h>
|
#include <luna/CString.h>
|
||||||
#include <luna/CType.h>
|
|
||||||
#include <luna/Format.h>
|
#include <luna/Format.h>
|
||||||
#include <luna/Result.h>
|
#include <luna/Result.h>
|
||||||
#include <luna/ScopeGuard.h>
|
#include <luna/ScopeGuard.h>
|
||||||
@ -110,7 +109,6 @@ namespace TextConsole
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
if (_iscntrl(c)) return;
|
|
||||||
putwchar_at(c, g_x_position, g_y_position);
|
putwchar_at(c, g_x_position, g_y_position);
|
||||||
next_char();
|
next_char();
|
||||||
if (at_end_of_screen())
|
if (at_end_of_screen())
|
||||||
|
@ -23,7 +23,6 @@ set(FREESTANDING_SOURCES
|
|||||||
src/Spinlock.cpp
|
src/Spinlock.cpp
|
||||||
src/PathParser.cpp
|
src/PathParser.cpp
|
||||||
src/UBSAN.cpp
|
src/UBSAN.cpp
|
||||||
src/Base64.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <luna/Buffer.h>
|
|
||||||
#include <luna/String.h>
|
|
||||||
|
|
||||||
namespace Base64
|
|
||||||
{
|
|
||||||
Result<String> encode(StringView data);
|
|
||||||
Result<String> encode(Slice<const u8> data);
|
|
||||||
Result<String> encode(const Buffer& data);
|
|
||||||
|
|
||||||
Result<Buffer> decode(StringView data, bool allow_garbage_chars = false);
|
|
||||||
Result<String> decode_string(StringView data, bool allow_garbage_chars = false);
|
|
||||||
}
|
|
@ -11,10 +11,6 @@ template <typename T> class Slice
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Tp> Slice(const Slice<Tp>& other) : m_data((T*)other.m_data), m_size(other.m_size)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const T* data() const
|
const T* data() const
|
||||||
{
|
{
|
||||||
return m_data;
|
return m_data;
|
||||||
@ -50,18 +46,6 @@ template <typename T> class Slice
|
|||||||
return m_data + m_size;
|
return m_data + m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& operator[](usize index) const
|
|
||||||
{
|
|
||||||
check(index < m_size);
|
|
||||||
return m_data[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
T& operator[](usize index)
|
|
||||||
{
|
|
||||||
check(index < m_size);
|
|
||||||
return m_data[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T* const m_data;
|
T* const m_data;
|
||||||
const usize m_size;
|
const usize m_size;
|
||||||
|
@ -1,144 +0,0 @@
|
|||||||
#include <luna/Base64.h>
|
|
||||||
#include <luna/CType.h>
|
|
||||||
#include <luna/DebugLog.h>
|
|
||||||
#include <luna/Slice.h>
|
|
||||||
#include <luna/StringBuilder.h>
|
|
||||||
|
|
||||||
static const char g_base64_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
||||||
|
|
||||||
static Option<u8> value_from_base64_character(char letter)
|
|
||||||
{
|
|
||||||
if (_isupper(letter)) return (u8)(letter - 'A');
|
|
||||||
if (_islower(letter)) return (u8)(26 + (letter - 'a'));
|
|
||||||
if (_isdigit(letter)) return (u8)(52 + (letter - '0'));
|
|
||||||
if (letter == '+') return 62;
|
|
||||||
if (letter == '/') return 63;
|
|
||||||
if (letter == '=') return {};
|
|
||||||
unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Result<void> decode_base64_buffer(const Vector<char>& input, Buffer& output)
|
|
||||||
{
|
|
||||||
const usize bytes_to_decode = 4;
|
|
||||||
|
|
||||||
Option<u8> base64_data[bytes_to_decode];
|
|
||||||
|
|
||||||
for (usize i = 0; i < 4; i++) { base64_data[i] = value_from_base64_character(input[i]); }
|
|
||||||
|
|
||||||
u8 decoded_bytes[3];
|
|
||||||
usize total_decoded_bytes = 0;
|
|
||||||
|
|
||||||
decoded_bytes[0] = (base64_data[0].value() << 2) | (base64_data[1].value() >> 4);
|
|
||||||
total_decoded_bytes++;
|
|
||||||
|
|
||||||
if (base64_data[2].has_value())
|
|
||||||
{
|
|
||||||
decoded_bytes[1] = ((base64_data[1].value() & 0b1111) << 4) | (base64_data[2].value() >> 2);
|
|
||||||
total_decoded_bytes++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (base64_data[3].has_value())
|
|
||||||
{
|
|
||||||
decoded_bytes[2] = ((base64_data[2].value() & 0b11) << 6) | base64_data[3].value();
|
|
||||||
total_decoded_bytes++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return output.append_data(decoded_bytes, total_decoded_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Base64
|
|
||||||
{
|
|
||||||
Result<String> encode(StringView data)
|
|
||||||
{
|
|
||||||
return encode(Slice<const u8> { (const u8*)data.chars(), data.length() });
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<String> encode(const Buffer& data)
|
|
||||||
{
|
|
||||||
return encode(Slice<const u8> { data.data(), data.size() });
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<String> encode(Slice<const u8> data)
|
|
||||||
{
|
|
||||||
StringBuilder sb;
|
|
||||||
|
|
||||||
for (usize i = 0; i < data.size(); i += 3)
|
|
||||||
{
|
|
||||||
usize bytes_to_encode = data.size() - i;
|
|
||||||
if (bytes_to_encode > 3) bytes_to_encode = 3;
|
|
||||||
|
|
||||||
TRY(sb.add(g_base64_alphabet[data[i] >> 2]));
|
|
||||||
if (bytes_to_encode > 1) TRY(sb.add(g_base64_alphabet[((data[i] & 0b11) << 4) | (data[i + 1] >> 4)]));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TRY(sb.add(g_base64_alphabet[(data[i] & 0b11) << 6]));
|
|
||||||
TRY(sb.add("=="_sv));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes_to_encode > 2) TRY(sb.add(g_base64_alphabet[((data[i + 1] & 0b1111) << 2) | (data[i + 2] >> 6)]));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TRY(sb.add(g_base64_alphabet[(data[i + 1] & 0b1111) << 2]));
|
|
||||||
TRY(sb.add("="_sv));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRY(sb.add(g_base64_alphabet[data[i + 2] & 0b111111]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.string();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<Buffer> decode(StringView data, bool allow_garbage_chars)
|
|
||||||
{
|
|
||||||
Buffer buf;
|
|
||||||
|
|
||||||
char* padding = strchr(data.chars(), '=');
|
|
||||||
if (padding)
|
|
||||||
{
|
|
||||||
// If the string ends with padding, it must be either one or two equals signs.
|
|
||||||
if (padding[1] != '=' && padding[1] != '\0') return err(EINVAL);
|
|
||||||
if (padding[1])
|
|
||||||
{
|
|
||||||
if (padding[strspn(&padding[2], "\n") + 2]) return err(EINVAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<char> chars_read;
|
|
||||||
|
|
||||||
for (const auto& c : data)
|
|
||||||
{
|
|
||||||
if (c == '\n') continue;
|
|
||||||
|
|
||||||
if (!_isalnum(c) && c != '+' && c != '/' && c != '=')
|
|
||||||
{
|
|
||||||
if (allow_garbage_chars) continue;
|
|
||||||
return err(EINVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
TRY(chars_read.try_append(c));
|
|
||||||
|
|
||||||
if (chars_read.size() == 4)
|
|
||||||
{
|
|
||||||
TRY(decode_base64_buffer(chars_read, buf));
|
|
||||||
chars_read.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unterminated input
|
|
||||||
if (chars_read.size() > 0) return err(EINVAL);
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<String> decode_string(StringView data, bool allow_garbage_chars)
|
|
||||||
{
|
|
||||||
auto buf = TRY(decode(data, allow_garbage_chars));
|
|
||||||
|
|
||||||
u8 nul_byte = '\0';
|
|
||||||
TRY(buf.append_data(&nul_byte, 1));
|
|
||||||
|
|
||||||
return String::from_cstring((char*)buf.data());
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,14 +24,6 @@ namespace os
|
|||||||
static Result<SharedPtr<File>> open_or_create(StringView path, OpenMode flags, mode_t mode = 0644);
|
static Result<SharedPtr<File>> open_or_create(StringView path, OpenMode flags, mode_t mode = 0644);
|
||||||
static Result<SharedPtr<File>> create(StringView path, OpenMode flags, mode_t mode = 0644);
|
static Result<SharedPtr<File>> create(StringView path, OpenMode flags, mode_t mode = 0644);
|
||||||
|
|
||||||
/*
|
|
||||||
If path is "-", return standard input (as is common for many CLI apps). Otherwise, open path for reading.
|
|
||||||
|
|
||||||
This function is a convenience function for CLI apps, so that they don't need to check path and open standard
|
|
||||||
input if necessary.
|
|
||||||
*/
|
|
||||||
static Result<SharedPtr<File>> open_input_file(StringView path);
|
|
||||||
|
|
||||||
static SharedPtr<File> standard_input();
|
static SharedPtr<File> standard_input();
|
||||||
static SharedPtr<File> standard_output();
|
static SharedPtr<File> standard_output();
|
||||||
static SharedPtr<File> standard_error();
|
static SharedPtr<File> standard_error();
|
||||||
@ -42,10 +34,8 @@ namespace os
|
|||||||
Result<void> write(const Buffer& buf);
|
Result<void> write(const Buffer& buf);
|
||||||
|
|
||||||
Result<String> read_line();
|
Result<String> read_line();
|
||||||
Result<String> read_all_as_string();
|
|
||||||
|
|
||||||
Result<void> read(Buffer& buf, usize size);
|
Result<void> read(Buffer& buf, usize size);
|
||||||
Result<Buffer> read_all();
|
|
||||||
|
|
||||||
Result<int> getchar();
|
Result<int> getchar();
|
||||||
|
|
||||||
|
@ -82,13 +82,6 @@ namespace os
|
|||||||
return construct(path, (int)flags | (O_CREAT | O_EXCL), mode);
|
return construct(path, (int)flags | (O_CREAT | O_EXCL), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<SharedPtr<File>> File::open_input_file(StringView path)
|
|
||||||
{
|
|
||||||
if (path == "-"_sv) return standard_input();
|
|
||||||
|
|
||||||
return construct(path, O_RDONLY, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<usize> File::raw_read(u8* buf, usize length)
|
Result<usize> File::raw_read(u8* buf, usize length)
|
||||||
{
|
{
|
||||||
long rc = syscall(SYS_read, m_fd, buf, length);
|
long rc = syscall(SYS_read, m_fd, buf, length);
|
||||||
@ -138,36 +131,6 @@ namespace os
|
|||||||
return String::from_cstring(data.data());
|
return String::from_cstring(data.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<String> File::read_all_as_string()
|
|
||||||
{
|
|
||||||
StringBuilder sb;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
auto line = TRY(read_line());
|
|
||||||
if (line.is_empty()) break;
|
|
||||||
TRY(sb.add(line));
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.string();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<Buffer> File::read_all()
|
|
||||||
{
|
|
||||||
Vector<u8> data;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
int c = TRY(getchar());
|
|
||||||
if (c == -1) break;
|
|
||||||
TRY(data.try_append((u8)c));
|
|
||||||
}
|
|
||||||
|
|
||||||
Buffer buf;
|
|
||||||
TRY(buf.append_data(data.data(), data.size()));
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> File::read(Buffer& buf, usize size)
|
Result<void> File::read(Buffer& buf, usize size)
|
||||||
{
|
{
|
||||||
u8* slice = TRY(buf.slice(0, size));
|
u8* slice = TRY(buf.slice(0, size));
|
||||||
@ -181,9 +144,9 @@ namespace os
|
|||||||
|
|
||||||
Result<int> File::getchar()
|
Result<int> File::getchar()
|
||||||
{
|
{
|
||||||
u8 value;
|
char value;
|
||||||
|
|
||||||
usize nread = TRY(raw_read(&value, 1));
|
usize nread = TRY(raw_read((u8*)&value, 1));
|
||||||
if (!nread) return -1;
|
if (!nread) return -1;
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
|
@ -17,4 +17,3 @@ function(luna_test SOURCE_FILE APP_NAME SETUID)
|
|||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
luna_test(libluna/TestVector.cpp TestVector OFF)
|
luna_test(libluna/TestVector.cpp TestVector OFF)
|
||||||
luna_test(libluna/TestBase64.cpp TestBase64 OFF)
|
|
||||||
|
@ -1,149 +0,0 @@
|
|||||||
#include <luna/Base64.h>
|
|
||||||
#include <test.h>
|
|
||||||
|
|
||||||
TestResult test_base64_encode_unpadded_message()
|
|
||||||
{
|
|
||||||
auto encoded = TRY(Base64::encode("abc"_sv));
|
|
||||||
|
|
||||||
validate(encoded.view() == "YWJj");
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult test_base64_decode_unpadded_message()
|
|
||||||
{
|
|
||||||
auto rc = Base64::decode_string("YWJj"_sv);
|
|
||||||
if (rc.has_error())
|
|
||||||
{
|
|
||||||
validate(rc.error() != EINVAL);
|
|
||||||
return rc.release_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto decoded = rc.release_value();
|
|
||||||
|
|
||||||
validate(decoded.view() == "abc"_sv);
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult test_base64_encode_padded_message()
|
|
||||||
{
|
|
||||||
auto encoded = TRY(Base64::encode("abcd"_sv));
|
|
||||||
|
|
||||||
validate(encoded.view() == "YWJjZA==");
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult test_base64_encode_padded_message_2()
|
|
||||||
{
|
|
||||||
auto encoded = TRY(Base64::encode("abcde"_sv));
|
|
||||||
|
|
||||||
validate(encoded.view() == "YWJjZGU=");
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult test_base64_decode_padded_message()
|
|
||||||
{
|
|
||||||
auto rc = Base64::decode_string("YWJjZA=="_sv);
|
|
||||||
if (rc.has_error())
|
|
||||||
{
|
|
||||||
validate(rc.error() != EINVAL);
|
|
||||||
return rc.release_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto decoded = rc.release_value();
|
|
||||||
|
|
||||||
validate(decoded.view() == "abcd"_sv);
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult test_base64_decode_padded_message_2()
|
|
||||||
{
|
|
||||||
auto rc = Base64::decode_string("YWJjZGU="_sv);
|
|
||||||
if (rc.has_error())
|
|
||||||
{
|
|
||||||
validate(rc.error() != EINVAL);
|
|
||||||
return rc.release_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto decoded = rc.release_value();
|
|
||||||
|
|
||||||
validate(decoded.view() == "abcde"_sv);
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult test_base64_decode_padded_message_with_newlines()
|
|
||||||
{
|
|
||||||
auto rc = Base64::decode_string("YWJj\nZA==\n"_sv);
|
|
||||||
if (rc.has_error())
|
|
||||||
{
|
|
||||||
validate(rc.error() != EINVAL);
|
|
||||||
return rc.release_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto decoded = rc.release_value();
|
|
||||||
|
|
||||||
validate(decoded.view() == "abcd"_sv);
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult test_base64_disallow_characters_after_padding()
|
|
||||||
{
|
|
||||||
auto rc = Base64::decode_string("YWJjZA==bd"_sv);
|
|
||||||
|
|
||||||
validate(rc.has_error());
|
|
||||||
|
|
||||||
if (rc.error() != EINVAL) return rc.release_error();
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult test_base64_disallow_garbage_chars_by_default()
|
|
||||||
{
|
|
||||||
auto rc = Base64::decode_string("YWJj?-ZA=="_sv);
|
|
||||||
|
|
||||||
validate(rc.has_error());
|
|
||||||
|
|
||||||
if (rc.error() != EINVAL) return rc.release_error();
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult test_base64_skip_garbage_chars_if_allowed()
|
|
||||||
{
|
|
||||||
auto rc = Base64::decode_string("YWJj?-ZA=="_sv, true);
|
|
||||||
if (rc.has_error())
|
|
||||||
{
|
|
||||||
validate(rc.error() != EINVAL);
|
|
||||||
return rc.release_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto decoded = rc.release_value();
|
|
||||||
|
|
||||||
validate(decoded.view() == "abcd"_sv);
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> test_main()
|
|
||||||
{
|
|
||||||
test_prelude;
|
|
||||||
|
|
||||||
run_test(test_base64_encode_unpadded_message);
|
|
||||||
run_test(test_base64_decode_unpadded_message);
|
|
||||||
run_test(test_base64_encode_padded_message);
|
|
||||||
run_test(test_base64_encode_padded_message_2);
|
|
||||||
run_test(test_base64_decode_padded_message);
|
|
||||||
run_test(test_base64_decode_padded_message_2);
|
|
||||||
run_test(test_base64_decode_padded_message_with_newlines);
|
|
||||||
run_test(test_base64_disallow_characters_after_padding);
|
|
||||||
run_test(test_base64_disallow_garbage_chars_by_default);
|
|
||||||
run_test(test_base64_skip_garbage_chars_if_allowed);
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user