micromegas_tracing/
property_set.rs

1//! Interned collection of PropertySet instances. Each PropertySet contains properties where the names and the values are statically allocated.
2//! The user is expected to manage the cardinality.
3use crate::static_string_ref::StaticStringRef;
4use internment::Intern;
5use micromegas_transit::{UserDefinedType, prelude::*};
6use std::{hash::Hash, sync::Arc};
7
8lazy_static::lazy_static! {
9    pub static ref PROPERTY_SET_DEP_TYPE_NAME: Arc<String> = Arc::new("PropertySetDependency".into());
10}
11
12#[derive(Debug, Eq, PartialEq, Hash, Clone, TransitReflect)]
13pub struct Property {
14    pub name: StaticStringRef,
15    pub value: StaticStringRef,
16}
17
18impl Property {
19    pub fn new(name: &'static str, value: &'static str) -> Self {
20        Self {
21            name: name.into(),
22            value: value.into(),
23        }
24    }
25}
26
27pub fn property_get<'a>(properties: &'a [Property], name: &str) -> Option<&'a str> {
28    properties.iter().find_map(|p| {
29        if p.name.as_str().eq_ignore_ascii_case(name) {
30            Some(p.value.as_str())
31        } else {
32            None
33        }
34    })
35}
36
37#[derive(Debug, Clone, Eq, PartialEq, Hash)]
38pub struct PropertySet {
39    properties: Vec<Property>,
40}
41
42impl PropertySet {
43    pub fn find_or_create(mut properties: Vec<Property>) -> &'static Self {
44        // sort properties by name to get the same hash
45        properties.sort_by(|a, b| b.name.as_str().cmp(a.name.as_str()));
46        let set = PropertySet { properties };
47        Intern::<PropertySet>::new(set).as_ref()
48    }
49
50    pub fn get_properties(&self) -> &[Property] {
51        &self.properties
52    }
53}
54
55#[derive(Debug)]
56pub struct PropertySetDependency {
57    set: &'static PropertySet,
58}
59
60impl PropertySetDependency {
61    pub fn new(set: &'static PropertySet) -> Self {
62        Self { set }
63    }
64}
65
66impl Reflect for PropertySetDependency {
67    fn reflect() -> UserDefinedType {
68        UserDefinedType {
69            name: PROPERTY_SET_DEP_TYPE_NAME.clone(),
70            size: 0,
71            members: vec![],
72            is_reference: false,
73            secondary_udts: vec![Property::reflect()],
74        }
75    }
76}
77
78impl InProcSerialize for PropertySetDependency {
79    const IN_PROC_SIZE: InProcSize = InProcSize::Dynamic;
80
81    fn get_value_size(&self) -> Option<u32> {
82        let header_size: u32 = std::mem::size_of::<u64>() as u32 + // id
83			std::mem::size_of::<u32>() as u32; // number of properties
84        let container_size: u32 =
85            self.set.get_properties().len() as u32 * std::mem::size_of::<Property>() as u32;
86        let size = header_size + container_size;
87        Some(size)
88    }
89
90    fn write_value(&self, buffer: &mut Vec<u8>) {
91        let id = self.set as *const _ as u64;
92        write_any(buffer, &id);
93        let nb_properties: u32 = self.set.get_properties().len() as u32;
94        write_any(buffer, &nb_properties);
95        for prop in self.set.get_properties() {
96            write_any(buffer, prop);
97        }
98    }
99
100    unsafe fn read_value(mut _window: &[u8]) -> Self {
101        // dependencies don't need to be read in the instrumented process
102        unimplemented!();
103    }
104}