From a141c401f78467bc15f62882fca5d55a007cacbb Mon Sep 17 00:00:00 2001
From: Steven Le Rouzic <steven.lerouzic@gmail.com>
Date: Mon, 17 Feb 2025 00:21:48 +0100
Subject: Reorganize everything

---
 asl/BUILD.bazel                      |  78 -----
 asl/allocator.cpp                    |  56 ----
 asl/allocator.hpp                    |  58 ----
 asl/annotations.hpp                  |   9 -
 asl/assert.cpp                       |  11 -
 asl/assert.hpp                       |  33 --
 asl/atomic.hpp                       |  51 ---
 asl/base/BUILD.bazel                 |  36 +++
 asl/base/annotations.hpp             |   9 +
 asl/base/assert.cpp                  |  12 +
 asl/base/assert.hpp                  |  33 ++
 asl/base/config.hpp                  |  17 +
 asl/base/float.hpp                   |  17 +
 asl/base/float_tests.cpp             |  23 ++
 asl/base/functional.hpp              |  65 ++++
 asl/base/functional_tests.cpp        |  73 +++++
 asl/base/integers.hpp                |  40 +++
 asl/base/integers_tests.cpp          |  15 +
 asl/base/meta.hpp                    | 248 ++++++++++++++
 asl/base/meta_tests.cpp              | 289 +++++++++++++++++
 asl/base/utility.hpp                 |  95 ++++++
 asl/base/utility_tests.cpp           |   1 +
 asl/box.hpp                          | 134 --------
 asl/buffer.hpp                       | 459 --------------------------
 asl/config.hpp                       |  17 -
 asl/containers/BUILD.bazel           |  58 ++++
 asl/containers/buffer.hpp            | 459 ++++++++++++++++++++++++++
 asl/containers/buffer_tests.cpp      | 603 +++++++++++++++++++++++++++++++++++
 asl/containers/hash_map.hpp          | 178 +++++++++++
 asl/containers/hash_map_tests.cpp    |  48 +++
 asl/containers/hash_set.hpp          | 418 ++++++++++++++++++++++++
 asl/containers/hash_set_tests.cpp    | 185 +++++++++++
 asl/float.hpp                        |  17 -
 asl/format.cpp                       | 201 ------------
 asl/format.hpp                       | 109 -------
 asl/format_float.cpp                 |  98 ------
 asl/formatting/BUILD.bazel           |  32 ++
 asl/formatting/format.cpp            | 201 ++++++++++++
 asl/formatting/format.hpp            | 109 +++++++
 asl/formatting/format_float.cpp      |  98 ++++++
 asl/formatting/format_tests.cpp      | 110 +++++++
 asl/functional.hpp                   |  65 ----
 asl/hash.hpp                         | 138 --------
 asl/hash_cityhash.cpp                | 517 ------------------------------
 asl/hash_map.hpp                     | 178 -----------
 asl/hash_set.hpp                     | 418 ------------------------
 asl/hashing/BUILD.bazel              |  33 ++
 asl/hashing/hash.hpp                 | 138 ++++++++
 asl/hashing/hash_cityhash.cpp        | 517 ++++++++++++++++++++++++++++++
 asl/hashing/hash_tests.cpp           | 260 +++++++++++++++
 asl/integers.hpp                     |  40 ---
 asl/io.hpp                           |  20 --
 asl/io/BUILD.bazel                   |  26 ++
 asl/io/print.cpp                     |  31 ++
 asl/io/print.hpp                     |  30 ++
 asl/io/writer.hpp                    |  20 ++
 asl/layout.hpp                       |  37 ---
 asl/logging/BUILD.bazel              |   6 +-
 asl/logging/logging.cpp              |   4 +-
 asl/logging/logging.hpp              |   6 +-
 asl/logging/logging_tests.cpp        |   2 +-
 asl/maybe_uninit.hpp                 |  72 -----
 asl/memory.hpp                       | 137 --------
 asl/memory/BUILD.bazel               |  16 +
 asl/memory/allocator.cpp             |  54 ++++
 asl/memory/allocator.hpp             |  58 ++++
 asl/memory/layout.hpp                |  37 +++
 asl/memory/memory.hpp                | 137 ++++++++
 asl/meta.hpp                         | 248 --------------
 asl/option.hpp                       | 509 -----------------------------
 asl/print.cpp                        |  31 --
 asl/print.hpp                        |  29 --
 asl/span.hpp                         | 235 --------------
 asl/status.cpp                       |  96 ------
 asl/status.hpp                       | 157 ---------
 asl/status_or.hpp                    | 186 -----------
 asl/string.hpp                       |  77 -----
 asl/string_builder.hpp               | 156 ---------
 asl/string_view.hpp                  | 107 -------
 asl/strings/BUILD.bazel              |  56 ++++
 asl/strings/string.hpp               |  77 +++++
 asl/strings/string_builder.hpp       | 156 +++++++++
 asl/strings/string_builder_tests.cpp |  23 ++
 asl/strings/string_tests.cpp         |  21 ++
 asl/strings/string_view.hpp          | 107 +++++++
 asl/strings/string_view_tests.cpp    | 117 +++++++
 asl/synchronization/BUILD.bazel      |  10 +
 asl/synchronization/atomic.hpp       |  51 +++
 asl/testing/BUILD.bazel              |   4 +-
 asl/testing/testing.cpp              |   2 +-
 asl/testing/testing.hpp              |   2 +-
 asl/tests/BUILD.bazel                |  10 +
 asl/tests/box_tests.cpp              | 102 ------
 asl/tests/buffer_tests.cpp           | 603 -----------------------------------
 asl/tests/float_tests.cpp            |  23 --
 asl/tests/format_tests.cpp           | 110 -------
 asl/tests/functional_tests.cpp       |  73 -----
 asl/tests/hash_map_tests.cpp         |  48 ---
 asl/tests/hash_set_tests.cpp         | 185 -----------
 asl/tests/hash_tests.cpp             | 260 ---------------
 asl/tests/integers_tests.cpp         |  15 -
 asl/tests/maybe_uninit_tests.cpp     |  22 --
 asl/tests/meta_tests.cpp             | 289 -----------------
 asl/tests/option_tests.cpp           | 330 -------------------
 asl/tests/span_tests.cpp             | 444 --------------------------
 asl/tests/status_or_tests.cpp        |  84 -----
 asl/tests/status_tests.cpp           |  82 -----
 asl/tests/string_builder_tests.cpp   |  23 --
 asl/tests/string_tests.cpp           |  21 --
 asl/tests/string_view_tests.cpp      | 117 -------
 asl/tests/test_types.hpp             |  92 ------
 asl/tests/types.hpp                  |  89 ++++++
 asl/tests/utility_tests.cpp          |   1 -
 asl/types/BUILD.bazel                | 135 ++++++++
 asl/types/box.hpp                    | 134 ++++++++
 asl/types/box_tests.cpp              | 102 ++++++
 asl/types/maybe_uninit.hpp           |  72 +++++
 asl/types/maybe_uninit_tests.cpp     |  22 ++
 asl/types/option.hpp                 | 509 +++++++++++++++++++++++++++++
 asl/types/option_tests.cpp           | 330 +++++++++++++++++++
 asl/types/span.hpp                   | 235 ++++++++++++++
 asl/types/span_tests.cpp             | 444 ++++++++++++++++++++++++++
 asl/types/status.cpp                 |  96 ++++++
 asl/types/status.hpp                 | 157 +++++++++
 asl/types/status_or.hpp              | 186 +++++++++++
 asl/types/status_or_tests.cpp        |  84 +++++
 asl/types/status_tests.cpp           |  82 +++++
 asl/utility.hpp                      |  96 ------
 128 files changed, 8150 insertions(+), 7814 deletions(-)
 delete mode 100644 asl/BUILD.bazel
 delete mode 100644 asl/allocator.cpp
 delete mode 100644 asl/allocator.hpp
 delete mode 100644 asl/annotations.hpp
 delete mode 100644 asl/assert.cpp
 delete mode 100644 asl/assert.hpp
 delete mode 100644 asl/atomic.hpp
 create mode 100644 asl/base/BUILD.bazel
 create mode 100644 asl/base/annotations.hpp
 create mode 100644 asl/base/assert.cpp
 create mode 100644 asl/base/assert.hpp
 create mode 100644 asl/base/config.hpp
 create mode 100644 asl/base/float.hpp
 create mode 100644 asl/base/float_tests.cpp
 create mode 100644 asl/base/functional.hpp
 create mode 100644 asl/base/functional_tests.cpp
 create mode 100644 asl/base/integers.hpp
 create mode 100644 asl/base/integers_tests.cpp
 create mode 100644 asl/base/meta.hpp
 create mode 100644 asl/base/meta_tests.cpp
 create mode 100644 asl/base/utility.hpp
 create mode 100644 asl/base/utility_tests.cpp
 delete mode 100644 asl/box.hpp
 delete mode 100644 asl/buffer.hpp
 delete mode 100644 asl/config.hpp
 create mode 100644 asl/containers/BUILD.bazel
 create mode 100644 asl/containers/buffer.hpp
 create mode 100644 asl/containers/buffer_tests.cpp
 create mode 100644 asl/containers/hash_map.hpp
 create mode 100644 asl/containers/hash_map_tests.cpp
 create mode 100644 asl/containers/hash_set.hpp
 create mode 100644 asl/containers/hash_set_tests.cpp
 delete mode 100644 asl/float.hpp
 delete mode 100644 asl/format.cpp
 delete mode 100644 asl/format.hpp
 delete mode 100644 asl/format_float.cpp
 create mode 100644 asl/formatting/BUILD.bazel
 create mode 100644 asl/formatting/format.cpp
 create mode 100644 asl/formatting/format.hpp
 create mode 100644 asl/formatting/format_float.cpp
 create mode 100644 asl/formatting/format_tests.cpp
 delete mode 100644 asl/functional.hpp
 delete mode 100644 asl/hash.hpp
 delete mode 100644 asl/hash_cityhash.cpp
 delete mode 100644 asl/hash_map.hpp
 delete mode 100644 asl/hash_set.hpp
 create mode 100644 asl/hashing/BUILD.bazel
 create mode 100644 asl/hashing/hash.hpp
 create mode 100644 asl/hashing/hash_cityhash.cpp
 create mode 100644 asl/hashing/hash_tests.cpp
 delete mode 100644 asl/integers.hpp
 delete mode 100644 asl/io.hpp
 create mode 100644 asl/io/BUILD.bazel
 create mode 100644 asl/io/print.cpp
 create mode 100644 asl/io/print.hpp
 create mode 100644 asl/io/writer.hpp
 delete mode 100644 asl/layout.hpp
 delete mode 100644 asl/maybe_uninit.hpp
 delete mode 100644 asl/memory.hpp
 create mode 100644 asl/memory/BUILD.bazel
 create mode 100644 asl/memory/allocator.cpp
 create mode 100644 asl/memory/allocator.hpp
 create mode 100644 asl/memory/layout.hpp
 create mode 100644 asl/memory/memory.hpp
 delete mode 100644 asl/meta.hpp
 delete mode 100644 asl/option.hpp
 delete mode 100644 asl/print.cpp
 delete mode 100644 asl/print.hpp
 delete mode 100644 asl/span.hpp
 delete mode 100644 asl/status.cpp
 delete mode 100644 asl/status.hpp
 delete mode 100644 asl/status_or.hpp
 delete mode 100644 asl/string.hpp
 delete mode 100644 asl/string_builder.hpp
 delete mode 100644 asl/string_view.hpp
 create mode 100644 asl/strings/BUILD.bazel
 create mode 100644 asl/strings/string.hpp
 create mode 100644 asl/strings/string_builder.hpp
 create mode 100644 asl/strings/string_builder_tests.cpp
 create mode 100644 asl/strings/string_tests.cpp
 create mode 100644 asl/strings/string_view.hpp
 create mode 100644 asl/strings/string_view_tests.cpp
 create mode 100644 asl/synchronization/BUILD.bazel
 create mode 100644 asl/synchronization/atomic.hpp
 create mode 100644 asl/tests/BUILD.bazel
 delete mode 100644 asl/tests/box_tests.cpp
 delete mode 100644 asl/tests/buffer_tests.cpp
 delete mode 100644 asl/tests/float_tests.cpp
 delete mode 100644 asl/tests/format_tests.cpp
 delete mode 100644 asl/tests/functional_tests.cpp
 delete mode 100644 asl/tests/hash_map_tests.cpp
 delete mode 100644 asl/tests/hash_set_tests.cpp
 delete mode 100644 asl/tests/hash_tests.cpp
 delete mode 100644 asl/tests/integers_tests.cpp
 delete mode 100644 asl/tests/maybe_uninit_tests.cpp
 delete mode 100644 asl/tests/meta_tests.cpp
 delete mode 100644 asl/tests/option_tests.cpp
 delete mode 100644 asl/tests/span_tests.cpp
 delete mode 100644 asl/tests/status_or_tests.cpp
 delete mode 100644 asl/tests/status_tests.cpp
 delete mode 100644 asl/tests/string_builder_tests.cpp
 delete mode 100644 asl/tests/string_tests.cpp
 delete mode 100644 asl/tests/string_view_tests.cpp
 delete mode 100644 asl/tests/test_types.hpp
 create mode 100644 asl/tests/types.hpp
 delete mode 100644 asl/tests/utility_tests.cpp
 create mode 100644 asl/types/BUILD.bazel
 create mode 100644 asl/types/box.hpp
 create mode 100644 asl/types/box_tests.cpp
 create mode 100644 asl/types/maybe_uninit.hpp
 create mode 100644 asl/types/maybe_uninit_tests.cpp
 create mode 100644 asl/types/option.hpp
 create mode 100644 asl/types/option_tests.cpp
 create mode 100644 asl/types/span.hpp
 create mode 100644 asl/types/span_tests.cpp
 create mode 100644 asl/types/status.cpp
 create mode 100644 asl/types/status.hpp
 create mode 100644 asl/types/status_or.hpp
 create mode 100644 asl/types/status_or_tests.cpp
 create mode 100644 asl/types/status_tests.cpp
 delete mode 100644 asl/utility.hpp

