use std::collections::BTreeMap;
use serde_cbor::{from_slice, Value};
use serde_json::json;
use crate::ServiceDescriptor;
pub fn find_services(capability: &str, doc: &BTreeMap<Value, Value>) -> Vec<ServiceDescriptor> {
let mut services = Vec::new();
let Some(Value::Array(nodes)) = doc.get(&Value::Text("ServiceNodes".to_string())) else {
println!("❌ No 'ServiceNodes' found in PKI document.");
return services;
};
for node in nodes {
let Value::Bytes(node_bytes) = node else { continue };
let Ok(mynode) = from_slice::<BTreeMap<Value, Value>>(node_bytes) else { continue };
if let Some(Value::Map(details)) = mynode.get(&Value::Text("Kaetzchen".to_string())) {
println!("🔍 Available Capabilities: {:?}", details.keys());
}
let Some(Value::Map(details)) = mynode.get(&Value::Text("Kaetzchen".to_string())) else { continue };
let Some(Value::Map(service)) = details.get(&Value::Text(capability.to_string())) else { continue };
let Some(Value::Text(endpoint)) = service.get(&Value::Text("endpoint".to_string())) else { continue };
println!("returning a service descriptor!");
services.push(ServiceDescriptor {
recipient_queue_id: endpoint.as_bytes().to_vec(),
mix_descriptor: mynode,
});
}
services
}
fn convert_to_pretty_json(value: &Value) -> serde_json::Value {
match value {
Value::Text(s) => serde_json::Value::String(s.clone()),
Value::Integer(i) => json!(*i),
Value::Bytes(b) => json!(hex::encode(b)), Value::Array(arr) => serde_json::Value::Array(arr.iter().map(convert_to_pretty_json).collect()),
Value::Map(map) => {
let converted_map: serde_json::Map<String, serde_json::Value> = map
.iter()
.map(|(key, value)| {
let key_str = match key {
Value::Text(s) => s.clone(),
_ => format!("{:?}", key),
};
(key_str, convert_to_pretty_json(value))
})
.collect();
serde_json::Value::Object(converted_map)
}
_ => serde_json::Value::Null, }
}
fn decode_cbor_nodes(nodes: &[Value]) -> Vec<Value> {
nodes
.iter()
.filter_map(|node| match node {
Value::Bytes(blob) => serde_cbor::from_slice::<BTreeMap<Value, Value>>(blob)
.ok()
.map(Value::Map),
_ => Some(node.clone()), })
.collect()
}
pub fn pretty_print_pki_doc(doc: &BTreeMap<Value, Value>) {
let mut new_doc = BTreeMap::new();
if let Some(Value::Array(gateway_nodes)) = doc.get(&Value::Text("GatewayNodes".to_string())) {
new_doc.insert(Value::Text("GatewayNodes".to_string()), Value::Array(decode_cbor_nodes(gateway_nodes)));
}
if let Some(Value::Array(service_nodes)) = doc.get(&Value::Text("ServiceNodes".to_string())) {
new_doc.insert(Value::Text("ServiceNodes".to_string()), Value::Array(decode_cbor_nodes(service_nodes)));
}
if let Some(Value::Array(topology_layers)) = doc.get(&Value::Text("Topology".to_string())) {
let decoded_topology: Vec<Value> = topology_layers
.iter()
.flat_map(|layer| match layer {
Value::Array(layer_nodes) => decode_cbor_nodes(layer_nodes),
_ => vec![],
})
.collect();
new_doc.insert(Value::Text("Topology".to_string()), Value::Array(decoded_topology));
}
for (key, value) in doc.iter() {
if !matches!(key, Value::Text(s) if ["GatewayNodes", "ServiceNodes", "Topology"].contains(&s.as_str())) {
let key_str = key.clone();
let decoded_value = match value {
Value::Bytes(blob) => serde_cbor::from_slice::<BTreeMap<Value, Value>>(blob)
.ok()
.map(Value::Map)
.unwrap_or(value.clone()), _ => value.clone(),
};
new_doc.insert(key_str, decoded_value);
}
}
let pretty_json = convert_to_pretty_json(&Value::Map(new_doc));
println!("{}", serde_json::to_string_pretty(&pretty_json).unwrap());
}