Skip to main content

sourcey_rustdoc/
spec.rs

1use rustdoc_types::ItemKind;
2use serde::{Deserialize, Serialize};
3use std::collections::BTreeMap;
4
5pub const SPEC_VERSION: u32 = 1;
6pub const SOURCEY_RUSTDOC_VERSION: &str = env!("CARGO_PKG_VERSION");
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct RustdocSpec {
10    pub version: u32,
11    pub sourcey_rustdoc_version: String,
12    pub rustdoc_format_version: u32,
13    pub rust_toolchain: String,
14    pub generated_at: String,
15    pub crates: Vec<CrateSpec>,
16    /// Diagnostics that apply to the whole snapshot rather than any single
17    /// crate (e.g. `RUSTDOC_FORMAT_VERSION_MISMATCH`).
18    #[serde(default)]
19    pub diagnostics: Vec<Diagnostic>,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct CrateSpec {
24    pub name: String,
25    pub version: Option<String>,
26    pub root_module_id: ItemId,
27    pub modules: Vec<ModuleSpec>,
28    /// Item id (string) → Item. Stable lookup keyed by rustdoc's per-snapshot id.
29    pub items: BTreeMap<String, Item>,
30    pub external_crates: Vec<ExternalCrateRef>,
31    pub diagnostics: Vec<Diagnostic>,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
35#[serde(transparent)]
36pub struct ItemId(pub String);
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct ModuleSpec {
40    pub id: ItemId,
41    pub path: Vec<String>,
42    pub docs_markdown: Option<String>,
43    pub doc_aliases: Vec<String>,
44    pub item_ids: Vec<ItemId>,
45    pub sub_module_paths: Vec<Vec<String>>,
46    pub source: Option<SourceLocation>,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct SourceLocation {
51    pub file: String,
52    pub line_start: u32,
53    pub line_end: u32,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct Item {
58    pub id: ItemId,
59    pub name: Option<String>,
60    pub path: Vec<String>,
61    pub visibility: Visibility,
62    pub source: Option<SourceLocation>,
63    pub docs_markdown: Option<String>,
64    pub doc_aliases: Vec<String>,
65    pub deprecation: Option<Deprecation>,
66    pub stability: Option<Stability>,
67    pub feature_gates: Vec<String>,
68    pub attrs_structured: Vec<String>,
69    /// Intra-doc link table: link label as it appears in the docstring,
70    /// mapped to a resolved target. Internal targets reference a local
71    /// item id; external targets carry enough metadata to render a docs.rs
72    /// or std URL without a second snapshot lookup.
73    pub links: BTreeMap<String, LinkTarget>,
74    pub inner: ItemInner,
75    pub doctests: Vec<Doctest>,
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
79#[serde(tag = "kind", rename_all = "snake_case")]
80pub enum Visibility {
81    Public,
82    Crate,
83    Restricted { path: String },
84    Default,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct Deprecation {
89    pub since: Option<String>,
90    pub note: Option<String>,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct Stability {
95    pub level: StabilityLevel,
96    pub since: Option<String>,
97    pub feature: Option<String>,
98    pub issue: Option<u32>,
99}
100
101#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
102#[serde(rename_all = "snake_case")]
103pub enum StabilityLevel {
104    Stable,
105    Unstable,
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize)]
109#[serde(tag = "kind", rename_all = "snake_case")]
110pub enum ItemInner {
111    Function(FunctionItem),
112    Struct(StructItem),
113    Enum(EnumItem),
114    Variant(VariantItem),
115    Union(UnionItem),
116    Trait(TraitItem),
117    TraitAlias(TraitAliasItem),
118    Impl(ImplItem),
119    TypeAlias(TypeAliasItem),
120    Constant(ConstantItem),
121    Static(StaticItem),
122    Macro(MacroItem),
123    ProcMacro(ProcMacroItem),
124    AssocType(AssocTypeItem),
125    AssocConst(AssocConstItem),
126    Use(UseItem),
127    StructField(StructFieldItem),
128    Module,
129    Primitive,
130    ExternType,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct FunctionItem {
135    pub signature: Signature,
136    pub generics: Generics,
137    pub is_const: bool,
138    pub is_async: bool,
139    pub is_unsafe: bool,
140    pub has_body: bool,
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize)]
144pub struct StructItem {
145    pub struct_kind: StructKindKind,
146    pub generics: Generics,
147    pub fields: Vec<ItemId>,
148    pub has_stripped_fields: bool,
149    pub impls: Vec<ItemId>,
150}
151
152#[derive(Debug, Clone, Serialize, Deserialize)]
153#[serde(rename_all = "snake_case")]
154pub enum StructKindKind {
155    Plain,
156    Tuple,
157    Unit,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct EnumItem {
162    pub generics: Generics,
163    pub variants: Vec<ItemId>,
164    pub has_stripped_variants: bool,
165    pub impls: Vec<ItemId>,
166}
167
168#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct VariantItem {
170    pub variant_kind: VariantKindKind,
171    pub discriminant: Option<String>,
172}
173
174#[derive(Debug, Clone, Serialize, Deserialize)]
175#[serde(rename_all = "snake_case")]
176pub enum VariantKindKind {
177    Plain,
178    Tuple,
179    Struct,
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
183pub struct UnionItem {
184    pub generics: Generics,
185    pub fields: Vec<ItemId>,
186    pub has_stripped_fields: bool,
187    pub impls: Vec<ItemId>,
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
191pub struct TraitItem {
192    pub is_auto: bool,
193    pub is_unsafe: bool,
194    pub is_dyn_compatible: bool,
195    pub generics: Generics,
196    pub bounds: Vec<String>,
197    pub items: Vec<ItemId>,
198    pub implementations: Vec<ItemId>,
199}
200
201#[derive(Debug, Clone, Serialize, Deserialize)]
202pub struct TraitAliasItem {
203    pub generics: Generics,
204    pub bounds: Vec<String>,
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
208pub struct ImplItem {
209    pub generics: Generics,
210    pub trait_path: Option<TypePath>,
211    pub for_type: TypePath,
212    pub items: Vec<ItemId>,
213    pub is_negative: bool,
214    pub is_synthetic: bool,
215    pub is_blanket: bool,
216    pub provided_trait_methods: Vec<String>,
217}
218
219#[derive(Debug, Clone, Serialize, Deserialize)]
220pub struct TypeAliasItem {
221    pub aliased_type: TypePath,
222    pub generics: Generics,
223}
224
225#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct ConstantItem {
227    pub type_display: String,
228    pub expr: String,
229    pub value: Option<String>,
230    pub is_literal: bool,
231}
232
233#[derive(Debug, Clone, Serialize, Deserialize)]
234pub struct StaticItem {
235    pub type_display: String,
236    pub expr: String,
237    pub is_mutable: bool,
238    pub is_unsafe: bool,
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct MacroItem {
243    pub source: String,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
247pub struct ProcMacroItem {
248    pub macro_kind: ProcMacroKindKind,
249    pub helpers: Vec<String>,
250}
251
252#[derive(Debug, Clone, Serialize, Deserialize)]
253#[serde(rename_all = "snake_case")]
254pub enum ProcMacroKindKind {
255    Bang,
256    Attr,
257    Derive,
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize)]
261pub struct AssocTypeItem {
262    pub generics: Generics,
263    pub bounds: Vec<String>,
264    pub default_display: Option<String>,
265}
266
267#[derive(Debug, Clone, Serialize, Deserialize)]
268pub struct AssocConstItem {
269    pub type_display: String,
270    pub default_display: Option<String>,
271}
272
273#[derive(Debug, Clone, Serialize, Deserialize)]
274pub struct UseItem {
275    pub source: String,
276    pub name: String,
277    pub target_id: Option<ItemId>,
278    pub is_glob: bool,
279}
280
281#[derive(Debug, Clone, Serialize, Deserialize)]
282pub struct StructFieldItem {
283    pub type_display: String,
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct Signature {
288    pub display: String,
289    pub tokens: Vec<SigToken>,
290    pub inputs: Vec<SigInput>,
291    pub output_display: Option<String>,
292    pub is_c_variadic: bool,
293}
294
295#[derive(Debug, Clone, Serialize, Deserialize)]
296pub struct SigInput {
297    pub name: String,
298    pub type_display: String,
299}
300
301#[derive(Debug, Clone, Serialize, Deserialize)]
302#[serde(tag = "kind", rename_all = "snake_case")]
303pub enum SigToken {
304    Keyword { text: String },
305    Punct { text: String },
306    Generic { text: String },
307    Lifetime { text: String },
308    Type { text: String, target: Option<TypePath> },
309    Whitespace,
310    Newline,
311}
312
313#[derive(Debug, Clone, Serialize, Deserialize)]
314pub struct TypePath {
315    pub crate_id: u32,
316    pub path: Vec<String>,
317    pub display: String,
318    pub external: bool,
319    pub html_root_url: Option<String>,
320    /// The target's kind, which names its rustdoc page (`trait.Error.html`).
321    #[serde(default, skip_serializing_if = "Option::is_none")]
322    pub item_kind: Option<ItemKind>,
323}
324
325#[derive(Debug, Clone, Serialize, Deserialize, Default)]
326pub struct Generics {
327    pub params: Vec<GenericParam>,
328    pub where_predicates: Vec<String>,
329}
330
331#[derive(Debug, Clone, Serialize, Deserialize)]
332pub struct GenericParam {
333    pub name: String,
334    pub kind: GenericParamKind,
335    pub default_display: Option<String>,
336    pub bounds: Vec<String>,
337}
338
339#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
340#[serde(rename_all = "snake_case")]
341pub enum GenericParamKind {
342    Lifetime,
343    Type,
344    Const,
345}
346
347#[derive(Debug, Clone, Serialize, Deserialize)]
348#[serde(tag = "kind", rename_all = "snake_case")]
349pub enum LinkTarget {
350    Internal {
351        id: ItemId,
352    },
353    External {
354        crate_name: String,
355        path: Vec<String>,
356        html_root_url: Option<String>,
357        /// The target's kind, which names its rustdoc page (`trait.Error.html`).
358        #[serde(default, skip_serializing_if = "Option::is_none")]
359        item_kind: Option<ItemKind>,
360    },
361}
362
363#[derive(Debug, Clone, Serialize, Deserialize)]
364pub struct Doctest {
365    pub lang: String,
366    pub fence_attributes: Vec<String>,
367    pub display_code: String,
368    pub executable_code: String,
369    pub implicit_main_wrap: bool,
370    pub source: Option<SourceLocation>,
371    pub ordinal: u32,
372}
373
374#[derive(Debug, Clone, Serialize, Deserialize)]
375pub struct ExternalCrateRef {
376    pub crate_id: u32,
377    pub name: String,
378    pub html_root_url: Option<String>,
379}
380
381#[derive(Debug, Clone, Serialize, Deserialize)]
382pub struct Diagnostic {
383    pub severity: DiagnosticSeverity,
384    pub code: String,
385    pub message: String,
386    pub crate_name: Option<String>,
387    pub file: Option<String>,
388    pub line: Option<u32>,
389}
390
391#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
392#[serde(rename_all = "snake_case")]
393pub enum DiagnosticSeverity {
394    Error,
395    Warning,
396    Info,
397}