specta_typescript/
context.rs

1use std::{borrow::Cow, fmt};
2
3use specta::ImplLocation;
4
5use crate::Typescript;
6
7#[derive(Clone, Debug)]
8pub(crate) enum PathItem {
9    Type(Cow<'static, str>),
10    TypeExtended(Cow<'static, str>, ImplLocation),
11    Field(Cow<'static, str>),
12    Variant(Cow<'static, str>),
13}
14
15#[derive(Clone)]
16pub(crate) struct ExportContext<'a> {
17    pub(crate) cfg: &'a Typescript,
18    pub(crate) path: Vec<PathItem>,
19    // `false` when inline'ing and `true` when exporting as named.
20    pub(crate) is_export: bool,
21}
22
23impl ExportContext<'_> {
24    pub(crate) fn with(&self, item: PathItem) -> Self {
25        Self {
26            path: self.path.iter().cloned().chain([item]).collect(),
27            ..*self
28        }
29    }
30
31    pub(crate) fn export_path(&self) -> ExportPath {
32        ExportPath::new(&self.path)
33    }
34}
35
36/// Represents the path of an error in the export tree.
37/// This is designed to be opaque, meaning it's internal format and `Display` impl are subject to change at will.
38pub struct ExportPath(String);
39
40impl ExportPath {
41    pub(crate) fn new(path: &[PathItem]) -> Self {
42        let mut s = String::new();
43        let mut path = path.iter().peekable();
44        while let Some(item) = path.next() {
45            s.push_str(match item {
46                PathItem::Type(v) => v,
47                PathItem::TypeExtended(_, loc) => loc.as_str(),
48                PathItem::Field(v) => v,
49                PathItem::Variant(v) => v,
50            });
51
52            if let Some(next) = path.peek() {
53                s.push_str(match next {
54                    PathItem::Type(_) => " -> ",
55                    PathItem::TypeExtended(_, _) => " -> ",
56                    PathItem::Field(_) => ".",
57                    PathItem::Variant(_) => "::",
58                });
59            } else {
60                break;
61            }
62        }
63
64        Self(s)
65    }
66
67    #[doc(hidden)]
68    pub fn new_unsafe(path: &str) -> Self {
69        Self(path.to_string())
70    }
71}
72
73impl PartialEq for ExportPath {
74    fn eq(&self, other: &Self) -> bool {
75        self.0 == other.0
76    }
77}
78
79impl fmt::Debug for ExportPath {
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        f.write_str(&self.0)
82    }
83}
84
85impl fmt::Display for ExportPath {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        write!(f, "{}", self.0)
88    }
89}