mimir_core/value.rs
1//! `Value` — the typed-value enum used in memory slots that accept either
2//! a symbol, a number, a boolean, a string, or a timestamp. Matches the
3//! value-tag set in `docs/concepts/ir-canonical-form.md` § 3.2.
4
5use crate::clock::ClockTime;
6use crate::symbol::SymbolId;
7
8/// A typed value that can appear in a memory slot such as
9/// [`crate::Semantic::o`] or [`crate::Procedural::trigger`].
10///
11/// Mirrors the canonical-form value tags:
12/// `Symbol` (0x01), `Integer` (0x02), `Float` (0x03), `Boolean` (0x04),
13/// `String` (0x05), `Timestamp` (0x06) — see `ir-canonical-form.md` § 3.2.
14///
15/// # Examples
16///
17/// ```
18/// use mimir_core::{SymbolId, Value};
19///
20/// let v = Value::Symbol(SymbolId::new(42));
21/// assert!(matches!(v, Value::Symbol(_)));
22/// ```
23#[derive(Clone, Debug, PartialEq)]
24pub enum Value {
25 /// A symbol reference (wire tag `0x01`).
26 Symbol(SymbolId),
27 /// A signed 64-bit integer (wire tag `0x02`, `ZigZag` varint-encoded).
28 Integer(i64),
29 /// An IEEE 754 binary64 float (wire tag `0x03`).
30 Float(f64),
31 /// A boolean (wire tag `0x04`).
32 Boolean(bool),
33 /// A UTF-8 string literal (wire tag `0x05`).
34 String(String),
35 /// A timestamp (wire tag `0x06`).
36 Timestamp(ClockTime),
37}
38
39impl Value {
40 /// Canonical-byte encoding used as an in-process `BTreeMap` key
41 /// — `Value` cannot implement `Ord` (it carries `f64`), but its
42 /// canonical-form encoding is byte-deterministic.
43 ///
44 /// `pub(crate)` rather than `pub` on purpose: the output is NOT
45 /// stable across wire-format revisions, so exposing it invites
46 /// callers to persist it as an identifier. The
47 /// `mimir_core::canonical` encoder remains the public boundary
48 /// for wire-format work.
49 #[must_use]
50 pub(crate) fn index_key_bytes(&self) -> Vec<u8> {
51 let mut out = Vec::new();
52 crate::canonical::encode_value(self, &mut out);
53 out
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn value_variants_compare_by_content() {
63 assert_eq!(Value::Integer(5), Value::Integer(5));
64 assert_ne!(Value::Integer(5), Value::Integer(6));
65 assert_ne!(Value::Integer(5), Value::Boolean(false));
66 }
67
68 #[test]
69 fn float_value_preserves_precision() {
70 let a = Value::Float(1.25);
71 let b = Value::Float(1.25);
72 assert_eq!(a, b);
73 }
74}