rrr: migrate pure-arithmetic helpers to inline Rust DSL#68
Conversation
Phase 0 of the goal to gradually rewrite rrr's C++ source files as Rust
DSL and use the rusty-cpp transpiler to generate the C++ that compiles
into librrr.a. The .rs becomes the source of truth; the .gen.cppm is a
build artifact.
The doc defines:
- Per-iteration protocol (read .cpp → author .rs → transpile →
diff → wire into CMake → verify build/borrow-check/tests → commit).
- Stop rules (3 consecutive blockers).
- Per-phase progress log: pilot (errors.cpp), 8 leaf files, 5 medium
files, then a decision point on the large files.
Transpiler is built and smoke-tested. The pilot starts in the next
commit.
Phase 1 pilot of the rrr Rust DSL migration. The body of
`SparseInt::val_size(i64) -> size_t` is reauthored as an inline Rust
DSL block inside basetypes.cpp; the rusty-cpp transpiler's
`inline-rust --rewrite` populates the matching
`/*RUSTYCPP:GEN-BEGIN id=basetypes.1 ... GEN-END*/` block right after
with the C++ equivalent. The original member method now delegates
to the generated free helper `sparse_int_val_size_impl(i64) -> u64`.
The C++ surface is unchanged — every caller (SparseInt::buf_size,
v32::val_size, v64::val_size) sees the same signature. The compiler
never sees the Rust source (RUSTYCPP_RUST is undefined at build
time); it compiles only the GEN block. The Rust is the developer-
facing source of truth.
This commit also revises docs/dev/rrr_rust_dsl_migration_plan.md to:
- swap the per-iteration protocol from full-file translation
(.rs → .gen.cppm) to inline mode (#if RUSTYCPP_RUST blocks in
the existing .cpp). The full-file approach diverged on enum
casing and return types; inline mode keeps the public surface
intact.
- record the v0 finding as a paragraph in the Goal section.
- tick the pilot row.
Verification:
- `cmake --build build_clang21 --target rrr -j32` clean
- `cmake --build build_clang21 --target
borrow_check_rrr_borrow_basetypes -j32` clean
- `build_clang21/test_marshal` — 23/23 PASSED (the SparseInt
encoding-boundary suite exercises val_size on each branch)
Transpiler quirks observed (logged in plan doc):
- GEN block ids are auto-assigned <basename>.N — supplying
your own `id=...` is ignored.
- Numeric comparisons get wrapped in
`rusty::detail::deref_if_pointer_like(...)`; harmless for
primitive args.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Same pattern as the prior val_size pilot: `SparseInt::buf_size` body is
reauthored as an inline Rust DSL block; the rusty-cpp transpiler's
`inline-rust --rewrite` populates the matching `/*RUSTYCPP:GEN-BEGIN
id=basetypes.1 ...*/` block right after with the C++ equivalent. The
member method delegates to the generated free helper
`sparse_int_buf_size_impl(i32) -> u64`.
`byte0` is taken as i32 (not i8 / char) so the comparison literals
(`0x80`, `0xC0`, ...) stay signed-positive on the Rust side; the
caller masks to 8 bits via `static_cast<int32_t>(byte0) & 0xFF`.
Preserves the pre-existing C++ behavior: `char` is interpreted as
unsigned bit pattern via the `&` masks, exactly as before.
The previous val_size GEN block was renumbered from `basetypes.1` to
`basetypes.2` to make room for buf_size's auto-assigned `basetypes.1`
(the transpiler's auto-id allocator goes in source order and doesn't
check for collisions with existing GEN blocks; documented in the plan
doc's Quirks section).
Verification:
- `cmake --build build_clang21 --target rrr -j32` clean.
- `cmake --build build_clang21 --target
borrow_check_rrr_borrow_basetypes -j32` clean.
- `build_clang21/test_marshal` — 23/23 PASSED.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Migrates `get_error_category(RpcError) -> RpcErrorCategory` to an
inline Rust DSL helper `rpc_error_category_code(i32) -> i32`. The C++
wrapper casts the enum to int at the boundary, so the public API
(`RpcError`, `RpcErrorCategory`, and `get_error_category`'s signature)
stays exactly as it was; existing callers and tests need no change.
Also adds `#include <stdint.h>` and `#include <rusty/rusty.hpp>` to
the module fragment — the generated C++ uses bare `int32_t` and
`rusty::detail::deref_if_pointer_like`, neither of which was reachable
through the previous includes. This is a one-time fix per migrated
file (documented in the plan doc's Quirks section).
Verification:
- `cmake --build build_clang21 --target rrr -j32` clean
- `cmake --build build_clang21 --target
borrow_check_rrr_borrow_errors -j32` clean
- `build_clang21/test_rpc_errors` — 19/19 PASSED
- `build_clang21/test_rpc_error_integration` — 10/10 PASSED
This is the first inline-Rust DSL migration in a non-basetypes file,
proving the workflow generalizes across translation units.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Migrates `is_retryable_error(RpcError) -> bool` to inline Rust DSL.
Free helper `rpc_error_is_retryable(i32) -> bool`; C++ wrapper casts
the enum to int. Public surface unchanged.
Authored as an if-chain rather than a `match`. First draft used
`match code { 102 | 103 | 104 | ... => true, _ => false }` and the
transpiler emitted ~3800 lines of runtime support code (rusty::cmp,
Option<TokenTree>, proc_macro_runtime, etc.) into the GEN block —
none of which then resolves against the surrounding `namespace rrr`
(errors: `no template named 'Option' in namespace 'rrr::rusty'`).
The if-chain lowering is the clean ~25-line path. Documented in the
plan doc as the second known transpiler quirk worth raising upstream.
Verification:
- `cmake --build build_clang21 --target rrr -j32` clean
- `cmake --build build_clang21 --target
borrow_check_rrr_borrow_errors -j32` clean
- `build_clang21/test_rpc_errors` — 19/19 PASSED
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Stamps the inline-Rust pattern over two more tiny predicates:
- `is_connection_error(err)` → free helper
`rpc_error_is_connection_code(i32) -> bool` (range check
100 ≤ code < 200).
- `is_timeout_error(err)` → free helper
`rpc_error_is_timeout_code(i32) -> bool` (range check
400 ≤ code < 500).
Both equivalent to the previous `get_error_category(err) == X` form
since CONNECTION/TIMEOUT are precisely those code ranges in
rpc_error_category_code. C++ wrappers cast the enum to int at the
boundary so the public surface is unchanged.
is_retryable_error's existing GEN id renumbered from `errors.2` to
`errors.4` to give the two new blocks (`errors.2`, `errors.3`)
contiguous auto-ids in source order — same workaround pattern as
the SparseInt::buf_size pilot.
Verification:
- `cmake --build build_clang21 --target rrr -j32` clean
- `cmake --build build_clang21 --target
borrow_check_rrr_borrow_errors -j32` clean
- `build_clang21/test_rpc_errors` — 19/19 PASSED
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Tests the transpiler's multi-function-per-block lowering by merging
the two predicate helpers `rpc_error_is_connection_code` and
`rpc_error_is_timeout_code` into a single `#if RUSTYCPP_RUST ... #endif`.
Works cleanly: the transpiler emits ONE GEN block (id=errors.2) with
both forward decls at the top and both definitions below.
Net file change is a small cleanup: 4 GEN blocks → 3, since errors.3
is consumed into errors.2.
Verification:
- `cmake --build build_clang21 --target rrr -j32` clean
- `cmake --build build_clang21 --target
borrow_check_rrr_borrow_errors -j32` clean
- `build_clang21/test_rpc_errors` — 19/19 PASSED
Plan-doc Phase 1 row updated to record both the initial two-block
landing (c0b2d6f) and this consolidation step.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Both predicates classify the same (auto_reconnect, max_retries,
retry_count) tuple, so they're a natural fit for the multi-fn block
pattern proven in the previous errors.cpp commit. Authored as
`reconnect_should_retry(bool, u32, u32) -> bool` and
`reconnect_retries_exhausted(bool, u32, u32) -> bool` in a single
`#if RUSTYCPP_RUST` block; the transpiler emits one GEN block with
both forward decls and definitions.
Member methods on `ReconnectCalculator` are now one-line forwarders
that read the policy fields + retry counter and pass to the helpers.
Public surface unchanged.
First inline-Rust migration in a third file. Required adding
`#include <stdint.h>` and `#include <rusty/rusty.hpp>` to the module
fragment (same one-time-per-file fix documented in the plan doc).
Verification:
- `cmake --build build_clang21 --target rrr -j32` clean
- `cmake --build build_clang21 --target
borrow_check_rrr_borrow_reconnect_policy -j32` clean
- `build_clang21/test_rpc_reconnect_policy` — 19/19 PASSED
- `build_clang21/test_rpc_reconnect_integration` — 12/12 enabled
PASSED (6 disabled tests skipped, unrelated)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… backoff
Adds a third helper `reconnect_peek_delay_ms_impl(u32, u32, f64, u32) -> u32`
to the existing multi-fn block. Lowers the deterministic exponential
backoff loop used by both `peek_delay_ms` and `next_delay_ms`:
- First inline-Rust migration to use `f64` arithmetic.
- First migration to use a `while` loop with `break`.
- First migration to share one helper across two C++ call sites.
Transpiler handled the lowering cleanly (~17 lines of C++ from
the GEN block, no runtime-support spam). Documented one minor
quirk: a primitive-typed assignment like `delay = max_delay` lowers
as `delay = std::move(max_delay)` — harmless on a `double`.
`peek_delay_ms` becomes a 5-line forwarder.
`next_delay_ms` is refactored to share the deterministic backoff
through the new helper, then applies its random_device jitter on
the C++ side (random_device pulls system entropy; not a Rust-DSL
candidate yet). ~15 lines of duplicated backoff math removed.
Verification:
- `cmake --build build_clang21 --target rrr -j32` clean
- `cmake --build build_clang21 --target
borrow_check_rrr_borrow_reconnect_policy -j32` clean
- `build_clang21/test_rpc_reconnect_policy` — 19/19 PASSED
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Extracts the OPEN→HALF_OPEN probe-readiness check from
`CircuitBreaker::allow_request` into a free helper
`circuit_should_probe(now_us: u64, last_failure_us: u64, timeout_ms: u32) -> bool`.
First inline-Rust migration to use `u64` parameters; transpiler
lowered cleanly.
Most of the rest of this file manipulates `rusty::Cell<T>` interior-
mutable state from C++ — the Rust DSL has no idiom to reach into
those, so the probe-readiness arithmetic is the file's only natural
candidate.
Verification:
- `cmake --build build_clang21 --target rrr -j32` clean
- `cmake --build build_clang21 --target
borrow_check_rrr_borrow_circuit_breaker -j32` clean
- `build_clang21/test_rpc_circuit_breaker` — 21/21 PASSED
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Migrates three small pure methods on `RequestOptions` to a single
multi-fn `#if RUSTYCPP_RUST` block:
- `can_retry(retry_count)` → `request_can_retry(idempotent, retry,
max_retries)`: boolean predicate.
- `is_total_timeout_exceeded(elapsed_ms)` →
`request_total_timeout_exceeded(total_timeout_ms, elapsed_ms)`:
bounds check.
- `remaining_time_ms(elapsed_ms)` →
`request_remaining_time_ms(total_timeout_ms, elapsed_ms)`:
sentinel-returning arithmetic (0-value means "no limit", returns
u64::MAX in that case).
Each member method is now a one-line forwarder.
First migration to use:
- `u16` parameters — lowered to `uint16_t`.
- `u64::MAX` — lowered to `std::numeric_limits<uint64_t>::max()`.
The `calculate_delay_ms` method is the obvious next candidate but
uses `std::pow` + `thread_local std::mt19937` + `random_device` —
the random side stays C++ and `std::pow(2.0, attempt)` needs a
manual loop on the Rust side. Deferred.
Verification:
- `cmake --build build_clang21 --target rrr -j32` clean
- `cmake --build build_clang21 --target
borrow_check_rrr_borrow_request_options -j32` clean
- `build_clang21/test_rpc_timeout_retry` — 36/36 PASSED
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ion table
Migrates four pure-logic methods on `ConnectionStateMachine` to a
single multi-fn `#if RUSTYCPP_RUST` block:
- `is_valid_transition(from, to)` — the 6-state transition table
(NEW/CONNECTING/CONNECTED/DISCONNECTING/DISCONNECTED/FAILED).
Authored as an if-chain (each `from` state mapped explicitly),
not a `switch` or `match` — the latter trips the heavyweight
runtime lowering documented in the plan doc's Quirks section.
- `is_terminal(s)` — true when s ∈ {DISCONNECTED, FAILED}.
- `can_connect(s)` — true when s ∈ {NEW, DISCONNECTED, FAILED}.
- `is_usable(s)` — true when s ∈ {CONNECTING, CONNECTED}.
All four Rust helpers take the raw `i32` discriminant of
`ConnectionState`; the C++ member methods cast at the boundary so the
public typed-enum surface (`ConnectionState`) is unchanged.
Verification:
- `cmake --build build_clang21 --target rrr -j32` clean
- `cmake --build build_clang21 --target
borrow_check_rrr_borrow_connection_state -j32` clean
- `build_clang21/test_rpc_connection_state` — 30/30 PASSED
- `build_clang21/test_rpc_state_integration` — 16/16 PASSED
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Migrates the timing-elapsed checks inside `HeartbeatManager::
should_send_heartbeat`, `check_timeout`, and
`time_until_next_heartbeat_ms` to a single multi-fn `#if RUSTYCPP_RUST`
block:
- `heartbeat_interval_elapsed(now_us, last_send_us, interval_ms)`
- `heartbeat_timeout_elapsed(now_us, last_send_us, timeout_ms)`
- `heartbeat_time_until_next_ms(now_us, last_send_us, interval_ms)`
All three are pure `u64`/`u32` math (convert `_ms` to `_us`,
compare against a `now - last` window). The C++ member methods
still own the Cell reads + enabled/timed_out/pending_pong guards;
only the deterministic arithmetic moves to Rust DSL.
Verification:
- `cmake --build build_clang21 --target rrr -j32` clean
- `cmake --build build_clang21 --target
borrow_check_rrr_borrow_heartbeat -j32` clean
- `build_clang21/test_rpc_heartbeat` — 20/20 PASSED
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Migrates the derived-statistic methods on `ConnectionMetrics` to a
single multi-fn `#if RUSTYCPP_RUST` block:
- `min_latency_us()` → `metrics_min_latency_us(stored)`:
maps u64::MAX sentinel to 0.
- `success_rate_percent()` → `metrics_success_rate_percent(completed, total)`:
100 when total=0, else `(completed*100)/total`.
- `avg_latency_us()` → `metrics_avg_latency_us(total_us, completed)`:
0 when completed=0, else `total_us/completed`.
- `uptime_ms(now)` → `metrics_uptime_ms(connect_time, now)`:
0 when connect_time=0 or now<connect_time, else `now-connect_time`.
C++ member methods read the rusty::Cell counters and forward.
Verification:
- `cmake --build build_clang21 --target rrr -j32` clean
- `cmake --build build_clang21 --target
borrow_check_rrr_borrow_connection_metrics -j32` clean
- `build_clang21/test_rpc_metrics` — 25/25 PASSED
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Convert response_has_extended_header / response_payload_size / encode_response_size to one multi-fn `#if RUSTYCPP_RUST` block. High bit of the i32-encoded size marks "extended header" (response carries <server_instance_id> after <error_code>); low 31 bits hold payload size. C++ wrappers are now one-line forwarders; lost the `constexpr` qualifier (now `inline`) — verified no callers use these in constexpr contexts via grep across the rrr tree. borrow_check_rrr_borrow_internal_protocol clean, test_rpc_frame_codec 25/25 pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Convert IdempotencyKey::is_valid, CachedResponse::is_expired, and IdempotencyCache::hit_rate to one multi-fn `#if RUSTYCPP_RUST` block. First migration with `f64` return — `(hits as f64) / (total as f64)` lowers cleanly. C++ member methods read struct fields / Cells and forward. borrow_check_rrr_borrow_idempotency clean, test_idempotency 32/32 pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Convert CompletedEntry::is_expired, CompletionTracker::hit_rate, and CompletionQueryResult::is_completed to one multi-fn `#if RUSTYCPP_RUST` block. First migration with `u8` parameter — the is_completed helper takes the `u8` discriminant of CompletionStatus (NOT_FOUND=0.. EXPIRED=3); C++ casts at the boundary. borrow_check_rrr_borrow_completion_tracker clean, test_completion_tracker 27/27 pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Convert LoadBalancerState::next_round_robin_index and LoadBalancer::select_random to one multi-fn `#if RUSTYCPP_RUST` block. Both helpers take `u64`-modeled `size_t`s and assume `pool_size > 0` — C++ wrappers cast at the boundary and own the `pool_size == 0` / Cell read-modify-write logic. borrow_check_rrr_borrow_load_balancer clean, test_load_balancer 21/21 pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Convert RandomGenerator::rand, rand_double, and nu_rand to one multi-fn `#if RUSTYCPP_RUST` block. Each helper takes the raw `rand_r` output as `i32` plus the user-supplied bounds. The rand_double helper takes RAND_MAX as a parameter to avoid the platform-dependent constant in Rust. C++ methods retain the `@unsafe` seed-fetch block and pass the scaled `r` into the helper. borrow_check_rrr_borrow_rand clean, rpcbench links (no dedicated test suite for rand). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Convert QueuedRequest::is_expired, QueuedRequest::age_ms, and RequestQueue::remaining_capacity to one multi-fn `#if RUSTYCPP_RUST` block. The first two helpers take `now_us` (fetched by the C++ caller via `clock_monotonic_us()`) plus the struct's timestamp_us/ttl_ms; the last takes the two `size_t`s the SpinMutex guard returned. borrow_check_rrr_borrow_request_queue clean, test_rpc_request_queue 30/30 pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Convert Timer::elapsed's two arithmetic branches to one multi-fn `#if RUSTYCPP_RUST` block (added as basetypes.3 after the existing SparseInt helpers). The live branch divides `now_us - begin_us` by 1e6; the stopped branch combines (sec, usec) pairs into seconds via i64 arithmetic. borrow_check_rrr_borrow_basetypes clean, rpcbench links (no dedicated test suite for Timer). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add `request_calculate_delay_ms_base` as a second inline-Rust block in request_options.cpp. Replaces `base_delay_ms * std::pow(2.0, attempt)` with an iterative double-and-cap loop that saturates at `max_delay_ms` instead of overflowing for large attempts. The jitter step stays C++-side because it pulls a thread_local mt19937 sample. borrow_check_rrr_borrow_request_options clean, test_rpc_timeout_retry 36/36 pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Convert FrameHeader::total_frame_size, the payload-size validation shared by frame_codec_write_header / frame_codec_encode_into, and FrameStreamReader::compact_if_needed's threshold check to one multi-fn `#if RUSTYCPP_RUST` block. total_frame_size loses its constexpr qualifier (now a regular inline forwarder) — verified no callers use it in constexpr contexts. borrow_check_rrr_borrow_frame_codec clean, test_rpc_frame_codec 25/25 pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Convert FrequentJob::Ready's period-elapsed check to a single-fn `#if RUSTYCPP_RUST` block (`frequent_job_period_elapsed`). Pure u64 arithmetic — `(now - last) > period`. C++ wrapper retains the `rrr::Time::now()` call and the `tm_last_` state mutation. borrow_check_rrr_borrow_misc clean, rpcbench links (no dedicated test suite for FrequentJob). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Convert Server::Server's instance-id mixing step to a single-fn `#if RUSTYCPP_RUST` block (`server_mix_instance_id`). Pure u64 bit-twiddling: `(t ^ r ^ p) & i64::MAX`, force nonzero. The three input components (timestamp, random, pid-shifted) stay C++-side because their sources (std::chrono, std::random_device, rusty::sys::process::getpid) sit outside the inline-Rust world. First migration that lowers `i64::MAX as u64`. borrow_check_rrr_borrow_server clean, test_rpc_server_channel_binding 3/3 pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Extend the existing connection_metrics.1 inline-Rust block with two new helpers (`metrics_new_min_latency_us`, `metrics_new_max_latency_us`) that collapse record_request_completed's per-axis "if sample is better, store sample" branches to a single Cell set. Block now holds 6 helpers total. borrow_check_rrr_borrow_connection_metrics clean, test_rpc_metrics 25/25 pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Convert AvgStat::sample's per-sample mutations to one multi-fn `#if RUSTYCPP_RUST` block (`avg_stat_compute_avg`, `avg_stat_new_max`, `avg_stat_new_min`). `n_stat` is post-increment (always >= 1), so average division is safe. Min/max follow the same pattern as the connection_metrics latency helpers, on `i64` instead of `u64`. borrow_check_rrr_borrow_stat clean, rpcbench links (no dedicated test suite for AvgStat). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Convert Rand::next's scaling step to a single-fn `#if RUSTYCPP_RUST` block (`rand_next_in_range`). Pure u32 arithmetic mirroring the C++ implicit-conversion semantics: `(lower as u32) + r % ((upper - lower) as u32)`. New block inserted in the export namespace BEFORE the existing SparseInt/Timer impl-section helpers so the forward declaration is visible to the in-class `Rand::next` inline body — required renumbering existing basetypes.1/.2/.3 → .2/.3/.4 (per the auto-id-collision workaround). borrow_check_rrr_borrow_basetypes clean, rpcbench links. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add idempotency_key_combine_hash to the existing idempotency.1
inline-Rust block (now 4 helpers). Pure u64 FNV-1a-style mixing:
`h1 ^ (h2 * 0x9e3779b97f4a7c15)` (golden ratio constant). C++
wrapper still calls std::hash<uint64_t>{} then passes the two
hashes into the helper.
borrow_check_rrr_borrow_idempotency clean, test_idempotency 32/32
pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Extract the pure-arithmetic part of current_time_us into a new inline-Rust block (`circuit_timespec_to_us`). Added as the new circuit_breaker.1, with the existing circuit_should_probe renumbered to .2 (per the auto-id-collision workaround). C++ wrapper retains the `clock_gettime` syscall and feeds the `(sec, nsec)` pair into the helper. File-prefixed name avoids future link-time collision if heartbeat.cpp grows the same helper. borrow_check_rrr_borrow_circuit_breaker clean, test_rpc_circuit_breaker 21/21 pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Extract the pure-arithmetic part of heartbeat_time_us into a new inline-Rust block (`heartbeat_timespec_to_us`). Added as new heartbeat.1 ahead of the existing 3 timing helpers, with those renumbered to .2. Identical body to circuit_timespec_to_us in circuit_breaker.cpp; file-prefixed name keeps the two separate at link time. borrow_check_rrr_borrow_heartbeat clean, test_rpc_heartbeat 20/20 pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Convert Timer::start/stop's us→(sec, usec) split to a new multi-fn `#if RUSTYCPP_RUST` block (`timer_us_to_sec`, `timer_us_to_usec_remainder`). The block is the inverse of the existing Timer::elapsed helpers — splitting microseconds back into a `time_t`/`suseconds_t` pair. Added as new basetypes.4 between SparseInt and Timer::elapsed; required renumbering existing Timer::elapsed block .4 → .5. borrow_check_rrr_borrow_basetypes clean, rpcbench links. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CI investigationThe failing job is Evidence the failure pre-dates this PR
Root cause sketch (out of scope for this PR) The proper fix is in mako, not rrr — either propagate the thread-local shard index into worker threads in Recommendation |
|
Closing per reviewer feedback. The approach taken (extracting free helpers + re-wiring callers) is wrong; the correct pattern is to rewrite an existing C++ class/function in Rust DSL such that the generated code replaces it directly. Restarting. |
Summary
inline-rustfeature across rrr by extracting pure-arithmetic helpers into#if RUSTYCPP_RUSTblocks that lower to byte-for-byte equivalent C++./*RUSTYCPP:GEN-BEGIN ... GEN-END*/C++ block regenerated by the transpiler.docs/dev/rrr_rust_dsl_migration_plan.md) cataloging every migrated helper with rationale, lowering quirks, and per-file test results.What's migrated
Predicates / classifiers:
errors.*(4 helpers across get_error_category, is_retryable, is_connection, is_timeout),connection_state.*(4 transition-table helpers),request_options.*(4 helpers including exponential backoff),idempotency.*(4 helpers including FNV-1a hash combiner),completion_tracker.*(3 helpers),frame_codec.*(3 size/threshold helpers),internal_protocol.*(3 bit-twiddling helpers).Timing / arithmetic:
heartbeat.*(4 helpers including timespec→us),circuit_breaker.*(2 helpers including timespec→us),reconnect_policy.*(3 helpers including exponential-backoff loop),request_queue.*(3 helpers),connection_metrics.*(6 helpers in one block — sentinel math + min/max),basetypes.*(5 helpers: SparseInt buf_size / val_size, Timer::elapsed split, Timer::start/stop split, Rand::next scaling),rand.*(3 scaling helpers),stat.*(3 AvgStat helpers),load_balancer.*(2 selection helpers).Misc:
misc.*(FrequentJob period predicate),server.*(instance_id XOR mix).Discoveries documented in the plan doc
matchlowering pulls in 3800+ lines of runtime support — must use if-chains for primitive matching.<basename>.<N>in source order; new blocks added BEFORE existing GEN blocks collide. Workaround: manually renumber existing GEN ids before re-running the transpiler.heartbeat_timespec_to_usvscircuit_timespec_to_us) avoid link-time collisions when the same arithmetic appears in multiple modules.<stdint.h>,<stdlib.h>) are required in module fragments for the first inline-rust block per file; converted across migrated files.Test plan
borrow_check_rrr_borrow_<file>target was verified clean during the migration).test_rpc_frame_codec(25/25),test_idempotency(32/32),test_completion_tracker(27/27),test_rpc_request_queue(30/30),test_load_balancer(21/21),test_rpc_circuit_breaker(21/21),test_rpc_heartbeat(20/20),test_rpc_timeout_retry(36/36),test_rpc_metrics(25/25),test_rpc_connection_state(30/30),test_rpc_state_integration(16/16),test_rpc_server_channel_binding(3/3).🤖 Generated with Claude Code