(limited to 'asl')

diff --git a/asl/BUILD.bazel b/asl/BUILD.bazel
deleted file mode 100644
index 2cc4af5..0000000
--- a/asl/BUILD.bazel
+++ /dev/null
@@ -1,78 +0,0 @@
-cc_library(
-    name = "asl",
-    hdrs = [
-        "allocator.hpp",
-        "annotations.hpp",
-        "assert.hpp",
-        "atomic.hpp",
-        "box.hpp",
-        "buffer.hpp",
-        "config.hpp",
-        "float.hpp",
-        "format.hpp",
-        "functional.hpp",
-        "hash.hpp",
-        "hash_map.hpp",
-        "hash_set.hpp",
-        "integers.hpp",
-        "io.hpp",
-        "layout.hpp",
-        "maybe_uninit.hpp",
-        "memory.hpp",
-        "meta.hpp",
-        "option.hpp",
-        "print.hpp",
-        "span.hpp",
-        "status.hpp",
-        "status_or.hpp",
-        "string.hpp",
-        "string_builder.hpp",
-        "string_view.hpp",
-        "utility.hpp",
-    ],
-    srcs = [
-        "allocator.cpp",
-        "assert.cpp",
-        "format.cpp",
-        "format_float.cpp",
-        "hash_cityhash.cpp",
-        "print.cpp",
-        "status.cpp",
-    ],
-    deps = [
-        "//vendor/dragonbox",
-    ],
-    visibility = ["//visibility:public"],
-)
-
-[cc_test(
-    name = "%s_tests" % name,
-    srcs = [
-        "tests/%s_tests.cpp" % name,
-        "tests/test_types.hpp",
-    ],
-    deps = [
-        ":asl",
-        "//asl/testing",
-    ],
-) for name in [
-    "box",
-    "buffer",
-    "float",
-    "format",
-    "functional",
-    "hash",
-    "hash_map",
-    "hash_set",
-    "integers",
-    "maybe_uninit",
-    "meta",
-    "option",
-    "span",
-    "status",
-    "status_or",
-    "string",
-    "string_builder",
-    "string_view",
-    "utility",
-]]
diff --git a/asl/allocator.cpp b/asl/allocator.cpp
deleted file mode 100644
index 59bff76..0000000
--- a/asl/allocator.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-#include "asl/allocator.hpp"
-#include "asl/assert.hpp"
-#include "asl/utility.hpp"
-#include "asl/memory.hpp"
-#include "asl/print.hpp"
-
-#include <cstdlib>
-
-// @Todo zalloc
-// @Todo Cookies
-// @Todo Debug values
-
-void* asl::GlobalHeap::alloc(const layout& layout)
-{
-#if ASL_OS_WINDOWS
-    void* ptr = ::_aligned_malloc(
-        static_cast<size_t>(layout.size),
-        static_cast<size_t>(layout.align));
-#elif ASL_OS_LINUX
-    void* ptr = ::aligned_alloc(
-        static_cast<size_t>(layout.align),
-        static_cast<size_t>(layout.size));
-#endif
-    ASL_ASSERT(ptr != nullptr); // @Todo panic
-    return ptr;
-}
-
-void* asl::GlobalHeap::realloc(void* old_ptr, [[maybe_unused]] const layout& old_layout, const layout& new_layout)
-{
-#if ASL_OS_WINDOWS
-    return ::_aligned_realloc(old_ptr,
-        static_cast<size_t>(new_layout.size),
-        static_cast<size_t>(new_layout.align));
-#elif ASL_OS_LINUX
-    if (new_layout.align <= old_layout.align)
-    {
-        void* new_ptr = ::realloc(old_ptr, static_cast<size_t>(new_layout.size));
-        ASL_ASSERT(new_ptr != nullptr); // @Todo panic
-        return new_ptr;
-    }
-
-    void* new_ptr = alloc(new_layout);
-    asl::memcpy(new_ptr, old_ptr, asl::min(old_layout.size, new_layout.size));
-    dealloc(old_ptr, old_layout);
-    return new_ptr;
-#endif
-}
-
-void asl::GlobalHeap::dealloc(void* ptr, const layout&)
-{
-#if ASL_OS_WINDOWS
-    ::_aligned_free(ptr);
-#elif ASL_OS_LINUX
-    ::free(ptr);
-#endif
-}
diff --git a/asl/allocator.hpp b/asl/allocator.hpp
deleted file mode 100644
index 90793dd..0000000
--- a/asl/allocator.hpp
+++ /dev/null
@@ -1,58 +0,0 @@
-#pragma once
-
-#include "asl/layout.hpp"
-#include "asl/meta.hpp"
-#include "asl/memory.hpp"
-
-namespace asl
-{
-
-template<typename T>
-concept allocator = moveable<T> && equality_comparable<T> &&
-    requires(T& alloc, layout layout, void* ptr)
-    {
-        { alloc.alloc(layout) } -> same_as<void*>;
-        { alloc.realloc(ptr, layout, layout) } -> same_as<void*>;
-        alloc.dealloc(ptr, layout);
-    };
-
-class GlobalHeap
-{
-public:
-    static void* alloc(const layout&);
-    static void* realloc(void* ptr, const layout& old, const layout& new_layout);
-    static void dealloc(void* ptr, const layout&);
-
-    constexpr bool operator==(const GlobalHeap&) const { return true; }
-};
-static_assert(allocator<GlobalHeap>);
-
-using DefaultAllocator = GlobalHeap;
-
-template<typename T>
-T* alloc_new(allocator auto& a, auto&&... args)
-{
-    void* ptr = a.alloc(layout::of<T>());
-    return construct_at<T>(ptr, ASL_FWD(args)...);
-}
-
-template<typename T>
-void alloc_delete(allocator auto& a, T* ptr)
-{
-    destroy(ptr);
-    a.dealloc(ptr, layout::of<T>());
-}
-
-template<typename T>
-constexpr T* alloc_new_default(auto&&... args)
-{
-    return alloc_new<T>(DefaultAllocator{}, ASL_FWD(args)...);
-}
-
-template<typename T>
-void alloc_delete_default(T* ptr)
-{
-    alloc_delete(DefaultAllocator{}, ptr);
-}
-
-} // namespace asl
diff --git a/asl/annotations.hpp b/asl/annotations.hpp
deleted file mode 100644
index 6ea3a84..0000000
--- a/asl/annotations.hpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-
-#include "asl/config.hpp"
-
-#if ASL_COMPILER_CLANG_CL
-    #define ASL_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
-#elif ASL_COMPILER_CLANG
-    #define ASL_NO_UNIQUE_ADDRESS [[no_unique_address]]
-#endif
diff --git a/asl/assert.cpp b/asl/assert.cpp
deleted file mode 100644
index 353232e..0000000
--- a/asl/assert.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "asl/assert.hpp"
-#include "asl/print.hpp"
-
-
-void asl::report_assert_failure(const char* msg, const source_location& sl)
-{
-    eprint("------------------------------------------------------------\n");
-    eprint("Assertion failure at {}, line {}:\n", sl.file, sl.line);
-    eprint("{}\n", msg);
-    eprint("------------------------------------------------------------\n");
-}
diff --git a/asl/assert.hpp b/asl/assert.hpp
deleted file mode 100644
index 608a44f..0000000
--- a/asl/assert.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-
-#include "asl/config.hpp"
-#include "asl/meta.hpp"
-
-namespace asl
-{
-
-void report_assert_failure(const char* msg, const source_location& sl = source_location{});
-
-} // namespace asl
-
-#if ASL_COMPILER_CLANG_CL
-    #define ASL_DEBUG_BREAK() __debugbreak()
-#elif ASL_COMPILER_CLANG
-    #define ASL_DEBUG_BREAK() __builtin_debugtrap()
-#endif
-
-#define ASL_ASSERT(...)                                                 \
-    if (__VA_ARGS__) {}                                                 \
-    else                                                                \
-    {                                                                   \
-        ::asl::report_assert_failure(#__VA_ARGS__);                     \
-        ASL_DEBUG_BREAK();                                              \
-    }
-
-#define ASL_ASSERT_RELEASE(...)                                         \
-    if (__VA_ARGS__) {}                                                 \
-    else                                                                \
-    {                                                                   \
-        ::asl::report_assert_failure(#__VA_ARGS__);                     \
-        ASL_DEBUG_BREAK();                                              \
-    }
diff --git a/asl/atomic.hpp b/asl/atomic.hpp
deleted file mode 100644
index 95c3715..0000000
--- a/asl/atomic.hpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#pragma once
-
-#include "asl/meta.hpp"
-
-namespace asl
-{
-
-enum class memory_order : int // NOLINT(*-enum-size)
-{
-    relaxed        = __ATOMIC_RELAXED,
-    acquire        = __ATOMIC_ACQUIRE,
-    release        = __ATOMIC_RELEASE,
-    acq_rel        = __ATOMIC_ACQ_REL,
-    seq_cst        = __ATOMIC_SEQ_CST,
-};
-
-template<typename T> struct atomic { T m_value{}; };
-
-inline void atomic_fence(memory_order order)
-{
-    __atomic_thread_fence(static_cast<int>(order));
-}
-
-template<is_integer T>
-inline void atomic_store(atomic<T>* a, T value, memory_order order = memory_order::relaxed)
-{
-    __atomic_store(&a->m_value, &value, static_cast<int>(order));
-}
-
-template<is_integer T>
-inline T atomic_load(atomic<T>* a, memory_order order = memory_order::relaxed)
-{
-    T value;
-    __atomic_load(&a->m_value, &value, static_cast<int>(order));
-    return value;
-}
-
-template<typename T>
-inline T atomic_fetch_increment(atomic<T>* a, memory_order order = memory_order::relaxed)
-{
-    return __atomic_fetch_add(&a->m_value, 1, static_cast<int>(order));
-}
-
-template<typename T>
-inline T atomic_fetch_decrement(atomic<T>* a, memory_order order = memory_order::relaxed)
-{
-    return __atomic_fetch_sub(&a->m_value, 1, static_cast<int>(order));
-}
-
-} // namespace asl
-
diff --git a/asl/base/BUILD.bazel b/asl/base/BUILD.bazel
new file mode 100644
index 0000000..317c20b
--- /dev/null
+++ b/asl/base/BUILD.bazel
@@ -0,0 +1,36 @@
+cc_library(
+    name = "base",
+    hdrs = [
+        "annotations.hpp",
+        "assert.hpp",
+        "config.hpp",
+        "float.hpp",
+        "functional.hpp",
+        "integers.hpp",
+        "meta.hpp",
+        "utility.hpp",
+    ],
+    srcs = [
+        "assert.cpp",
+    ],
+    visibility = ["//visibility:public"],
+)
+
+[cc_test(
+    name = "%s_tests" % name,
+    srcs = [
+        "%s_tests.cpp" % name,
+    ],
+    deps = [
+        ":base",
+        "//asl/tests:utils",
+        "//asl/testing",
+        "//asl/types:box",
+    ],
+) for name in [
+    "float",
+    "functional",
+    "integers",
+    "meta",
+    "utility",
+]]
diff --git a/asl/base/annotations.hpp b/asl/base/annotations.hpp
new file mode 100644
index 0000000..b87dbde
--- /dev/null
+++ b/asl/base/annotations.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "asl/base/config.hpp"
+
+#if ASL_COMPILER_CLANG_CL
+    #define ASL_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
+#elif ASL_COMPILER_CLANG
+    #define ASL_NO_UNIQUE_ADDRESS [[no_unique_address]]
+#endif
diff --git a/asl/base/assert.cpp b/asl/base/assert.cpp
new file mode 100644
index 0000000..2383e9e
--- /dev/null
+++ b/asl/base/assert.cpp
@@ -0,0 +1,12 @@
+#include "asl/base/assert.hpp"
+// #include "asl/io/print.hpp"
+
+
+void asl::report_assert_failure(const char* msg, const source_location& sl)
+{
+    // @Todo(org)
+    // eprint("------------------------------------------------------------\n");
+    // eprint("Assertion failure at {}, line {}:\n", sl.file, sl.line);
+    // eprint("{}\n", msg);
+    // eprint("------------------------------------------------------------\n");
+}
diff --git a/asl/base/assert.hpp b/asl/base/assert.hpp
new file mode 100644
index 0000000..42e8635
--- /dev/null
+++ b/asl/base/assert.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "asl/base/config.hpp"
+#include "asl/base/meta.hpp"
+
+namespace asl
+{
+
+void report_assert_failure(const char* msg, const source_location& sl = source_location{});
+
+} // namespace asl
+
+#if ASL_COMPILER_CLANG_CL
+    #define ASL_DEBUG_BREAK() __debugbreak()
+#elif ASL_COMPILER_CLANG
+    #define ASL_DEBUG_BREAK() __builtin_debugtrap()
+#endif
+
+#define ASL_ASSERT(...)                                                 \
+    if (__VA_ARGS__) {}                                                 \
+    else                                                                \
+    {                                                                   \
+        ::asl::report_assert_failure(#__VA_ARGS__);                     \
+        ASL_DEBUG_BREAK();                                              \
+    }
+
+#define ASL_ASSERT_RELEASE(...)                                         \
+    if (__VA_ARGS__) {}                                                 \
+    else                                                                \
+    {                                                                   \
+        ::asl::report_assert_failure(#__VA_ARGS__);                     \
+        ASL_DEBUG_BREAK();                                              \
+    }
diff --git a/asl/base/config.hpp b/asl/base/config.hpp
new file mode 100644
index 0000000..e182569
--- /dev/null
+++ b/asl/base/config.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#if defined(_WIN32)
+    #define ASL_OS_WINDOWS 1
+#elif defined(__linux__)
+    #define ASL_OS_LINUX 1
+#else
+    #error Unknown OS
+#endif
+
+#if defined(__clang__) && defined(_MSC_VER)
+    #define ASL_COMPILER_CLANG_CL 1
+#elif defined(__clang__)
+    #define ASL_COMPILER_CLANG 1
+#else
+    #error Unknown compiler
+#endif
diff --git a/asl/base/float.hpp b/asl/base/float.hpp
new file mode 100644
index 0000000..2de2e0c
--- /dev/null
+++ b/asl/base/float.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "asl/base/meta.hpp"
+
+namespace asl
+{
+
+template<is_floating_point T> constexpr T infinity() { return __builtin_inf(); }
+
+template<is_floating_point T> constexpr T nan() { return static_cast<T>(__builtin_nanf("")); }
+
+template<is_floating_point T> constexpr bool is_infinity(T f) { return __builtin_isinf(f); }
+
+template<is_floating_point T> constexpr bool is_nan(T f) { return __builtin_isnan(f); }
+
+} // namespace asl
+
diff --git a/asl/base/float_tests.cpp b/asl/base/float_tests.cpp
new file mode 100644
index 0000000..0a5bebf
--- /dev/null
+++ b/asl/base/float_tests.cpp
@@ -0,0 +1,23 @@
+#include "asl/base/float.hpp"
+
+#include "asl/testing/testing.hpp"
+
+ASL_TEST(is_infinity)
+{
+    ASL_TEST_EXPECT(!asl::is_infinity(0.0F));
+    ASL_TEST_EXPECT(!asl::is_infinity(-25.0F));
+    ASL_TEST_EXPECT(asl::is_infinity(45.0F / 0.0F));
+    ASL_TEST_EXPECT(asl::is_infinity(-45.0F / 0.0F));
+    ASL_TEST_EXPECT(asl::is_infinity(asl::infinity<float>()));
+    ASL_TEST_EXPECT(asl::is_infinity(-asl::infinity<double>()));
+}
+
+ASL_TEST(is_nan)
+{
+    ASL_TEST_EXPECT(!asl::is_nan(0.0F));
+    ASL_TEST_EXPECT(!asl::is_nan(-25.0F));
+    ASL_TEST_EXPECT(!asl::is_nan(45.0F / 0.0F));
+    ASL_TEST_EXPECT(asl::is_nan(asl::nan<float>()));
+    ASL_TEST_EXPECT(asl::is_nan(asl::nan<double>()));
+}
+
diff --git a/asl/base/functional.hpp b/asl/base/functional.hpp
new file mode 100644
index 0000000..d820bce
--- /dev/null
+++ b/asl/base/functional.hpp
@@ -0,0 +1,65 @@
+#pragma once
+
+#include "asl/base/meta.hpp"
+#include "asl/base/utility.hpp"
+
+namespace asl {
+
+template<typename... Args, typename C>
+constexpr auto invoke(is_func auto C::* f, auto&& self, Args&&... args)
+    requires requires {
+        (self.*f)(ASL_FWD(args)...);
+    }
+{
+    return (ASL_FWD(self).*f)(ASL_FWD(args)...);
+}
+
+template<typename... Args, typename C>
+constexpr auto invoke(is_func auto C::* f, auto* self, Args&&... args)
+    requires requires {
+        (self->*f)(ASL_FWD(args)...);
+    }
+{
+    return (self->*f)(ASL_FWD(args)...);
+}
+
+template<typename... Args, typename C>
+constexpr auto invoke(is_object auto C::* m, auto&& self, Args&&...)
+    requires (
+        sizeof...(Args) == 0 &&
+        requires { self.*m; }
+    )
+{
+    return ASL_FWD(self).*m;
+}
+
+template<typename... Args, typename C>
+constexpr auto invoke(is_object auto C::* m, auto* self, Args&&...)
+    requires (
+        sizeof...(Args) == 0 &&
+        requires { self->*m; }
+    )
+{
+    return self->*m;
+}
+
+template<typename... Args>
+constexpr auto invoke(auto&& f, Args&&... args)
+    requires requires {
+        f(ASL_FWD(args)...);
+    }
+{
+    return ASL_FWD(f)(ASL_FWD(args)...);
+}
+
+template<typename F> struct _result_of_helper;
+
+template<typename R, typename... Args>
+struct _result_of_helper<R(Args...)>
+{
+    using type = decltype(invoke(declval<R>(), declval<Args>()...));
+};
+
+template<typename F> using result_of_t = _result_of_helper<F>::type;
+
+} // namespace asl
diff --git a/asl/base/functional_tests.cpp b/asl/base/functional_tests.cpp
new file mode 100644
index 0000000..92c5c7b
--- /dev/null
+++ b/asl/base/functional_tests.cpp
@@ -0,0 +1,73 @@
+#include "asl/base/functional.hpp"
+#include "asl/testing/testing.hpp"
+
+struct HasFunction
+{
+    void do_something(int, float) {}
+};
+
+struct HasMember
+{
+    int member{};
+    int member_array[4]{};
+    void (*member_fn)(){};
+};
+
+struct Functor
+{
+    int64_t operator()() { return 35; }
+    int operator()(int x) { return x; }
+};
+
+static int some_func0() { return 1; }
+static int some_func1(int x) { return x + 1; }
+[[maybe_unused]] static float some_func1(float x) { return x + 1; }
+static int some_func2(int x, int b) { return x + b; }
+
+static_assert(asl::same_as<asl::result_of_t<Functor()>, int64_t>);
+static_assert(asl::same_as<asl::result_of_t<Functor(int)>, int>);
+static_assert(asl::same_as<asl::result_of_t<decltype(static_cast<float(*)(float)>(some_func1))(float)>, float>);
+static_assert(asl::same_as<asl::result_of_t<decltype(&HasFunction::do_something)(HasFunction, int, float)>, void>);
+static_assert(asl::same_as<asl::result_of_t<decltype(&HasMember::member)(HasMember)>, int>);
+
+ASL_TEST(invoke_member_function)
+{
+    HasFunction c;
+    asl::invoke(&HasFunction::do_something, c, 5, 5.0F);
+    asl::invoke(&HasFunction::do_something, &c, 5, 5.0F);
+}
+
+ASL_TEST(invoke_member_data)
+{
+    HasMember c;
+
+    asl::invoke(&HasMember::member, c);
+    asl::invoke(&HasMember::member_array, c);
+    asl::invoke(&HasMember::member_fn, c);
+    asl::invoke(&HasMember::member, &c);
+    asl::invoke(&HasMember::member_array, &c);
+    asl::invoke(&HasMember::member_fn, &c);
+}
+
+ASL_TEST(invoke_fn)
+{
+    ASL_TEST_EXPECT(asl::invoke(some_func0) == 1);
+    ASL_TEST_EXPECT(asl::invoke(static_cast<int(*)(int)>(some_func1), 8) == 9);
+    ASL_TEST_EXPECT(asl::invoke(some_func2, 4, 8) == 12);
+    ASL_TEST_EXPECT(asl::invoke(&some_func0) == 1);
+    ASL_TEST_EXPECT(asl::invoke(static_cast<int(*)(int)>(&some_func1), 8) == 9);
+    ASL_TEST_EXPECT(asl::invoke(&some_func2, 4, 8) == 12);
+}
+
+ASL_TEST(invoke_operator_call)
+{
+    Functor f;
+    ASL_TEST_EXPECT(asl::invoke(f) == 35);
+    ASL_TEST_EXPECT(asl::invoke(f, 8) == 8);
+}
+
+ASL_TEST(invoke_lambda)
+{
+    ASL_TEST_EXPECT(asl::invoke([](){ return 35; }) == 35);
+    ASL_TEST_EXPECT(asl::invoke([](int x){ return x + 2; }, 6) == 8);
+}
diff --git a/asl/base/integers.hpp b/asl/base/integers.hpp
new file mode 100644
index 0000000..c18c850
--- /dev/null
+++ b/asl/base/integers.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "asl/base/config.hpp"
+
+using int8_t  = signed char;
+using int16_t = signed short;
+using int32_t = signed int;
+#if ASL_OS_WINDOWS
+    using int64_t = signed long long;
+#elif ASL_OS_LINUX
+    using int64_t = signed long;
+#endif
+
+using uint8_t  = unsigned char;
+using uint16_t = unsigned short;
+using uint32_t = unsigned int;
+#if ASL_OS_WINDOWS
+    using uint64_t = unsigned long long;
+#elif ASL_OS_LINUX
+    using uint64_t = unsigned long;
+#endif
+
+struct uint128_t
+{
+    uint64_t high;
+    uint64_t low;
+};
+
+using size_t  = uint64_t;
+using isize_t = int64_t;
+
+using uintptr_t = size_t;
+
+namespace asl
+{
+
+enum class byte : uint8_t {};
+
+} // namespace asl
+
diff --git a/asl/base/integers_tests.cpp b/asl/base/integers_tests.cpp
new file mode 100644
index 0000000..52feb85
--- /dev/null
+++ b/asl/base/integers_tests.cpp
@@ -0,0 +1,15 @@
+#include "asl/base/integers.hpp"
+
+static_assert(sizeof(int8_t)  == 1);
+static_assert(sizeof(int16_t) == 2);
+static_assert(sizeof(int32_t) == 4);
+static_assert(sizeof(int64_t) == 8);
+
+static_assert(sizeof(uint8_t)  == 1);
+static_assert(sizeof(uint16_t) == 2);
+static_assert(sizeof(uint32_t) == 4);
+static_assert(sizeof(uint64_t) == 8);
+
+static_assert(sizeof(asl::byte) == 1);
+
+static_assert(sizeof(uintptr_t) == sizeof(void*));
diff --git a/asl/base/meta.hpp b/asl/base/meta.hpp
new file mode 100644
index 0000000..ce17420
--- /dev/null
+++ b/asl/base/meta.hpp
@@ -0,0 +1,248 @@
+#pragma once
+
+#include "asl/base/integers.hpp"
+
+namespace asl {
+
+struct source_location
+{
+    const char* file;
+    int         line;
+
+    explicit source_location(
+        const char* file_ = __builtin_FILE(),
+        int line_ = __builtin_LINE())
+        : file{file_}
+        , line{line_}
+    {}
+};
+
+struct empty {};
+
+template<typename T> struct id { using type = T; };
+
+template<typename... Args> static constexpr isize_t types_count = sizeof...(Args);
+
+template<typename T, T kValue> struct integral_constant { static constexpr T value = kValue; };
+template<bool B> using bool_constant = integral_constant<bool, B>;
+
+using true_type  = bool_constant<true>;
+using false_type = bool_constant<false>;
+
+template<bool kSelect, typename U, typename V> struct _select_helper             { using type = V; };
+template<typename U, typename V>               struct _select_helper<true, U, V> { using type = U; };
+
+template<bool kSelect, typename U, typename V> using select_t = _select_helper<kSelect, U, V>::type;
+
+template<typename U, typename V> struct _same_as_helper       : false_type {};
+template<typename T>             struct _same_as_helper<T, T> : true_type {};
+
+template<typename U, typename V> concept same_as = _same_as_helper<U, V>::value && _same_as_helper<V, U>::value;
+
+template<typename T> auto _as_lref_helper(int) -> id<T&>;
+template<typename T> auto _as_lref_helper(...) -> id<T>;
+
+template<typename T> auto _as_rref_helper(int) -> id<T&&>;
+template<typename T> auto _as_rref_helper(...) -> id<T>;
+
+template<typename T> using as_lref_t = decltype(_as_lref_helper<T>(0))::type;
+template<typename T> using as_rref_t = decltype(_as_rref_helper<T>(0))::type;
+
+template<typename T> consteval as_rref_t<T> declval() {}
+
+template<typename T> struct _un_ref_t      { using type = T; };
+template<typename T> struct _un_ref_t<T&>  { using type = T; };
+template<typename T> struct _un_ref_t<T&&> { using type = T; };
+
+template<typename T> using un_ref_t = _un_ref_t<T>::type;
+
+template<typename T, typename... Args> concept constructible_from = __is_constructible(T, Args...);
+
+template<typename T> concept default_constructible = constructible_from<T>;
+template<typename T> concept copy_constructible    = constructible_from<T, as_lref_t<const T>>;
+template<typename T> concept move_constructible    = constructible_from<T, as_rref_t<T>>;
+
+template<typename T, typename... Args> concept trivially_constructible_from = __is_trivially_constructible(T, Args...);
+
+template<typename T> concept trivially_default_constructible = trivially_constructible_from<T>;
+template<typename T> concept trivially_copy_constructible    = trivially_constructible_from<T, as_lref_t<const T>>;
+template<typename T> concept trivially_move_constructible    = trivially_constructible_from<T, as_rref_t<T>>;
+
+template<typename T, typename... Args> concept assignable_from = __is_assignable(T, Args...);
+
+template<typename T> concept copy_assignable = assignable_from<as_lref_t<T>, as_lref_t<const T>>;
+template<typename T> concept move_assignable = assignable_from<as_lref_t<T>, as_rref_t<T>>;
+
+template<typename T, typename... Args> concept trivially_assignable_from = __is_trivially_assignable(T, Args...);
+
+template<typename T> concept trivially_copy_assignable = trivially_assignable_from<as_lref_t<T>, as_lref_t<const T>>;
+template<typename T> concept trivially_move_assignable = trivially_assignable_from<as_lref_t<T>, as_rref_t<T>>;
+
+template<typename T> concept trivially_destructible = __is_trivially_destructible(T);
+
+template<typename T> concept copyable = copy_constructible<T> && copy_assignable<T>;
+template<typename T> concept moveable = move_constructible<T> && move_assignable<T>;
+
+template<typename To, typename From>
+concept convertible_from = __is_convertible(From, To);
+
+template<typename Derived, class Base>
+concept derived_from = __is_class(Derived) && __is_class(Base) && convertible_from<const volatile Base*, const volatile Derived*>;
+
+using nullptr_t = decltype(nullptr);
+
+template<typename T> struct _un_const_helper          { using type = T; };
+template<typename T> struct _un_const_helper<const T> { using type = T; };
+
+template<typename T> using un_const_t = _un_const_helper<T>::type;
+
+template<typename T> struct _is_const_helper          : false_type {};
+template<typename T> struct _is_const_helper<const T> : true_type {};
+
+template<typename T> concept is_const = _is_const_helper<T>::value;
+
+template<typename T> struct _un_volatile_helper             { using type = T; };
+template<typename T> struct _un_volatile_helper<volatile T> { using type = T; };
+
+template<typename T> using un_volatile_t = _un_volatile_helper<T>::type;
+
+template<typename T> using un_cv_t = un_volatile_t<un_const_t<T>>;
+
+template<typename T> using un_cvref_t = un_ref_t<un_cv_t<T>>;
+
+template<typename T> concept is_void = same_as<void, un_cv_t<T>>;
+
+template<typename T> struct _is_ref_helper      { static constexpr bool l = false; static constexpr bool r = false; };
+template<typename T> struct _is_ref_helper<T&>  { static constexpr bool l = true;  static constexpr bool r = false; };
+template<typename T> struct _is_ref_helper<T&&> { static constexpr bool l = false; static constexpr bool r = true;  };
+
+template<typename T> concept is_ref = _is_ref_helper<T>::l || _is_ref_helper<T>::r;
+template<typename T> concept is_rref = _is_ref_helper<T>::r;
+template<typename T> concept is_lref = _is_ref_helper<T>::l;
+
+template<typename T> struct _is_ptr_helper     : false_type {};
+template<typename T> struct _is_ptr_helper<T*> : true_type {};
+
+template<typename T> concept is_ptr = _is_ptr_helper<un_cv_t<T>>::value;
+
+template<typename T> struct _tame_helper { using type = T; };
+
+#define TAME_HELPER_IMPL(TRAILING)                                  \
+    template<typename R, typename... Args>                          \
+    struct _tame_helper<R(Args...) TRAILING> { using type = R(Args...); }
+
+TAME_HELPER_IMPL();
+TAME_HELPER_IMPL(&);
+TAME_HELPER_IMPL(&&);
+TAME_HELPER_IMPL(const);
+TAME_HELPER_IMPL(const &);
+TAME_HELPER_IMPL(const &&);
+TAME_HELPER_IMPL(volatile);
+TAME_HELPER_IMPL(volatile &);
+TAME_HELPER_IMPL(volatile &&);
+TAME_HELPER_IMPL(const volatile);
+TAME_HELPER_IMPL(const volatile &);
+TAME_HELPER_IMPL(const volatile &&);
+TAME_HELPER_IMPL(noexcept);
+TAME_HELPER_IMPL(& noexcept);
+TAME_HELPER_IMPL(&& noexcept);
+TAME_HELPER_IMPL(const noexcept);
+TAME_HELPER_IMPL(const & noexcept);
+TAME_HELPER_IMPL(const && noexcept);
+TAME_HELPER_IMPL(volatile noexcept);
+TAME_HELPER_IMPL(volatile & noexcept);
+TAME_HELPER_IMPL(volatile && noexcept);
+TAME_HELPER_IMPL(const volatile noexcept);
+TAME_HELPER_IMPL(const volatile & noexcept);
+TAME_HELPER_IMPL(const volatile && noexcept);
+
+#undef TAME_HELPER_IMPL
+
+template<typename T> using tame_t = _tame_helper<T>::type;
+
+template<typename T>                   struct _is_func_helper             : false_type {};
+template<typename R, typename... Args> struct _is_func_helper<R(Args...)> : true_type {};
+
+template<typename T> concept is_func = _is_func_helper<tame_t<T>>::value;
+
+template<typename T> concept is_object = !is_void<T> && !is_ref<T> && !is_func<T>;
+
+template<typename T>        struct _is_array_helper       : false_type {};
+template<typename T>        struct _is_array_helper<T[]>  : true_type  {};
+template<typename T, int N> struct _is_array_helper<T[N]> : true_type  {};
+
+template<typename T> concept is_array = _is_array_helper<T>::value;
+
+template<typename T> struct _is_floating_point_helper         : false_type {};
+template<>           struct _is_floating_point_helper<float>  : true_type  {};
+template<>           struct _is_floating_point_helper<double> : true_type  {};
+
+template<typename T> concept is_floating_point = _is_floating_point_helper<un_cv_t<T>>::value;
+
+template<typename T> struct _is_integer_helper           : false_type {};
+template<>           struct _is_integer_helper<int8_t>   : true_type  {};
+template<>           struct _is_integer_helper<int16_t>  : true_type  {};
+template<>           struct _is_integer_helper<int32_t>  : true_type  {};
+template<>           struct _is_integer_helper<int64_t>  : true_type  {};
+template<>           struct _is_integer_helper<uint8_t>  : true_type  {};
+template<>           struct _is_integer_helper<uint16_t> : true_type  {};
+template<>           struct _is_integer_helper<uint32_t> : true_type  {};
+template<>           struct _is_integer_helper<uint64_t> : true_type  {};
+
+template<typename T> concept is_integer = _is_integer_helper<un_cv_t<T>>::value;
+
+template<typename T> concept is_enum = __is_enum(T);
+
+template<typename T> struct is_uniquely_represented : false_type {};
+template<is_integer T> struct is_uniquely_represented<T> : true_type {};
+template<is_enum T> struct is_uniquely_represented<T> : true_type {};
+template<> struct is_uniquely_represented<uint128_t> : true_type {};
+template<> struct is_uniquely_represented<byte> : true_type {};
+
+template<typename T> concept uniquely_represented = is_uniquely_represented<un_cv_t<T>>::value;
+
+template<typename T, typename U>
+concept equality_comparable_with = requires (const un_cvref_t<T>& a, const un_cvref_t<U>& b)
+{
+    { a == b } -> same_as<bool>;
+    { b == a } -> same_as<bool>;
+    { a != b } -> same_as<bool>;
+    { b != a } -> same_as<bool>;
+};
+
+template<typename T> concept equality_comparable = equality_comparable_with<T, T>;
+
+struct niche_t {};
+
+template<typename T>
+concept has_niche = constructible_from<T, niche_t> && equality_comparable_with<T, niche_t>;
+
+template<typename T>
+concept is_niche = same_as<un_cvref_t<T>, niche_t>;
+
+template<typename T, typename U>
+concept _derefs_with_indirection_as = requires(T& t)
+{
+    *t;
+    requires convertible_from<U&, decltype(*t)>;
+};
+
+template<typename T, typename U>
+concept _derefs_reference_as = is_ref<T> && convertible_from<U&, T>;
+
+template<typename T, typename U>
+concept _derefs_value_as = !is_ref<T> && convertible_from<U&, T&>;
+
+template<typename U, _derefs_with_indirection_as<U> T>
+constexpr U& deref(T&& t) { return static_cast<U&>(*t); }
+
+template<typename U, _derefs_reference_as<U> T>
+constexpr U& deref(T&& t) { return static_cast<U&>(t); }
+
+template<typename U, _derefs_value_as<U> T>
+constexpr U& deref(T&& t) { return static_cast<U&>(t); }
+
+template<typename T, typename U>
+concept derefs_as = _derefs_with_indirection_as<T, U> || _derefs_reference_as<T, U> || _derefs_value_as<T, U>;
+
+} // namespace asl
diff --git a/asl/base/meta_tests.cpp b/asl/base/meta_tests.cpp
new file mode 100644
index 0000000..7aa7145
--- /dev/null
+++ b/asl/base/meta_tests.cpp
@@ -0,0 +1,289 @@
+#include "asl/base/meta.hpp"
+#include "asl/tests/types.hpp"
+#include "asl/testing/testing.hpp"
+#include "asl/types/box.hpp"
+
+struct Struct {};
+union Union {};
+enum Enum : uint8_t { EnumVariant = 0, };
+enum class EnumClass : uint8_t { Variant = 0, };
+
+static_assert(!asl::same_as<long, short>);
+static_assert(asl::same_as<int, int>);
+
+static_assert(asl::same_as<asl::select_t<false, int, float>, float>);
+static_assert(asl::same_as<asl::select_t<true, int, float>, int>);
+
+static_assert(asl::default_constructible<int>);
+static_assert(asl::default_constructible<TrivialType>);
+static_assert(asl::default_constructible<TrivialTypeDefaultValue>);
+
+static_assert(asl::trivially_default_constructible<int>);
+static_assert(asl::trivially_default_constructible<TrivialType>);
+static_assert(!asl::trivially_default_constructible<TrivialTypeDefaultValue>);
+
+static_assert(asl::copy_constructible<int>);
+static_assert(asl::copy_constructible<TrivialType>);
+static_assert(asl::copy_constructible<Copyable>);
+static_assert(!asl::copy_constructible<MoveableOnly>);
+static_assert(!asl::copy_constructible<Pinned>);
+
+static_assert(asl::trivially_copy_constructible<int>);
+static_assert(asl::trivially_copy_constructible<TrivialType>);
+static_assert(asl::trivially_copy_constructible<TrivialTypeDefaultValue>);
+static_assert(!asl::trivially_copy_constructible<WithDestructor>);
+static_assert(!asl::trivially_copy_constructible<Copyable>);
+static_assert(!asl::trivially_copy_constructible<MoveableOnly>);
+static_assert(!asl::trivially_copy_constructible<Pinned>);
+
+static_assert(asl::move_constructible<int>);
+static_assert(asl::move_constructible<TrivialType>);
+static_assert(asl::move_constructible<Copyable>);
+static_assert(asl::move_constructible<MoveableOnly>);
+static_assert(!asl::move_constructible<Pinned>);
+
+static_assert(asl::trivially_move_constructible<int>);
+static_assert(asl::trivially_move_constructible<TrivialType>);
+static_assert(asl::trivially_move_constructible<TrivialTypeDefaultValue>);
+static_assert(!asl::trivially_move_constructible<WithDestructor>);
+static_assert(!asl::trivially_move_constructible<Copyable>);
+static_assert(!asl::trivially_move_constructible<MoveableOnly>);
+static_assert(!asl::trivially_move_constructible<Pinned>);
+
+static_assert(asl::copy_assignable<int>);
+static_assert(asl::copy_assignable<TrivialType>);
+static_assert(asl::copy_assignable<Copyable>);
+static_assert(!asl::copy_assignable<MoveableOnly>);
+static_assert(!asl::copy_assignable<Pinned>);
+
+static_assert(asl::trivially_copy_assignable<int>);
+static_assert(asl::trivially_copy_assignable<TrivialType>);
+static_assert(asl::trivially_copy_assignable<TrivialTypeDefaultValue>);
+static_assert(asl::trivially_copy_assignable<WithDestructor>);
+static_assert(!asl::trivially_copy_assignable<Copyable>);
+static_assert(!asl::trivially_copy_assignable<MoveableOnly>);
+static_assert(!asl::trivially_copy_assignable<Pinned>);
+
+static_assert(asl::copyable<int>);
+static_assert(asl::copyable<TrivialType>);
+static_assert(asl::copyable<Copyable>);
+static_assert(!asl::copyable<MoveableOnly>);
+static_assert(!asl::copyable<Pinned>);
+
+static_assert(asl::moveable<int>);
+static_assert(asl::moveable<TrivialType>);
+static_assert(asl::moveable<Copyable>);
+static_assert(asl::moveable<MoveableOnly>);
+static_assert(!asl::moveable<Pinned>);
+
+static_assert(asl::move_assignable<int>);
+static_assert(asl::move_assignable<TrivialType>);
+static_assert(asl::move_assignable<Copyable>);
+static_assert(asl::move_assignable<MoveableOnly>);
+static_assert(!asl::move_assignable<Pinned>);
+
+static_assert(asl::trivially_move_assignable<int>);
+static_assert(asl::trivially_move_assignable<TrivialType>);
+static_assert(asl::trivially_move_assignable<TrivialTypeDefaultValue>);
+static_assert(asl::trivially_move_assignable<WithDestructor>);
+static_assert(!asl::trivially_move_assignable<Copyable>);
+static_assert(!asl::trivially_move_assignable<MoveableOnly>);
+static_assert(!asl::trivially_move_assignable<Pinned>);
+
+static_assert(asl::trivially_destructible<int>);
+static_assert(asl::trivially_destructible<TrivialType>);
+static_assert(asl::trivially_destructible<TrivialTypeDefaultValue>);
+static_assert(!asl::trivially_destructible<WithDestructor>);
+static_assert(asl::trivially_destructible<Copyable>);
+static_assert(asl::trivially_destructible<MoveableOnly>);
+static_assert(asl::trivially_destructible<Pinned>);
+
+static_assert(asl::same_as<int, asl::un_const_t<int>>);
+static_assert(asl::same_as<int, asl::un_const_t<const int>>);
+static_assert(asl::same_as<const int&, asl::un_const_t<const int&>>);
+
+static_assert(asl::same_as<int, asl::un_volatile_t<int>>);
+static_assert(asl::same_as<int, asl::un_volatile_t<volatile int>>);
+static_assert(asl::same_as<volatile int&, asl::un_volatile_t<volatile int&>>);
+
+static_assert(asl::same_as<int, asl::un_cv_t<int>>);
+static_assert(asl::same_as<int, asl::un_cv_t<const int>>);
+static_assert(asl::same_as<int, asl::un_cv_t<const volatile int>>);
+static_assert(asl::same_as<int, asl::un_cv_t<volatile int>>);
+
+static_assert(asl::is_void<void>);
+static_assert(asl::is_void<const void>);
+static_assert(asl::is_void<const volatile void>);
+static_assert(asl::is_void<volatile void>);
+static_assert(!asl::is_void<int>);
+static_assert(!asl::is_void<Struct>);
+static_assert(!asl::is_void<int&>);
+static_assert(!asl::is_void<int&&>);
+static_assert(!asl::is_void<void()>);
+static_assert(!asl::is_void<void() const &&>);
+
+static_assert(asl::is_ref<int&>);
+static_assert(asl::is_ref<const int&>);
+static_assert(asl::is_ref<const volatile int&>);
+static_assert(asl::is_ref<int&&>);
+static_assert(!asl::is_ref<int>);
+static_assert(!asl::is_ref<void>);
+static_assert(!asl::is_ref<void()>);
+static_assert(!asl::is_ref<void() const &&>);
+
+static_assert(asl::is_ptr<int*>);
+static_assert(asl::is_ptr<const int* const>);
+static_assert(asl::is_ptr<const volatile int*>);
+static_assert(!asl::is_ptr<int>);
+static_assert(!asl::is_ptr<void>);
+static_assert(!asl::is_ptr<void()>);
+static_assert(!asl::is_ptr<void() const &&>);
+
+static_assert(asl::same_as<int, asl::tame_t<int>>);
+static_assert(asl::same_as<int(), asl::tame_t<int()>>);
+static_assert(asl::same_as<int(float), asl::tame_t<int(float)>>);
+static_assert(asl::same_as<int(float), asl::tame_t<int(float) &>>);
+static_assert(asl::same_as<int(float), asl::tame_t<int(float) const &&>>);
+static_assert(asl::same_as<int(float), asl::tame_t<int(float) volatile noexcept>>);
+static_assert(asl::same_as<int(float), asl::tame_t<int(float) && noexcept>>);
+static_assert(asl::same_as<int(float), asl::tame_t<int(float) const>>);
+
+static_assert(asl::is_func<void()>);
+static_assert(asl::is_func<void(int)>);
+static_assert(asl::is_func<void(int, float)>);
+static_assert(asl::is_func<void() &>);
+static_assert(asl::is_func<void() const &&>);
+static_assert(asl::is_func<void() volatile noexcept>);
+static_assert(!asl::is_func<void(*)()>);
+static_assert(!asl::is_func<int>);
+static_assert(!asl::is_func<int&>);
+static_assert(!asl::is_func<void>);
+
+static_assert(asl::is_object<Struct>);
+static_assert(asl::is_object<int>);
+static_assert(asl::is_object<int*>);
+static_assert(asl::is_object<int Struct::*>);
+static_assert(asl::is_object<int (Struct::*)(float)>);
+static_assert(asl::is_object<int[]>);
+static_assert(asl::is_object<int[45]>);
+static_assert(asl::is_object<Enum>);
+static_assert(!asl::is_object<int&>);
+static_assert(!asl::is_object<void>);
+static_assert(!asl::is_object<void(int)>);
+static_assert(!asl::is_object<int(float) const && noexcept>);
+
+static_assert(!asl::is_array<Struct>);
+static_assert(!asl::is_array<int>);
+static_assert(!asl::is_array<int*>);
+static_assert(!asl::is_array<int Struct::*>);
+static_assert(!asl::is_array<int (Struct::*)(float)>);
+static_assert(asl::is_array<int[]>);
+static_assert(asl::is_array<int[45]>);
+static_assert(!asl::is_array<Enum>);
+static_assert(!asl::is_array<int&>);
+static_assert(!asl::is_array<void>);
+static_assert(!asl::is_array<void(int)>);
+static_assert(!asl::is_array<int(float) const && noexcept>);
+
+static_assert(asl::same_as<int, asl::un_ref_t<int>>);
+static_assert(asl::same_as<int, asl::un_ref_t<int&>>);
+static_assert(asl::same_as<int, asl::un_ref_t<int&&>>);
+static_assert(asl::same_as<int() &, asl::un_ref_t<int() &>>);
+
+static_assert(asl::types_count<int, float> == 2);
+static_assert(asl::types_count<int, int> == 2);
+static_assert(asl::types_count<int> == 1);
+static_assert(asl::types_count<> == 0);
+
+class Base {};
+class Derived : public Base {};
+class C {};
+class D { public: operator C() { return c; } C c; }; // NOLINT
+class E { public: template<class T> E(T&&) {} }; // NOLINT
+
+static_assert(asl::convertible_from<Base*, Derived*>);
+static_assert(!asl::convertible_from<Derived*, Base*>);
+static_assert(asl::convertible_from<C, D>);
+static_assert(!asl::convertible_from<C*, Derived*>);
+static_assert(asl::convertible_from<E, Base>);
+
+static_assert(!asl::convertible_from<int16_t(&)[], int32_t(&)[]>);
+static_assert(asl::convertible_from<const int16_t(&)[], int16_t(&)[]>);
+static_assert(asl::convertible_from<const int16_t(&)[], const int16_t(&)[]>);
+static_assert(asl::convertible_from<int16_t(&)[], int16_t(&)[]>);
+static_assert(!asl::convertible_from<int32_t(&)[], int16_t(&)[]>);
+static_assert(!asl::convertible_from<int16_t(&)[], const int16_t(&)[]>);
+static_assert(!asl::convertible_from<C(&)[], D(&)[]>);
+
+static_assert(asl::derived_from<Derived, Base>);
+static_assert(!asl::derived_from<Base, Derived>);
+static_assert(!asl::derived_from<D, C>);
+static_assert(!asl::derived_from<C, D>);
+static_assert(!asl::derived_from<uint8_t, uint16_t>);
+static_assert(!asl::derived_from<uint16_t, uint8_t>);
+static_assert(!asl::derived_from<int, int>);
+
+static_assert(!asl::is_const<int>);
+static_assert(asl::is_const<const int>);
+static_assert(!asl::is_const<const int*>);
+static_assert(asl::is_const<int* const>);
+
+static_assert(asl::is_floating_point<float>);
+static_assert(asl::is_floating_point<const float>);
+static_assert(asl::is_floating_point<volatile double>);
+static_assert(!asl::is_floating_point<const float&>);
+static_assert(!asl::is_floating_point<int>);
+static_assert(!asl::is_floating_point<C>);
+
+static_assert(asl::uniquely_represented<int>);
+static_assert(asl::uniquely_represented<uint128_t>);
+static_assert(!asl::uniquely_represented<bool>);
+
+enum Enum1 {};
+enum class Enum2 {};
+
+static_assert(asl::uniquely_represented<Enum1>);
+static_assert(asl::uniquely_represented<Enum2>);
+
+static_assert(!asl::is_enum<int>);
+static_assert(asl::is_enum<Enum1>);
+static_assert(asl::is_enum<Enum2>);
+
+static_assert(asl::derefs_as<int, int>);
+static_assert(asl::derefs_as<int*, int>);
+static_assert(asl::derefs_as<int&, int>);
+static_assert(asl::derefs_as<asl::box<int>, int>);
+
+static_assert(asl::derefs_as<Derived, Base>);
+static_assert(asl::derefs_as<Derived*, Base>);
+static_assert(asl::derefs_as<Derived&, Base>);
+static_assert(asl::derefs_as<asl::box<Derived>, Base>);
+
+static void wants_int(int) {}
+static void wants_base(Base&) {}
+static void wants_base_ptr(Base*) {}
+
+ASL_TEST(deref)
+{
+    int a = 4;
+    auto b = asl::make_box<int>(5);
+
+    wants_int(asl::deref<int>(5));
+    wants_int(asl::deref<int>(a));
+    wants_int(asl::deref<int>(&a));
+    wants_int(asl::deref<int>(b));
+
+    Derived c{};
+    auto d = asl::make_box<Derived>();
+
+    wants_base(asl::deref<Base>(Derived{}));
+    wants_base(asl::deref<Base>(c));
+    wants_base(asl::deref<Base>(&c));
+    wants_base(asl::deref<Base>(d));
+
+    wants_base_ptr(&asl::deref<Base>(Derived{}));
+    wants_base_ptr(&asl::deref<Base>(c));
+    wants_base_ptr(&asl::deref<Base>(&c));
+    wants_base_ptr(&asl::deref<Base>(d));
+}
+
diff --git a/asl/base/utility.hpp b/asl/base/utility.hpp
new file mode 100644
index 0000000..c03554f
--- /dev/null
+++ b/asl/base/utility.hpp
@@ -0,0 +1,95 @@
+#pragma once
+
+#include "asl/base/meta.hpp"
+#include "asl/base/assert.hpp"
+
+#define ASL_MOVE(...) (static_cast<::asl::un_ref_t<decltype(__VA_ARGS__)>&&>(__VA_ARGS__))
+
+#define ASL_FWD(expr_) (static_cast<decltype(expr_)&&>(expr_))
+
+namespace asl
+{
+
+struct in_place_t {};
+static constexpr in_place_t in_place{};
+
+template<moveable T>
+constexpr void swap(T& a, T& b)
+{
+    T tmp{ASL_MOVE(a)};
+    a = ASL_MOVE(b);
+    b = ASL_MOVE(tmp);
+}
+
+template<typename T, typename U>
+T exchange(T& obj, U&& new_value)
+{
+    T old_value = ASL_MOVE(obj);
+    obj = ASL_FWD(new_value);
+    return old_value;
+}
+
+template<trivially_copy_constructible U, trivially_copy_constructible T>
+constexpr U bit_cast(T value) requires (sizeof(T) == sizeof(U))
+{
+    return __builtin_bit_cast(U, value);
+}
+
+template<typename T>
+constexpr T min(T a, T b)
+{
+    return (a <= b) ? a : b;
+}
+
+template<typename T>
+constexpr T max(T a, T b)
+{
+    return (a >= b) ? a : b;
+}
+
+constexpr uint64_t round_up_pow2(uint64_t v)
+{
+    ASL_ASSERT(v <= 0x8000'0000'0000'0000);
+
+    v -= 1;
+
+    v |= v >> 1;
+    v |= v >> 2;
+    v |= v >> 4;
+    v |= v >> 8;
+    v |= v >> 16;
+    v |= v >> 32;
+
+    return v + 1;
+}
+
+constexpr bool is_pow2(isize_t v)
+{
+    return v > 0 && ((v - 1) & v) == 0;
+}
+
+#define ASL_DELETE_COPY(T)                         \
+    T(const T&) = delete;                          \
+    T& operator=(const T&) = delete;
+
+#define ASL_DELETE_MOVE(T)                         \
+    T(T&&) = delete;                               \
+    T& operator=(T&&) = delete;
+
+#define ASL_DELETE_COPY_MOVE(T)                    \
+    ASL_DELETE_COPY(T)                             \
+    ASL_DELETE_MOVE(T)
+
+#define ASL_DEFAULT_COPY(T)                         \
+    T(const T&) = default;                          \
+    T& operator=(const T&) = default;
+
+#define ASL_DEFAULT_MOVE(T)                         \
+    T(T&&) = default;                               \
+    T& operator=(T&&) = default;
+
+#define ASL_DEFAULT_COPY_MOVE(T)                    \
+    ASL_DEFAULT_COPY(T)                             \
+    ASL_DEFAULT_MOVE(T)
+
+} // namespace asl
diff --git a/asl/base/utility_tests.cpp b/asl/base/utility_tests.cpp
new file mode 100644
index 0000000..4b8e3d1
--- /dev/null
+++ b/asl/base/utility_tests.cpp
@@ -0,0 +1 @@
+#include "asl/base/utility.hpp"
diff --git a/asl/box.hpp b/asl/box.hpp
deleted file mode 100644
index 9d3c7f0..0000000
--- a/asl/box.hpp
+++ /dev/null
@@ -1,134 +0,0 @@
-#pragma once
-
-#include "asl/allocator.hpp"
-#include "asl/assert.hpp"
-#include "asl/annotations.hpp"
-#include "asl/memory.hpp"
-#include "asl/utility.hpp"
-#include "asl/hash.hpp"
-
-namespace asl
-{
-
-template<is_object T, allocator Allocator = DefaultAllocator>
-class box
-{
-    T* m_ptr;
-    ASL_NO_UNIQUE_ADDRESS Allocator m_alloc;
-
-public:
-    explicit constexpr box(niche_t)
-        requires default_constructible<Allocator>
-        : m_ptr{nullptr}
-        , m_alloc{}
-    {}
-
-    constexpr box(T* ptr, Allocator alloc)
-        : m_ptr{ptr}
-        , m_alloc{ASL_MOVE(alloc)}
-    {
-        ASL_ASSERT(m_ptr != nullptr);
-    }
-
-    constexpr box(box&& other)
-        : m_ptr{exchange(other.m_ptr, nullptr)}
-        , m_alloc{ASL_MOVE(other.m_alloc)}
-    {}
-
-    template<is_object U>
-    requires convertible_from<T*, U*>
-    constexpr box(box<U, Allocator>&& other) // NOLINT(*-explicit-conversions)
-        : m_ptr{exchange(other.m_ptr, nullptr)}
-        , m_alloc{ASL_MOVE(other.m_alloc)}
-    {}
-
-    constexpr box& operator=(box&& other)
-    {
-        if (this == &other) { return *this; }
-
-        if (m_ptr != nullptr) { reset(); }
-
-        m_ptr = exchange(other.m_ptr, nullptr);
-        m_alloc = ASL_MOVE(other.m_alloc);
-
-        return *this;
-    }
-
-    box(const box&) = delete;
-    box& operator=(const box&) = delete;
-
-    constexpr ~box()
-    {
-        reset();
-    }
-
-    constexpr void reset()
-    {
-        if (m_ptr != nullptr)
-        {
-            destroy(m_ptr);
-            m_alloc.dealloc(m_ptr, layout::of<T>());
-            m_ptr = nullptr;
-        }
-    }
-
-    constexpr T* get() const { return m_ptr; }
-
-    constexpr T& operator*() const
-    {
-        ASL_ASSERT(m_ptr != nullptr);
-        return *m_ptr;
-    }
-
-    constexpr T* operator->() const
-    {
-        ASL_ASSERT(m_ptr != nullptr);
-        return m_ptr;
-    }
-
-    constexpr bool operator==(niche_t) const
-    {
-        return m_ptr == nullptr;
-    }
-
-    template<typename H>
-    requires hashable<T>
-    friend H AslHashValue(H h, const box& b)
-    {
-        return H::combine(ASL_MOVE(h), *b);
-    }
-
-    template<is_object U, allocator A>
-    friend constexpr U* leak(box<U, A>&&);
-
-    template<is_object U, allocator A>
-    friend class box;
-};
-
-template<is_object T, allocator Allocator = DefaultAllocator, typename... Args>
-constexpr box<T, Allocator> make_box_in(Allocator allocator, Args&&... args)
-    requires constructible_from<T, Args&&...>
-{
-    void* raw_ptr = allocator.alloc(layout::of<T>());
-    auto* ptr = construct_at<T>(raw_ptr, ASL_FWD(args)...);
-    return box(ptr, ASL_MOVE(allocator));
-}
-
-template<is_object T, allocator Allocator = DefaultAllocator, typename... Args>
-constexpr box<T, Allocator> make_box(Args&&... args)
-    requires default_constructible<Allocator> && constructible_from<T, Args&&...>
-{
-    Allocator allocator{};
-    void* raw_ptr = allocator.alloc(layout::of<T>());
-    auto* ptr = construct_at<T>(raw_ptr, ASL_FWD(args)...);
-    return box<T>(ptr, ASL_MOVE(allocator));
-}
-
-template<is_object T, allocator A>
-constexpr T* leak(box<T, A>&& b)
-{
-    return exchange(b.m_ptr, nullptr);
-}
-
-} // namespace asl
-
diff --git a/asl/buffer.hpp b/asl/buffer.hpp
deleted file mode 100644
index 5cf9964..0000000
--- a/asl/buffer.hpp
+++ /dev/null
@@ -1,459 +0,0 @@
-#pragma once
-
-#include "asl/meta.hpp"
-#include "asl/allocator.hpp"
-#include "asl/annotations.hpp"
-#include "asl/memory.hpp"
-#include "asl/assert.hpp"
-#include "asl/span.hpp"
-#include "asl/hash.hpp"
-
-namespace asl
-{
-
-template<is_object T, allocator Allocator = DefaultAllocator>
-class buffer
-{
-    T*         m_data{};
-    isize_t    m_capacity{};
-
-    static constexpr size_t kOnHeapMask = 0x8000'0000'0000'0000ULL;
-
-    // bit 63       : 1 = on heap, 0 = inline
-    // bits [62:56] : size when inline
-    // bits [62:0]  : size when on heap
-    size_t     m_size_encoded_{};
-
-    ASL_NO_UNIQUE_ADDRESS Allocator m_allocator;
-
-    static constexpr isize_t kInlineRegionSize = size_of<T*> + size_of<isize_t> + size_of<size_t>;
-
-public:
-    static constexpr isize_t kInlineCapacity = []() {
-        // 1 byte is used for size inline in m_size_encoded.
-        // This is enough because we have at most 24 bytes available,
-        // so 23 chars of capacity.
-        const isize_t available_size = kInlineRegionSize - 1;
-        return available_size / size_of<T>;
-    }();
-
-private:
-    static_assert(align_of<T> <= align_of<T*>);
-    static_assert(align_of<T*> == align_of<isize_t>);
-    static_assert(align_of<T*> == align_of<size_t>);
-
-    constexpr size_t load_size_encoded() const
-    {
-        size_t s{};
-        asl::memcpy(&s, &m_size_encoded_, sizeof(size_t));
-        return s;
-    }
-
-    constexpr void store_size_encoded(size_t encoded)
-    {
-        asl::memcpy(&m_size_encoded_, &encoded, sizeof(size_t));
-    }
-
-    static constexpr bool is_on_heap(size_t size_encoded)
-    {
-        return (size_encoded & kOnHeapMask) != 0;
-    }
-
-    static constexpr size_t encode_size_heap(isize_t size)
-    {
-        return static_cast<size_t>(size) | kOnHeapMask;
-    }
-
-    static constexpr isize_t decode_size(size_t size_encoded)
-    {
-        if constexpr (kInlineCapacity == 0)
-        {
-            return is_on_heap(size_encoded)
-                ? static_cast<isize_t>(size_encoded & (~kOnHeapMask))
-                : 0;
-        }
-        else
-        {
-            return is_on_heap(size_encoded)
-                ? static_cast<isize_t>(size_encoded & (~kOnHeapMask))
-                : static_cast<isize_t>(size_encoded >> 56);
-        }
-    }
-
-    constexpr bool is_on_heap() const
-    {
-        return is_on_heap(load_size_encoded());
-    }
-
-    constexpr T* push_uninit()
-    {
-        isize_t sz = size();
-        resize_uninit_inner(sz + 1);
-        return data() + sz;
-    }
-
-    constexpr void resize_uninit_inner(isize_t new_size)
-    {
-        isize_t old_size = size();
-        if (!trivially_destructible<T> && new_size < old_size)
-        {
-            destroy_n(data() + new_size, old_size - new_size);
-        }
-        reserve_capacity(new_size);
-        set_size(new_size);
-    }
-
-    constexpr void set_size_inline(isize_t new_size)
-    {
-        ASL_ASSERT(new_size >= 0 && new_size <= kInlineCapacity);
-        size_t size_encoded = (load_size_encoded() & size_t{0x00ff'ffff'ffff'ffff}) | (bit_cast<size_t>(new_size) << 56);
-        store_size_encoded(size_encoded);
-    }
-
-    constexpr void set_size(isize_t new_size)
-    {
-        ASL_ASSERT(new_size >= 0 && new_size <= capacity());
-        if (is_on_heap())
-        {
-            store_size_encoded(encode_size_heap(new_size));
-        }
-        else
-        {
-            set_size_inline(new_size);
-        }
-    }
-
-    // NOLINTNEXTLINE(*-rvalue-reference-param-not-moved)
-    void move_from_other(buffer&& other, bool assign)
-    {
-        if (other.is_on_heap())
-        {
-            destroy();
-            m_data = other.m_data;
-            m_capacity = other.m_capacity;
-            store_size_encoded(other.load_size_encoded());
-        }
-        else if (trivially_move_constructible<T>)
-        {
-            destroy();
-            asl::memcpy(this, &other, kInlineRegionSize);
-        }
-        else if (!assign || m_allocator == other.m_allocator)
-        {
-            isize_t other_n = other.size();
-            isize_t this_n = size();
-            resize_uninit_inner(other_n);
-            if (other_n <= this_n)
-            {
-                relocate_assign_n(data(), other.data(), other_n);
-            }
-            else
-            {
-                relocate_assign_n(data(), other.data(), this_n);
-                relocate_uninit_n