hara_native/lang/data/
pointer.rs1use crate::core::Value;
2use crate::lang::data::{Keyword, Map, Metadata};
3use crate::lang::hash::JavaHash;
4use crate::lang::protocol::{HashType, IDisplay, IHash, IMetadata, IObjType, ObjType};
5use std::fmt;
6use std::hash::{Hash, Hasher};
7use std::rc::Rc;
8
9#[derive(Debug, Clone)]
14pub struct Pointer {
15 context: Keyword,
16 fields: Map<Value, Value>,
17 metadata: Option<Rc<Metadata>>,
18}
19
20impl Pointer {
21 pub fn new(context: Keyword, fields: Map<Value, Value>) -> Self {
22 Self {
23 context,
24 fields,
25 metadata: None,
26 }
27 }
28
29 pub fn context(&self) -> &Keyword {
30 &self.context
31 }
32
33 pub fn fields(&self) -> &Map<Value, Value> {
34 &self.fields
35 }
36
37 pub fn get(&self, key: &Value) -> Option<&Value> {
38 self.fields.get(key)
39 }
40
41 pub fn descriptor(&self) -> Map<Value, Value> {
42 self.fields.assoc_value(
43 Value::Keyword(Keyword::from("context")),
44 Value::Keyword(self.context.clone()),
45 )
46 }
47}
48
49impl PartialEq for Pointer {
50 fn eq(&self, other: &Self) -> bool {
51 self.context == other.context && self.fields == other.fields
52 }
53}
54
55impl Eq for Pointer {}
56
57impl IMetadata for Pointer {
58 type Metadata = Rc<Metadata>;
59
60 fn meta(&self) -> Option<&Self::Metadata> {
61 self.metadata.as_ref()
62 }
63
64 fn with_meta(&self, metadata: Option<Self::Metadata>) -> Self {
65 Self {
66 context: self.context.clone(),
67 fields: self.fields.clone(),
68 metadata,
69 }
70 }
71}
72
73impl IDisplay for Pointer {
74 fn display(&self) -> String {
75 format!("#ptr {}", Value::Map(self.descriptor()).display())
76 }
77}
78
79impl IObjType for Pointer {
80 fn obj_type(&self) -> ObjType {
81 ObjType::Pointer
82 }
83}
84
85impl IHash for Pointer {
86 fn hash_calc(&self, hash_type: HashType) -> u64 {
87 crate::lang::hash::compose_ordered(
88 "POINTER",
89 [
90 self.context.java_hash(hash_type),
91 self.fields.hash_calc(hash_type) as i64,
92 ],
93 ) as u64
94 }
95}
96
97impl crate::lang::hash::JavaHash for Pointer {
98 fn java_hash(&self, hash_type: HashType) -> i64 {
99 self.hash_calc(hash_type) as i64
100 }
101}
102
103impl Hash for Pointer {
104 fn hash<H: Hasher>(&self, state: &mut H) {
105 state.write_u64(self.hash_calc(crate::lang::hash::DEFAULT_HASH));
106 }
107}
108
109impl fmt::Display for Pointer {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 f.write_str(&self.display())
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn pointer_identity_is_structural_and_display_is_literal() {
121 let fields: Map<Value, Value> = vec![(
122 Value::Keyword(Keyword::from("id")),
123 Value::String("ROOT".into()),
124 )]
125 .into_iter()
126 .collect();
127 let left = Pointer::new(Keyword::from("kernel"), fields.clone());
128 let right = Pointer::new(Keyword::from("kernel"), fields);
129 assert_eq!(left, right);
130 assert_eq!(
131 left.hash_calc(HashType::Rapid),
132 right.hash_calc(HashType::Rapid)
133 );
134 assert!(left.display().starts_with("#ptr {"));
135 assert!(left.display().contains(":context :kernel"));
136 assert!(left.display().contains(":id \"ROOT\""));
137 }
138}