@auto_js/utility 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CMakeLists.txt CHANGED
@@ -6,7 +6,6 @@ target_include_directories(utility_js PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/includ
6
6
 
7
7
  target_sources(utility_js
8
8
  PRIVATE
9
- assertions.cc
10
9
  platform/timer.cc
11
10
  PUBLIC FILE_SET CXX_MODULES FILES
12
11
  _module.cc
@@ -43,3 +42,9 @@ target_sources(utility_js
43
42
  utility/utility.cc
44
43
  utility/variant.cc
45
44
  )
45
+ if(CMAKE_BUILD_TYPE STREQUAL Debug)
46
+ target_sources(utility_js
47
+ PRIVATE
48
+ assertions.cc
49
+ )
50
+ endif()
package/_module.cc CHANGED
@@ -4,6 +4,7 @@ export import :container.sealed_map;
4
4
  export import :container.segmented_priority_queue;
5
5
  export import :container.tinker_queue;
6
6
  export import :functional;
7
+ export import :functional.flat_tuple;
7
8
  export import :memory;
8
9
  export import :meta.algorithm;
9
10
  export import :platform.lockable;
package/assertions.cc CHANGED
@@ -1,32 +1,30 @@
1
- #include <tuple> // IWYU pragma: keep
2
- #include <type_traits>
1
+ import std;
3
2
  import util;
4
3
 
5
4
  constexpr auto assert_strings_equal(auto... strings) {
6
- const auto [... left ] = util::sequence<sizeof...(strings)>;
7
- const auto [... right ] = util::sequence<sizeof...(strings)>;
8
- static_assert(
9
- (([ = ]() -> bool {
10
- auto left_string = strings...[ left ];
11
- using char_type = std::remove_extent_t<typename decltype(left_string)::value_type>;
12
- // NOLINTNEXTLINE(modernize-type-traits)
13
- return ((left_string == util::interpolate_string<char_type>(strings...[ right ])) && ...);
14
- }()) &&
15
- ...)
16
- );
5
+ const auto [... left ] = std::tuple{std::basic_string_view{strings}...};
6
+ const auto [... right ] = std::tuple{std::basic_string_view{strings}...};
7
+ (..., ([ = ](auto left) -> void {
8
+ using char_type = decltype(left)::value_type;
9
+ // NOLINTNEXTLINE(modernize-type-traits)
10
+ if ((... || (left != util::transcode_string<char_type>(right)))) {
11
+ std::unreachable();
12
+ }
13
+ }(left)));
17
14
  }
18
15
 
19
- [[maybe_unused]] constexpr auto result = []() -> int {
16
+ static_assert([]() -> int {
20
17
  // https://en.cppreference.com/w/cpp/language/string_literal.html
21
18
 
22
19
  // Quick check of interpolation matrix
23
- assert_strings_equal(util::cw<u8"💖">, util::cw<u"💖">, util::cw<U"💖">);
24
- assert_strings_equal(util::cw<"wow">, util::cw<u8"wow">, util::cw<u"wow">, util::cw<U"wow">);
20
+ assert_strings_equal(u8"💖", u"💖");
21
+ assert_strings_equal("wow", u8"wow", u"wow", U"wow");
22
+ assert_strings_equal(std::basic_string_view{"\x00", 1}, std::basic_string_view{u8"\x00", 1}, std::basic_string_view{u"\x00", 1}, std::basic_string_view{U"\x00", 1});
25
23
 
26
24
  // Unpaired utf-16 surrogates
27
- constexpr auto one_high_surrogate = util::cw<u"\xd83d">;
28
- static_assert(one_high_surrogate == util::interpolate_string<char16_t>(one_high_surrogate));
29
- constexpr auto two_high_surrogate = util::cw<u"\xd83d\xd83d">;
30
- static_assert(two_high_surrogate == util::interpolate_string<char16_t>(two_high_surrogate));
31
- return 0;
32
- }();
25
+ constexpr auto one_high_surrogate = std::basic_string_view{u"\xd83d"};
26
+ static_assert(one_high_surrogate == util::transcode_string<char16_t>(one_high_surrogate));
27
+ constexpr auto two_high_surrogate = std::basic_string_view{u"\xd83d\xd83d"};
28
+ static_assert(two_high_surrogate == util::transcode_string<char16_t>(two_high_surrogate));
29
+ return true;
30
+ }());
@@ -1,8 +1,5 @@
1
- module;
2
- #include <concepts>
3
- #include <queue>
4
- #include <utility>
5
1
  export module util:container.mutable_priority_queue;
2
+ import std;
6
3
 
7
4
  namespace util {
8
5
 
@@ -1,18 +1,14 @@
1
1
  module;
2
- #include <algorithm>
3
2
  #include <concepts>
4
- #include <format>
5
- #include <ranges>
6
- #include <type_traits>
7
- #include <utility>
8
3
  export module util:container.sealed_map;
9
4
  import :functional;
5
+ import std;
10
6
 
11
7
  namespace util {
12
8
 
13
9
  struct sorted_equivalent_t {};
14
10
 
15
- export template <class Key, class Type, size_t Size>
11
+ export template <class Key, class Type, std::size_t Size>
16
12
  class sealed_map {
17
13
  public:
18
14
  using key_type = Key;
@@ -22,7 +18,7 @@ class sealed_map {
22
18
  private:
23
19
  // Holder for consteval'd key into the map
24
20
  struct key_for {
25
- using value_type = size_t;
21
+ using value_type = std::size_t;
26
22
  constexpr key_for() :
27
23
  index_{std::numeric_limits<value_type>::max()} {}
28
24
  explicit constexpr key_for(auto index) :
@@ -32,7 +28,7 @@ class sealed_map {
32
28
  explicit constexpr operator bool() const { return index_ != std::numeric_limits<value_type>::max(); }
33
29
 
34
30
  private:
35
- size_t index_;
31
+ std::size_t index_;
36
32
  };
37
33
 
38
34
  // Check for duplicates
@@ -71,9 +67,9 @@ class sealed_map {
71
67
  util::elide{[ & ]() -> container_type {
72
68
  // Sort without invoking `operator()=`, which might not exist on the value type
73
69
  auto entries = std::array<value_type, Size>{std::move(pairs)...};
74
- auto indices = std::array<size_t, Size>{};
75
- std::ranges::copy(std::ranges::iota_view{size_t{0}, Size}, indices.begin());
76
- const auto projection = [ & ](size_t ii) -> const auto& { return entries.at(ii).first; };
70
+ auto indices = std::array<std::size_t, Size>{};
71
+ std::ranges::copy(std::ranges::views::iota(std::size_t{0}, Size), indices.begin());
72
+ const auto projection = [ & ](std::size_t ii) -> const auto& { return entries.at(ii).first; };
77
73
  std::ranges::sort(indices, std::less{}, projection);
78
74
  const auto [... sorted_indices ] = indices;
79
75
  return {value_type(std::move(entries.at(sorted_indices)))...};
@@ -1,11 +1,5 @@
1
- module;
2
- #include <algorithm>
3
- #include <array>
4
- #include <functional>
5
- #include <iterator>
6
- #include <span>
7
- #include <utility>
8
1
  export module util:container.segmented_priority_queue;
2
+ import std;
9
3
 
10
4
  namespace util {
11
5
 
@@ -25,7 +19,7 @@ class ratchet_span : public std::span<Type> {
25
19
  };
26
20
 
27
21
  // N number of queues, which tracks which ones currently may have elements
28
- export template <class Queue, size_t Size>
22
+ export template <class Queue, std::size_t Size>
29
23
  class segmented_priority_queue {
30
24
  public:
31
25
  using container_type = Queue;
@@ -34,7 +28,7 @@ class segmented_priority_queue {
34
28
 
35
29
  [[nodiscard]] auto containers() const -> std::span<const container_type> { return not_empty_; }
36
30
  [[nodiscard]] auto empty() const -> bool { return std::ranges::all_of(containers(), &Queue::empty); }
37
- [[nodiscard]] auto size() const -> size_t { return std::ranges::fold_left(containers(), 0UZ, std::plus{}, &Queue::size); }
31
+ [[nodiscard]] auto size() const -> std::size_t { return std::ranges::fold_left(containers(), 0UZ, std::plus{}, &Queue::size); }
38
32
  auto at(unsigned priority) -> container_type&;
39
33
  auto at(unsigned priority) const -> const container_type& { return queues_.at(priority); }
40
34
  auto containers() -> std::span<container_type> { return not_empty_; }
@@ -79,7 +73,7 @@ auto ratchet_span<Type>::make_iterator(auto it) -> iterator {
79
73
  }
80
74
 
81
75
  // `segmented_priority_queue`
82
- template <class Queue, size_t Size>
76
+ template <class Queue, std::size_t Size>
83
77
  auto segmented_priority_queue<Queue, Size>::at(unsigned priority) -> container_type& {
84
78
  // We don't know what you're about to do with it, so assume that it will gain an element
85
79
  auto& queue = queues_.at(priority);
@@ -87,7 +81,7 @@ auto segmented_priority_queue<Queue, Size>::at(unsigned priority) -> container_t
87
81
  return queue;
88
82
  }
89
83
 
90
- template <class Queue, size_t Size>
84
+ template <class Queue, std::size_t Size>
91
85
  auto segmented_priority_queue<Queue, Size>::pop() -> void {
92
86
  for (auto& queue : not_empty_) {
93
87
  if (queue.empty()) {
@@ -1,10 +1,7 @@
1
1
  module;
2
- #include <algorithm>
3
2
  #include <cassert>
4
- #include <concepts>
5
- #include <deque>
6
- #include <utility>
7
3
  export module util:container.tinker_queue;
4
+ import std;
8
5
 
9
6
  namespace util {
10
7
 
@@ -19,7 +16,7 @@ class tinker_queue {
19
16
  using value_type = Value;
20
17
 
21
18
  [[nodiscard]] auto empty() const -> bool { return size() == 0; }
22
- [[nodiscard]] auto size() const -> size_t { return queue_.size() - empty_middle_values_; }
19
+ [[nodiscard]] auto size() const -> std::size_t { return queue_.size() - empty_middle_values_; }
23
20
  // nb: You don't want a `clear` method here because you want tasks to be destroyed in the order
24
21
  // they were added
25
22
  auto emplace(auto&&... args) -> void;
@@ -29,7 +26,7 @@ class tinker_queue {
29
26
 
30
27
  private:
31
28
  container_type queue_;
32
- size_t empty_middle_values_{};
29
+ std::size_t empty_middle_values_{};
33
30
  };
34
31
 
35
32
  // ---
@@ -1,11 +1,9 @@
1
1
  module;
2
2
  #include "auto_js/no_unique_address.h"
3
- #include <type_traits>
4
- #include <utility>
5
3
  export module util:functional.bind;
6
4
  import :functional.flat_tuple;
7
- import :type_traits;
8
5
  import :utility;
6
+ import std;
9
7
 
10
8
  namespace util {
11
9
 
@@ -83,7 +81,7 @@ class bind_explicit<Invocable, auto(Args...) noexcept(Nx)->Result, Bound...> : p
83
81
 
84
82
  using try_cvref_type = apply_cvref_t<ensure_reference_t<invocable_type_t<Invocable>>, Invocable>;
85
83
  using cvref_type =
86
- std::conditional_t<std::is_invocable_v<try_cvref_type, apply_cvref_t<try_cvref_type, Bound>...>, try_cvref_type, bind_explicit&>;
84
+ std::conditional_t<std::is_invocable_v<try_cvref_type, apply_cvref_t<try_cvref_type, Bound>..., Args...>, try_cvref_type, bind_explicit&>;
87
85
  using this_type = apply_cvref_t<cvref_type, bind_explicit>;
88
86
  constexpr static auto invoke_as_mutable = std::is_same_v<this_type, bind_explicit&>;
89
87
  constexpr static auto invoke_as_forward = !invoke_as_mutable;
@@ -148,4 +146,5 @@ template <class Invocable, class... Bound>
148
146
  class bind<Invocable, Bound...> : public bind_explicit_params_t<Invocable, Bound...> {
149
147
  using bind_explicit_params_t<Invocable, Bound...>::bind_explicit_params_t;
150
148
  };
149
+
151
150
  } // namespace util
@@ -1,9 +1,7 @@
1
1
  module;
2
2
  #include "auto_js/no_unique_address.h"
3
- #include <concepts>
4
- #include <tuple>
5
- #include <utility>
6
3
  export module util:functional.elide;
4
+ import std;
7
5
 
8
6
  namespace util {
9
7
 
@@ -1,8 +1,7 @@
1
1
  module;
2
2
  #include "auto_js/no_unique_address.h"
3
- #include <type_traits>
4
- #include <utility>
5
3
  export module util:functional.flat_tuple;
4
+ import std;
6
5
 
7
6
  namespace util {
8
7
 
@@ -1,8 +1,6 @@
1
- module;
2
- #include <concepts>
3
- #include <utility>
4
1
  export module util:functional.function_constant;
5
2
  import :type_traits;
3
+ import std;
6
4
 
7
5
  namespace util {
8
6
 
@@ -1,10 +1,7 @@
1
- module;
2
- #include <concepts>
3
- #include <type_traits>
4
- #include <utility>
5
1
  export module util:functional.function_ref;
6
2
  import :functional.elide;
7
3
  import :type_traits;
4
+ import std;
8
5
 
9
6
  namespace util {
10
7
 
@@ -27,7 +24,11 @@ class function_ref<auto(Args...) noexcept(Nx)->Result> {
27
24
 
28
25
  // NOLINTNEXTLINE(google-explicit-constructor)
29
26
  constexpr function_ref(signature_type* function) :
30
- function_ref{std::type_identity<signature_type>{}, static_cast<void*>(function)} {}
27
+ invoke_{[](void* ptr, Args... args) noexcept(Nx) -> Result {
28
+ auto& fn = *reinterpret_cast<signature_type*>(ptr);
29
+ return fn(std::forward<Args>(args)...);
30
+ }},
31
+ ptr_{reinterpret_cast<void*>(function)} {}
31
32
 
32
33
  template <std::invocable<Args...> Object>
33
34
  requires(type<Object> != type<function_ref>)
@@ -54,6 +55,17 @@ class function_ref<auto(Args...) noexcept(Nx)->Result> {
54
55
  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
55
56
  ptr_{const_cast<void*>(static_cast<const void*>(&bound))} {}
56
57
 
58
+ template <class Object, std::invocable<Object*, Args...> Function>
59
+ requires std::is_empty_v<Function>
60
+ constexpr explicit function_ref(Function /*function*/, Object* bound) :
61
+ invoke_{[](void* ptr, Args... args) noexcept(Nx) -> Result {
62
+ auto* object = static_cast<Object*>(ptr);
63
+ constexpr auto function = Function{};
64
+ return function(object, std::forward<Args>(args)...);
65
+ }},
66
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
67
+ ptr_{const_cast<void*>(static_cast<const void*>(bound))} {}
68
+
57
69
  constexpr auto operator()(Args... args) const noexcept(Nx) -> Result {
58
70
  return invoke_(ptr_, std::forward<Args>(args)...);
59
71
  }
@@ -65,4 +77,19 @@ class function_ref<auto(Args...) noexcept(Nx)->Result> {
65
77
  void* ptr_;
66
78
  };
67
79
 
80
+ // Deduction guide helper for bound object ref
81
+ template <class Signature>
82
+ struct function_ref_deduction_guide;
83
+
84
+ template <class Result, bool Nx, class Object, class... Args>
85
+ struct function_ref_deduction_guide<auto(Object, Args...) noexcept(Nx)->Result>
86
+ : std::type_identity<auto(Args...) noexcept(Nx)->Result> {};
87
+
88
+ export template <class Function>
89
+ function_ref(Function, auto&&)
90
+ -> function_ref<typename function_ref_deduction_guide<function_signature_t<Function>>::type>;
91
+
92
+ export template <class Function>
93
+ function_ref(Function) -> function_ref<function_signature_t<Function>>;
94
+
68
95
  } // namespace util
@@ -1,13 +1,10 @@
1
- module;
2
- #include <functional>
3
- #include <utility>
4
1
  export module util:functional;
5
2
  export import :functional.bind;
6
3
  export import :functional.elide;
7
4
  export import :functional.function_constant;
8
5
  export import :functional.function_ref;
9
6
  export import :functional.regular_return;
10
- import :type_traits;
7
+ import std;
11
8
 
12
9
  namespace util {
13
10
 
@@ -1,8 +1,6 @@
1
- module;
2
- #include <utility>
3
1
  export module util:functional.regular_return;
4
- import :type_traits;
5
2
  import :utility;
3
+ import std;
6
4
 
7
5
  namespace util {
8
6
 
@@ -0,0 +1,17 @@
1
+ #if EXPORT_IS_EXPORT
2
+
3
+ #if _WIN64
4
+ #define EXPORT __declspec(dllexport)
5
+ #else
6
+ #define EXPORT __attribute__((visibility("default")))
7
+ #endif
8
+
9
+ #else
10
+
11
+ #if _WIN64
12
+ #define EXPORT __declspec(dllimport)
13
+ #else
14
+ #define EXPORT
15
+ #endif
16
+
17
+ #endif
@@ -0,0 +1,6 @@
1
+ #if __GNUC__ > 14
2
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124957
3
+ #define GCC_ABI_TAG [[gnu::abi_tag("cxx11")]]
4
+ #else
5
+ #define GCC_ABI_TAG
6
+ #endif
@@ -1,13 +1,10 @@
1
1
  module;
2
2
  #include "auto_js/no_unique_address.h"
3
- #include <algorithm>
4
3
  #include <cassert>
5
- #include <memory>
6
- #include <utility>
7
- #include <vector>
8
4
  export module util:memory.autorelease_pool;
9
5
  import :memory.comparator;
10
6
  import :utility;
7
+ import std;
11
8
 
12
9
  namespace util {
13
10
 
@@ -1,6 +1,5 @@
1
- module;
2
- #include <memory>
3
1
  export module util:memory.comparator;
2
+ import std;
4
3
 
5
4
  namespace util {
6
5
 
package/memory/memory.cc CHANGED
@@ -1,12 +1,8 @@
1
- module;
2
- #include <concepts>
3
- #include <functional>
4
- #include <memory>
5
- #include <type_traits>
6
1
  export module util:memory;
7
2
  export import :memory.autorelease_pool;
8
3
  export import :memory.comparator;
9
4
  export import :memory.noinit_allocator;
5
+ import std;
10
6
 
11
7
  namespace util {
12
8
 
@@ -1,10 +1,7 @@
1
1
  module;
2
2
  #include "auto_js/no_unique_address.h"
3
- #include <concepts>
4
- #include <memory>
5
- #include <type_traits>
6
- #include <utility>
7
3
  export module util:memory.noinit_allocator;
4
+ import std;
8
5
 
9
6
  namespace util {
10
7
 
package/meta/algorithm.cc CHANGED
@@ -1,8 +1,6 @@
1
- module;
2
- #include <type_traits>
3
1
  export module util:meta.algorithm;
4
2
  import :functional;
5
- import :utility;
3
+ import std;
6
4
 
7
5
  namespace util {
8
6
 
@@ -10,11 +8,20 @@ namespace util {
10
8
  export constexpr auto make_type_pack = util::overloaded{
11
9
  // nb: Prevent `make_type_pack{type_pack_of{...}}` from turning into a mess of hidden types
12
10
  []<class... Types>(type_pack_of<Types...> pack) consteval -> auto { return pack; },
13
- []<template <class> class Pack, class... Types>(std::type_identity<Pack<Types...>> /*type*/) consteval -> auto {
11
+ []<template <class...> class Pack, class... Types>(std::type_identity<Pack<Types...>> /*type*/) consteval -> auto {
14
12
  return type_pack_of{type<Types>...};
15
13
  },
16
14
  };
17
15
 
16
+ // Resolves a `Something<T...>` from `SomethingElse<T...>`
17
+ export template <template <class...> class Into>
18
+ constexpr auto spread_type_pack = util::overloaded{
19
+ []<class... Hidden>(type_pack_of<Hidden...> /*pack*/) consteval -> auto { return type<Into<typename Hidden::type...>>; },
20
+ []<template <class...> class Pack, class... Types>(std::type_identity<Pack<Types...>> /*type*/) consteval -> auto {
21
+ return type<Into<Types...>>;
22
+ },
23
+ };
24
+
18
25
  // Concatenate 0..N `util::type_packs` together
19
26
  export constexpr auto pack_concat = util::overloaded{
20
27
  []() consteval -> auto { return type_pack{}; },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@auto_js/utility",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "author": "https://github.com/laverdet/",
5
5
  "homepage": "https://github.com/laverdet/isolated-vm/tree/experimental/packages/utility",
6
6
  "license": "ISC",
@@ -1,17 +1,9 @@
1
1
  module;
2
2
  #include "auto_js/no_unique_address.h"
3
3
  #include <cassert>
4
- #include <concepts>
5
- #include <condition_variable>
6
- #include <functional>
7
- #include <mutex>
8
- #include <shared_mutex>
9
- #include <stop_token>
10
- #include <utility>
11
- #include <variant>
12
4
  export module util:platform.lockable;
13
- import :type_traits;
14
5
  import :utility;
6
+ import std;
15
7
 
16
8
  namespace util {
17
9
 
@@ -237,8 +229,8 @@ struct lockable_traits {
237
229
  bool shared{};
238
230
  };
239
231
 
240
- export template <class Resource, lockable_traits Traits = {}>
241
- using lockable_with = type_t<[]() consteval {
232
+ template <class Resource, lockable_traits Traits = {}>
233
+ constexpr auto make_lockable_traits = []() consteval {
242
234
  using mutex_type = type_t<[]() {
243
235
  if constexpr (Traits.shared) {
244
236
  return type<std::shared_mutex>;
@@ -256,6 +248,9 @@ using lockable_with = type_t<[]() consteval {
256
248
  }
257
249
  }()>;
258
250
  return type<lockable<Resource, mutex_type, cv_type>>;
259
- }()>;
251
+ };
252
+ export template <class Resource, lockable_traits Traits = {}>
253
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124953
254
+ using lockable_with = decltype(make_lockable_traits<Resource, Traits>())::type;
260
255
 
261
256
  } // namespace util
@@ -1,25 +1,24 @@
1
- module;
2
- #include <stop_token>
3
- #include <utility>
4
1
  export module util:platform.stop_token;
5
2
  import :functional;
6
- import :utility;
3
+ import std;
7
4
 
8
5
  namespace util {
9
6
 
10
7
  // Combine multiple `std::stop_token`s into one `std::stop_token` that is stopped when any of the
11
8
  // source tokens is stopped.
12
- export template <size_t Size>
9
+ export template <std::size_t Size>
13
10
  class composite_stop_token : private std::stop_source, public std::stop_token {
14
11
  private:
15
- static auto make_callback(std::stop_source stop_source) {
16
- // I wonder what's better: copying the stop state into each callback, or using function
17
- // pointer..
18
- return [ stop_source = std::move(stop_source) ]() mutable -> void { stop_source.request_stop(); };
19
- }
12
+ class bound_stop_callback {
13
+ public:
14
+ explicit bound_stop_callback(std::stop_source source) : stop_source_{std::move(source)} {}
15
+ auto operator()() { stop_source_.request_stop(); }
20
16
 
21
- using callback_type = decltype(make_callback(std::declval<std::stop_source>()));
22
- using stop_callback_type = std::stop_callback<callback_type>;
17
+ private:
18
+ std::stop_source stop_source_;
19
+ };
20
+
21
+ using stop_callback_type = std::stop_callback<bound_stop_callback>;
23
22
  using callback_pack_type = std::array<stop_callback_type, Size>;
24
23
 
25
24
  public:
@@ -76,13 +75,13 @@ class composite_stop_token : private std::stop_source, public std::stop_token {
76
75
  case 0:
77
76
  case 1:
78
77
  {
79
- auto callback = make_callback(std::stop_source{});
78
+ auto callback = bound_stop_callback{std::stop_source{}};
80
79
  return {stop_callback_type{(util::unused(tokens), std::stop_token{}), callback}...};
81
80
  }
82
81
  // Make callback pack
83
82
  default:
84
83
  {
85
- auto callback = make_callback(std::move(static_cast<std::stop_source&>(*this)));
84
+ auto callback = bound_stop_callback{std::move(static_cast<std::stop_source&>(*this))};
86
85
  return {stop_callback_type{std::forward<decltype(tokens)>(tokens), callback}...};
87
86
  }
88
87
  }
package/platform/timer.cc CHANGED
@@ -1,18 +1,8 @@
1
- module;
2
- #include <algorithm>
3
- #include <array>
4
- #include <chrono>
5
- #include <functional>
6
- #include <memory>
7
- #include <ranges>
8
- #include <stop_token>
9
- #include <thread>
10
- #include <utility>
11
- #include <vector>
12
1
  module util;
13
2
  import :functional;
14
3
  import :platform.lockable;
15
4
  import :platform.timer;
5
+ import std;
16
6
 
17
7
  namespace util {
18
8
 
@@ -1,8 +1,5 @@
1
- module;
2
- #include <chrono>
3
- #include <memory>
4
- #include <stop_token>
5
1
  export module util:platform.timer;
2
+ import std;
6
3
 
7
4
  namespace util {
8
5
 
@@ -1,8 +1,6 @@
1
- module;
2
- #include <concepts>
3
- #include <type_traits>
4
1
  export module util:type_traits.function_traits;
5
2
  import :type_traits.transform;
3
+ import std;
6
4
 
7
5
  namespace util {
8
6
 
@@ -1,6 +1,5 @@
1
- module;
2
- #include <type_traits>
3
1
  export module util:type_traits.transform;
2
+ import std;
4
3
 
5
4
  namespace util {
6
5
 
@@ -1,6 +1,5 @@
1
- module;
2
- #include <type_traits>
3
1
  export module util:type_traits.type_of;
2
+ import std;
4
3
 
5
4
  namespace util {
6
5
 
@@ -1,8 +1,6 @@
1
- module;
2
- #include <tuple>
3
- #include <type_traits>
4
1
  export module util:type_traits.type_pack;
5
2
  import :type_traits.type_of;
3
+ import std;
6
4
 
7
5
  namespace util {
8
6
 
@@ -1,6 +1,5 @@
1
- module;
2
- #include <algorithm>
3
1
  export module util:utility.constant_wrapper;
2
+ import std;
4
3
 
5
4
  // Lifted from P2781R8:
6
5
  // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2781r8.html
@@ -1,9 +1,7 @@
1
- module;
2
- #include <utility>
3
- #include <variant>
4
1
  export module util:utility.covariant_value;
5
- import :utility.facade;
6
2
  import :type_traits;
3
+ import :utility.facade;
4
+ import std;
7
5
 
8
6
  namespace util {
9
7
 
@@ -17,7 +15,7 @@ class covariant_value : public pointer_facade {
17
15
  constexpr explicit covariant_value(Derived value) :
18
16
  value_{std::move(value)} {}
19
17
 
20
- constexpr auto operator*(this auto& self) -> auto& {
18
+ constexpr auto operator*(this auto& self) noexcept -> auto& {
21
19
  using reference_type = util::apply_cvref_t<decltype(self), Type>;
22
20
  if (self.value_.index() == std::variant_npos) {
23
21
  std::unreachable();
package/utility/facade.cc CHANGED
@@ -1,35 +1,39 @@
1
- module;
2
- #include <memory>
3
- #include <type_traits>
4
- #include <utility>
5
1
  export module util:utility.facade;
2
+ import std;
6
3
 
7
4
  namespace util {
8
5
 
9
- // Internal addition facade
10
- template <class difference_type_>
11
- class addition_facade {
6
+ // Implements `Type++` via `++Type`
7
+ export class incrementable_facade {
12
8
  public:
13
- using difference_type = difference_type_;
14
-
15
- // ++Type
16
- auto operator++(this auto& self) -> auto& { return self += 1; }
9
+ using difference_type = int;
17
10
 
18
11
  // Type++
19
- auto operator++(this auto& self, int) {
12
+ constexpr auto operator++(this auto& self, int) {
20
13
  auto result = self;
21
14
  ++self;
22
15
  return result;
23
16
  }
17
+ };
18
+
19
+ // Implements addition operators via `operator+=()`
20
+ export template <class difference_type_>
21
+ class addition_facade : public incrementable_facade {
22
+ public:
23
+ using incrementable_facade::operator++;
24
+ using difference_type = difference_type_;
25
+
26
+ // ++Type
27
+ constexpr auto operator++(this auto& self) -> auto& { return self += 1; }
24
28
 
25
29
  // Type + difference_type
26
- auto operator+(this const auto& self, difference_type offset) {
30
+ constexpr auto operator+(this const auto& self, difference_type offset) {
27
31
  auto result = self;
28
32
  return result += offset;
29
33
  }
30
34
 
31
35
  // difference_type + Type
32
- friend auto operator+(difference_type left, const auto& right) {
36
+ constexpr friend auto operator+(difference_type left, const auto& right) {
33
37
  return right + left;
34
38
  }
35
39
  };
@@ -50,26 +54,26 @@ class subtraction_facade<difference_type_, wide_size_type> {
50
54
  using difference_type = difference_type_;
51
55
 
52
56
  // Type -= difference_type
53
- auto operator-=(this auto& self, difference_type offset) -> auto& { return self += -offset; }
57
+ constexpr auto operator-=(this auto& self, difference_type offset) -> auto& { return self += -offset; }
54
58
 
55
59
  // --Type
56
- auto operator--(this auto& self) -> auto& { return self -= 1; }
60
+ constexpr auto operator--(this auto& self) -> auto& { return self -= 1; }
57
61
 
58
62
  // Type--
59
- auto operator--(this auto& self, int) {
63
+ constexpr auto operator--(this auto& self, int) {
60
64
  auto result = self;
61
65
  --self;
62
66
  return result;
63
67
  }
64
68
 
65
69
  // Type - difference_type
66
- auto operator-(this const auto& self, difference_type offset) {
70
+ constexpr auto operator-(this const auto& self, difference_type offset) {
67
71
  auto result = self;
68
72
  return result -= offset;
69
73
  }
70
74
 
71
75
  // Type - Type
72
- auto operator-(this const auto& self, decltype(self) right) -> difference_type {
76
+ constexpr auto operator-(this const auto& self, decltype(self) right) -> difference_type {
73
77
  return static_cast<difference_type>(wide_size_type{+self} - wide_size_type{+right});
74
78
  }
75
79
  };
@@ -100,7 +104,7 @@ class arithmetic_facade
100
104
  export template <class difference_type>
101
105
  class array_facade {
102
106
  public:
103
- auto operator[](this auto&& self, difference_type offset) -> decltype(auto) {
107
+ constexpr auto operator[](this auto&& self, difference_type offset) -> decltype(auto) {
104
108
  return *(std::forward<decltype(self)>(self) + offset);
105
109
  }
106
110
  };
package/utility/hash.cc CHANGED
@@ -1,20 +1,15 @@
1
- module;
2
- #include <array>
3
- #include <bit>
4
- #include <cstdint>
5
- #include <source_location>
6
- #include <string_view>
7
1
  export module util:utility.hash;
2
+ import std;
8
3
 
9
4
  namespace util {
10
5
 
11
6
  // `constexpr` hash for property lookup
12
7
  export template <class Char>
13
- constexpr auto fnv1a_hash(std::basic_string_view<Char> view) -> uint32_t {
14
- constexpr uint32_t prime = 0x100'0193;
15
- uint32_t hash = 0x811c'9dc5;
8
+ constexpr auto fnv1a_hash(std::basic_string_view<Char> view) -> std::uint32_t {
9
+ constexpr std::uint32_t prime = 0x100'0193;
10
+ std::uint32_t hash = 0x811c'9dc5;
16
11
  for (auto character : view) {
17
- auto bytes = std::bit_cast<std::array<uint8_t, sizeof(Char)>>(character);
12
+ auto bytes = std::bit_cast<std::array<std::uint8_t, sizeof(Char)>>(character);
18
13
  for (auto byte : bytes) {
19
14
  hash = hash ^ byte;
20
15
  hash *= prime;
@@ -25,8 +20,8 @@ constexpr auto fnv1a_hash(std::basic_string_view<Char> view) -> uint32_t {
25
20
 
26
21
  // constexpr `typeid(Type).hash_code()` replacement
27
22
  template <class Type>
28
- consteval auto make_type_hash() -> uint32_t {
29
- // "uint32_t make_type_hash() [Type = int]"
23
+ consteval auto make_type_hash() -> std::uint32_t {
24
+ // "std::uint32_t make_type_hash() [Type = int]"
30
25
  constexpr auto name = std::source_location::current().function_name();
31
26
  return fnv1a_hash(std::string_view{name});
32
27
  }
package/utility/ranges.cc CHANGED
@@ -52,4 +52,15 @@ export constexpr auto into_range(meta_range auto&& range) {
52
52
  return std::forward<decltype(range)>(range).into_range();
53
53
  }
54
54
 
55
+ // Returns either a `std::tuple<size_type>` with the range's size, or `std::tuple<>` if it can't be
56
+ // determined in constant time.
57
+ export template <class Type>
58
+ constexpr auto maybe_range_size(const Type& range) {
59
+ if constexpr (std::ranges::sized_range<Type>) {
60
+ return std::tuple{std::ranges::size(range)};
61
+ } else {
62
+ return std::tuple{};
63
+ }
64
+ }
65
+
55
66
  } // namespace util
package/utility/string.cc CHANGED
@@ -1,29 +1,20 @@
1
- module;
2
- #include <algorithm>
3
- #include <array>
4
- #include <bit>
5
- #include <cstdint>
6
- #include <limits>
7
- #include <stdexcept>
8
- #include <string>
9
- #include <utility>
10
1
  export module util:utility.string;
11
2
  import :utility.constant_wrapper;
3
+ import std;
12
4
 
13
5
  namespace util {
14
6
 
15
- // Helper to make `std::string_view` from a constant_wrapper or string literal
16
7
  export template <class Char, std::size_t Size>
17
- struct consteval_string_view : public std::basic_string_view<Char> {
18
- constexpr explicit consteval_string_view(const Char (&string)[ Size + 1 ]) noexcept : std::basic_string_view<Char>{string, Size} {}
19
- };
20
-
21
- template <class Char, std::size_t Size>
22
8
  // NOLINTNEXTLINE(modernize-avoid-c-arrays)
23
- consteval_string_view(const Char (&string)[ Size ]) -> consteval_string_view<Char, Size - 1>;
9
+ consteval auto make_consteval_string_view(const Char (&string)[ Size ]) -> std::basic_string_view<Char> {
10
+ return std::basic_string_view{string, Size - 1};
11
+ }
24
12
 
25
- template <class Char, std::size_t Extent, fixed_value<Char[ Extent ]> Value>
26
- consteval_string_view(util::constant_wrapper<Value>) -> consteval_string_view<Char, Extent - 1>;
13
+ // NOLINTNEXTLINE(modernize-avoid-c-arrays)
14
+ export template <class Char, std::size_t Size, fixed_value<Char[ Size ]> Value>
15
+ consteval auto make_consteval_string_view(constant_wrapper<Value> /*cw*/) -> std::basic_string_view<Char> {
16
+ return make_consteval_string_view(constant_wrapper<Value>::value);
17
+ }
27
18
 
28
19
  // Helper for `codepoint_char_sequence` which stores an array of the most characters it will take to
29
20
  // represent a codepoint in a given character type.
@@ -39,7 +30,7 @@ class codepoint_char_container {
39
30
 
40
31
  [[nodiscard]] constexpr auto begin() const -> iterator { return chars_.begin(); }
41
32
  [[nodiscard]] constexpr auto data() -> container_type& { return chars_; }
42
- [[nodiscard]] constexpr auto end() const -> iterator { return std::ranges::find(chars_, 0); }
33
+ [[nodiscard]] constexpr auto end() const -> iterator { return std::find(std::next(chars_.begin()), chars_.end(), 0); }
43
34
  [[nodiscard]] constexpr auto size() const -> std::size_t { return end() - begin(); }
44
35
 
45
36
  private:
@@ -113,15 +104,8 @@ class codepoint_char_range<char16_t> : public codepoint_char_container<char16_t,
113
104
  data()[ 1 ] = 0;
114
105
  } else if (codepoint < 0x11'0000) {
115
106
  auto twenty_bits = codepoint - 0x1'0000;
116
- // /usr/include/c++/v1/__type_traits/promote.h:38:1: error: redefinition of '__promote_t' as different kind of symbol
117
- // 38 | using __promote_t _LIBCPP_NODEBUG =
118
- // | ^
119
- // /usr/include/c++/v1/__type_traits/promote.h:38:1: note: previous definition is here
120
- // 38 | using __promote_t _LIBCPP_NODEBUG =
121
- // nb: `twenty_bits >> 10` == `twenty_bits / 0x400`
122
- data()[ 0 ] = static_cast<char16_t>((twenty_bits >> 10) + 0xd800);
123
- // nb: `twenty_bits & 0x3ff` == `twenty_bits % 0x400`
124
- data()[ 1 ] = static_cast<char16_t>((twenty_bits & 0x3ff) + 0xdc00);
107
+ data()[ 0 ] = static_cast<char16_t>((twenty_bits / 0x400) + 0xd800);
108
+ data()[ 1 ] = static_cast<char16_t>((twenty_bits % 0x400) + 0xdc00);
125
109
  } else {
126
110
  std::unreachable();
127
111
  }
@@ -188,7 +172,7 @@ class codepoint_utf8_forward_view {
188
172
  constexpr auto read() -> char32_t {
189
173
  // Check the expected length of the byte sequence from the leading byte's bit pattern
190
174
  auto sequence_length = [ & ]() -> unsigned {
191
- auto byte0 = std::bit_cast<uint8_t>(*pos_);
175
+ auto byte0 = std::bit_cast<std::uint8_t>(*pos_);
192
176
  if (byte0 < 0x80) {
193
177
  return 1;
194
178
  } else if (byte0 < 0xe0) {
@@ -213,7 +197,7 @@ class codepoint_utf8_forward_view {
213
197
  std::array<Char, 4> characters{};
214
198
  std::ranges::copy_n(pos_, sequence_length, characters.begin());
215
199
  pos_ += sequence_length;
216
- auto [ byte0, byte1, byte2, byte3 ] = std::bit_cast<std::array<uint8_t, 4>>(characters);
200
+ auto [ byte0, byte1, byte2, byte3 ] = std::bit_cast<std::array<std::uint8_t, 4>>(characters);
217
201
 
218
202
  // Convert byte sequence to codepoint
219
203
  switch (sequence_length) {
@@ -249,14 +233,14 @@ class codepoint_forward_view<char16_t> {
249
233
 
250
234
  constexpr auto read() -> char32_t {
251
235
  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
252
- auto char0 = *pos_++;
236
+ auto char0 = static_cast<char32_t>(*pos_++);
253
237
  if (char0 >= 0xd800 && char0 < 0xdc00) {
254
238
  if (eof()) {
255
239
  // nb: Unpaired surrogate
256
240
  return char0;
257
241
  }
258
242
  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
259
- auto char1 = *pos_++;
243
+ auto char1 = static_cast<char32_t>(*pos_++);
260
244
  if (char1 >= 0xdc00 && char1 < 0xe000) {
261
245
  return ((char0 - 0xd800) * 0x400) + (char1 - 0xdc00) + 0x1'0000;
262
246
  } else {
@@ -278,7 +262,7 @@ class codepoint_forward_view<char16_t> {
278
262
  // Interpolate the given character range to a `std::basic_string<Char>`. If the requested character
279
263
  // type is too small to represent a codepoint, a `std::range_error` is thrown.
280
264
  export template <class To, class From>
281
- constexpr auto interpolate_string(std::basic_string_view<From> from) -> std::basic_string<To> {
265
+ constexpr auto transcode_string(std::basic_string_view<From> from) -> std::basic_string<To> {
282
266
  auto reader = codepoint_forward_view{from};
283
267
  std::basic_string<To> result;
284
268
 
@@ -297,7 +281,7 @@ constexpr auto interpolate_string(std::basic_string_view<From> from) -> std::bas
297
281
  }();
298
282
 
299
283
  // Write string
300
- result.resize_and_overwrite(size, [ & ](To* result, size_t /*length*/) -> size_t {
284
+ result.resize_and_overwrite(size, [ & ](To* result, std::size_t /*length*/) -> std::size_t {
301
285
  auto first = result;
302
286
  while (!reader.eof()) {
303
287
  auto chunk = codepoint_char_range<To>{reader.read()};
@@ -311,14 +295,14 @@ constexpr auto interpolate_string(std::basic_string_view<From> from) -> std::bas
311
295
 
312
296
  // NOLINTNEXTLINE(modernize-avoid-c-arrays)
313
297
  export template <class To, class From, std::size_t Extent, fixed_value<From[ Extent ]> Value>
314
- constexpr auto interpolate_string(util::constant_wrapper<Value> /*cw*/) {
315
- constexpr auto make = []() { return interpolate_string<To>(std::basic_string_view{Value.value, Extent - 1}); };
298
+ constexpr auto transcode_string(util::constant_wrapper<Value> /*cw*/) {
299
+ constexpr auto make = []() { return transcode_string<To>(std::basic_string_view{Value.value, Extent - 1}); };
316
300
  constexpr auto chars = [ = ]() {
317
301
  std::array<To, make().size()> result{};
318
302
  std::ranges::copy(make(), result.data());
319
303
  return result;
320
304
  }();
321
- return [ = ]<std::size_t... Indices>(std::index_sequence<Indices...>) {
305
+ return [ & ]<std::size_t... Indices>(std::index_sequence<Indices...>) {
322
306
  // NOLINTNEXTLINE(modernize-avoid-c-arrays)
323
307
  constexpr To string[ chars.size() + 1 ] = {chars[ Indices ]..., 0};
324
308
  return util::cw<string>;
@@ -1,8 +1,3 @@
1
- module;
2
- #include <concepts>
3
- #include <stdexcept>
4
- #include <string_view>
5
- #include <utility>
6
1
  export module util:utility;
7
2
  export import :utility.constant_wrapper;
8
3
  export import :utility.covariant_value;
@@ -11,7 +6,7 @@ export import :utility.hash;
11
6
  export import :utility.ranges;
12
7
  export import :utility.string;
13
8
  // export import :utility.variant;
14
- import :type_traits;
9
+ import std;
15
10
 
16
11
  namespace util {
17
12
 
@@ -40,11 +35,11 @@ export class non_moveable {
40
35
  export template <std::size_t Size>
41
36
  constexpr auto sequence = []() consteval -> auto {
42
37
  // With C++26 P2686 we can do constexpr decomposition. So instead of the `tuple` of
43
- // `integral_constants` it can be an array of `size_t`.
38
+ // `integral_constants` it can be an array of `std::size_t`.
44
39
  // https://clang.llvm.org/cxx_status.html
45
40
 
46
41
  // std::array<std::size_t, Size> result{};
47
- // std::ranges::copy(std::ranges::iota_view{std::size_t{0}, Size}, result.begin());
42
+ // std::ranges::copy(std::ranges::views::iota(std::size_t{0}, Size), result.begin());
48
43
  // return result;
49
44
 
50
45
  return []<std::size_t... Index>(std::index_sequence<Index...> /*sequence*/) consteval {
@@ -89,7 +84,7 @@ class just : public pointer_facade {
89
84
  Type value_;
90
85
  };
91
86
 
92
- export template <class Type>
87
+ template <class Type>
93
88
  class just<Type&> : public pointer_facade {
94
89
  public:
95
90
  explicit constexpr just(Type& value) : value_{&value} {}
@@ -143,8 +138,38 @@ struct slice_t<const Type> {
143
138
  };
144
139
 
145
140
  export template <class Type>
146
- constexpr auto slice(Type& value) {
141
+ constexpr auto slice(const Type& value) {
147
142
  return slice_t<const Type>{value};
148
143
  }
149
144
 
145
+ // Implements construction of containers with variadic elements
146
+ template <class Type>
147
+ struct inplace_container_constructor {
148
+ constexpr auto operator()(auto&&... args) const -> Type {
149
+ return Type{std::in_place, std::forward<decltype(args)>(args)...};
150
+ }
151
+ };
152
+
153
+ template <class Type, std::size_t Size>
154
+ struct inplace_container_constructor<std::array<Type, Size>> {
155
+ constexpr auto operator()(auto&&... args) const -> std::array<Type, Size> {
156
+ return std::array<Type, Size>{std::forward<decltype(args)>(args)...};
157
+ }
158
+ };
159
+
160
+ template <class Type, class Alloc>
161
+ struct inplace_container_constructor<std::vector<Type, Alloc>> {
162
+ constexpr auto operator()(auto&&... args) const -> std::vector<Type, Alloc> {
163
+ auto container = std::vector<Type, Alloc>{};
164
+ container.reserve(sizeof...(args));
165
+ (..., container.emplace_back(std::forward<decltype(args)>(args)));
166
+ return container;
167
+ }
168
+ };
169
+
170
+ export template <class Type>
171
+ auto make_inplace_container(auto&&... args) -> Type {
172
+ return inplace_container_constructor<Type>{}(std::forward<decltype(args)>(args)...);
173
+ }
174
+
150
175
  } // namespace util
@@ -1,16 +1,13 @@
1
- module;
2
- #include <utility>
3
- #include <variant>
4
1
  export module util:utility.variant;
5
2
  import :meta.algorithm;
6
- import :type_traits;
3
+ import std;
7
4
 
8
5
  namespace util {
9
6
 
10
7
  // Apply a visitor to a variant and map its result to a new variant type. Repeated types are collapsed.
11
8
  export auto map_variant(auto&& variant, auto visit) {
12
- constexpr auto result_from = [](auto alternative) {
13
- return type<decltype(visit)>(type<util::apply_cvref_t<decltype(variant), type_t<alternative>>>);
9
+ constexpr auto result_from = []<class Type>(std::type_identity<Type> /*alternative*/) {
10
+ return type<decltype(visit)>(type<util::apply_cvref_t<decltype(variant), Type>>);
14
11
  };
15
12
  const auto [... alternative_types ] = util::make_type_pack(util::remove_cvref(type<decltype(variant)>));
16
13
  const auto [... result_types ] = util::pack_unique(result_from(alternative_types)...);