1use crate::class::Class;
2use crate::field::{FieldPath, FieldState};
3use crate::field_value::FieldValue;
4use crate::serializer::SerializerError;
5use prettytable::{row, Table};
6use std::fmt::{Debug, Display, Formatter};
7use std::rc::Rc;
8
9#[derive(Debug, Clone, Copy, Eq, PartialEq)]
10pub enum EntityEvents {
11 Created,
12 Updated,
13 Deleted,
14}
15
16impl EntityEvents {
17 #[inline]
18 pub(crate) fn from_cmd(cmd: u32) -> Self {
19 match cmd {
20 0 => EntityEvents::Updated,
21 2 => EntityEvents::Created,
22 3 => EntityEvents::Deleted,
23 _ => unreachable!(),
24 }
25 }
26}
27
28#[derive(thiserror::Error, Debug)]
29pub enum EntityError {
30 #[error("No entities found at index {0}")]
31 IndexNotFound(usize),
32
33 #[error("No entities found for handle {0}")]
34 HandleNotFound(usize),
35
36 #[error("No entities found for class with id {0}")]
37 ClassIdNotFound(i32),
38
39 #[error("No entities found for class with name {0}")]
40 ClassNameNotFound(String),
41
42 #[error("No property found for name {0} (Class: {1}, FieldPath: {2})")]
43 PropertyNameNotFound(String, String, String),
44
45 #[error(transparent)]
46 FieldPathNotFound(#[from] SerializerError),
47}
48
49pub struct Entities {
51 pub(crate) entities_vec: Vec<Option<Entity>>,
52}
53
54impl Default for Entities {
55 fn default() -> Self {
56 Entities {
57 entities_vec: vec![None; 8192],
58 }
59 }
60}
61
62impl Entities {
63 pub fn iter(&self) -> impl Iterator<Item = &Entity> {
89 self.entities_vec.iter().flatten()
90 }
91
92 pub fn get_by_index(&self, index: usize) -> Result<&Entity, EntityError> {
94 self.entities_vec
95 .get(index)
96 .and_then(|x| x.as_ref())
97 .ok_or(EntityError::IndexNotFound(index))
98 }
99
100 pub fn get_by_handle(&self, handle: usize) -> Result<&Entity, EntityError> {
102 self.get_by_index(handle & 0x3fff)
103 .map_err(|_| EntityError::HandleNotFound(handle))
104 }
105
106 pub fn get_by_class_id(&self, id: i32) -> Result<&Entity, EntityError> {
108 self.iter()
109 .find(|&entity| entity.class().id() == id)
110 .ok_or(EntityError::ClassIdNotFound(id))
111 }
112
113 pub fn get_by_class_name(&self, name: &str) -> Result<&Entity, EntityError> {
115 self.iter()
116 .find(|&entity| entity.class().name() == name)
117 .ok_or(EntityError::ClassNameNotFound(name.to_string()))
118 }
119}
120
121#[derive(Clone)]
122pub struct Entity {
123 index: u32,
124 serial: u32,
125 pub(crate) class: Rc<Class>,
126 pub(crate) state: FieldState,
127}
128
129impl Entity {
130 pub(crate) fn new(index: u32, serial: u32, class: Rc<Class>, state: FieldState) -> Self {
131 Entity {
132 index,
133 serial,
134 class,
135 state,
136 }
137 }
138
139 pub fn index(&self) -> u32 {
140 self.index
141 }
142
143 pub fn serial(&self) -> u32 {
144 self.serial
145 }
146
147 pub fn handle(&self) -> u32 {
148 self.serial << 14 | self.index
149 }
150
151 pub fn class(&self) -> &Class {
152 &self.class
153 }
154
155 pub fn get_property_by_name(&self, name: &str) -> Result<&FieldValue, EntityError> {
189 self.get_property_by_field_path(&self.class.serializer.get_field_path_for_name(name)?)
190 }
191
192 pub(crate) fn get_property_by_field_path(
193 &self,
194 fp: &FieldPath,
195 ) -> Result<&FieldValue, EntityError> {
196 self.state.get_value(fp).ok_or_else(|| {
197 EntityError::PropertyNameNotFound(
198 self.class.serializer.get_name_for_field_path(fp),
199 self.class.name().to_string(),
200 format!("{}", fp),
201 )
202 })
203 }
204}
205
206impl Display for Entities {
207 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
208 let mut table = Table::new();
209 table.add_row(row!["idx", "serial", "handle", "class"]);
210 for e in self.entities_vec.iter().flatten() {
211 table.add_row(row![
212 e.index().to_string(),
213 e.serial().to_string(),
214 e.handle().to_string(),
215 e.class().name(),
216 ]);
217 }
218 write!(f, "{}", table)
219 }
220}
221
222impl Display for Entity {
223 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
224 let mut table = Table::new();
225
226 table.add_row(row!["#", "Field", "Type", "Value"]);
227
228 for fp in self
229 .class
230 .serializer
231 .get_field_paths(&mut FieldPath::new(), &self.state)
232 {
233 let field_type = self.class.serializer.get_type_for_field_path(&fp);
234 let name = self.class.serializer.get_name_for_field_path(&fp);
235 let value = self.state.get_value(&fp);
236 if let Some(v) = value {
237 table.add_row(row![fp, name, field_type.as_string(), format!("{:?}", v)]);
238 } else {
239 table.add_row(row![fp, name, field_type.as_string(), "None"]);
240 }
241 }
242
243 write!(f, "{}", table)
244 }
245}