Skip to main content

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}