geam_core/runtime/value/
external.rs1use crate::host::ExternalPayloadLease;
2use crate::plan::ExternalType;
3use ecow::EcoString;
4
5#[derive(Clone)]
6pub struct ExternalValue {
7 type_: ExternalType,
8 identity: ExternalValueIdentity,
9 inspection: EcoString,
10 _lease: ExternalPayloadLease,
11}
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub struct ExternalValueIdentity(u64);
15
16impl ExternalValue {
17 pub(crate) fn from_evaluated(
18 type_: ExternalType,
19 lease: ExternalPayloadLease,
20 inspection: EcoString,
21 ) -> Self {
22 Self {
23 type_,
24 identity: ExternalValueIdentity(lease.id()),
25 inspection,
26 _lease: lease,
27 }
28 }
29
30 pub fn type_(&self) -> &ExternalType {
31 &self.type_
32 }
33
34 pub fn identity(&self) -> ExternalValueIdentity {
35 self.identity
36 }
37
38 pub fn inspection(&self) -> &EcoString {
39 &self.inspection
40 }
41}
42
43impl PartialEq for ExternalValue {
44 fn eq(&self, other: &Self) -> bool {
45 self.identity == other.identity
46 }
47}
48
49impl std::fmt::Debug for ExternalValue {
50 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 formatter
52 .debug_struct("ExternalValue")
53 .field("type_", &self.type_)
54 .field("identity", &self.identity)
55 .field("inspection", &self.inspection)
56 .finish_non_exhaustive()
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::ExternalValue;
63 use crate::host::HostExternalStore;
64 use crate::plan::{ExternalType, ExternalTypeName};
65
66 #[test]
67 fn opaque_external_value_exposes_identity_and_inspection_without_payload_access() {
68 let store = HostExternalStore::default();
69 let source_hash = |_: &crate::host::HostExternalHashing<'_>, value: &usize| *value as u64;
70 let inspect = |context: &crate::host::HostExternalInspection<'_>, value: &usize| {
71 let stored = crate::host::HostStoredValue::<num_bigint::BigInt>::new(
72 crate::runtime::StoredRuntimeValue::test_int((*value).into()),
73 );
74 format!("Resource({})", context.inspect_stored_value(&stored)).into()
75 };
76 let first = store.insert(7usize, |_, left, right| left == right, source_hash, inspect);
77 let second = store.insert(7usize, |_, left, right| left == right, source_hash, inspect);
78 let type_ = ExternalType::new(
79 ExternalTypeName::new("domain".into(), "domain/resource".into(), "Resource".into()),
80 Vec::new(),
81 );
82 let stored_equal =
83 |_: &crate::runtime::StoredRuntimeValue, _: &crate::runtime::StoredRuntimeValue| false;
84 let equality = crate::host::HostExternalEquality::new(&stored_equal);
85 let stored_hash = |_: &crate::runtime::StoredRuntimeValue| 17;
86 let stored_inspect = |_: &crate::runtime::StoredRuntimeValue| "7".into();
87 let hashing = crate::host::HostExternalHashing::new(&stored_hash);
88 let inspection = crate::host::HostExternalInspection::new(&stored_inspect);
89 assert!(first.source_equal(&equality, &second));
90 assert!(second.source_equal(&equality, &first));
91 assert_eq!(first.source_hash(&hashing), 7);
92 assert_eq!(first.inspection(&inspection), "Resource(7)");
93 assert_eq!(second.inspection(&inspection), "Resource(7)");
94 let first = ExternalValue::from_evaluated(type_.clone(), first, "Resource(7)".into());
95 let second = ExternalValue::from_evaluated(type_.clone(), second, "Resource(7)".into());
96 let cloned = first.clone();
97 let debug = format!("{first:?}");
98
99 assert_eq!(first.type_(), &type_);
100 assert_eq!(first.inspection(), "Resource(7)");
101 assert_eq!(first, cloned);
102 assert_ne!(first, second);
103 assert_eq!(first.identity(), cloned.identity());
104 assert!(debug.contains("ExternalValue"));
105 assert!(debug.contains("Resource(7)"));
106 assert!(!debug.contains("7usize"));
107 }
108}