switchback_traits/traits/contract_family.rs
1//! `ContractFamily` identity and capability metadata.
2
3use crate::error::Result;
4use crate::ids::SpecVersion;
5use crate::traits::companion::CompanionStrategy;
6use crate::traits::contract::Contract;
7use crate::traits::entity_category::EntityCategory;
8use crate::traits::link::LinkExtractor;
9
10/// Raw document bytes before full parse, used for version detection.
11///
12/// In-memory only; not serialized on the wire.
13#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct RawDoc {
15 /// Optional filesystem path hint for error messages and version heuristics.
16 pub path_hint: Option<String>,
17 /// MIME type of the raw bytes (e.g. `"application/yaml"`).
18 pub media_type: String,
19 /// Unparsed contract source bytes.
20 pub bytes: Vec<u8>,
21}
22
23/// One supported spec version entry in a family's version matrix.
24#[derive(Clone, Copy, Debug, PartialEq, Eq)]
25pub struct SupportedVersion {
26 /// Version label string (e.g. `"3.1.0"`).
27 pub version: &'static str,
28 /// Deployment status hint for tooling and UI.
29 pub status: VersionStatus,
30}
31
32/// Lifecycle status of a supported contract spec version.
33#[derive(Clone, Copy, Debug, PartialEq, Eq)]
34pub enum VersionStatus {
35 /// Current recommended version for new work.
36 Latest,
37 /// Common in production but not the newest release.
38 WidelyDeployed,
39 /// Still parsed but no longer recommended.
40 Legacy,
41 /// Scheduled for removal; parsers may warn.
42 Deprecated,
43}
44
45/// Identity and capability metadata for one contract family.
46///
47/// Each parser crate provides a zero-sized or lightweight implementor describing
48/// OpenAPI, Protobuf, AsyncAPI, etc. Associated types wire up family-specific
49/// link extraction and companion discovery.
50pub trait ContractFamily: Send + Sync + Sized + 'static {
51 /// Entity category enum or newtype for this family.
52 type Category: EntityCategory;
53 /// Family-specific [`LinkExtractor`] implementation.
54 type LinkExtractor: LinkExtractor<Family = Self> + Send + Sync;
55 /// Family-specific [`CompanionStrategy`] implementation.
56 type CompanionStrategy: CompanionStrategy + Send + Sync;
57
58 /// Short family name (e.g. `"openapi"`, `"protobuf"`).
59 fn name(&self) -> &'static str;
60
61 /// Default fenced-code language tag for this family's entities.
62 fn fence_language(&self) -> &'static str;
63
64 /// Default manual title when the input does not specify one.
65 fn default_title(&self) -> &'static str;
66
67 /// Default markdown output root relative to the book root.
68 fn default_markdown_root(&self) -> &'static str;
69
70 /// Filename extensions recognized for contract inputs (e.g. `["yaml", "yml"]`).
71 fn extensions(&self) -> &'static [&'static str];
72
73 /// Filename extensions searched for companion documents.
74 ///
75 /// Defaults to [`Self::extensions`] when companions share input extensions.
76 fn companion_extensions(&self) -> &'static [&'static str] {
77 self.extensions()
78 }
79
80 /// Returns the companion discovery strategy for this family.
81 fn companion_strategy(&self) -> &Self::CompanionStrategy;
82
83 /// All category slug strings this family emits.
84 fn category_names(&self) -> &'static [&'static str];
85
86 /// Detects the spec version from raw bytes, when possible.
87 fn detect_version(&self, raw: &RawDoc) -> Option<SpecVersion>;
88
89 /// Supported spec versions and their lifecycle status.
90 fn supported_versions(&self) -> &'static [SupportedVersion];
91
92 /// Returns optional meta-schema bytes for validation at `version`, when available.
93 fn meta_schema(&self, version: &SpecVersion) -> Option<&'static [u8]> {
94 let _ = version;
95 None
96 }
97
98 /// Returns the link extractor instance for this family.
99 fn link_extractor(&self) -> &Self::LinkExtractor;
100
101 /// Protocol slugs this family may attach during populate.
102 fn supported_protocols(&self) -> &'static [&'static str] {
103 &[]
104 }
105
106 /// Default protocol slug for this family when populate attaches one binding.
107 fn default_protocol(&self) -> &'static str {
108 ""
109 }
110
111 /// Additional CLI or config option tokens understood by this family's tooling.
112 fn extra_option_tokens(&self) -> &'static [&'static str] {
113 &[]
114 }
115}
116
117/// Async loading of remote or multi-document contracts (I/O primary API).
118///
119/// Parser crates implement this for fetch-and-parse workflows. The loaded value
120/// implements [`Contract`] for in-memory traversal.
121pub trait AsyncContractLoader: Send + Sync {
122 /// Contract family metadata for the loader.
123 type Family: ContractFamily;
124 /// Loaded contract type produced by this loader.
125 type Loaded: Contract<Family = Self::Family> + Send + Sync;
126
127 /// Fetches inputs and returns a fully loaded contract.
128 async fn load(&self) -> Result<Self::Loaded>;
129}