rdf_fusion_encoding/
encodings.rs

1use crate::object_id::{ObjectIdEncoding, ObjectIdMapping};
2use crate::plain_term::PlainTermEncoding;
3use crate::sortable_term::SortableTermEncoding;
4use crate::typed_value::TypedValueEncoding;
5use crate::{EncodingName, TermEncoding};
6use datafusion::arrow::datatypes::DataType;
7use std::hash::{Hash, Hasher};
8use std::sync::Arc;
9
10/// Holds a configuration instance for each RDF Fusion encoding.
11///
12/// This is an instance (as opposed to a type) as some encodings can be configured. At least
13/// this is planned for the future. For each RDF Fusion instance, the encodings are fixed once it
14/// is created.
15///
16/// # Equality
17///
18/// The equality and hashing functions check for pointer equality of the underlying encodings.
19#[derive(Debug, Clone)]
20pub struct RdfFusionEncodings {
21    /// The [PlainTermEncoding] configuration.
22    plain_term: Arc<PlainTermEncoding>,
23    /// The [TypedValueEncoding] configuration.
24    typed_value: Arc<TypedValueEncoding>,
25    /// The [ObjectIdEncoding] configuration.
26    object_id: Option<Arc<ObjectIdEncoding>>,
27    /// The used [ObjectIdMapping]. The encoding configuration can be obtained from the mapping.
28    object_id_mapping: Option<Arc<dyn ObjectIdMapping>>,
29    /// The [SortableTermEncoding] configuration.
30    sortable_term: Arc<SortableTermEncoding>,
31}
32
33impl RdfFusionEncodings {
34    /// Creates a new [RdfFusionEncodings].
35    pub fn new(
36        plain_term: PlainTermEncoding,
37        typed_value: TypedValueEncoding,
38        object_id_mapping: Option<Arc<dyn ObjectIdMapping>>,
39        sortable_term: SortableTermEncoding,
40    ) -> Self {
41        Self {
42            plain_term: Arc::new(plain_term),
43            typed_value: Arc::new(typed_value),
44            object_id: object_id_mapping
45                .as_ref()
46                .map(|mapping| Arc::new(mapping.encoding())),
47            object_id_mapping,
48            sortable_term: Arc::new(sortable_term),
49        }
50    }
51
52    /// Provides a reference to the used [PlainTermEncoding].
53    pub fn plain_term(&self) -> &PlainTermEncoding {
54        &self.plain_term
55    }
56
57    /// Provides a reference to the used [TypedValueEncoding].
58    pub fn typed_value(&self) -> &TypedValueEncoding {
59        &self.typed_value
60    }
61
62    /// Provides a reference to the used [ObjectIdEncoding].
63    pub fn object_id(&self) -> Option<&ObjectIdEncoding> {
64        self.object_id.as_ref().map(AsRef::as_ref)
65    }
66
67    /// Provides a reference to the used [ObjectIdEncoding].
68    pub fn object_id_mapping(&self) -> Option<&dyn ObjectIdMapping> {
69        self.object_id_mapping.as_ref().map(AsRef::as_ref)
70    }
71
72    /// Provides a reference to the used [SortableTermEncoding].
73    pub fn sortable_term(&self) -> &SortableTermEncoding {
74        &self.sortable_term
75    }
76
77    /// Returns a vector of [EncodingName] for the given `names`.
78    ///
79    /// If some encodings are not defined in this RDF Fusion instance (e.g., no object ID encoding),
80    /// the corresponding [EncodingName] is ignored.
81    pub fn get_data_types(&self, names: &[EncodingName]) -> Vec<DataType> {
82        let mut result = Vec::new();
83
84        if names.contains(&EncodingName::PlainTerm) {
85            result.push(self.plain_term.data_type());
86        }
87
88        if names.contains(&EncodingName::TypedValue) {
89            result.push(self.typed_value.data_type());
90        }
91
92        if let Some(object_id) = self.object_id.as_ref()
93            && names.contains(&EncodingName::ObjectId)
94        {
95            result.push(object_id.as_ref().data_type());
96        }
97
98        if names.contains(&EncodingName::Sortable) {
99            result.push(self.sortable_term.data_type());
100        }
101
102        result
103    }
104
105    /// Tries to obtain an [EncodingName] from a [DataType]. As we currently only support built-in
106    /// encodings this mapping is unique.
107    ///
108    /// In the future we might use a field here such that we can access metadata information.
109    pub fn try_get_encoding_name(&self, data_type: &DataType) -> Option<EncodingName> {
110        if data_type == &PlainTermEncoding.data_type() {
111            return Some(EncodingName::PlainTerm);
112        }
113
114        if data_type == &self.typed_value.data_type() {
115            return Some(EncodingName::TypedValue);
116        }
117
118        if let Some(object_id) = self.object_id.as_ref()
119            && data_type == &object_id.data_type()
120        {
121            return Some(EncodingName::ObjectId);
122        }
123
124        if data_type == &self.sortable_term.data_type() {
125            return Some(EncodingName::Sortable);
126        }
127
128        None
129    }
130}
131
132impl PartialEq for RdfFusionEncodings {
133    fn eq(&self, other: &Self) -> bool {
134        let object_id_equal = match (&self.object_id, &other.object_id) {
135            (Some(a), Some(b)) => Arc::ptr_eq(a, b),
136            (None, None) => true,
137            _ => false,
138        };
139
140        object_id_equal
141            && Arc::ptr_eq(&self.plain_term, &other.plain_term)
142            && Arc::ptr_eq(&self.typed_value, &other.typed_value)
143            && Arc::ptr_eq(&self.sortable_term, &other.sortable_term)
144    }
145}
146
147impl Eq for RdfFusionEncodings {}
148
149impl Hash for RdfFusionEncodings {
150    fn hash<H: Hasher>(&self, state: &mut H) {
151        state.write_usize(Arc::as_ptr(&self.plain_term) as usize);
152        state.write_usize(Arc::as_ptr(&self.typed_value) as usize);
153        if let Some(object_id) = &self.object_id {
154            state.write_usize(Arc::as_ptr(object_id) as usize);
155        }
156        state.write_usize(Arc::as_ptr(&self.sortable_term) as usize);
157    }
158}