bones_schema/alloc/
type_datas.rs1use append_only_vec::AppendOnlyVec;
2
3use crate::prelude::*;
4
5#[derive(Debug)]
10pub struct TypeDatas(AppendOnlyVec<SchemaBox>);
16impl Default for TypeDatas {
17 fn default() -> Self {
18 Self(AppendOnlyVec::new())
19 }
20}
21impl Clone for TypeDatas {
22 fn clone(&self) -> Self {
23 let clone = TypeDatas::default();
24 for entry in self.0.iter() {
25 clone.insert(entry.clone()).unwrap();
26 }
27 clone
28 }
29}
30
31impl TypeDatas {
32 pub fn insert<T: HasSchema>(&self, data: T) -> Result<(), TypeDataAlreadyInserted> {
34 self.insert_box(SchemaBox::new(data))
35 }
36
37 pub fn insert_box(&self, data: SchemaBox) -> Result<(), TypeDataAlreadyInserted> {
39 let schema = data.schema();
40 for entry in self.0.iter() {
41 if entry.schema() == schema {
42 return Err(TypeDataAlreadyInserted(schema));
43 }
44 }
45 self.0.push(data);
46 Ok(())
47 }
48
49 pub fn get<T: HasSchema>(&self) -> Option<&T> {
51 let id = T::schema().id();
52 for data in self.0.iter() {
53 if data.schema().id() == id {
54 return Some(data.cast_ref());
55 }
56 }
57 None
58 }
59
60 pub fn get_ref(&self, id: SchemaId) -> Option<SchemaRef<'_>> {
62 for data in self.0.iter() {
63 if data.schema().id() == id {
64 return Some(data.as_ref());
65 }
66 }
67 None
68 }
69
70 pub fn iter(&self) -> impl DoubleEndedIterator<Item = &SchemaBox> {
72 self.0.iter()
73 }
74}
75
76#[derive(Debug)]
78pub struct TypeDataAlreadyInserted(&'static Schema);
79
80impl std::fmt::Display for TypeDataAlreadyInserted {
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 f.write_fmt(format_args!(
83 "Type data already contains an entry of type: {}",
84 self.0.full_name,
85 ))
86 }
87}
88impl std::error::Error for TypeDataAlreadyInserted {}
89
90#[cfg(test)]
91mod test {
92 use super::*;
93
94 #[test]
95 fn smoke() {
96 let tds = TypeDatas::default();
97
98 tds.insert(String::from("hi")).unwrap();
99 assert_eq!(Some("hi"), tds.get::<String>().map(|x| x.as_str()));
100
101 tds.insert(7u32).unwrap();
102 assert_eq!(Some(&7), tds.get::<u32>());
103
104 let result = tds.insert(String::from("bye"));
105 assert!(matches!(result, Err(TypeDataAlreadyInserted(_))));
106 }
107}