Skip to content

Commit 1488067

Browse files
Merge sedsprintf_rs upstream main
2 parents c3a21cd + 22dc5d6 commit 1488067

File tree

9 files changed

+1135
-9
lines changed

9 files changed

+1135
-9
lines changed

sedsprintf_rs/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "sedsprintf_rs_2026"
3-
version = "1.1.1"
3+
version = "1.2.0"
44
edition = "2024"
55
build = "build.rs"
66
authors = ["Rylan Meilutis <rylan@rylanswebsite.com>"]

sedsprintf_rs/header_templates/sedsprintf.h.txt

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ typedef uint64_t (* SedsNowMsFn)(void * user);
2222

2323
typedef struct SedsRouter SedsRouter;
2424

25+
typedef struct SedsRelay SedsRelay;
26+
27+
2528
typedef struct SedsPacketView
2629
{
2730
uint32_t ty;
@@ -259,6 +262,110 @@ SedsResult seds_owned_header_view(const SedsOwnedHeader * h, SedsPacketView * ou
259262

260263
void seds_owned_header_free(SedsOwnedHeader * h);
261264

265+
/* ==============================
266+
Relay lifecycle
267+
============================== */
268+
269+
/**
270+
* @brief Create a new relay instance.
271+
*
272+
* @param now_ms_cb Optional monotonic clock callback (may be NULL).
273+
* @param user Opaque user pointer passed back into @p now_ms_cb.
274+
*
275+
* @return Non-NULL relay handle on success; NULL on failure.
276+
*/
277+
SedsRelay * seds_relay_new(SedsNowMsFn now_ms_cb, void * user);
278+
279+
/**
280+
* @brief Destroy a relay previously returned by seds_relay_new().
281+
*/
282+
void seds_relay_free(SedsRelay * r);
283+
284+
/**
285+
* @brief Add a new side/network to the relay.
286+
*
287+
* The side is identified by a small integer ID (0,1,2,...) returned from
288+
* this function. The same SedsTransmitFn type is used as for SedsRouter.
289+
*
290+
* @param r Relay handle.
291+
* @param name Optional UTF-8 name (may be NULL).
292+
* @param name_len Length of @p name in bytes (0 if unused).
293+
* @param tx TX callback for this side (must not be NULL).
294+
* @param tx_user Opaque user pointer passed to @p tx.
295+
*
296+
* @return On success: non-negative side ID.
297+
* On error: negative SedsResult error code.
298+
*/
299+
int32_t seds_relay_add_side(SedsRelay * r,
300+
const char * name,
301+
size_t name_len,
302+
SedsTransmitFn tx,
303+
void * tx_user);
304+
305+
/**
306+
* @brief Feed serialized bytes that arrived on a given side into the relay.
307+
*
308+
* This corresponds to “RX from network into relay”. The relay will fan-out
309+
* the packet to all other sides when you later call the process_* functions.
310+
*
311+
* @param r Relay handle.
312+
* @param side_id Side ID returned by seds_relay_add_side().
313+
* @param bytes Serialized packet bytes.
314+
* @param len Length of @p bytes.
315+
*
316+
* @return SEDS_OK on success or a negative SedsResult on error.
317+
*/
318+
SedsResult seds_relay_rx_serialized_from_side(SedsRelay * r,
319+
uint32_t side_id,
320+
const uint8_t * bytes,
321+
size_t len);
322+
323+
/* --- Relay queue processing (matching router style) --- */
324+
325+
/**
326+
* @brief Process all pending RX in the relay RX queue (expand into TX).
327+
*/
328+
SedsResult seds_relay_process_rx_queue(SedsRelay * r);
329+
330+
/**
331+
* @brief Process all pending TX in the relay TX queue (invoke side TX callbacks).
332+
*/
333+
SedsResult seds_relay_process_tx_queue(SedsRelay * r);
334+
335+
/**
336+
* @brief Process both RX and TX queues until they are empty.
337+
*/
338+
SedsResult seds_relay_process_all_queues(SedsRelay * r);
339+
340+
/**
341+
* @brief Clear both RX and TX queues without processing.
342+
*/
343+
SedsResult seds_relay_clear_queues(SedsRelay * r);
344+
345+
/* --- Relay queue processing with time budget (ms) --- */
346+
347+
/**
348+
* @brief Process RX queue until timeout (ms) or completion.
349+
*
350+
* If @p timeout_ms is 0, drains the queue fully.
351+
*/
352+
SedsResult seds_relay_process_rx_queue_with_timeout(SedsRelay * r, uint32_t timeout_ms);
353+
354+
/**
355+
* @brief Process TX queue until timeout (ms) or completion.
356+
*
357+
* If @p timeout_ms is 0, drains the queue fully.
358+
*/
359+
SedsResult seds_relay_process_tx_queue_with_timeout(SedsRelay * r, uint32_t timeout_ms);
360+
361+
/**
362+
* @brief Process RX and TX queues until timeout (ms) or completion.
363+
*
364+
* If @p timeout_ms is 0, drains both queues fully.
365+
*/
366+
SedsResult seds_relay_process_all_queues_with_timeout(SedsRelay * r, uint32_t timeout_ms);
367+
368+
262369
#ifdef __cplusplus
263370
} /* extern "C" */
264371
#endif

sedsprintf_rs/header_templates/sedsprintf_rs.pyi.txt

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ PacketHandler = Callable[["Packet"], None]
4242
SerializedHandler = Callable[[bytes], None]
4343
"""Endpoint handler invoked with raw serialized packet bytes."""
4444

45+
SideId = int
46+
"""Logical relay side index (e.g. CAN, UART, RADIO)."""
4547

4648
# ==============================
4749
# Packet object (immutable view of a telemetry packet)
@@ -181,6 +183,127 @@ class Router:
181183
def process_all_queues_with_timeout(self, timeout_ms: int) -> None: ...
182184

183185

186+
# ==============================
187+
# Relay (fan-out of serialized packets)
188+
# ==============================
189+
190+
class Relay:
191+
"""
192+
Serialized-packet relay.
193+
194+
The Relay:
195+
- fans out serialized telemetry packets from one side to all others
196+
- has RX and TX queues (same pattern as Router)
197+
- supports time-budgeted queue processing
198+
- uses the same monotonic clock callback style as Router
199+
"""
200+
201+
def __init__(self, now_ms: Optional[NowMsCallback] = ...) -> None:
202+
"""
203+
Create a new Relay.
204+
205+
Parameters
206+
----------
207+
now_ms:
208+
Optional zero-arg callback returning an integer timestamp in ms.
209+
If None, timeouts are based on a default clock that returns 0.
210+
"""
211+
...
212+
213+
def add_side(self, name: str, tx: TxCallback) -> SideId:
214+
"""
215+
Add a new relay side (e.g. 'CAN', 'UART', 'RADIO').
216+
217+
Parameters
218+
----------
219+
name:
220+
Human-readable name for this side (used for debugging).
221+
tx:
222+
Transmit callback. Called as ``tx(bytes)`` when the relay
223+
wants to send data on this side.
224+
225+
Returns
226+
-------
227+
SideId
228+
Integer side id to use with ``rx_serialized_from_side``.
229+
"""
230+
...
231+
232+
def rx_serialized_from_side(
233+
self,
234+
side_id: SideId,
235+
data: Buffer | bytes | bytearray | memoryview,
236+
) -> None:
237+
"""
238+
Enqueue serialized bytes that arrived on a given side into the relay RX queue.
239+
240+
Parameters
241+
----------
242+
side_id:
243+
Side id previously returned by :meth:`add_side`.
244+
data:
245+
Serialized packet bytes.
246+
"""
247+
...
248+
249+
# Queue clearing
250+
251+
def clear_queues(self) -> None:
252+
"""Clear both RX and TX queues."""
253+
...
254+
255+
def clear_rx_queue(self) -> None:
256+
"""Clear only the RX queue."""
257+
...
258+
259+
def clear_tx_queue(self) -> None:
260+
"""Clear only the TX queue."""
261+
...
262+
263+
# Queue processing (no timeout)
264+
265+
def process_rx_queue(self) -> None:
266+
"""Drain the RX queue fully, expanding each item into TX items."""
267+
...
268+
269+
def process_tx_queue(self) -> None:
270+
"""Drain the TX queue fully, invoking per-side TX callbacks."""
271+
...
272+
273+
def process_all_queues(self) -> None:
274+
"""
275+
Process RX then TX queues fully (one pass), until both queues are empty.
276+
"""
277+
...
278+
279+
# Time-budgeted queue processing
280+
281+
def process_rx_queue_with_timeout(self, timeout_ms: int) -> None:
282+
"""
283+
Process the RX queue with a time budget in milliseconds.
284+
285+
Stops when the queue is empty or the timeout elapses.
286+
"""
287+
...
288+
289+
def process_tx_queue_with_timeout(self, timeout_ms: int) -> None:
290+
"""
291+
Process the TX queue with a time budget in milliseconds.
292+
293+
Stops when the queue is empty or the timeout elapses.
294+
"""
295+
...
296+
297+
def process_all_queues_with_timeout(self, timeout_ms: int) -> None:
298+
"""
299+
Process RX and TX queues interleaved with a time budget in ms.
300+
301+
If ``timeout_ms == 0``, drains fully (no time limit), matching the Rust
302+
implementation semantics.
303+
"""
304+
...
305+
306+
184307
# ==============================
185308
# Top-level helpers
186309
# ==============================

sedsprintf_rs/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "maturin"
44

55
[project]
66
name = "sedsprintf_rs_2026"
7-
version = "1.1.1"
7+
version = "1.2.0"
88
description = "Rust telemetry and serialization library"
99
authors = [{ name = "Rylan Meilutis", email = "rylan.meilutis@gmail.com" }]
1010
readme = "README.md"

0 commit comments

Comments
 (0)