From 1502a4219e94ef94e7f8582f5d6faa4a6df43e0f Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Sun, 25 Oct 2026 21:25:57 -0700 Subject: [PATCH 1/2] chore(quest): claim quest/m1/ffi-export.md Quest-Claim: ee13fd7b38456bde From 7949d269db733809eb7bdbf002fa87faa00f7a5e Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Sun, 25 Oct 2026 21:35:48 -0700 Subject: [PATCH 2/2] feat(ffi): export moq-net's origin roots and request paths Bump the moq pin to moq-dev/moq@88448d9, past moq-dev/moq#6808, so origin root(), absolute(), and Request::path() return PathOwned and export. moq.c drives root and absolute, and takes create_broadcast's new Publication. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_0115AT2ue6x9cT5e5J9SZtCn --- ffi/moq/ffi.toml | 22 +++++----------------- ffi/moq/moq.c | 22 ++++++++++++++++++---- quest/m1/ffi-export.md | 13 ++++++------- ts/justfile | 2 +- 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/ffi/moq/ffi.toml b/ffi/moq/ffi.toml index d8d21d830..70e4a0cbb 100644 --- a/ffi/moq/ffi.toml +++ b/ffi/moq/ffi.toml @@ -7,9 +7,9 @@ exclude = [ "AsPath", "Client::connect", "Client::with_publisher", + "Client::with_url", "Consume", "Driver::poll", - "Epoch::time", "Error::from_transport", "Hops::as_slice", "Hops::iter", @@ -17,7 +17,6 @@ exclude = [ "InvalidPattern", "Path::borrow", "Path::new", - "Path::next_part", "Path::parts", "Path::strip_prefix", "Pattern", @@ -30,20 +29,15 @@ exclude = [ "Timestamp::as_millis", "Timestamp::as_nanos", "Timestamp::as_scale", - "Version::names", "Versions::alpns", "Versions::iter", "announce::Announce::captures", - "announce::Consumer::absolute", - "announce::Consumer::root", + "announce::Consumer::poll_synced", "auth::Grant::expires", "auth::Grant::publish", "auth::Grant::subscribe", - "broadcast::Finish::poll_closed", - "broadcast::Lister::poll_unused", - "broadcast::Lister::poll_used", "bytes", - "cache::Pool::gc", + "cache::Pool::poll", "frame::Buffer", "frame::Frame::arrived", "frame::Producer::group", @@ -52,27 +46,22 @@ exclude = [ "group::Consumer::read_frames", "group::Producer::write_frames", "kio", - "origin::Consumer::absolute", "origin::Consumer::allowed", - "origin::Consumer::root", "origin::Consumer::scope", "origin::Driver::poll", - "origin::Producer::absolute", "origin::Producer::allowed", - "origin::Producer::root", "origin::Producer::scope", - "origin::Request::path", "origin::Requesting::poll_ok", "path::Relative::borrow", "path::Relative::new", "path::Segment", "path::Specificity", + "server::Handshake::with_deadline", "server::Handshake::with_publisher", "stats::Config::exclude", "stats::Config::with_exclude", "stats::Failure::ALL", - "stats::Refusal::ALL", - "stats::Registry::exclude", + "stats::RefusalKind::ALL", "stats::Report::sessions", "stats::Report::traffic", "stats::Snapshot::control", @@ -80,7 +69,6 @@ exclude = [ "stats::Snapshot::traffic", "time::Driver", "time::Instant", - "time::now", "time::run", "track::Querying::poll_ok", "track::Subscribing::poll_ok", diff --git a/ffi/moq/moq.c b/ffi/moq/moq.c index 618c0ed36..329306dd3 100644 --- a/ffi/moq/moq.c +++ b/ffi/moq/moq.c @@ -121,16 +121,30 @@ int main(void) { moq_broadcast_producer_free(broadcast); /* An origin and the driver that runs it, a tuple returned through two out pointers. - * A broadcast it creates is stamped with its path, which its info lends as a new - * handle to a clone. */ + * Its root, which it lends, is returned as a new handle to a clone. */ moq_origin_config *config = moq_origin_config_default(); moq_origin_producer *origin = NULL; moq_origin_driver *driver = NULL; moq_origin_producer_new(config, &origin, &driver); moq_origin_config_free(config); CHECK(origin != NULL && driver != NULL); - moq_broadcast_producer *created = NULL; - CHECK(moq_origin_producer_create_broadcast(origin, str("room/alice"), &created, &err)); + moq_path *root = moq_origin_producer_root(origin); + CHECK(is(moq_path_as_str(root), "")); + moq_path_free(root); + moq_path *absolute = moq_origin_producer_absolute(origin, str("room/alice")); + CHECK(is(moq_path_as_str(absolute), "room/alice")); + moq_path_free(absolute); + moq_origin_consumer *reader = moq_origin_producer_consume(origin); + absolute = moq_origin_consumer_absolute(reader, str("room/bob")); + CHECK(is(moq_path_as_str(absolute), "room/bob")); + moq_path_free(absolute); + moq_origin_consumer_free(reader); + + /* A broadcast the origin creates is stamped with its path, which its info lends. */ + moq_origin_publication *publication = NULL; + CHECK(moq_origin_producer_create_broadcast(origin, str("room/alice"), &publication, &err)); + moq_broadcast_producer *created = moq_origin_publication_broadcast(publication); + moq_origin_publication_free(publication); moq_broadcast_info *stamped = moq_broadcast_producer_info(created); moq_path *path = moq_broadcast_info_path(stamped); CHECK(is(moq_path_as_str(path), "room/alice")); diff --git a/quest/m1/ffi-export.md b/quest/m1/ffi-export.md index 08925a939..bd6918e84 100644 --- a/quest/m1/ffi-export.md +++ b/quest/m1/ffi-export.md @@ -15,16 +15,15 @@ Decided with the maintainer on 2026-10-25, from the spike the fork's paused feature quests into it. Split into quests as work starts, ranked by what the census refuses and what moq waits on: -- **Paths borrowed from their handle**: moq-net's `root`, `absolute`, and - `origin::Request::path` return a `Path<'_>` that borrows `&self`, so the census refuses them. - [moq-dev/moq#6808](https://github.com/moq-dev/moq/pull/6808) returns the `PathOwned` they - already hold or build. Once it lands, bump the moq pin and drop their seven entries from - [the exclude list](/ffi/moq/ffi.toml). -- **Several crates**: moq-native's sessions and the media crates hold moq-ffi's remaining API. +- **Paths without a lifetime**: [moq-dev/moq#6843](https://github.com/moq-dev/moq/pull/6843) + makes `Path` owned. Once it lands, bump the moq pin: the census then exports `Path::new`, + `strip_prefix`, and `Relative::new`, and drops `AsPath` and the `borrow` methods from + [the exclude list](/ffi/moq/ffi.toml), refusing only `Path::from_static`'s `'static` borrow. +- **Several crates**: moq-tokio's sessions and the media crates hold moq-ffi's remaining API. Export each with its own census, naming another export's types across crates, as moq-pattern's re-exports already need. - **Driving**: sessions and origins run a `Driver` polled with a time and a `kio::Waiter`. - Decide between exporting that poll, a generated thread that drives it, or moq-native's + Decide between exporting that poll, a generated thread that drives it, or moq-tokio's runtime helpers. - **A contract symbol** per build, checked when bindings load, so a header and a library from different builds refuse to mix. It replaces the fork's namespaced contract and per-method diff --git a/ts/justfile b/ts/justfile index d204fa697..38164a174 100644 --- a/ts/justfile +++ b/ts/justfile @@ -9,7 +9,7 @@ set shell := ["bash", "-euo", "pipefail", "-c"] export PATH := if env("RUST2_TS_TOOLCHAIN", "") == "" { env("PATH") } else { env("RUST2_TS_TOOLCHAIN") / "bin:" + env("PATH") } # The moq revision `moq` translates by default. -moq_rev := "2f146e8324ea867d1e5988d8f4ea62da2390251d" +moq_rev := "88448d9c66ddf4b202eb873edbfe0ef859835a21" default: @just --list