kampu/
forest.rs

1use std::collections::HashMap;
2use std::sync::{Mutex};
3use once_cell::sync::Lazy;
4use serde_json::Value;
5
6use crate::tree::{parse_schema, schema_to_tree, Tree};
7
8pub static PLANTED_PARSE_TREES:Lazy<Mutex<HashMap<u64, Tree>>> = Lazy::new(|| {
9    let hm:HashMap<u64, Tree> = HashMap::new();
10    Mutex::new(hm)
11});
12
13pub fn is_tree_planted(unique_tree_id:u64) -> bool {
14    PLANTED_PARSE_TREES.lock().unwrap().contains_key(&unique_tree_id)
15}
16
17pub fn plant_tree_schema(unique_tree_id:u64, schema: Tree) -> i32 {
18    let mut hm = PLANTED_PARSE_TREES.lock().unwrap();
19    hm.insert(unique_tree_id, schema);
20    0
21}
22
23pub fn plant_tree(unique_tree_id:u64, schema: Value) -> i32 {
24    plant_tree_schema(unique_tree_id, schema_to_tree(schema))
25}
26
27pub fn parse_tree(
28    unique_tree_id: u64,
29    data: &[u8]
30) -> Result<Value, String>
31{
32    let schema:Tree = {
33        //use this block to quickly get, clone and release the lock on the mutex-locked map
34        let reg_map = PLANTED_PARSE_TREES.lock().unwrap();
35        let sr = reg_map.get(&unique_tree_id).ok_or(format!("No tree with unique_tree_id {} found", unique_tree_id))?;
36        let so = sr.clone();
37        so
38    };
39
40    let mut previous_values = HashMap::new();
41    let parse_ret = parse_schema(&data, &schema.branches, false, &mut previous_values);
42    match parse_ret {
43        Ok((parsed_json, _parse_pos)) => {
44            Ok(parsed_json)
45        }
46        Err((partially_parsed_json, errstr)) => {
47            println!("WARNING: (normal for infinite loops or loops beyond bytes provided) parse_schema() failed with error: {errstr}, returning partially_parsed_json struct");
48            Ok(partially_parsed_json)
49        }
50    }
51}
52
53#[cfg(test)]
54use serde_json::json;
55#[cfg(test)]
56use crate::utils::hex_to_bin;
57
58#[test]
59fn test_simple_packet() {
60    const TREE_ID:u64 = 1;
61    let data = hex_to_bin("01 00 E8 03");
62    plant_tree(
63        TREE_ID,
64        json!({
65                "branches": [
66                    { "name": "fix_status", "type": "u8" },
67                    { "name": "rcr", "type": "u8" },
68                    { "name": "millisecond", "type": "u16_le" }
69                ]
70            })
71    );
72    let parsed_json = parse_tree(TREE_ID, &data).unwrap();
73    assert_eq!(parsed_json, json!({
74            "fix_status": 1,
75            "rcr": 0,
76            "millisecond": 1000
77        }));
78}