reflectapi_schema/
subst.rs1use std::collections::HashMap;
2
3use crate::{Enum, Field, Fields, Struct, TypeParameter, TypeReference, Variant};
4
5#[doc(hidden)]
6pub fn mk_subst(
7 parameters: &[TypeParameter],
8 args: &[TypeReference],
9) -> HashMap<String, TypeReference> {
10 assert_eq!(
11 parameters.len(),
12 args.len(),
13 "expected {} type arguments, got {}",
14 parameters.len(),
15 args.len()
16 );
17
18 parameters
19 .iter()
20 .map(|p| p.name.to_owned())
21 .zip(args.iter().cloned())
22 .collect()
23}
24
25pub trait Instantiate {
26 fn instantiate(self, args: &[TypeReference]) -> Self;
35}
36
37#[doc(hidden)]
38pub trait Substitute {
39 fn subst(self, subst: &HashMap<String, TypeReference>) -> Self;
43}
44
45impl Substitute for TypeReference {
46 fn subst(self, subst: &HashMap<String, TypeReference>) -> Self {
47 match subst.get(&self.name) {
48 Some(ty) => {
49 assert!(
50 self.arguments.is_empty(),
51 "type parameter cannot have type arguments"
52 );
53 ty.clone()
54 }
55 None => TypeReference {
56 name: self.name,
57 arguments: self.arguments.into_iter().map(|a| a.subst(subst)).collect(),
58 },
59 }
60 }
61}
62
63impl Substitute for Fields {
64 fn subst(self, subst: &HashMap<String, TypeReference>) -> Self {
65 match self {
66 Fields::Named(fields) => {
67 Fields::Named(fields.into_iter().map(|f| f.subst(subst)).collect())
68 }
69 Fields::Unnamed(fields) => {
70 Fields::Unnamed(fields.into_iter().map(|f| f.subst(subst)).collect())
71 }
72 Fields::None => Fields::None,
73 }
74 }
75}
76
77impl Substitute for Field {
78 fn subst(self, subst: &HashMap<String, TypeReference>) -> Self {
79 Field {
80 type_ref: self.type_ref.subst(subst),
81 ..self
82 }
83 }
84}
85
86impl Substitute for Variant {
87 fn subst(self, subst: &HashMap<String, TypeReference>) -> Self {
88 Self {
89 fields: self.fields.subst(subst),
90 ..self
91 }
92 }
93}
94
95impl Instantiate for Struct {
96 fn instantiate(self, type_args: &[TypeReference]) -> Self {
98 let subst = mk_subst(&self.parameters, type_args);
99
100 Self {
101 parameters: vec![],
102 fields: self.fields.subst(&subst),
103 ..self
104 }
105 }
106}
107
108impl Instantiate for Enum {
109 fn instantiate(self, type_args: &[TypeReference]) -> Self {
111 let subst = mk_subst(&self.parameters, type_args);
112
113 Self {
114 parameters: vec![],
115 variants: self.variants.into_iter().map(|v| v.subst(&subst)).collect(),
116 ..self
117 }
118 }
119}