1use corium_core::{EntityId, Value};
4use corium_db::Db;
5
6use crate::edn::Edn;
7use crate::exec::UNKNOWN_KEYWORD;
8
9#[must_use]
14pub fn value_to_edn(db: &Db, value: &Value) -> Edn {
15 match value {
16 Value::Bool(v) => Edn::Bool(*v),
17 Value::Long(v) => Edn::Long(*v),
18 Value::Double(v) => Edn::Double(*v),
19 Value::Str(v) => Edn::Str(v.to_string()),
20 Value::Instant(ms) => Edn::Tagged("inst".into(), Box::new(Edn::Long(*ms))),
21 Value::Uuid(v) => Edn::Tagged("uuid".into(), Box::new(Edn::Str(format!("{v:032x}")))),
22 Value::Bytes(bytes) => Edn::Tagged(
23 "bytes".into(),
24 Box::new(Edn::Str(bytes.iter().fold(String::new(), |mut acc, b| {
25 use std::fmt::Write as _;
26 let _ = write!(acc, "{b:02x}");
27 acc
28 }))),
29 ),
30 Value::Keyword(id) => db.interner().resolve(*id).map_or_else(
31 || {
32 Edn::Tagged(
33 "kw".into(),
34 Box::new(Edn::Long(i64::try_from(*id).unwrap_or(-1))),
35 )
36 },
37 |keyword| Edn::Keyword(keyword.clone()),
38 ),
39 Value::Ref(e) => Edn::Long(i64::try_from(e.raw()).unwrap_or(i64::MAX)),
40 }
41}
42
43#[must_use]
49pub fn edn_to_value(db: Option<&Db>, form: &Edn) -> Option<Value> {
50 match form {
51 Edn::Bool(v) => Some(Value::Bool(*v)),
52 Edn::Long(v) => Some(Value::Long(*v)),
53 Edn::Double(v) => Some(Value::Double(*v)),
54 Edn::Str(v) => Some(Value::Str(v.as_str().into())),
55 Edn::Keyword(k) => Some(Value::Keyword(
56 db.and_then(|db| db.interner().get(k))
57 .unwrap_or(UNKNOWN_KEYWORD),
58 )),
59 Edn::Tagged(tag, value) => match (tag.as_str(), value.as_ref()) {
60 ("eid", Edn::Long(n)) => u64::try_from(*n)
61 .ok()
62 .map(|n| Value::Ref(EntityId::from_raw(n))),
63 ("tx", Edn::Long(t)) => u64::try_from(*t)
64 .ok()
65 .map(|t| Value::Ref(EntityId::new(corium_core::Partition::Tx as u32, t))),
66 ("inst", Edn::Long(ms)) => Some(Value::Instant(*ms)),
67 ("uuid", Edn::Str(hex)) => u128::from_str_radix(hex, 16).ok().map(Value::Uuid),
68 _ => None,
69 },
70 _ => None,
71 }
72}