1use corium_core::{
12 AttrId, Attribute, Cardinality, Datom, EntityId, Keyword, Partition, Schema, Value, ValueType,
13};
14
15use crate::Idents;
16
17pub const TX_INSTANT: AttrId = EntityId::new(Partition::Db as u32, 50);
19
20#[must_use]
22pub fn tx_instant_ident() -> Keyword {
23 Keyword::new(Some("db"), "txInstant")
24}
25
26#[must_use]
31pub const fn tx_instant_attribute() -> Attribute {
32 Attribute {
33 id: TX_INSTANT,
34 value_type: ValueType::Instant,
35 cardinality: Cardinality::One,
36 unique: None,
37 is_component: false,
38 indexed: true,
39 no_history: false,
40 }
41}
42
43pub fn install(schema: &mut Schema, idents: &mut Idents) {
48 schema.insert(tx_instant_attribute());
49 idents.insert(tx_instant_ident(), TX_INSTANT);
50}
51
52pub fn install_schema(schema: &mut Schema) {
54 schema.insert(tx_instant_attribute());
55}
56
57#[must_use]
59pub fn tx_instant_datom(t: u64, instant: i64) -> Datom {
60 let tx = EntityId::new(Partition::Tx as u32, t);
61 Datom {
62 e: tx,
63 a: TX_INSTANT,
64 v: Value::Instant(instant),
65 tx,
66 added: true,
67 }
68}
69
70#[must_use]
75pub fn asserted_instant(t: u64, datoms: &[Datom]) -> Option<i64> {
76 let tx = EntityId::new(Partition::Tx as u32, t);
77 let mut asserted = None;
78 for datom in datoms {
79 if let Datom {
80 e,
81 a,
82 v: Value::Instant(instant),
83 added,
84 ..
85 } = datom
86 && *e == tx
87 && *a == TX_INSTANT
88 {
89 if *added {
90 asserted = Some(*instant);
91 } else if asserted == Some(*instant) {
92 asserted = None;
93 }
94 }
95 }
96 asserted
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn install_is_idempotent() {
105 let mut schema = Schema::default();
106 let mut idents = Idents::default();
107 install(&mut schema, &mut idents);
108 install(&mut schema, &mut idents);
109 assert_eq!(schema.iter().count(), 1);
110 assert_eq!(idents.iter().count(), 1);
111 assert_eq!(idents.entid(&tx_instant_ident()), Some(TX_INSTANT));
112 }
113
114 #[test]
115 fn asserted_instant_finds_transaction_metadata() {
116 let datoms = vec![tx_instant_datom(7, 1_700_000_000_000)];
117 assert_eq!(asserted_instant(7, &datoms), Some(1_700_000_000_000));
118 assert_eq!(asserted_instant(8, &datoms), None);
119 }
120
121 #[test]
122 fn asserted_instant_uses_the_final_cardinality_one_value() {
123 let mut datoms = vec![tx_instant_datom(7, 2_000)];
124 let mut retract = tx_instant_datom(7, 2_000);
125 retract.added = false;
126 datoms.push(retract);
127 datoms.push(tx_instant_datom(7, 1_000));
128 assert_eq!(asserted_instant(7, &datoms), Some(1_000));
129 }
130}