1use std::borrow::Cow;
2use std::ptr::NonNull;
3
4use crate::views::DatabaseDownCaster;
5use crate::zalsa::{IngredientIndex, ZalsaDatabase};
6use crate::{Durability, Revision};
7
8#[derive(Copy, Clone)]
9pub struct RawDatabase<'db> {
10 pub(crate) ptr: NonNull<()>,
11 _marker: std::marker::PhantomData<&'db dyn Database>,
12}
13
14impl<'db, Db: Database + ?Sized> From<&'db Db> for RawDatabase<'db> {
15 #[inline]
16 fn from(db: &'db Db) -> Self {
17 RawDatabase {
18 ptr: NonNull::from(db).cast(),
19 _marker: std::marker::PhantomData,
20 }
21 }
22}
23
24impl<'db, Db: Database + ?Sized> From<&'db mut Db> for RawDatabase<'db> {
25 #[inline]
26 fn from(db: &'db mut Db) -> Self {
27 RawDatabase {
28 ptr: NonNull::from(db).cast(),
29 _marker: std::marker::PhantomData,
30 }
31 }
32}
33
34pub trait Database: Send + ZalsaDatabase + AsDynDatabase {
37 fn trigger_lru_eviction(&mut self) {
44 let zalsa_mut = self.zalsa_mut();
45 zalsa_mut.evict_lru();
46 }
47
48 fn synthetic_write(&mut self, durability: Durability) {
57 let zalsa_mut = self.zalsa_mut();
58 zalsa_mut.new_revision();
59 zalsa_mut.runtime_mut().report_tracked_write(durability);
60 }
61
62 fn trigger_cancellation(&mut self) {
67 let _ = self.zalsa_mut();
68 }
69
70 fn report_untracked_read(&self) {
75 let (zalsa, zalsa_local) = self.zalsas();
76 zalsa_local.report_untracked_read(zalsa.current_revision())
77 }
78
79 fn ingredient_debug_name(&self, ingredient_index: IngredientIndex) -> Cow<'_, str> {
85 Cow::Borrowed(
86 self.zalsa()
87 .lookup_ingredient(ingredient_index)
88 .debug_name(),
89 )
90 }
91
92 fn unwind_if_revision_cancelled(&self) {
105 let (zalsa, zalsa_local) = self.zalsas();
106 zalsa.unwind_if_revision_cancelled(zalsa_local);
107 }
108
109 #[inline(always)]
111 fn attach<R>(&self, op: impl FnOnce(&Self) -> R) -> R
112 where
113 Self: Sized,
114 {
115 crate::attach::attach(self, || op(self))
116 }
117
118 #[cold]
119 #[inline(never)]
120 #[doc(hidden)]
121 fn zalsa_register_downcaster(&self) -> &DatabaseDownCaster<dyn Database> {
122 self.zalsa().views().downcaster_for::<dyn Database>()
123 }
125
126 #[doc(hidden)]
127 #[inline(always)]
128 fn downcast(&self) -> &dyn Database
129 where
130 Self: Sized,
131 {
132 self
134 }
135}
136
137pub trait AsDynDatabase {
141 fn as_dyn_database(&self) -> &dyn Database;
142}
143
144impl<T: Database> AsDynDatabase for T {
145 #[inline(always)]
146 fn as_dyn_database(&self) -> &dyn Database {
147 self
148 }
149}
150
151pub fn current_revision<Db: ?Sized + Database>(db: &Db) -> Revision {
152 db.zalsa().current_revision()
153}
154
155#[cfg(feature = "persistence")]
156mod persistence {
157 use crate::plumbing::Ingredient;
158 use crate::zalsa::Zalsa;
159 use crate::{Database, IngredientIndex, Runtime};
160
161 use std::fmt;
162
163 use serde::de::{self, DeserializeSeed, SeqAccess};
164 use serde::ser::SerializeMap;
165
166 impl dyn Database {
167 pub fn as_serialize(&mut self) -> impl serde::Serialize + '_ {
170 SerializeDatabase {
171 runtime: self.zalsa().runtime(),
172 ingredients: SerializeIngredients(self.zalsa()),
173 }
174 }
175
176 pub fn deserialize<'db, D>(&mut self, deserializer: D) -> Result<(), D::Error>
180 where
181 D: serde::Deserializer<'db>,
182 {
183 DeserializeDatabase(self.zalsa_mut()).deserialize(deserializer)
184 }
185 }
186
187 #[derive(serde::Serialize)]
188 #[serde(rename = "Database")]
189 pub struct SerializeDatabase<'db> {
190 pub runtime: &'db Runtime,
191 pub ingredients: SerializeIngredients<'db>,
192 }
193
194 pub struct SerializeIngredients<'db>(pub &'db Zalsa);
195
196 impl serde::Serialize for SerializeIngredients<'_> {
197 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
198 where
199 S: serde::Serializer,
200 {
201 let SerializeIngredients(zalsa) = self;
202
203 let mut ingredients = zalsa
204 .ingredients()
205 .filter(|ingredient| ingredient.should_serialize(zalsa))
206 .collect::<Vec<_>>();
207
208 ingredients.sort_by_key(|ingredient| ingredient.jar_kind());
211
212 let mut map = serializer.serialize_map(Some(ingredients.len()))?;
213 for ingredient in ingredients {
214 map.serialize_entry(
215 &ingredient.ingredient_index().as_u32(),
216 &SerializeIngredient(ingredient, zalsa),
217 )?;
218 }
219
220 map.end()
221 }
222 }
223
224 struct SerializeIngredient<'db>(&'db dyn Ingredient, &'db Zalsa);
225
226 impl serde::Serialize for SerializeIngredient<'_> {
227 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
228 where
229 S: serde::Serializer,
230 {
231 let mut result = None;
232 let mut serializer = Some(serializer);
233
234 unsafe {
236 self.0.serialize(self.1, &mut |serialize| {
237 let serializer = serializer.take().expect(
238 "`Ingredient::serialize` must invoke the serialization callback only once",
239 );
240
241 result = Some(erased_serde::serialize(&serialize, serializer))
242 })
243 };
244
245 result.expect("`Ingredient::serialize` must invoke the serialization callback")
246 }
247 }
248
249 #[derive(serde::Deserialize)]
250 #[serde(field_identifier, rename_all = "lowercase")]
251 enum DatabaseField {
252 Runtime,
253 Ingredients,
254 }
255
256 pub struct DeserializeDatabase<'db>(pub &'db mut Zalsa);
257
258 impl<'de> de::DeserializeSeed<'de> for DeserializeDatabase<'_> {
259 type Value = ();
260
261 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
262 where
263 D: de::Deserializer<'de>,
264 {
265 deserializer.deserialize_struct("Database", &["runtime", "ingredients"], self)
268 }
269 }
270
271 impl<'de> serde::de::Visitor<'de> for DeserializeDatabase<'_> {
272 type Value = ();
273
274 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
275 formatter.write_str("struct Database")
276 }
277
278 fn visit_seq<V>(self, mut seq: V) -> Result<(), V::Error>
279 where
280 V: SeqAccess<'de>,
281 {
282 let mut runtime = seq
283 .next_element()?
284 .ok_or_else(|| de::Error::invalid_length(0, &self))?;
285 let () = seq
286 .next_element_seed(DeserializeIngredients(self.0))?
287 .ok_or_else(|| de::Error::invalid_length(1, &self))?;
288
289 self.0.runtime_mut().deserialize_from(&mut runtime);
290 Ok(())
291 }
292
293 fn visit_map<V>(self, mut map: V) -> Result<(), V::Error>
294 where
295 V: serde::de::MapAccess<'de>,
296 {
297 let mut runtime = None;
298 let mut ingredients = None;
299
300 while let Some(key) = map.next_key()? {
301 match key {
302 DatabaseField::Runtime => {
303 if runtime.is_some() {
304 return Err(serde::de::Error::duplicate_field("runtime"));
305 }
306
307 runtime = Some(map.next_value()?);
308 }
309 DatabaseField::Ingredients => {
310 if ingredients.is_some() {
311 return Err(serde::de::Error::duplicate_field("ingredients"));
312 }
313
314 ingredients = Some(map.next_value_seed(DeserializeIngredients(self.0))?);
315 }
316 }
317 }
318
319 let mut runtime = runtime.ok_or_else(|| serde::de::Error::missing_field("runtime"))?;
320 let () = ingredients.ok_or_else(|| serde::de::Error::missing_field("ingredients"))?;
321
322 self.0.runtime_mut().deserialize_from(&mut runtime);
323
324 Ok(())
325 }
326 }
327
328 struct DeserializeIngredients<'db>(&'db mut Zalsa);
329
330 impl<'de> serde::de::Visitor<'de> for DeserializeIngredients<'_> {
331 type Value = ();
332
333 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
334 formatter.write_str("a map")
335 }
336
337 fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
338 where
339 M: serde::de::MapAccess<'de>,
340 {
341 let DeserializeIngredients(zalsa) = self;
342
343 while let Some(index) = access.next_key::<u32>()? {
344 let index = IngredientIndex::new(index);
345
346 let mut ingredient = zalsa.take_ingredient(index);
349
350 access.next_value_seed(DeserializeIngredient(&mut *ingredient, zalsa))?;
352
353 zalsa.replace_ingredient(index, ingredient);
354 }
355
356 Ok(())
357 }
358 }
359
360 impl<'de> serde::de::DeserializeSeed<'de> for DeserializeIngredients<'_> {
361 type Value = ();
362
363 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
364 where
365 D: serde::Deserializer<'de>,
366 {
367 deserializer.deserialize_map(self)
368 }
369 }
370
371 struct DeserializeIngredient<'db>(&'db mut dyn Ingredient, &'db mut Zalsa);
372
373 impl<'de> serde::de::DeserializeSeed<'de> for DeserializeIngredient<'_> {
374 type Value = ();
375
376 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
377 where
378 D: serde::Deserializer<'de>,
379 {
380 let deserializer = &mut <dyn erased_serde::Deserializer>::erase(deserializer);
381
382 self.0
383 .deserialize(self.1, deserializer)
384 .map_err(serde::de::Error::custom)
385 }
386 }
387}
388
389#[cfg(feature = "salsa_unstable")]
390pub use memory_usage::IngredientInfo;
391
392#[cfg(feature = "salsa_unstable")]
393pub(crate) use memory_usage::{MemoInfo, SlotInfo};
394
395#[cfg(feature = "salsa_unstable")]
396mod memory_usage {
397 use hashbrown::HashMap;
398
399 use crate::Database;
400
401 impl dyn Database {
402 pub fn memory_usage(&self) -> DatabaseInfo {
404 let mut queries = HashMap::new();
405 let mut structs = Vec::new();
406
407 for input_ingredient in self.zalsa().ingredients() {
408 let Some(input_info) = input_ingredient.memory_usage(self) else {
409 continue;
410 };
411
412 let mut size_of_fields = 0;
413 let mut size_of_metadata = 0;
414 let mut count = 0;
415 let mut heap_size_of_fields = None;
416
417 for input_slot in input_info {
418 count += 1;
419 size_of_fields += input_slot.size_of_fields;
420 size_of_metadata += input_slot.size_of_metadata;
421
422 if let Some(slot_heap_size) = input_slot.heap_size_of_fields {
423 heap_size_of_fields =
424 Some(heap_size_of_fields.unwrap_or_default() + slot_heap_size);
425 }
426
427 for memo in input_slot.memos {
428 let info = queries.entry(memo.debug_name).or_insert(IngredientInfo {
429 debug_name: memo.output.debug_name,
430 ..Default::default()
431 });
432
433 info.count += 1;
434 info.size_of_fields += memo.output.size_of_fields;
435 info.size_of_metadata += memo.output.size_of_metadata;
436
437 if let Some(memo_heap_size) = memo.output.heap_size_of_fields {
438 info.heap_size_of_fields =
439 Some(info.heap_size_of_fields.unwrap_or_default() + memo_heap_size);
440 }
441 }
442 }
443
444 structs.push(IngredientInfo {
445 count,
446 size_of_fields,
447 size_of_metadata,
448 heap_size_of_fields,
449 debug_name: input_ingredient.debug_name(),
450 });
451 }
452
453 DatabaseInfo { structs, queries }
454 }
455 }
456
457 pub struct DatabaseInfo {
459 pub structs: Vec<IngredientInfo>,
461
462 pub queries: HashMap<&'static str, IngredientInfo>,
465 }
466
467 #[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
469 pub struct IngredientInfo {
470 debug_name: &'static str,
471 count: usize,
472 size_of_metadata: usize,
473 size_of_fields: usize,
474 heap_size_of_fields: Option<usize>,
475 }
476
477 impl IngredientInfo {
478 pub fn debug_name(&self) -> &'static str {
480 self.debug_name
481 }
482
483 pub fn size_of_fields(&self) -> usize {
485 self.size_of_fields
486 }
487
488 pub fn heap_size_of_fields(&self) -> Option<usize> {
492 self.heap_size_of_fields
493 }
494
495 pub fn size_of_metadata(&self) -> usize {
497 self.size_of_metadata
498 }
499
500 pub fn count(&self) -> usize {
502 self.count
503 }
504 }
505
506 pub struct SlotInfo {
508 pub(crate) debug_name: &'static str,
509 pub(crate) size_of_metadata: usize,
510 pub(crate) size_of_fields: usize,
511 pub(crate) heap_size_of_fields: Option<usize>,
512 pub(crate) memos: Vec<MemoInfo>,
513 }
514
515 pub struct MemoInfo {
517 pub(crate) debug_name: &'static str,
518 pub(crate) output: SlotInfo,
519 }
520}