Preview of the proposed up-rust native-frame-model branch (up-rust b6b99c6d, up-spec f0e9b17) — not released documentation. branch · write-up

up_rust/
lib.rs

1/********************************************************************************
2 * Copyright (c) 2023 Contributors to the Eclipse Foundation
3 *
4 * See the NOTICE file(s) distributed with this work for additional
5 * information regarding copyright ownership.
6 *
7 * This program and the accompanying materials are made available under the
8 * terms of the Apache License Version 2.0 which is available at
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * SPDX-License-Identifier: Apache-2.0
12 ********************************************************************************/
13
14/*!
15up-rust is the Rust language library for [Eclipse uProtocol™](https://github.com/eclipse-uprotocol/up-spec/blob/v1.6.0-alpha.7/README.adoc) —
16a protocol that lets software components (in vehicles and beyond) publish
17data, subscribe to it, and call each other's services over whatever
18messaging technology a deployment happens to use: MQTT, Zenoh, DDS,
19shared memory, and more.
20
21The idea in one sentence: **you write against one small messaging API, and
22the technology underneath stays swappable.**
23
24## Your first message
25
26```rust,no_run
27use up_rust::{UMessageBuilder, UPayloadFormat, UTransport, UUri};
28
29async fn publish_engine_temp(transport: &dyn UTransport) -> Result<(), Box<dyn std::error::Error>> {
30    // Every message has a source address: authority / entity / version / resource.
31    let topic = UUri::try_from_parts("my-vehicle", 0x1_0001, 1, 0x8001)?;
32
33    let message = UMessageBuilder::publish(topic)
34        .build_with_payload("92.5", UPayloadFormat::Text)?;
35
36    transport.send(message).await?;
37    Ok(())
38}
39```
40
41That is the whole application-side model: build a [`UMessage`], hand it to
42a [`UTransport`] someone has configured, done. Receiving is the mirror
43image — register a [`UListener`] for the addresses you care about.
44
45## Which reader are you?
46
47| You want to… | Start at | Cargo features |
48| --- | --- | --- |
49| **Write an application** — publish, subscribe, or call/serve RPC | The role traits in [`communication`]: `Publisher`, `Subscriber`, `Notifier`, `RpcClient`, `RpcServer` — ready-made on top of any transport | `communication` |
50| **Connect a messaging technology** — make uProtocol run over your broker/bus | [`UTransport`] (start here), then the [`guide`]'s transport chapter for the richer frame-based options | `transport-implementer-api` |
51| **Add a payload encoding** — carry a new serialization format efficiently | The [`guide`]'s wire chapter and [`wire_implementer_api`] | `wire-implementer-api` |
52| **Move large payloads without copies** — camera frames, LiDAR scans, big tables | The typed path in the [transport chapter](crate::guide::applications::transport) (apps) or the [zero-copy tutorial](crate::guide::transports::zero_copy) (transports) | `zero-copy-transport` (+ your side's feature above) |
53
54The [`guide`] walks each path end to end with code.
55
56## Five words you'll meet everywhere
57
58* **uEntity** — any software component that talks uProtocol (an app, a
59  service, a sensor feed).
60* **Transport Layer ("up-L1")** — the layer that physically moves message
61  bytes; a *transport* is one implementation of it (Zenoh, MQTT, DDS, …).
62* **Communication Layer ("up-L2")** — the friendly role API
63  (publish/subscribe/RPC) built on top of any transport.
64* **Wire format** — how a payload is encoded into bytes (protobuf, CDR,
65  Arrow, …). Wires and transports are independent: any wire can ride any
66  capable transport.
67* **Zero-copy loan** — for large payloads, a transport can *lend* you its
68  own transmit buffer so you write data exactly once, directly where it
69  will be sent from. The receive side hands payloads out the same way, as
70  read-only *leases*.
71
72## Module map
73
74* [`communication`] — the up-L2 roles most applications use.
75* [`umessage`](UMessage), [`uri`](UUri), [`uattributes`](UAttributes) — the
76  core message model.
77* [`utransport`](UTransport) — the up-L1 contract transports implement.
78* [`wire`] and [`payload`] — wire identities and payload codecs.
79* [`frame`] — the validated frame model advanced transports exchange.
80* [`guide`] — tutorials for every audience above.
81
82## Features
83
84No feature is enabled by default; enable what your role needs. Each
85feature below silently enables everything it requires. Constrained
86publish-only builds need **no feature at all**: use the Transport Layer
87directly — it's the first example above, and it carries no protobuf and
88no tokio.
89
90*/
91#![cfg_attr(feature = "document-features", doc = document_features::document_features!())]
92#![doc = "## References"]
93#![doc = ""]
94#![doc = "* [uProtocol Specification](https://github.com/eclipse-uprotocol/up-spec/tree/v1.6.0-alpha.7)"]
95
96// The stable-payload derives expand absolute ::up_rust paths; alias the
97// crate to its external name so they resolve in-crate too.
98extern crate self as up_rust;
99
100#[cfg(feature = "cloudevents")]
101mod cloudevents;
102#[cfg(feature = "cloudevents")]
103pub use cloudevents::{CloudEvent, CONTENT_TYPE_CLOUDEVENTS_PROTOBUF};
104
105// [impl->dsn~communication-layer-api-namespace~1]
106#[cfg(feature = "communication-api")]
107pub mod communication;
108
109#[cfg(any(feature = "udiscovery", feature = "usubscription"))]
110pub mod core;
111
112#[cfg(feature = "util")]
113pub mod local_transport;
114#[cfg(feature = "util")]
115pub use local_transport::LocalTransport;
116
117#[cfg(feature = "symphony")]
118pub mod symphony;
119
120mod uattributes;
121pub use uattributes::{
122    NotificationValidator, PublishValidator, RequestValidator, ResponseValidator, UAttributes,
123    UAttributesError, UAttributesValidator, UAttributesValidators, UMessageType, UPayloadFormat,
124    UPriority,
125};
126
127mod umessage;
128pub use umessage::{
129    BuilderState, NotificationBuilderState, PublishBuilderState, RequestBuilderState,
130    ResponseBuilderState, UMessage, UMessageBuilder, UMessageError,
131};
132
133mod uri;
134pub use uri::{ExactUUri, UUri, UUriError};
135
136mod ustatus;
137pub use ustatus::{UAny, UCode, UStatus};
138
139mod utransport;
140pub use utransport::{
141    verify_filter_criteria, ComparableListener, LocalUriProvider, StaticUriProvider, UListener,
142    UTransport,
143};
144#[cfg(feature = "test-util")]
145pub use utransport::{MockLocalUriProvider, MockTransport, MockUListener};
146
147mod uuid;
148pub use uuid::UUID;
149
150#[cfg(feature = "up-core-api")]
151// protoc-generated types, see build.rs
152pub(crate) mod up_core_api {
153    include!(concat!(env!("OUT_DIR"), "/uprotocol/mod.rs"));
154}
155
156#[cfg(feature = "protobuf-support")]
157mod protobuf_mappable;
158#[cfg(feature = "protobuf-support")]
159pub use protobuf_mappable::ProtobufMappable;
160
161mod serialization_error;
162pub use serialization_error::SerializationError;
163
164// ---- native frame model ----
165
166mod validation_state;
167pub use validation_state::{Unvalidated, Validated};
168
169/// The native frame data model: metadata, canonical field-block codec, and
170/// the read-side frame view contract.
171pub mod frame;
172pub use frame::metadata::{
173    FrameMessageKind, FramePriority, PayloadEncoding, UFrameMetadata, UFrameMetadataError,
174};
175pub use frame::{validate_frame_view_for_transport, UFrameView};
176
177/// Payload codec contracts shared by the frame families.
178pub mod payload;
179pub use payload::UWireError;
180
181// ---- owned-frame transport family ----
182
183#[cfg(feature = "owned-frame-transport")]
184pub use frame::envelope::{UFrameWireError, UFrameWireFormat};
185
186#[cfg(feature = "owned-frame-transport")]
187mod owned_frame;
188#[cfg(all(feature = "owned-frame-transport", any(test, feature = "test-util")))]
189pub use owned_frame::InMemoryOwnedTransport;
190#[cfg(feature = "owned-frame-transport")]
191pub use owned_frame::UOwnedFrame;
192
193#[cfg(feature = "owned-frame-transport")]
194pub use utransport::{UOwnedListener, UOwnedTransport, UOwnedTransportImpl};
195
196// ---- zero-copy transport family ----
197
198pub use payload::codec::{
199    DecodePayload, EncodePayload, PayloadCodec, PayloadFormat, PayloadLayout, ProtobufPayload,
200    ReadDecodePayload,
201};
202pub use payload::loan::LoanPayload;
203#[cfg(feature = "zero-copy-transport")]
204pub use payload::loan::{LoanUninitPayload, LoanedInitPayload, LoanedUninitPayload};
205pub use payload::stable::{
206    assert_stable_payload_byte_backed_uninit, stable_payload_supports_byte_backed_uninit,
207    ByteBackedStablePayload, InitializedStablePayload, StableContainerPayload,
208    StableContainerPayloadInfo, StablePayload, StablePayloadInit, StablePayloadInitContext,
209};
210
211#[cfg(feature = "zero-copy-transport")]
212mod zero_copy;
213#[cfg(all(feature = "test-util", feature = "zero-copy-transport"))]
214pub use zero_copy::InMemoryZeroCopyTransport;
215#[cfg(feature = "perf-diagnostics")]
216#[doc(hidden)]
217pub use zero_copy::UninitStableSendPhases;
218#[cfg(feature = "zero-copy-transport")]
219pub use zero_copy::{
220    validate_tx_buffer_for_transport, verify_tx_buffer_payload_layout,
221    verify_uninit_tx_buffer_payload_layout, LoanedPayload, LoanedPayloadUninitMut,
222    PayloadAlignment, PayloadLoanProvenance, ULoanedContiguousZeroCopyRxFrame, UTxBuffer,
223    UTxLoanSpec, UTxPayloadSpec, UUninitTxBuffer, UVecRxLease, UVecTxBuffer, UVecUninitTxBuffer,
224    UZeroCopyListener, UZeroCopyRxLease, UZeroCopyTransport, UZeroCopyTransportExt,
225    UZeroCopyTransportImpl, UZeroCopyUninitTransportImpl,
226};
227#[cfg(feature = "zero-copy-transport")]
228pub use zero_copy::{UZeroCopyUninitTransport, UZeroCopyUninitTransportExt};
229
230#[cfg(any(test, feature = "test-util", feature = "payload-contract-fixtures"))]
231pub mod test_support;
232
233/// Derives for stable payload types.
234pub use up_rust_macros::{ByteBackedStablePayload, StablePayload, StablePayloadInit};
235
236#[doc(hidden)]
237pub mod __derive_support {
238    pub use crate::payload::stable::{
239        ByteBackedStablePayloadField, StablePayloadInitSet, StablePayloadInitSlot,
240        StablePayloadInitUnset,
241    };
242}
243
244// ---- wire formats ----
245
246#[cfg(feature = "wire-implementer-api")]
247pub mod wire;
248#[cfg(not(feature = "wire-implementer-api"))]
249mod wire;
250#[cfg(any(feature = "selected-wire-user-api", feature = "wire-implementer-api"))]
251pub use wire::NativePrefixFrameMetadataCodec;
252#[cfg(any(feature = "selected-wire-user-api", feature = "wire-implementer-api"))]
253pub use wire::{
254    ProtobufWire, StableContainerWireFormat, UProtocolNativeWire, WireCompatibility, WireIdentity,
255    WireIdentityRef, NATIVE_EXPLICIT_PAYLOAD_FAMILY_ID, NATIVE_PREFIX_METADATA_LAYOUT_ID,
256    PROTOBUF_PAYLOAD_FAMILY_ID, PROTOBUF_WIRE_ID, STABLE_CONTAINER_PAYLOAD_FAMILY_ID,
257    STABLE_CONTAINER_WIRE_ID, UFRAME_FIELDS_METADATA_LAYOUT_ID, UPROTOCOL_NATIVE_WIRE_ID,
258    XCDR_V2_PAYLOAD_FAMILY_ID, XCDR_V2_WIRE_ID,
259};
260#[cfg(feature = "wire-implementer-api")]
261pub use wire::{UWire, UWireDecode, UWireEncode, UWirePayload, UWireReadDecode};
262#[cfg(feature = "wire-implementer-api")]
263pub use wire::{
264    UWireMetadataCodec, UWireMetadataCodecFor, UWireMetadataContext, UWireMetadataError,
265};
266
267/// Compatibility import surface for wire-format implementers.
268///
269/// The crate root remains canonical; this role-oriented module groups the same
270/// public contracts for existing wire crates and focused imports.
271#[cfg(feature = "wire-implementer-api")]
272pub mod wire_implementer_api {
273    pub use crate::{
274        NativePrefixFrameMetadataCodec, ProtobufWire, StableContainerWireFormat,
275        UProtocolNativeWire, UWire, UWireDecode, UWireEncode, UWireMetadataCodec,
276        UWireMetadataCodecFor, UWireMetadataContext, UWireMetadataError, UWirePayload,
277        UWireReadDecode, WireCompatibility, WireIdentity, WireIdentityRef,
278        NATIVE_EXPLICIT_PAYLOAD_FAMILY_ID, NATIVE_PREFIX_METADATA_LAYOUT_ID,
279        PROTOBUF_PAYLOAD_FAMILY_ID, PROTOBUF_WIRE_ID, STABLE_CONTAINER_PAYLOAD_FAMILY_ID,
280        STABLE_CONTAINER_WIRE_ID, UFRAME_FIELDS_METADATA_LAYOUT_ID, UPROTOCOL_NATIVE_WIRE_ID,
281        XCDR_V2_PAYLOAD_FAMILY_ID, XCDR_V2_WIRE_ID,
282    };
283}
284
285// ---- selected-wire transport ----
286
287#[cfg(all(
288    feature = "selected-wire-transport-core",
289    feature = "transport-implementer-api"
290))]
291pub mod wire_transport;
292#[cfg(all(
293    feature = "selected-wire-transport-core",
294    not(feature = "transport-implementer-api")
295))]
296mod wire_transport;
297
298#[cfg(feature = "transport-implementer-api")]
299pub use wire_transport::UEncodedRxFrame;
300#[cfg(all(feature = "selected-wire-user-api", feature = "zero-copy-transport"))]
301pub use wire_transport::USelectedWireZeroCopyTransport;
302#[cfg(all(
303    feature = "selected-wire-transport-core",
304    any(
305        feature = "transport-implementer-api",
306        feature = "wire-implementer-api"
307    )
308))]
309pub use wire_transport::UWireTransport;
310#[cfg(all(
311    feature = "owned-frame-transport",
312    feature = "transport-implementer-api"
313))]
314pub use wire_transport::{
315    EncodedOwnedFrame, PreparedOwnedFrame, UEncodedOwnedListener, UOwnedTransportCore,
316};
317#[cfg(all(feature = "transport-implementer-api", feature = "zero-copy-transport"))]
318pub use wire_transport::{
319    PreparedTxLoanSpec, UEncodedLoanedRxFrame, UEncodedZeroCopyListener, UZeroCopyTransportCore,
320    UZeroCopyUninitTransportCore,
321};
322#[cfg(feature = "selected-wire-user-api")]
323pub use wire_transport::{
324    ProtobufWireTransport, StableContainerWireTransport, UNativePrefixWireTransport,
325    UWithNativePrefixWire,
326};
327#[cfg(feature = "selected-wire-user-api")]
328pub use wire_transport::{UHasWire, UWireRx};
329
330/// Compatibility import surface for selected-wire users.
331///
332/// The crate root remains canonical; this role-oriented module groups the same
333/// public contracts for existing applications and focused imports.
334#[cfg(feature = "selected-wire-user-api")]
335pub mod selected_wire_user_api {
336    #[cfg(feature = "zero-copy-transport")]
337    pub use crate::USelectedWireZeroCopyTransport;
338    pub use crate::{
339        ProtobufWire, ProtobufWireTransport, StableContainerWireFormat,
340        StableContainerWireTransport, UHasWire, UNativePrefixWireTransport, UProtocolNativeWire,
341        UWireRx, UWithNativePrefixWire, WireCompatibility, WireIdentity, WireIdentityRef,
342    };
343    #[cfg(feature = "zero-copy-transport")]
344    pub use crate::{UZeroCopyUninitTransport, UZeroCopyUninitTransportExt};
345}
346
347/// Compatibility import surface for transport implementers.
348///
349/// The crate root remains canonical; this role-oriented module groups the same
350/// encoded-core contracts for existing transports and focused imports.
351#[cfg(feature = "transport-implementer-api")]
352pub mod transport_implementer_api {
353    #[cfg(feature = "owned-frame-transport")]
354    pub use crate::{
355        EncodedOwnedFrame, PreparedOwnedFrame, UEncodedOwnedListener, UOwnedTransportCore,
356    };
357    #[cfg(feature = "zero-copy-transport")]
358    pub use crate::{
359        PreparedTxLoanSpec, UEncodedLoanedRxFrame, UEncodedZeroCopyListener,
360        UZeroCopyTransportCore, UZeroCopyUninitTransportCore,
361    };
362    pub use crate::{UEncodedRxFrame, UWireTransport};
363}
364
365// ---- the guide ----
366
367#[doc = include_str!("guide/README.md")]
368pub mod guide {
369    #[cfg_attr(
370        all(feature = "communication", feature = "util"),
371        doc = include_str!("guide/applications.md")
372    )]
373    #[cfg_attr(
374        not(all(feature = "communication", feature = "util")),
375        doc = "Enable `communication` and `util` for the runnable application guide."
376    )]
377    pub mod applications {
378        #[cfg_attr(
379            all(
380                feature = "communication",
381                feature = "util",
382                feature = "test-util",
383                feature = "selected-wire-user-api",
384                feature = "owned-frame-transport",
385                feature = "zero-copy-transport"
386            ),
387            doc = include_str!("guide/communication.md")
388        )]
389        #[cfg_attr(
390            not(all(
391                feature = "communication",
392                feature = "util",
393                feature = "test-util",
394                feature = "selected-wire-user-api",
395                feature = "owned-frame-transport",
396                feature = "zero-copy-transport"
397            )),
398            doc = "Enable the documented communication, transport-family and test features for the runnable communication guide."
399        )]
400        pub mod communication {}
401        #[doc = include_str!("guide/transport.md")]
402        pub mod transport {}
403    }
404    #[doc = include_str!("guide/transports.md")]
405    pub mod transports {
406        #[doc = include_str!("guide/utransport.md")]
407        pub mod utransport {}
408        #[cfg_attr(
409            feature = "owned-frame-transport",
410            doc = include_str!("guide/owned.md")
411        )]
412        #[cfg_attr(
413            not(feature = "owned-frame-transport"),
414            doc = "Enable `owned-frame-transport` for the runnable owned-frame guide."
415        )]
416        pub mod owned {}
417        #[cfg_attr(
418            all(
419                feature = "zero-copy-transport",
420                feature = "test-util",
421                feature = "transport-implementer-api",
422                feature = "selected-wire-user-api"
423            ),
424            doc = include_str!("guide/zero_copy.md")
425        )]
426        #[cfg_attr(
427            not(all(
428                feature = "zero-copy-transport",
429                feature = "test-util",
430                feature = "transport-implementer-api",
431                feature = "selected-wire-user-api"
432            )),
433            doc = "Enable the documented zero-copy, selected-wire, transport-implementer and test features for the runnable zero-copy guide."
434        )]
435        pub mod zero_copy {}
436    }
437    #[doc = include_str!("guide/wires.md")]
438    pub mod wires {}
439    #[doc = include_str!("guide/trait_map.md")]
440    pub mod trait_map {}
441}
442
443#[cfg(feature = "payload-contract-fixtures")]
444pub mod bench_fixtures;