summaryrefslogtreecommitdiff
path: root/lib/CWayland/CWayland.cc
diff options
context:
space:
mode:
authorHannes Schulze <haschu0103@outlook.de>2026-03-13 20:10:14 +0100
committerHannes Schulze <haschu0103@outlook.de>2026-03-13 20:10:14 +0100
commitad2c02141844d48e9c50a05f5ce872db283751ce (patch)
tree834f91b1278cf823063a218e08a1516314b227a6 /lib/CWayland/CWayland.cc
parenta5457cc2f8c62d3b0946e8b80923c47ce94f99a3 (diff)
type map implementation
Diffstat (limited to 'lib/CWayland/CWayland.cc')
-rw-r--r--lib/CWayland/CWayland.cc183
1 files changed, 183 insertions, 0 deletions
diff --git a/lib/CWayland/CWayland.cc b/lib/CWayland/CWayland.cc
index ecb87fc..57da46a 100644
--- a/lib/CWayland/CWayland.cc
+++ b/lib/CWayland/CWayland.cc
@@ -3,8 +3,10 @@
#include <array>
#include <vector>
#include <queue>
+#include <memory>
#include <unordered_map>
#include <chrono>
+#include <cassert>
#include <poll.h>
#include <fcntl.h>
#include <unistd.h>
@@ -623,6 +625,187 @@ lean_obj_res waylean_event_loop_quit(b_lean_obj_arg loop_obj)
// EventLoop.poll : (eventLoop : @& EventLoop M) → IO (Option M)
lean_obj_res waylean_event_loop_poll(b_lean_obj_arg loop_obj)
{
+ struct wl_interface x;
auto loop = static_cast<event_loop*>(lean_get_external_data(loop_obj));
return lean_io_result_mk_ok(loop->poll().release());
+}
+
+// -- Type Map
+
+namespace
+{
+ template<std::size_t Size = 4096>
+ class arena
+ {
+ struct region
+ {
+ std::array<std::byte, Size> buffer;
+ std::unique_ptr<region> prev;
+ std::size_t used{ 0 };
+ };
+
+ std::unique_ptr<region> curr;
+
+ public:
+ explicit arena()
+ {
+ curr = std::make_unique<region>();
+ }
+
+ template<typename T>
+ T* alloc_uninitialized(std::size_t count = 1)
+ {
+ std::size_t size = count * sizeof(T);
+ if (curr->used + size > Size)
+ {
+ // no more space -> allocate a new region
+ assert(size <= Size && "object too big for arena");
+ auto new_region = std::make_unique<region>();
+ new_region->prev = std::move(curr);
+ curr = std::move(new_region);
+ }
+
+ std::byte* res = &curr->buffer[curr->used];
+ curr->used += size;
+ return std::launder(reinterpret_cast<T*>(res));
+ }
+ };
+
+ struct interface
+ {
+ wl_interface desc;
+ bool initialized;
+ };
+
+ class type_map
+ {
+ arena<> a;
+ std::unordered_map<std::string_view, interface*> interfaces;
+
+ public:
+ bool contains_iface(std::string_view iface_name)
+ {
+ auto it = interfaces.find(iface_name);
+ return it != interfaces.end() && it->second->initialized;
+ }
+
+ interface* resolve_iface(std::string_view iface_name)
+ {
+ auto it = interfaces.find(iface_name);
+ if (it != interfaces.end()) { return it->second; }
+
+ char* name = copy_string(iface_name);
+ interface* iface = a.alloc_uninitialized<interface>();
+ iface->desc = wl_interface{ 0 };
+ iface->desc.name = name;
+ iface->initialized = false;
+
+ interfaces[name] = iface;
+ return iface;
+ }
+
+ void register_iface(b_lean_obj_arg iface_desc)
+ {
+ // structure Interface where
+ // name : String
+ // version : UInt32
+ // requests : Array Message
+ // events : Array Message
+
+ lean_object* iface_name = lean_ctor_get(iface_desc, 0);
+
+ interface* iface = resolve_iface(lean_string_cstr(iface_name));
+ if (iface->initialized) { return; }
+ iface->initialized = true;
+ wl_interface* desc = &iface->desc;
+
+ lean_object* iface_requests = lean_ctor_get(iface_desc, 1);
+ std::size_t request_count = lean_array_size(iface_requests);
+ wl_message* requests = a.alloc_uninitialized<wl_message>(request_count);
+ for (std::size_t i = 0; i < request_count; ++i)
+ {
+ initialize_message(&requests[i], lean_array_get_core(iface_requests, i));
+ }
+ desc->method_count = request_count;
+ desc->methods = requests;
+
+ lean_object* iface_events = lean_ctor_get(iface_desc, 2);
+ std::size_t event_count = lean_array_size(iface_events);
+ wl_message* events = a.alloc_uninitialized<wl_message>(event_count);
+ for (std::size_t i = 0; i < event_count; ++i)
+ {
+ initialize_message(&events[i], lean_array_get_core(iface_events, i));
+ }
+ desc->event_count = event_count;
+ desc->events = events;
+
+ desc->version = lean_ctor_get_uint32(iface_desc, 3 * sizeof(void*));
+ }
+
+ private:
+ char* copy_string(std::string_view str)
+ {
+ char* res = a.alloc_uninitialized<char>(str.length() + 1);
+ std::copy(str.begin(), str.end(), res);
+ res[str.length()] = 0;
+ return res;
+ }
+
+ void initialize_message(wl_message* msg, b_lean_obj_arg msg_desc)
+ {
+ // structure Message where
+ // name : String
+ // signature : String
+ // types : Array (Option String)
+
+ lean_object* msg_name = lean_ctor_get(msg_desc, 0);
+ msg->name = copy_string(lean_string_cstr(msg_name));
+
+ lean_object* msg_signature = lean_ctor_get(msg_desc, 1);
+ msg->signature = copy_string(lean_string_cstr(msg_signature));
+
+ lean_object* msg_types = lean_ctor_get(msg_desc, 2);
+ std::size_t type_count = lean_array_size(msg_types);
+ wl_interface const** types = a.alloc_uninitialized<wl_interface const*>(type_count);
+ for (std::size_t i = 0; i < type_count; ++i)
+ {
+ char const* type = option_cstr_or_null(lean_array_get_core(msg_types, i));
+ types[i] = type ? &resolve_iface(type)->desc : nullptr;
+ }
+ msg->types = types;
+ }
+ };
+
+ lean_external_class* waylean_type_map_class()
+ {
+ static lean_external_class* klass = lean_register_external_class(
+ [](void* ptr) { delete static_cast<type_map*>(ptr); },
+ [](void*, b_lean_obj_arg fn) { }
+ );
+ return klass;
+ }
+}
+
+// TypeMap.new : IO TypeMap
+lean_obj_res waylean_type_map_new(void)
+{
+ type_map* map = new type_map;
+ lean_object* waylean_map = lean_alloc_external(waylean_type_map_class(), map);
+ return lean_io_result_mk_ok(waylean_map);
+}
+
+// TypeMap.contains : (typeMap : @& TypeMap) → (ifaceName : @& String) → IO Bool
+lean_obj_res waylean_type_map_contains(b_lean_obj_arg map_obj, b_lean_obj_arg iface_name)
+{
+ auto map = static_cast<type_map*>(lean_get_external_data(map_obj));
+ auto res = map->contains_iface(lean_string_cstr(iface_name));
+ return lean_io_result_mk_ok(lean_box(res ? 1 : 0));
+}
+
+// TypeMap.register : (typeMap : @& TypeMap) → (ifaceDesc : @& Interface) → IO Unit
+lean_obj_res waylean_type_map_register(b_lean_obj_arg map_obj, b_lean_obj_arg iface_desc)
+{
+ auto map = static_cast<type_map*>(lean_get_external_data(map_obj));
+ map->register_iface(iface_desc);
+ return lean_io_result_mk_ok(lean_box(0));
} \ No newline at end of file