geam_core/host/
external.rs1mod dynamic;
2mod store;
3mod stored;
4
5use crate::host::{HostProfile, HostProvider, HostTypeListEnd};
6use ecow::EcoString;
7use std::marker::PhantomData;
8
9pub(crate) use crate::provider_support::HostStoredValueFamily;
10pub use dynamic::HostStoredDynamic;
11pub use store::HostExternalStore;
12pub(crate) use store::{ExternalPayloadLease, ExternalPayloadView};
13pub use stored::{
14 HostExternalPayloadBuilder, HostExternalPayloadView, HostStoredType, HostStoredValue,
15};
16
17pub trait HostExternalSchema: Send + Sync + 'static {
19 const PACKAGE: &'static str;
20 const MODULE: &'static str;
21 const NAME: &'static str;
22 const PARAMETER_COUNT: usize;
23}
24
25pub trait HostExternalStorage<Profile, Schema>: Send + Sync + 'static
33where
34 Profile: HostProfile,
35 Schema: HostExternalSchema,
36{
37 type Payload: 'static;
38
39 fn store(stores: &Profile::ExternalStores) -> &HostExternalStore<Self::Payload>;
41
42 fn source_equal(
44 context: &HostExternalEquality<'_>,
45 left: &Self::Payload,
46 right: &Self::Payload,
47 ) -> bool;
48
49 fn source_hash(context: &HostExternalHashing<'_>, value: &Self::Payload) -> u64;
51
52 fn inspect(context: &HostExternalInspection<'_>, value: &Self::Payload) -> EcoString;
54}
55
56pub trait HostExternalBinding<Profile, Schema>: HostProvider<Profile>
58where
59 Profile: HostProfile,
60 Schema: HostExternalSchema,
61{
62 type Storage: HostExternalStorage<Profile, Schema>;
63}
64
65pub struct HostExternalEquality<'context> {
67 equal: &'context dyn Fn(
68 &crate::runtime::StoredRuntimeValue,
69 &crate::runtime::StoredRuntimeValue,
70 ) -> bool,
71}
72
73pub struct HostExternalHashing<'context> {
75 source_hash: &'context dyn Fn(&crate::runtime::StoredRuntimeValue) -> u64,
76}
77
78pub struct HostExternalInspection<'context> {
80 inspect: &'context dyn Fn(&crate::runtime::StoredRuntimeValue) -> EcoString,
81}
82
83pub struct HostExternalType<Schema, Arguments = HostTypeListEnd>(PhantomData<(Schema, Arguments)>);
85
86impl<'context> HostExternalEquality<'context> {
87 pub(crate) fn new(
88 equal: &'context dyn Fn(
89 &crate::runtime::StoredRuntimeValue,
90 &crate::runtime::StoredRuntimeValue,
91 ) -> bool,
92 ) -> Self {
93 Self { equal }
94 }
95
96 pub fn stored_values_equal<Type>(
98 &self,
99 left: &HostStoredValue<Type>,
100 right: &HostStoredValue<Type>,
101 ) -> bool {
102 (self.equal)(&left.value, &right.value)
103 }
104
105 pub fn dynamic_values_equal(
107 &self,
108 left: &HostStoredDynamic,
109 right: &HostStoredDynamic,
110 ) -> bool {
111 (self.equal)(left.runtime_value(), right.runtime_value())
112 }
113}
114
115impl<'context> HostExternalHashing<'context> {
116 pub(crate) fn new(
117 source_hash: &'context dyn Fn(&crate::runtime::StoredRuntimeValue) -> u64,
118 ) -> Self {
119 Self { source_hash }
120 }
121
122 pub fn stored_value_hash<Type>(&self, value: &HostStoredValue<Type>) -> u64 {
124 (self.source_hash)(&value.value)
125 }
126
127 pub fn dynamic_value_hash(&self, value: &HostStoredDynamic) -> u64 {
129 (self.source_hash)(value.runtime_value())
130 }
131}
132
133impl<'context> HostExternalInspection<'context> {
134 pub(crate) fn new(
135 inspect: &'context dyn Fn(&crate::runtime::StoredRuntimeValue) -> EcoString,
136 ) -> Self {
137 Self { inspect }
138 }
139
140 pub fn inspect_stored_value<Type>(&self, value: &HostStoredValue<Type>) -> EcoString {
142 (self.inspect)(&value.value)
143 }
144
145 pub fn inspect_dynamic_value(&self, value: &HostStoredDynamic) -> EcoString {
147 (self.inspect)(value.runtime_value())
148 }
149}
150
151#[derive(Debug, Clone, PartialEq, Eq)]
153pub struct HostExternalTypeSchema {
154 package: EcoString,
155 module: EcoString,
156 name: EcoString,
157 parameter_count: usize,
158}
159
160impl HostExternalTypeSchema {
161 pub fn of<Schema: HostExternalSchema>() -> Self {
162 Self::new(
163 Schema::PACKAGE,
164 Schema::MODULE,
165 Schema::NAME,
166 Schema::PARAMETER_COUNT,
167 )
168 }
169
170 pub fn new(
171 package: impl Into<EcoString>,
172 module: impl Into<EcoString>,
173 name: impl Into<EcoString>,
174 parameter_count: usize,
175 ) -> Self {
176 Self {
177 package: package.into(),
178 module: module.into(),
179 name: name.into(),
180 parameter_count,
181 }
182 }
183
184 pub fn package(&self) -> &EcoString {
185 &self.package
186 }
187
188 pub fn module(&self) -> &EcoString {
189 &self.module
190 }
191
192 pub fn name(&self) -> &EcoString {
193 &self.name
194 }
195
196 pub fn parameter_count(&self) -> usize {
197 self.parameter_count
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::{
204 HostExternalEquality, HostExternalHashing, HostExternalInspection, HostStoredDynamic,
205 HostStoredValue,
206 };
207 use num_bigint::BigInt;
208
209 #[test]
210 fn external_semantics_contexts_delegate_typed_and_dynamic_values() {
211 let typed = HostStoredValue::<BigInt>::new(crate::runtime::StoredRuntimeValue::test_int(
212 BigInt::from(7),
213 ));
214 let other = HostStoredValue::<BigInt>::new(crate::runtime::StoredRuntimeValue::test_int(
215 BigInt::from(8),
216 ));
217 let dynamic = HostStoredDynamic::new(crate::runtime::StoredRuntimeValue::test_int(
218 BigInt::from(9),
219 ));
220 let other_dynamic = HostStoredDynamic::new(crate::runtime::StoredRuntimeValue::test_int(
221 BigInt::from(10),
222 ));
223 let equal =
224 |_: &crate::runtime::StoredRuntimeValue, _: &crate::runtime::StoredRuntimeValue| true;
225 let source_hash = |_: &crate::runtime::StoredRuntimeValue| 17;
226 let inspect = |_: &crate::runtime::StoredRuntimeValue| "Int".into();
227 let equality = HostExternalEquality::new(&equal);
228 let hashing = HostExternalHashing::new(&source_hash);
229 let inspection = HostExternalInspection::new(&inspect);
230
231 assert!(equality.stored_values_equal(&typed, &other));
232 assert!(equality.dynamic_values_equal(&dynamic, &other_dynamic));
233 assert_eq!(hashing.stored_value_hash(&typed), 17);
234 assert_eq!(hashing.dynamic_value_hash(&dynamic), 17);
235 assert_eq!(inspection.inspect_stored_value(&typed), "Int");
236 assert_eq!(inspection.inspect_dynamic_value(&dynamic), "Int");
237 }
238}
239
240#[cfg(test)]
241pub(crate) struct ExternalTestProfile;
242
243#[cfg(test)]
244#[derive(Default)]
245pub(crate) struct ExternalTestRunState {
246 pub(crate) provider: (),
247}
248
249#[cfg(test)]
250#[derive(Default)]
251pub(crate) struct ExternalTestStores {
252 pub(crate) units: HostExternalStore<()>,
253 pub(crate) integers: HostExternalStore<num_bigint::BigInt>,
254 pub(crate) indices: HostExternalStore<usize>,
255}
256
257#[cfg(test)]
258impl HostProfile for ExternalTestProfile {
259 type RunState = ExternalTestRunState;
260 type ExternalStores = ExternalTestStores;
261}