1use exocore_protos::{
2 prost::Message,
3 store::{Entity, Trait},
4 NamedMessage,
5};
6
7pub type EntityId = String;
8pub type EntityIdRef<'s> = &'s str;
9pub type TraitId = String;
10pub type TraitIdRef<'s> = &'s str;
11
12pub struct TraitInstance<'e, M: NamedMessage + Message + Default> {
13 pub instance: M,
14 pub trt: &'e Trait,
15}
16
17pub trait EntityExt {
18 fn trait_with_id<M: NamedMessage + Message + Default>(
19 &self,
20 id: &str,
21 ) -> Option<TraitInstance<M>>;
22
23 fn traits_of_type<M: NamedMessage + Message + Default>(&self) -> Vec<TraitInstance<M>>;
24
25 fn trait_of_type<M: NamedMessage + Message + Default>(&self) -> Option<TraitInstance<M>>;
26}
27
28impl EntityExt for Entity {
29 fn trait_with_id<M: NamedMessage + Message + Default>(
30 &self,
31 id: &str,
32 ) -> Option<TraitInstance<M>> {
33 let msg_any_url = M::protobuf_any_url();
34
35 self.traits
36 .iter()
37 .filter(|t| t.id == id)
38 .flat_map(|t| {
39 let msg = t.message.as_ref()?;
40 if msg.type_url == msg_any_url {
41 let instance = M::decode(msg.value.as_slice()).ok()?;
42 Some(TraitInstance { instance, trt: t })
43 } else {
44 None
45 }
46 })
47 .next()
48 }
49
50 fn traits_of_type<M: NamedMessage + Message + Default>(&self) -> Vec<TraitInstance<M>> {
51 let msg_any_url = M::protobuf_any_url();
52
53 self.traits
54 .iter()
55 .flat_map(|t| {
56 let msg = t.message.as_ref()?;
57 if msg.type_url == msg_any_url {
58 let instance = M::decode(msg.value.as_slice()).ok()?;
59 Some(TraitInstance { instance, trt: t })
60 } else {
61 None
62 }
63 })
64 .collect()
65 }
66
67 fn trait_of_type<M: NamedMessage + Message + Default>(&self) -> Option<TraitInstance<M>> {
68 let msg_any_url = M::protobuf_any_url();
69
70 self.traits
71 .iter()
72 .flat_map(|t| {
73 let msg = t.message.as_ref()?;
74 if msg.type_url == msg_any_url {
75 let instance = M::decode(msg.value.as_slice()).ok()?;
76 Some(TraitInstance { instance, trt: t })
77 } else {
78 None
79 }
80 })
81 .next()
82 }
83}