switchback_traits/model/link.rs
1//! Intra-links, structural references, and link targets.
2
3/// Structural cross-reference in an entity body (schema `$ref`, protobuf FQN, etc.).
4///
5/// Serialized on the wire as part of [`StoredEntity`](super::entity::StoredEntity).
6#[derive(Clone, Debug, PartialEq, Eq)]
7pub struct Reference {
8 /// Address of the referenced entity within the manual.
9 pub target: EntityRef,
10 /// How the reference is expressed in source (internal, external, inline, etc.).
11 pub kind: RefKind,
12}
13
14/// Classification of a structural reference in source.
15#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
16pub enum RefKind {
17 /// Reference kind not specified or unrecognized.
18 #[default]
19 Unspecified,
20 /// Reference to another entity in the same manual.
21 Internal,
22 /// Reference to an entity outside the manual (by FQN or URL).
23 External,
24 /// OpenAPI-style component reference.
25 Component,
26 /// Inline definition with no separate entity target.
27 Inline,
28}
29
30/// Address of an entity within a manual.
31///
32/// Wire-safe cross-reference key used in [`Reference`], [`IntraLink`] targets, and
33/// the [`ResolvedManual`](super::resolved::ResolvedManual) index.
34#[derive(Clone, Debug, PartialEq, Eq, Hash)]
35pub struct EntityRef {
36 /// Owning [`Module`](super::manual::Module) id string.
37 pub module: String,
38 /// Group id string within the contract.
39 pub group: String,
40 /// Entity category slug.
41 pub category: String,
42 /// Entity name within the group and category.
43 pub name: String,
44}
45
46/// Address of a group within a manual.
47#[derive(Clone, Debug, PartialEq, Eq, Hash)]
48pub struct GroupRef {
49 /// Owning module id string.
50 pub module: String,
51 /// Group id string within the contract.
52 pub group: String,
53}
54
55/// Address of a contract within a manual.
56#[derive(Clone, Debug, PartialEq, Eq, Hash)]
57pub struct ContractRef {
58 /// Owning module id string.
59 pub module: String,
60 /// [`ContractFamily`](crate::traits::ContractFamily) name.
61 pub family: String,
62 /// Contract spec version string.
63 pub version: String,
64}
65
66/// Address of a module within a manual.
67#[derive(Clone, Debug, PartialEq, Eq, Hash)]
68pub struct ModuleRef {
69 /// Module id string.
70 pub module: String,
71}
72
73/// Cross-manual reference by URI with optional inner target.
74#[derive(Clone, Debug, PartialEq, Eq)]
75pub struct ManualRef {
76 /// URI of the external manual (may be a file path or registry URL).
77 pub uri: String,
78 /// Version pin or label for the external manual, when specified.
79 pub version: String,
80 /// Optional entity or group target within the external manual.
81 pub inner: Option<ManualRefInner>,
82}
83
84/// Inner target of a [`ManualRef`] cross-manual link.
85#[derive(Clone, Debug, PartialEq, Eq)]
86pub enum ManualRefInner {
87 /// Link to a specific entity in the external manual.
88 Entity(EntityRef),
89 /// Link to a group overview in the external manual.
90 Group(GroupRef),
91}
92
93/// External URL link target (not resolved to an in-manual entity).
94#[derive(Clone, Debug, PartialEq, Eq, Hash)]
95pub struct ExternalUrl {
96 /// Absolute or relative URL string as authored.
97 pub url: String,
98}
99
100/// Prose-level link with anchor, resolved target, and raw author text.
101///
102/// Serialized on the wire as part of [`StoredEntity`](super::entity::StoredEntity).
103/// The `target` field uses wire-safe variants only at serialize time; see
104/// [`LinkTarget::Unresolved`].
105#[derive(Clone, Debug, PartialEq, Eq)]
106pub struct IntraLink {
107 /// Byte span locating the link within a prose field.
108 pub anchor: Anchor,
109 /// Resolved link destination.
110 pub target: LinkTarget,
111 /// Raw link text as authored in source prose.
112 pub raw: String,
113}
114
115/// Byte span within a prose field (`doc`, `fence_body`, etc.).
116#[derive(Clone, Debug, PartialEq, Eq)]
117pub struct Anchor {
118 /// Name of the field containing the link (e.g. `"doc"`, `"fence_body"`).
119 pub field: String,
120 /// Inclusive start byte offset within `field`'s UTF-8 content.
121 pub byte_start: u32,
122 /// Exclusive end byte offset within `field`'s UTF-8 content.
123 pub byte_end: u32,
124}
125
126/// Resolved intra-link destination.
127#[derive(Clone, Debug, PartialEq, Eq)]
128pub enum LinkTarget {
129 /// Link to an entity in the current or another module.
130 Entity(EntityRef),
131 /// Link to a group overview page.
132 Group(GroupRef),
133 /// Link to a contract within a module.
134 Contract(ContractRef),
135 /// Link to a module overview page.
136 Module(ModuleRef),
137 /// Link to another manual (possibly with an inner entity/group target).
138 Manual(ManualRef),
139 /// Link to an external URL.
140 External(ExternalUrl),
141 /// Link target could not be resolved during extraction.
142 ///
143 /// In-memory only; not serialized on the wire. Parsers may emit this during
144 /// extraction; codecs should reject or strip unresolved targets at serialize time.
145 Unresolved,
146}