Skip to main content

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}