Skip to main content

std_rs/
lib.rs

1//! # C reference pins
2//!
3//! Every `file.c:NNN` citation in this crate resolves at the tree and revision
4//! below, not at whatever that tree's working copy holds today. These trees are
5//! checked out on local branches here and run ahead of their pins.
6//!
7//! | tree | pinned revision |
8//! | --- | --- |
9//! | `std` | `R3-6-4` |
10//! | `epics-base` | `R7.0.10` |
11//!
12//! **Resolve by symbol at the pin; the line is a hint.** Find the named
13//! function, struct, macro or field first, and treat the line number as a hint
14//! that has to land inside that construct. Three cases follow:
15//!
16//! 1. Construct at the pin, line lands in it — the citation is exact. A
17//!    reference checkout ahead of the pin will disagree; that disagreement is
18//!    the checkout's, not the citation's.
19//! 2. Construct at the pin, line lands outside it — line drift. Keep the
20//!    symbol and move the line to the pin's.
21//! 3. Construct absent at the pin — the citation means code added after it,
22//!    and is NOT moved onto the pin, where it would point at lines that do not
23//!    exist. It names the revision it means inline, beside the line span: the
24//!    upstream PR and commit, and that both are later than the pin this table
25//!    gives. `epics-libcom-rs` already carries that form.
26//!
27//! Every pin above passes `git merge-base --is-ancestor <pin> origin/<default>`
28//! in its own tree, which is the test a pin has to meet. A `git describe`
29//! string names an exact commit and is worth as much as a tag; what
30//! disqualifies a revision is being reachable only from a fork branch or an
31//! unmerged PR, because then it names nothing a reader outside this workspace
32//! can fetch.
33//!
34//! Resolve each citation on its own. One sentence can cite two lines that are
35//! right at different revisions, and a check run at either revision then
36//! reports a single tidy error while vouching for the very citation the other
37//! condemns.
38//!
39//! A row reading *no settled pin* means no revision has been agreed for that
40//! tree: say which revision you read, and do not take its `HEAD` for the pin.
41//! Citations into non-EPICS sources (libc, RTEMS, `rtems-libbsd`, VxWorks,
42//! vendored third-party) are outside this table and carry no pin.
43
44#![allow(
45    clippy::collapsible_if,
46    clippy::derivable_impls,
47    clippy::field_reassign_with_default,
48    clippy::type_complexity
49)]
50
51pub mod device_support;
52pub mod records;
53pub mod seq_runner;
54pub mod snl;
55
56pub use device_support::time_of_day::{SecPastEpochDeviceSupport, TimeOfDayStringDeviceSupport};
57pub use records::epid::EpidRecord;
58pub use records::throttle::ThrottleRecord;
59pub use records::timestamp::TimestampRecord;
60
61/// Path to the bundled database template directory.
62pub const STD_DB_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/db");
63
64/// Return the epid record type factory for injection into IocBuilder.
65pub fn epid_record_factory() -> (&'static str, epics_base_rs::server::RecordFactory) {
66    ("epid", Box::new(|| Box::new(EpidRecord::default())))
67}
68
69/// Return the throttle record type factory for injection into IocBuilder.
70pub fn throttle_record_factory() -> (&'static str, epics_base_rs::server::RecordFactory) {
71    ("throttle", Box::new(|| Box::new(ThrottleRecord::default())))
72}
73
74/// Return the timestamp record type factory for injection into IocBuilder.
75pub fn timestamp_record_factory() -> (&'static str, epics_base_rs::server::RecordFactory) {
76    (
77        "timestamp",
78        Box::new(|| Box::new(TimestampRecord::default())),
79    )
80}
81
82/// Return all std record type factories for bulk registration.
83pub fn std_record_factories() -> Vec<(&'static str, epics_base_rs::server::RecordFactory)> {
84    vec![
85        epid_record_factory(),
86        throttle_record_factory(),
87        timestamp_record_factory(),
88    ]
89}
90
91/// Register all std record types via the global registry (legacy).
92/// Prefer `std_record_factories()` with `IocBuilder::register_record_type()`.
93pub fn register_std_record_types() {
94    for (name, factory) in std_record_factories() {
95        epics_base_rs::server::db_loader::register_record_type(name, factory);
96    }
97}
98
99/// Return the "Sec Past Epoch" (`ai`) device support factory from
100/// `devTimeOfDay.c` (`devAiTodSeconds`) for injection into a builder.
101pub fn sec_past_epoch_device_factory() -> (&'static str, epics_base_rs::server::DeviceSupportFactory)
102{
103    (
104        "Sec Past Epoch",
105        Box::new(|| Box::new(SecPastEpochDeviceSupport::new())),
106    )
107}
108
109/// Return the "Time of Day" (`stringin`) device support factory from
110/// `devTimeOfDay.c` (`devSiTodString`) for injection into a builder.
111pub fn time_of_day_device_factory() -> (&'static str, epics_base_rs::server::DeviceSupportFactory) {
112    (
113        "Time of Day",
114        Box::new(|| Box::new(TimeOfDayStringDeviceSupport::new())),
115    )
116}
117
118/// Return all std-module device support factories for bulk registration.
119///
120/// These are the `devTimeOfDay.c` DTYPs ("Sec Past Epoch" ai, "Time of Day"
121/// stringin). They need only the framework's `ProcessContext` (PHAS/TSE), no
122/// INP, so a static [`DeviceSupportFactory`](epics_base_rs::server::DeviceSupportFactory)
123/// suffices. Register each onto an `IocBuilder` / `IocApplication` /
124/// `CaServerBuilder` via its `register_device_support(dtyp, factory)` — the
125/// boxed factory satisfies the method's `Fn` bound — mirroring how
126/// [`std_record_factories()`] is injected via `register_record_type()`.
127pub fn std_device_supports() -> Vec<(&'static str, epics_base_rs::server::DeviceSupportFactory)> {
128    vec![
129        sec_past_epoch_device_factory(),
130        time_of_day_device_factory(),
131    ]
132}