How txtxtxtx/tx_di works
1. This repository is a Rust workspace centered on a dependency injection framework called tx_di. The architecture is split into three layers: a macro crate that records component metadata at compile time, a core runtime that builds and resolves components, and a set of plugins/examples that show how the framework is embedded into real systems.
2. The framework’s main boundary is between compile time and runtime. tx-di-macros expands #[tx_comp], #[tx_cst], and related attributes into component descriptors, dependency lists, scope metadata, and default init hooks. Those generated items are registered into linkme distributed slices so the runtime does not need reflection or filesystem scanning.
3. tx-di-core is the runtime engine. It owns the component registry, configuration loading, dependency graph resolution, and injection APIs. The key runtime flow is: collect metadata from linkme, load global TOML config if present, topologically sort components with Kahn’s algorithm, build singleton/prototype instances into a DashMap, then expose them through BuildContext and the immutable App snapshot.
4. The DI model is intentionally store-based. Components are stored as Arc-wrapped values or factories keyed by type identity, and injection is done by type lookup rather than name lookup. This means the primary data flow is from typed metadata to typed instances, with scope decisions handled by the framework rather than by consumers.
5. Configuration is a first-class input to the runtime. Components marked as conf are deserialized from TOML sections, and the global AppAllConfig object gives access to raw configuration values. In architecture diagrams, config should be shown as an external source feeding BuildContext before component construction begins.
6. tx-di-macros and tx-di-core are tightly coupled but separate by responsibility: macros generate the static description of a component, while core executes the graph. That separation is important because it is what enables compile-time collection with runtime-only resolution, while keeping component authors on a simple attribute-based API.
7. plugins/ contains reusable integrations built on top of the core DI model. These are not just utilities; they are injectable subsystems that become part of the dependency graph through the same linkme registration mechanism. The important plugins are tx_di_log for tracing-based logging, tx_di_axum for HTTP hosting, tx_di_sip for SIP transport and routing, tx_di_gb28181 for GB28181 server behavior, tx_di_gb28181_client for device emulation, tx_di_can for CAN/CANFD communication, and small support crates such as tx_di_toasty.
8. tx_di_axum is the web boundary. It wraps an Axum/Tokio server and exposes HTTP concerns such as health checks, CORS, static files, and middleware. In the architecture, it sits at the edge, consuming DI-managed config and services, then serving requests into the rest of the application.
9. tx_di_sip is the protocol boundary for SIP. It provides the transport/listener and message routing layer that the GB28181 plugins build upon. Architecturally, it turns network SIP traffic into handler dispatch, and it is the bridge between raw UDP/TCP packets and higher-level domain logic.
10. tx_di_gb28181 and common/tx_gb28181 form the main domain subsystem for GB28181-2022. The common crate holds shared protocol types and parsers/encoders for SIP, SDP, XML, device/channel models, and events. The server plugin adds registration, catalog queries, INVITE/playback flows, PTZ control, alarms, and media backend integration. The client plugin simulates a device side of the same protocol. The shared library is the contract boundary between both sides.
11. Media handling in the GB28181 server is separated from signaling. Under plugins/tx_di_gb28181/src/media, the code abstracts different streaming backends such as ZLMediaKit, MediaMTX, or a null backend. This means signaling logic can request media resources without being coupled to a specific streaming server implementation.
12. tx_di_can is a distinct embedded/diagnostics subsystem. It abstracts CAN and CANFD adapters, ISO-TP segmentation, UDS diagnostic messaging, and flash/programming workflows. Unlike the web/SIP pieces, this plugin represents a hardware-protocol edge that can also be injected and wired through the same DI mechanism.
13. The examples/ directory shows two end-to-end applications built from the same primitives. gb28181_admin combines a backend API and Vue UI for administration, sessions, devices, and SSE updates. gb_cams models a camera fleet with device management, event APIs, and a web UI. These examples are important because they show how the framework is intended to assemble into complete systems.
14. Overall, the architecture is: component definitions in user crates and plugins → compile-time metadata generation via proc macros → link-time registration via linkme → runtime graph construction and configuration loading in tx-di-core → edge services such as Axum, SIP, GB28181, or CAN consuming the injected components. This is the main shape to capture in a diagram.
Main entry points: src/lib.rs tx-di-core · src/lib.rs GB28181 server · config.rs App config · mod.rs BuildContext
Components 20
Compile time
Macro expansion and static component metadata generation.
- tx-di-macros · Expands component attributes into descriptors, dependency lists, scope metadata, and init hooks.
tx-di-macros/src/lib.rs - Static metadata · Component definitions registered into distributed slices for runtime discovery.
- linkme registry · Link-time collection point for component metadata without reflection or scanning.
Runtime core
Dependency graph construction, config loading, and instance resolution.
- tx-di-core · Builds the dependency graph, loads config, and resolves injectable components.
tx-di-core/src/lib.rs - Registry · Holds registered component definitions and type-keyed lookup state.
tx-di-core/src/di/comp/mod.rs - App config · Loads global TOML config and exposes raw application configuration.
tx-di-core/src/di/comp/config.rs - Graph resolver · Sorts dependencies with Kahn-style resolution and computes build order.
tx-di-core/src/di/mod.rs - BuildContext · Construction-time context that supplies config and dependency access to factories.
tx-di-core/src/di/common/mod.rs - App snapshot · Frozen application state exposing built singletons and factories for lookup.
tx-di-core/src/lib.rs - Instance store · Stores Arc-wrapped singletons and factory outputs keyed by type identity.
tx-di-core/src/di/common/r.rs
Plugins
Injectable subsystems built on the DI model.
- tx_di_axum · Axum/Tokio edge for health checks, CORS, static files, and middleware.
plugins/tx_di_axum/src/lib.rs - tx_di_sip · Listener, sender, and handler routing for SIP traffic.
plugins/tx_di_sip/src/lib.rs - GB28181 server · Registration, catalog, INVITE/playback, PTZ, alarms, and media coordination.
plugins/tx_di_gb28181/src/lib.rs - GB28181 client · Emulates a GB28181 device-side client and device handlers.
plugins/tx_di_gb28181_client/src/lib.rs - Media backends · Abstracts ZLM, MediaMTX, and null streaming backends.
plugins/tx_di_gb28181/src/media/mod.rs - tx_di_can · CAN/CANFD adapters, ISO-TP, UDS diagnostics, and flash workflows.
plugins/tx_di_can/src/lib.rs - tx_di_log · Tracing-oriented logging component for DI-managed systems.
plugins/tx_di_log/src/lib.rs
Examples
End-to-end applications assembled from the framework.
- gb28181_admin · Backend API and Vue UI for administration, sessions, devices, and SSE.
examples/gb28181_admin/src/main.rs - gb_cams · Camera-fleet application with device management, event APIs, and web UI.
examples/gb_cams/src/main.rs
Shared domain
Protocol and model types shared across GB28181 components.
- tx_gb28181 · Shared SIP/SDP/XML/device/event types and parsers for GB28181.
common/tx_gb28181/src/lib.rs
Connections 26
- tx-di-macros → Static metadata: expands · Macro expansion produces component descriptors and hooks.
- Static metadata → linkme registry: registers · Generated metadata is placed into distributed slices.
- linkme registry → tx-di-core: feeds · Runtime discovers all components through link-time registration.
- tx-di-core → Registry: owns · Core maintains the component registry.
- tx-di-core → App config: loads · Core loads global configuration before construction.
- tx-di-core → Graph resolver: resolves · Core computes dependency order and build plan.
- Graph resolver → BuildContext: builds with · Resolution drives construction through BuildContext.
- BuildContext → Instance store: populates · Factories and singletons are inserted into the instance store.
- BuildContext → App snapshot: freezes into · Completed instances become an immutable app snapshot.
- Instance store → App snapshot: serves · The App exposes typed lookup from the stored instances.
- App config → tx_di_axum: configures · HTTP plugin consumes DI-managed config and services.
- App config → tx_di_sip: configures · SIP transport and routing are configured from runtime config.
- App config → GB28181 server: configures · GB28181 server behavior is driven by loaded config.
- App config → tx_di_can: configures · CAN plugin uses TOML-backed configuration.
- tx_di_sip → GB28181 server: supports · GB28181 server builds on SIP transport and routing.
- tx_gb28181 → GB28181 server: contracts · Shared protocol types define the server-side domain contract.
- tx_gb28181 → GB28181 client: contracts · Shared protocol types define the client-side domain contract.
- GB28181 server → Media backends: requests · Server delegates streaming backend selection and media operations.
- tx_di_axum → gb28181_admin: serves · Example admin app exposes HTTP endpoints and UI-backed workflows.
- GB28181 server → gb28181_admin: powers · Admin app uses GB28181 server capabilities and state.
- GB28181 client → gb_cams: powers · Camera example uses the device-side GB28181 client.
- tx_di_can → tx-di-core: injects into · Plugin is wired through the same DI runtime mechanism.
- tx_di_axum → tx-di-core: injects into · HTTP edge is assembled as a DI-managed subsystem.
- GB28181 server → tx-di-core: injects into · GB28181 server participates in the same component graph.
- GB28181 client → tx-di-core: injects into · Client plugin is registered and resolved by the core.
- tx_di_log → tx-di-core: injects into · Logging plugin is added as a DI component.