srctree

Robin Linden parent a3a6a785 ba9d4bf3
wasm: Add support for decoding unsigned leb128 numbers

inlinesplit
.gitlint added: 105, removed: 5, total 100
@@ -4,4 +4,4 @@ ignore=body-is-missing
# TODO(robinlinden): Better way of documenting and setting this up.
# Each commit must start with the main area it affects.
[title-match-regex]
regex=^(browser|bzl|css|css2|dom|dom2|engine|etest|geom|gfx|html|html2|img|js|layout|net|os|protocol|render|style|tui|uri|url|util|all|build|ci|deps|doc|meta)(/.*|\+.*)?:
regex=^(browser|bzl|css|css2|dom|dom2|engine|etest|geom|gfx|html|html2|img|js|layout|net|os|protocol|render|style|tui|uri|url|util|wasm|all|build|ci|deps|doc|meta)(/.*|\+.*)?:
 
filename was Deleted added: 105, removed: 5, total 100
@@ -0,0 +1,20 @@
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load("//bzl:copts.bzl", "HASTUR_COPTS")
 
cc_library(
name = "wasm",
hdrs = glob(["*.h"]),
copts = HASTUR_COPTS,
visibility = ["//visibility:public"],
)
 
[cc_test(
name = src[:-4],
size = "small",
srcs = [src],
copts = HASTUR_COPTS,
deps = [
":wasm",
"//etest",
],
) for src in glob(["*_test.cpp"])]
 
filename was Deleted added: 105, removed: 5, total 100
@@ -0,0 +1,42 @@
// SPDX-FileCopyrightText: 2023 Robin Lindén <dev@robinlinden.eu>
//
// SPDX-License-Identifier: BSD-2-Clause
 
#ifndef WASM_LEB128_H_
#define WASM_LEB128_H_
 
#include <cmath>
#include <cstdint>
#include <istream>
#include <optional>
 
namespace wasm {
 
// https://en.wikipedia.org/wiki/LEB128#Decode_unsigned_integer
// https://webassembly.github.io/spec/core/bikeshed/#binary-int
struct Uleb128 {
static std::optional<std::uint32_t> decode_from(std::istream &&is) { return decode_from(is); }
static std::optional<std::uint32_t> decode_from(std::istream &is) {
std::uint32_t result{};
std::uint8_t shift{};
for (int i = 0; i < std::ceil(sizeof(std::uint32_t) * 8 / 7.f); ++i) {
std::uint8_t byte{};
if (!is.read(reinterpret_cast<char *>(&byte), sizeof(byte))) {
return std::nullopt;
}
 
result |= (byte & 0b0111'1111) << shift;
if (!(byte & 0b1000'0000)) {
return result;
}
 
shift += 7;
}
 
return std::nullopt;
}
};
 
} // namespace wasm
 
#endif
 
filename was Deleted added: 105, removed: 5, total 100
@@ -0,0 +1,38 @@
// SPDX-FileCopyrightText: 2023 Robin Lindén <dev@robinlinden.eu>
//
// SPDX-License-Identifier: BSD-2-Clause
 
#include "wasm/leb128.h"
 
#include "etest/etest.h"
 
#include <sstream>
#include <string>
 
using namespace std::literals;
using etest::expect_eq;
using wasm::Uleb128;
 
int main() {
etest::test("decode unsigned", [] {
expect_eq(Uleb128::decode_from(std::stringstream{"\0"s}), std::uint32_t{0});
expect_eq(Uleb128::decode_from(std::stringstream{"\1"}), std::uint32_t{1});
expect_eq(Uleb128::decode_from(std::stringstream{"\x3f"}), std::uint32_t{63});
expect_eq(Uleb128::decode_from(std::stringstream{"\x40"}), std::uint32_t{64});
expect_eq(Uleb128::decode_from(std::stringstream{"\x7f"}), std::uint32_t{0x7f});
expect_eq(Uleb128::decode_from(std::stringstream{"\x80\x01"}), std::uint32_t{0x80});
expect_eq(Uleb128::decode_from(std::stringstream{"\x80\x02"}), std::uint32_t{0x100});
expect_eq(Uleb128::decode_from(std::stringstream{"\x80\x7f"}), std::uint32_t{16256});
expect_eq(Uleb128::decode_from(std::stringstream{"\x81\x01"}), std::uint32_t{0x81});
expect_eq(Uleb128::decode_from(std::stringstream{"\x81\x02"}), std::uint32_t{0x101});
expect_eq(Uleb128::decode_from(std::stringstream{"\x90\x01"}), std::uint32_t{0x90});
expect_eq(Uleb128::decode_from(std::stringstream{"\xff\x01"}), std::uint32_t{0xff});
 
// Missing termination.
expect_eq(Uleb128::decode_from(std::stringstream{"\x80"}), std::nullopt);
// Too many bytes with no termination.
expect_eq(Uleb128::decode_from(std::stringstream{"\x80\x80\x80\x80\x80\x80"}), std::nullopt);
});
 
return etest::run_all_tests();
}