1use std::any::{Any, TypeId};
2use std::fmt;
3use std::ops::IndexMut;
4
5pub mod input_field;
6pub mod setter;
7pub mod singleton;
8
9use input_field::FieldIngredientImpl;
10
11use crate::function::VerifyResult;
12use crate::hash::{FxHashSet, FxIndexSet};
13use crate::id::{AsId, FromId, FromIdWithDb};
14use crate::ingredient::Ingredient;
15use crate::input::singleton::{Singleton, SingletonChoice};
16use crate::key::DatabaseKeyIndex;
17use crate::plumbing::{self, Jar, ZalsaLocal};
18use crate::sync::Arc;
19use crate::table::memo::{MemoTable, MemoTableTypes};
20use crate::table::{Slot, Table};
21use crate::zalsa::{IngredientIndex, JarKind, Zalsa};
22use crate::zalsa_local::QueryEdge;
23use crate::{Durability, Id, Revision, Runtime};
24
25pub trait Configuration: Any {
26 const DEBUG_NAME: &'static str;
27 const FIELD_DEBUG_NAMES: &'static [&'static str];
28 const LOCATION: crate::ingredient::Location;
29
30 const PERSIST: bool;
32
33 type Singleton: SingletonChoice + Send + Sync;
35
36 type Struct: FromId + AsId + 'static + Send + Sync;
38
39 type Fields: Send + Sync;
41
42 #[cfg(feature = "persistence")]
44 type Revisions: Send
45 + Sync
46 + fmt::Debug
47 + IndexMut<usize, Output = Revision>
48 + plumbing::serde::Serialize
49 + for<'de> plumbing::serde::Deserialize<'de>;
50
51 #[cfg(not(feature = "persistence"))]
52 type Revisions: Send + Sync + fmt::Debug + IndexMut<usize, Output = Revision>;
53
54 #[cfg(feature = "persistence")]
56 type Durabilities: Send
57 + Sync
58 + fmt::Debug
59 + IndexMut<usize, Output = Durability>
60 + plumbing::serde::Serialize
61 + for<'de> plumbing::serde::Deserialize<'de>;
62
63 #[cfg(not(feature = "persistence"))]
64 type Durabilities: Send + Sync + fmt::Debug + IndexMut<usize, Output = Durability>;
65
66 fn heap_size(_value: &Self::Fields) -> Option<usize> {
68 None
69 }
70
71 fn serialize<S>(value: &Self::Fields, serializer: S) -> Result<S::Ok, S::Error>
75 where
76 S: plumbing::serde::Serializer;
77
78 fn deserialize<'de, D>(deserializer: D) -> Result<Self::Fields, D::Error>
82 where
83 D: plumbing::serde::Deserializer<'de>;
84}
85
86pub struct JarImpl<C: Configuration> {
87 _phantom: std::marker::PhantomData<C>,
88}
89
90impl<C: Configuration> Default for JarImpl<C> {
91 fn default() -> Self {
92 Self {
93 _phantom: Default::default(),
94 }
95 }
96}
97
98impl<C: Configuration> Jar for JarImpl<C> {
99 fn create_ingredients(
100 _zalsa: &mut Zalsa,
101 struct_index: crate::zalsa::IngredientIndex,
102 ) -> Vec<Box<dyn Ingredient>> {
103 let struct_ingredient: IngredientImpl<C> = IngredientImpl::new(struct_index);
104
105 std::iter::once(Box::new(struct_ingredient) as _)
106 .chain((0..C::FIELD_DEBUG_NAMES.len()).map(|field_index| {
107 Box::new(<FieldIngredientImpl<C>>::new(struct_index, field_index)) as _
108 }))
109 .collect()
110 }
111
112 fn id_struct_type_id() -> TypeId {
113 TypeId::of::<C::Struct>()
114 }
115}
116
117pub struct IngredientImpl<C: Configuration> {
118 ingredient_index: IngredientIndex,
119 singleton: C::Singleton,
120 memo_table_types: Arc<MemoTableTypes>,
121 _phantom: std::marker::PhantomData<C::Struct>,
122}
123
124impl<C: Configuration> IngredientImpl<C> {
125 pub fn new(index: IngredientIndex) -> Self {
126 Self {
127 ingredient_index: index,
128 singleton: Default::default(),
129 memo_table_types: Arc::new(MemoTableTypes::default()),
130 _phantom: std::marker::PhantomData,
131 }
132 }
133
134 fn data(zalsa: &Zalsa, id: Id) -> &Value<C> {
135 zalsa.table().get(id)
136 }
137
138 fn data_raw(table: &Table, id: Id) -> *mut Value<C> {
139 table.get_raw(id)
140 }
141
142 pub fn database_key_index(&self, id: Id) -> DatabaseKeyIndex {
143 DatabaseKeyIndex::new(self.ingredient_index, id)
144 }
145
146 pub fn new_input(
147 &self,
148 zalsa: &Zalsa,
149 zalsa_local: &ZalsaLocal,
150 fields: C::Fields,
151 revisions: C::Revisions,
152 durabilities: C::Durabilities,
153 ) -> C::Struct {
154 let id = self.singleton.with_scope(|| {
155 zalsa_local
156 .allocate(zalsa, self.ingredient_index, |_| Value::<C> {
157 fields,
158 revisions,
159 durabilities,
160 memos: unsafe { MemoTable::new(self.memo_table_types()) },
163 })
164 .0
165 });
166
167 FromIdWithDb::from_id(id, zalsa)
168 }
169
170 pub fn set_field<R>(
180 &mut self,
181 runtime: &mut Runtime,
182 id: C::Struct,
183 field_index: usize,
184 durability: Option<Durability>,
185 setter: impl FnOnce(&mut C::Fields) -> R,
186 ) -> R {
187 let id: Id = id.as_id();
188
189 let data_raw = Self::data_raw(runtime.table(), id);
190
191 let data = unsafe { &mut *data_raw };
194
195 data.revisions[field_index] = runtime.current_revision();
196
197 let field_durability = &mut data.durabilities[field_index];
198 if *field_durability != Durability::MIN {
199 runtime.report_tracked_write(*field_durability);
200 }
201 *field_durability = durability.unwrap_or(*field_durability);
202
203 setter(&mut data.fields)
204 }
205
206 #[doc(hidden)]
208 pub fn get_singleton_input(&self, zalsa: &Zalsa) -> Option<C::Struct>
209 where
210 C: Configuration<Singleton = Singleton>,
211 {
212 self.singleton
213 .index()
214 .map(|id| FromIdWithDb::from_id(id, zalsa))
215 }
216
217 pub fn field<'db>(
221 &'db self,
222 zalsa: &'db Zalsa,
223 zalsa_local: &'db ZalsaLocal,
224 id: C::Struct,
225 field_index: usize,
226 ) -> &'db C::Fields {
227 let field_ingredient_index = self.ingredient_index.successor(field_index);
228 let id = id.as_id();
229 let value = Self::data(zalsa, id);
230 let durability = value.durabilities[field_index];
231 let revision = value.revisions[field_index];
232 zalsa_local.report_tracked_read_simple(
233 DatabaseKeyIndex::new(field_ingredient_index, id),
234 durability,
235 revision,
236 );
237 &value.fields
238 }
239
240 pub fn entries<'db>(&'db self, zalsa: &'db Zalsa) -> impl Iterator<Item = StructEntry<'db, C>> {
242 zalsa
243 .table()
244 .slots_of::<Value<C>>()
245 .map(|(id, value)| StructEntry {
246 value,
247 key: self.database_key_index(id),
248 })
249 }
250
251 pub fn leak_fields<'db>(&'db self, zalsa: &'db Zalsa, id: C::Struct) -> &'db C::Fields {
254 let id = id.as_id();
255 let value = Self::data(zalsa, id);
256 &value.fields
257 }
258}
259
260pub struct StructEntry<'db, C>
262where
263 C: Configuration,
264{
265 value: &'db Value<C>,
266 key: DatabaseKeyIndex,
267}
268
269impl<'db, C> StructEntry<'db, C>
270where
271 C: Configuration,
272{
273 pub fn key(&self) -> DatabaseKeyIndex {
275 self.key
276 }
277
278 pub fn as_struct(&self) -> C::Struct {
280 FromId::from_id(self.key.key_index())
281 }
282
283 #[cfg(feature = "salsa_unstable")]
284 pub fn value(&self) -> &'db Value<C> {
285 self.value
286 }
287}
288
289impl<C: Configuration> Ingredient for IngredientImpl<C> {
290 fn location(&self) -> &'static crate::ingredient::Location {
291 &C::LOCATION
292 }
293
294 fn ingredient_index(&self) -> IngredientIndex {
295 self.ingredient_index
296 }
297
298 unsafe fn maybe_changed_after(
299 &self,
300 _zalsa: &crate::zalsa::Zalsa,
301 _db: crate::database::RawDatabase<'_>,
302 _input: Id,
303 _revision: Revision,
304 ) -> VerifyResult {
305 panic!("nothing should ever depend on an input struct directly")
308 }
309
310 fn collect_minimum_serialized_edges(
311 &self,
312 _zalsa: &Zalsa,
313 _edge: QueryEdge,
314 _serialized_edges: &mut FxIndexSet<QueryEdge>,
315 _visited_edges: &mut FxHashSet<QueryEdge>,
316 ) {
317 panic!("nothing should ever depend on an input struct directly")
318 }
319
320 fn flatten_cycle_head_dependencies(
321 &self,
322 _zalsa: &Zalsa,
323 _id: Id,
324 _flattened_input_outputs: &mut FxIndexSet<QueryEdge>,
325 _seen: &mut FxHashSet<DatabaseKeyIndex>,
326 ) {
327 panic!("nothing should ever depend on an input struct directly")
328 }
329
330 fn debug_name(&self) -> &'static str {
331 C::DEBUG_NAME
332 }
333
334 fn jar_kind(&self) -> JarKind {
335 JarKind::Struct
336 }
337
338 fn memo_table_types(&self) -> &Arc<MemoTableTypes> {
339 &self.memo_table_types
340 }
341
342 fn memo_table_types_mut(&mut self) -> &mut Arc<MemoTableTypes> {
343 &mut self.memo_table_types
344 }
345
346 #[cfg(feature = "salsa_unstable")]
348 fn memory_usage(&self, db: &dyn crate::Database) -> Option<Vec<crate::database::SlotInfo>> {
349 let memory_usage = self
350 .entries(db.zalsa())
351 .map(|entry| unsafe { entry.value.memory_usage(&self.memo_table_types) })
354 .collect();
355
356 Some(memory_usage)
357 }
358
359 fn is_persistable(&self) -> bool {
360 C::PERSIST
361 }
362
363 fn should_serialize(&self, zalsa: &Zalsa) -> bool {
364 C::PERSIST && self.entries(zalsa).next().is_some()
365 }
366
367 #[cfg(feature = "persistence")]
368 unsafe fn serialize<'db>(
369 &'db self,
370 zalsa: &'db Zalsa,
371 f: &mut dyn FnMut(&dyn erased_serde::Serialize),
372 ) {
373 f(&persistence::SerializeIngredient {
374 zalsa,
375 _ingredient: self,
376 })
377 }
378
379 #[cfg(feature = "persistence")]
380 fn deserialize(
381 &mut self,
382 zalsa: &mut Zalsa,
383 deserializer: &mut dyn erased_serde::Deserializer,
384 ) -> Result<(), erased_serde::Error> {
385 let deserialize = persistence::DeserializeIngredient {
386 zalsa,
387 ingredient: self,
388 };
389
390 serde::de::DeserializeSeed::deserialize(deserialize, deserializer)
391 }
392}
393
394impl<C: Configuration> std::fmt::Debug for IngredientImpl<C> {
395 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
396 f.debug_struct(std::any::type_name::<Self>())
397 .field("index", &self.ingredient_index)
398 .finish()
399 }
400}
401
402#[derive(Debug)]
403pub struct Value<C>
404where
405 C: Configuration,
406{
407 fields: C::Fields,
412
413 revisions: C::Revisions,
415
416 durabilities: C::Durabilities,
418
419 memos: MemoTable,
421}
422
423impl<C> Value<C>
424where
425 C: Configuration,
426{
427 #[cfg(feature = "salsa_unstable")]
432 pub fn fields(&self) -> &C::Fields {
433 &self.fields
434 }
435
436 #[cfg(feature = "salsa_unstable")]
442 unsafe fn memory_usage(&self, memo_table_types: &MemoTableTypes) -> crate::database::SlotInfo {
443 let heap_size = C::heap_size(&self.fields);
444 let memos = unsafe { memo_table_types.attach_memos(&self.memos) };
446
447 crate::database::SlotInfo {
448 debug_name: C::DEBUG_NAME,
449 size_of_metadata: std::mem::size_of::<Self>() - std::mem::size_of::<C::Fields>(),
450 size_of_fields: std::mem::size_of::<C::Fields>(),
451 heap_size_of_fields: heap_size,
452 memos: memos.memory_usage(),
453 }
454 }
455}
456
457pub trait HasBuilder {
458 type Builder;
459}
460
461unsafe impl<C> Slot for Value<C>
463where
464 C: Configuration,
465{
466 #[inline(always)]
467 unsafe fn memos(
468 this: *const Self,
469 _current_revision: Revision,
470 ) -> *const crate::table::memo::MemoTable {
471 unsafe { &raw const (*this).memos }
473 }
474
475 #[inline(always)]
476 fn memos_mut(&mut self) -> &mut crate::table::memo::MemoTable {
477 &mut self.memos
478 }
479}
480
481#[cfg(feature = "persistence")]
482mod persistence {
483 use std::fmt;
484
485 use serde::ser::{SerializeMap, SerializeStruct};
486 use serde::{Deserialize, de};
487
488 use super::{Configuration, IngredientImpl, Value};
489 use crate::Id;
490 use crate::input::singleton::SingletonChoice;
491 use crate::plumbing::Ingredient;
492 use crate::table::memo::MemoTable;
493 use crate::zalsa::Zalsa;
494
495 pub struct SerializeIngredient<'db, C>
496 where
497 C: Configuration,
498 {
499 pub zalsa: &'db Zalsa,
500 pub _ingredient: &'db IngredientImpl<C>,
501 }
502
503 impl<C> serde::Serialize for SerializeIngredient<'_, C>
504 where
505 C: Configuration,
506 {
507 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
508 where
509 S: serde::Serializer,
510 {
511 let Self { zalsa, .. } = self;
512
513 let count = zalsa.table().slots_of::<Value<C>>().count();
514 let mut map = serializer.serialize_map(Some(count))?;
515
516 for (id, value) in zalsa.table().slots_of::<Value<C>>() {
517 map.serialize_entry(&id.as_bits(), value)?;
518 }
519
520 map.end()
521 }
522 }
523
524 impl<C> serde::Serialize for Value<C>
525 where
526 C: Configuration,
527 {
528 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
529 where
530 S: serde::Serializer,
531 {
532 let mut value = serializer.serialize_struct("Value", 3)?;
533
534 let Value {
535 fields,
536 revisions,
537 durabilities,
538 memos: _,
539 } = self;
540
541 value.serialize_field("durabilities", &durabilities)?;
542 value.serialize_field("revisions", &revisions)?;
543 value.serialize_field("fields", &SerializeFields::<C>(fields))?;
544
545 value.end()
546 }
547 }
548
549 struct SerializeFields<'db, C: Configuration>(&'db C::Fields);
550
551 impl<C> serde::Serialize for SerializeFields<'_, C>
552 where
553 C: Configuration,
554 {
555 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
556 where
557 S: serde::Serializer,
558 {
559 C::serialize(self.0, serializer)
560 }
561 }
562
563 pub struct DeserializeIngredient<'db, C>
564 where
565 C: Configuration,
566 {
567 pub zalsa: &'db mut Zalsa,
568 pub ingredient: &'db mut IngredientImpl<C>,
569 }
570
571 impl<'de, C> de::DeserializeSeed<'de> for DeserializeIngredient<'_, C>
572 where
573 C: Configuration,
574 {
575 type Value = ();
576
577 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
578 where
579 D: serde::Deserializer<'de>,
580 {
581 deserializer.deserialize_map(self)
582 }
583 }
584
585 impl<'de, C> de::Visitor<'de> for DeserializeIngredient<'_, C>
586 where
587 C: Configuration,
588 {
589 type Value = ();
590
591 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
592 formatter.write_str("a map")
593 }
594
595 fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
596 where
597 M: de::MapAccess<'de>,
598 {
599 let DeserializeIngredient { zalsa, ingredient } = self;
600
601 while let Some((id, value)) = access.next_entry::<u64, DeserializeValue<C>>()? {
602 let id = Id::from_bits(id);
603 let (page_idx, _) = crate::table::split_id(id);
604
605 let value = Value::<C> {
606 fields: value.fields.0,
607 revisions: value.revisions,
608 durabilities: value.durabilities,
609 memos: unsafe { MemoTable::new(ingredient.memo_table_types()) },
612 };
613
614 zalsa.table_mut().force_page::<Value<C>>(
616 page_idx,
617 ingredient.ingredient_index(),
618 ingredient.memo_table_types(),
619 );
620
621 let allocated_id = ingredient.singleton.with_scope(|| unsafe {
625 zalsa
626 .table()
627 .page(page_idx)
628 .allocate(page_idx, |_| value)
629 .unwrap_or_else(|_| panic!("serialized an invalid `Id`: {id:?}"))
630 .0
631 });
632
633 assert_eq!(
634 allocated_id, id,
635 "values are serialized in allocation order"
636 );
637 }
638
639 Ok(())
640 }
641 }
642
643 #[derive(Deserialize)]
644 #[serde(rename = "Value")]
645 pub struct DeserializeValue<C: Configuration> {
646 durabilities: C::Durabilities,
647 revisions: C::Revisions,
648 #[serde(bound = "C: Configuration")]
649 fields: DeserializeFields<C>,
650 }
651
652 struct DeserializeFields<C: Configuration>(C::Fields);
653
654 impl<'de, C> serde::Deserialize<'de> for DeserializeFields<C>
655 where
656 C: Configuration,
657 {
658 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
659 where
660 D: serde::Deserializer<'de>,
661 {
662 C::deserialize(deserializer)
663 .map(DeserializeFields)
664 .map_err(de::Error::custom)
665 }
666 }
667}