Skip to main content

typst_pack/compile/
identity.rs

1//! Embedded implementation identities and diagnostic attribution.
2
3use std::hash::{Hash, Hasher};
4
5/// The role of an embedded implementation in compilation.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum ImplementationRole {
8    Engine,
9    Exporter,
10}
11
12/// The exact embedded implementation that participated in a result.
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub struct ImplementationIdentity {
15    pub(super) role: ImplementationRole,
16    pub(super) implementation: &'static str,
17    pub(super) version: &'static str,
18    pub(super) source_checksum: &'static str,
19    pub(super) target: &'static str,
20    pub(super) target_features: &'static str,
21    pub(super) feature_set: &'static str,
22    pub(super) debug_assertions: bool,
23}
24
25impl Hash for ImplementationIdentity {
26    fn hash<H: Hasher>(&self, state: &mut H) {
27        // The role is represented by the engine/exporter position in schema v1.
28        self.implementation.hash(state);
29        self.version.hash(state);
30        self.source_checksum.hash(state);
31        self.target.hash(state);
32        self.target_features.hash(state);
33        let feature_set = if self.feature_set == env!("TYPST_PACK_FEATURE_SET") {
34            env!("TYPST_PACK_IDENTITY_FEATURE_SET")
35        } else {
36            self.feature_set
37        };
38        feature_set.hash(state);
39        self.debug_assertions.hash(state);
40    }
41}
42
43impl ImplementationIdentity {
44    pub(crate) const fn new(
45        role: ImplementationRole,
46        implementation: &'static str,
47        version: &'static str,
48        source_checksum: &'static str,
49    ) -> Self {
50        Self {
51            role,
52            implementation,
53            version,
54            source_checksum,
55            target: env!("TYPST_PACK_TARGET"),
56            target_features: env!("TYPST_PACK_CARGO_CFG_TARGET_FEATURE"),
57            feature_set: env!("TYPST_PACK_FEATURE_SET"),
58            debug_assertions: cfg!(debug_assertions),
59        }
60    }
61
62    /// Whether this implementation is the engine or an exporter.
63    pub fn role(self) -> ImplementationRole {
64        self.role
65    }
66
67    pub fn implementation(self) -> &'static str {
68        self.implementation
69    }
70
71    pub fn version(self) -> &'static str {
72        self.version
73    }
74
75    pub fn source_checksum(self) -> &'static str {
76        self.source_checksum
77    }
78
79    pub fn target(self) -> &'static str {
80        self.target
81    }
82
83    pub fn target_features(self) -> &'static str {
84        self.target_features
85    }
86
87    pub fn feature_set(self) -> &'static str {
88        self.feature_set
89    }
90
91    pub fn debug_assertions(self) -> bool {
92        self.debug_assertions
93    }
94}
95
96/// The exact embedded implementation that emitted a diagnostic.
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
98pub struct DiagnosticProducer(DiagnosticProducerRole);
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
101enum DiagnosticProducerRole {
102    Engine(ImplementationIdentity),
103    Exporter(ImplementationIdentity),
104}
105
106impl DiagnosticProducer {
107    pub const fn new(identity: ImplementationIdentity) -> Self {
108        match identity.role {
109            ImplementationRole::Engine => Self(DiagnosticProducerRole::Engine(identity)),
110            ImplementationRole::Exporter => Self(DiagnosticProducerRole::Exporter(identity)),
111        }
112    }
113
114    pub fn implementation_identity(self) -> ImplementationIdentity {
115        match self.0 {
116            DiagnosticProducerRole::Engine(identity)
117            | DiagnosticProducerRole::Exporter(identity) => identity,
118        }
119    }
120}