1use sha2::{Digest, Sha256};
2
3#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
5pub struct SwiftEvidenceDigest([u8; 32]);
6
7impl SwiftEvidenceDigest {
8 #[must_use]
10 pub fn of(bytes: impl AsRef<[u8]>) -> Self {
11 Self(Sha256::digest(bytes.as_ref()).into())
12 }
13
14 #[must_use]
16 pub const fn into_bytes(self) -> [u8; 32] {
17 self.0
18 }
19}
20
21#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub struct SwiftCallableEvidenceLimits {
24 pub max_mangling_bytes: u64,
26 pub max_mangling_nodes: u64,
28 pub max_identifier_bytes: u64,
30 pub max_context_depth: u64,
32 pub max_type_ast_depth: u64,
34 pub max_type_ast_nodes: u64,
36}
37
38impl SwiftCallableEvidenceLimits {
39 pub(super) fn validate(self) -> Result<(), String> {
40 if self.max_mangling_bytes == 0
41 || self.max_mangling_nodes == 0
42 || self.max_identifier_bytes == 0
43 || self.max_context_depth == 0
44 || self.max_type_ast_depth == 0
45 || self.max_type_ast_nodes == 0
46 {
47 return Err("Swift callable evidence limits must all be nonzero".into());
48 }
49 Ok(())
50 }
51}
52
53#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
55pub enum SwiftManglingScheme {
56 StableSwift,
58 EmbeddedSwift,
60 LegacySwift,
62}
63
64#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
66pub enum SwiftManglingGap {
67 UnsupportedScheme,
69 UnsupportedNode,
71 UnsupportedRepresentation,
73 UnsupportedRequirement,
75 UnsupportedBuiltin,
77 ProfileMismatch,
79 TypeAstDepthExceeded,
81 TypeAstNodesExceeded,
83}
84
85#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
87pub enum SwiftTypeDeclarationKind {
88 Class,
90 Struct,
92 Enum,
94 Protocol,
96 TypeAlias,
98 Opaque,
100 ObjcClass,
102}
103
104#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
106pub enum SwiftDeclarationPathComponent {
107 Identifier {
109 value: String,
111 },
112 PrivateContext {
114 discriminator_sha256: SwiftEvidenceDigest,
116 },
117 LocalContext {
119 discriminator_sha256: SwiftEvidenceDigest,
121 },
122 ExtensionContext {
124 defining_module: String,
126 extended_declaration_sha256: SwiftEvidenceDigest,
128 },
129}
130
131#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
133pub struct SwiftTypeDeclaration {
134 pub module: String,
136 pub declaration_path: Vec<SwiftDeclarationPathComponent>,
138 pub kind: SwiftTypeDeclarationKind,
140}
141
142#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
144pub enum SwiftCallableKind {
145 Function,
147 InstanceMethod,
149 StaticMethod,
151 ClassMethod,
153 Initializer,
155 Allocator,
157 Deinitializer,
159 SubscriptGet,
161 SubscriptSet,
163 PropertyGet,
165 PropertySet,
167 PropertyRead,
169 PropertyModify,
171 Closure,
173}
174
175#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
177pub enum SwiftCallableVariantRole {
178 DirectEntry,
180 ClassVtableEntry,
182 ProtocolWitnessEntry,
184 DispatchThunk,
186 ReabstractionThunk,
188 Specialization,
190 Prespecialization,
192 AsyncEntry,
194 AsyncResume,
196 CoroutineEntry,
198 CoroutineResume,
200 DestroyingDeallocator,
202 DeallocatingDeallocator,
204 DynamicReplacement,
206 MetadataAccessor,
208 WitnessAccessor,
210}
211
212#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
214pub enum SwiftFunctionRepresentation {
215 Thin,
217 Thick,
219 Method,
221 WitnessMethod,
223 CFunction,
225 Block,
227}
228
229#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
231pub enum SwiftMetatypeRepresentation {
232 Thick,
234 Thin,
236 Objc,
238}
239
240#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
242pub struct SwiftTupleElement {
243 pub label: Option<String>,
245 pub r#type: SwiftTypeEvidence,
247}
248
249#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
251pub struct SwiftFormalParameter {
252 pub label: Option<String>,
254 pub r#type: SwiftTypeEvidence,
256 pub variadic: bool,
258}
259
260#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
262pub enum SwiftTypeEvidence {
263 Nominal {
265 declaration: SwiftTypeDeclaration,
267 arguments: Vec<Self>,
269 },
270 GenericParameter {
272 depth: u64,
274 index: u64,
276 },
277 DependentMember {
279 base: Box<Self>,
281 member: String,
283 protocol: Option<SwiftTypeDeclaration>,
285 },
286 Tuple {
288 elements: Vec<SwiftTupleElement>,
290 },
291 Function {
293 representation: SwiftFunctionRepresentation,
295 parameters: Vec<SwiftFormalParameter>,
297 result: Box<Self>,
299 r#async: bool,
301 throwing: bool,
303 },
304 Metatype {
306 representation: SwiftMetatypeRepresentation,
308 instance: Box<Self>,
310 },
311 Existential {
313 protocols: Vec<SwiftTypeDeclaration>,
315 superclass: Option<Box<Self>>,
317 class_constraint: bool,
319 },
320 Inout {
322 value: Box<Self>,
324 },
325 Owned {
327 value: Box<Self>,
329 },
330 Shared {
332 value: Box<Self>,
334 },
335 Pack {
337 elements: Vec<Self>,
339 },
340 PackExpansion {
342 pattern: Box<Self>,
344 },
345 Builtin {
347 profile_atom: String,
349 },
350}
351
352#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
354pub struct SwiftFormalTypeEvidence {
355 pub representation: SwiftFunctionRepresentation,
357 pub parameters: Vec<SwiftFormalParameter>,
359 pub result: SwiftTypeEvidence,
361 pub r#async: bool,
363 pub throwing: bool,
365}
366
367#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
369pub enum SwiftGenericRequirementEvidence {
370 Conformance {
372 subject: SwiftTypeEvidence,
374 protocol: SwiftTypeDeclaration,
376 },
377 SameType {
379 left: SwiftTypeEvidence,
381 right: SwiftTypeEvidence,
383 },
384 Superclass {
386 subject: SwiftTypeEvidence,
388 superclass: SwiftTypeEvidence,
390 },
391 SameShape {
393 left: SwiftTypeEvidence,
395 right: SwiftTypeEvidence,
397 },
398}
399
400#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
402pub struct SwiftSpecializationEvidence {
403 pub substitutions: Vec<SwiftTypeEvidence>,
405 pub pass_id: Option<String>,
407}
408
409#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
411pub struct SwiftMangledEntityEvidence {
412 pub module: String,
414 pub declaration_path: Vec<SwiftDeclarationPathComponent>,
416 pub declaration: Option<SwiftTypeDeclaration>,
418 pub callable_kind: Option<SwiftCallableKind>,
420 pub base_name: Option<String>,
422 pub formal_type: Option<SwiftFormalTypeEvidence>,
424 pub generic_requirements: Vec<SwiftGenericRequirementEvidence>,
426 pub variant_role: Option<SwiftCallableVariantRole>,
428 pub specialization: Option<SwiftSpecializationEvidence>,
430}
431
432#[derive(Clone, Debug, Eq, PartialEq)]
434pub enum SwiftManglingEvidence {
435 Supported {
437 raw: Vec<u8>,
439 scheme: SwiftManglingScheme,
441 entity: Box<SwiftMangledEntityEvidence>,
443 display: String,
445 },
446 Unsupported {
448 raw: Vec<u8>,
450 reason: SwiftManglingGap,
452 safe_detail: String,
454 },
455 Malformed {
457 raw: Vec<u8>,
459 diagnostic: String,
461 },
462}
463
464pub(super) fn validate_entity(
465 entity: &SwiftMangledEntityEvidence,
466 limits: &SwiftCallableEvidenceLimits,
467) -> Result<(), String> {
468 limits.validate()?;
469 if entity.module.is_empty() || entity.module.len() as u64 > limits.max_identifier_bytes {
470 return Err("Swift mangling module is empty or oversized".into());
471 }
472 if entity.declaration_path.len() as u64 > limits.max_context_depth {
473 return Err("Swift mangling context depth exceeds the selected limit".into());
474 }
475 let mut nodes = 0_u64;
476 if let Some(formal) = &entity.formal_type {
477 for parameter in &formal.parameters {
478 validate_type(¶meter.r#type, 1, limits, &mut nodes)?;
479 }
480 validate_type(&formal.result, 1, limits, &mut nodes)?;
481 }
482 Ok(())
483}
484
485fn validate_type(
486 value: &SwiftTypeEvidence,
487 depth: u64,
488 limits: &SwiftCallableEvidenceLimits,
489 nodes: &mut u64,
490) -> Result<(), String> {
491 *nodes = nodes
492 .checked_add(1)
493 .ok_or_else(|| "Swift type AST node count overflowed".to_string())?;
494 if depth > limits.max_type_ast_depth || *nodes > limits.max_type_ast_nodes {
495 return Err("Swift type AST structural limit exceeded".into());
496 }
497 match value {
498 SwiftTypeEvidence::Nominal { arguments, .. }
499 | SwiftTypeEvidence::Pack {
500 elements: arguments,
501 } => {
502 for child in arguments {
503 validate_type(child, depth + 1, limits, nodes)?;
504 }
505 }
506 SwiftTypeEvidence::DependentMember { base, .. }
507 | SwiftTypeEvidence::Metatype { instance: base, .. }
508 | SwiftTypeEvidence::Inout { value: base }
509 | SwiftTypeEvidence::Owned { value: base }
510 | SwiftTypeEvidence::Shared { value: base }
511 | SwiftTypeEvidence::PackExpansion { pattern: base } => {
512 validate_type(base, depth + 1, limits, nodes)?;
513 }
514 SwiftTypeEvidence::Tuple { elements } => {
515 for element in elements {
516 validate_type(&element.r#type, depth + 1, limits, nodes)?;
517 }
518 }
519 SwiftTypeEvidence::Function {
520 parameters, result, ..
521 } => {
522 for parameter in parameters {
523 validate_type(¶meter.r#type, depth + 1, limits, nodes)?;
524 }
525 validate_type(result, depth + 1, limits, nodes)?;
526 }
527 SwiftTypeEvidence::Existential { superclass, .. } => {
528 if let Some(superclass) = superclass {
529 validate_type(superclass, depth + 1, limits, nodes)?;
530 }
531 }
532 SwiftTypeEvidence::GenericParameter { .. } | SwiftTypeEvidence::Builtin { .. } => {}
533 }
534 Ok(())
535}
536
537#[must_use]
539pub fn swift_mangling_scheme(raw: &str) -> Option<(SwiftManglingScheme, &str)> {
540 let value = raw.strip_prefix('_').unwrap_or(raw);
541 if value.starts_with("$s") || value.starts_with("$S") {
542 Some((SwiftManglingScheme::StableSwift, value))
543 } else if value.starts_with("$e") {
544 Some((SwiftManglingScheme::EmbeddedSwift, value))
545 } else if value.starts_with("_T") {
546 Some((SwiftManglingScheme::LegacySwift, value))
547 } else {
548 None
549 }
550}