somatize_core/key.rs
1//! What names what a node produces, before it produces it.
2//!
3//! A key is a Merkle hash **over the recipe** and not over the data: the
4//! identity of the node, what it was built with, the digest of the state it is
5//! settled at, and the keys of its predecessors. Only a root hashes content, so
6//! the key is known before anything runs and changing the classifier does not
7//! touch the key of the embeddings underneath it.
8//!
9//! The core computes none of them: hashing needs an algorithm and the core has
10//! no dependencies, so a `Key` arrives from the [`Keeper`](crate::Keeper) and
11//! this is only the shape it arrives in.
12
13use std::fmt;
14
15/// What a node's output is called, wherever it is kept. Text and not bytes
16/// because it is a name: it ends up in an index, a log line and an error.
17#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
18#[cfg_attr(
19 feature = "serde",
20 derive(serde::Serialize, serde::Deserialize),
21 serde(transparent)
22)]
23pub struct Key(String);
24
25impl Key {
26 /// A key somebody else computed. Only a [`Keeper`](crate::Keeper) should be
27 /// calling this: two keys made by different recipes have to be different,
28 /// and nothing here can check that.
29 pub fn new(text: impl Into<String>) -> Self {
30 Self(text.into())
31 }
32
33 /// As text.
34 pub fn as_str(&self) -> &str {
35 &self.0
36 }
37}
38
39impl fmt::Display for Key {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 f.write_str(&self.0)
42 }
43}
44
45/// What a node's output is called: one name, or one per item.
46///
47/// The second is what a [`.mapped()`](crate::Memory::map) node produces: with
48/// one name per node, adding a document to a list of a thousand misses all
49/// thousand; with one per item, the thousand hit and the new one runs.
50#[derive(Debug, Clone, PartialEq, Eq)]
51#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
52pub enum Keys {
53 /// The output is one thing and has one name.
54 One(Key),
55 /// The output is a list, and each item is named on its own — in order, and
56 /// as long as the list.
57 PerItem(Vec<Key>),
58}
59
60impl Keys {
61 /// The one name, if there is one. `None` for a list of them: what a single
62 /// name over many is made of is
63 /// [`Keeper::combine`](crate::Keeper::combine)'s to decide.
64 pub fn one(&self) -> Option<&Key> {
65 match self {
66 Self::One(key) => Some(key),
67 Self::PerItem(_) => None,
68 }
69 }
70
71 /// Every name in it, in order: one, or as many as there are items.
72 pub fn each(&self) -> &[Key] {
73 match self {
74 Self::One(key) => std::slice::from_ref(key),
75 Self::PerItem(keys) => keys,
76 }
77 }
78}
79
80impl fmt::Display for Keys {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 match self {
83 Self::One(key) => key.fmt(f),
84 Self::PerItem(keys) => write!(f, "{} items", keys.len()),
85 }
86 }
87}