reductionml_core/
interactions.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4use crate::{hash::hash_bytes, sparse_namespaced_features::Namespace};
5
6#[derive(Serialize, Deserialize, Clone, JsonSchema, Debug)]
7pub enum NamespaceDef {
8    Name(String),
9    Default,
10}
11
12pub type Interaction = Vec<NamespaceDef>;
13pub type HashedInteraction = Vec<Namespace>;
14
15pub fn hash_interaction(interaction: &Interaction, hash_seed: u32) -> HashedInteraction {
16    if interaction.is_empty() || interaction.len() > 3 {
17        panic!("Interaction must be between 1 and 3 namespaces")
18    }
19    interaction
20        .iter()
21        .map(|ns| match ns {
22            NamespaceDef::Name(name) => {
23                let namespace_hash = hash_bytes(name.as_bytes(), hash_seed);
24                Namespace::Named(namespace_hash.into())
25            }
26            NamespaceDef::Default => Namespace::Default,
27        })
28        .collect()
29}
30
31type InteractionPair = (Namespace, Namespace);
32type InteractionTriple = (Namespace, Namespace, Namespace);
33
34pub fn compile_interactions(
35    interactions: &[Interaction],
36    hash_seed: u32,
37) -> (Vec<InteractionPair>, Vec<InteractionTriple>) {
38    let pairs: Vec<(Namespace, Namespace)> = interactions
39        .iter()
40        .filter(|interaction| interaction.len() == 2)
41        .map(|interaction| {
42            let hashed_interaction = hash_interaction(interaction, hash_seed);
43            (hashed_interaction[0], hashed_interaction[1])
44        })
45        .collect();
46
47    let triples: Vec<(Namespace, Namespace, Namespace)> = interactions
48        .iter()
49        .filter(|interaction| interaction.len() == 3)
50        .map(|interaction| {
51            let hashed_interaction = hash_interaction(interaction, hash_seed);
52            (
53                hashed_interaction[0],
54                hashed_interaction[1],
55                hashed_interaction[2],
56            )
57        })
58        .collect();
59
60    if pairs.len() + triples.len() != interactions.len() {
61        panic!("Invalid interaction. Only pairs and triples are supported")
62    }
63
64    (pairs, triples)
65}