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: 'static + 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>(
184 &mut self,
185 runtime: &mut Runtime,
186 id: C::Struct,
187 field_index: usize,
188 durability: Option<Durability>,
189 setter: impl FnOnce(&mut C::Fields) -> R,
190 ) -> R {
191 let id: Id = id.as_id();
192
193 let data_raw = Self::data_raw(runtime.table(), id);
194
195 let data = unsafe { &mut *data_raw };
198
199 assert_ne!(
200 data.durabilities[field_index],
201 Durability::NEVER_CHANGE,
202 "never-changing inputs cannot be mutated"
203 );
204
205 data.revisions[field_index] = runtime.current_revision();
206
207 let field_durability = &mut data.durabilities[field_index];
208 if *field_durability != Durability::MIN {
209 runtime.report_tracked_write(*field_durability);
210 }
211 *field_durability = durability.unwrap_or(*field_durability);
212
213 setter(&mut data.fields)
214 }
215
216 #[doc(hidden)]
218 pub fn get_singleton_input(&self, zalsa: &Zalsa) -> Option<C::Struct>
219 where
220 C: Configuration<Singleton = Singleton>,
221 {
222 self.singleton
223 .index()
224 .map(|id| FromIdWithDb::from_id(id, zalsa))
225 }
226
227 pub fn field<'db>(
231 &'db self,
232 zalsa: &'db Zalsa,
233 zalsa_local: &'db ZalsaLocal,
234 id: C::Struct,
235 field_index: usize,
236 ) -> &'db C::Fields {
237 let field_ingredient_index = self.ingredient_index.successor(field_index);
238 let id = id.as_id();
239 let value = Self::data(zalsa, id);
240 let durability = value.durabilities[field_index];
241 let revision = value.revisions[field_index];
242 zalsa_local.report_tracked_read_simple(
243 DatabaseKeyIndex::new(field_ingredient_index, id),
244 durability,
245 revision,
246 );
247 &value.fields
248 }
249
250 pub fn entries<'db>(&'db self, zalsa: &'db Zalsa) -> impl Iterator<Item = StructEntry<'db, C>> {
252 zalsa
253 .table()
254 .slots_of::<Value<C>>()
255 .map(|(id, value)| StructEntry {
256 value,
257 key: self.database_key_index(id),
258 })
259 }
260
261 pub fn leak_fields<'db>(&'db self, zalsa: &'db Zalsa, id: C::Struct) -> &'db C::Fields {
264 let id = id.as_id();
265 let value = Self::data(zalsa, id);
266 &value.fields
267 }
268}
269
270pub struct StructEntry<'db, C>
272where
273 C: Configuration,
274{
275 #[cfg_attr(not(feature = "salsa_unstable"), allow(dead_code))]
276 value: &'db Value<C>,
277 key: DatabaseKeyIndex,
278}
279
280impl<'db, C> StructEntry<'db, C>
281where
282 C: Configuration,
283{
284 pub fn key(&self) -> DatabaseKeyIndex {
286 self.key
287 }
288
289 pub fn as_struct(&self) -> C::Struct {
291 FromId::from_id(self.key.key_index())
292 }
293
294 #[cfg(feature = "salsa_unstable")]
295 pub fn value(&self) -> &'db Value<C> {
296 self.value
297 }
298}
299
300impl<C: Configuration> Ingredient for IngredientImpl<C> {
301 fn location(&self) -> &'static crate::ingredient::Location {
302 &C::LOCATION
303 }
304
305 fn ingredient_index(&self) -> IngredientIndex {
306 self.ingredient_index
307 }
308
309 unsafe fn maybe_changed_after(
310 &self,
311 _zalsa: &crate::zalsa::Zalsa,
312 _db: crate::database::RawDatabase<'_>,
313 _input: Id,
314 _revision: Revision,
315 ) -> VerifyResult {
316 panic!("nothing should ever depend on an input struct directly")
319 }
320
321 fn collect_minimum_serialized_edges(
322 &self,
323 _zalsa: &Zalsa,
324 _edge: QueryEdge,
325 _serialized_edges: &mut FxIndexSet<QueryEdge>,
326 _visited_edges: &mut FxHashSet<QueryEdge>,
327 ) {
328 panic!("nothing should ever depend on an input struct directly")
329 }
330
331 fn flatten_cycle_head_dependencies(
332 &self,
333 _zalsa: &Zalsa,
334 _id: Id,
335 _flattened_input_outputs: &mut FxIndexSet<QueryEdge>,
336 _seen: &mut FxHashSet<DatabaseKeyIndex>,
337 ) {
338 panic!("nothing should ever depend on an input struct directly")
339 }
340
341 fn debug_name(&self) -> &'static str {
342 C::DEBUG_NAME
343 }
344
345 fn jar_kind(&self) -> JarKind {
346 JarKind::Struct
347 }
348
349 fn memo_table_types(&self) -> &Arc<MemoTableTypes> {
350 &self.memo_table_types
351 }
352
353 fn memo_table_types_mut(&mut self) -> &mut Arc<MemoTableTypes> {
354 &mut self.memo_table_types
355 }
356
357 #[cfg(feature = "salsa_unstable")]
359 fn memory_usage(&self, db: &dyn crate::Database) -> Option<Vec<crate::database::SlotInfo>> {
360 let memory_usage = self
361 .entries(db.zalsa())
362 .map(|entry| unsafe { entry.value.memory_usage(&self.memo_table_types) })
365 .collect();
366
367 Some(memory_usage)
368 }
369
370 fn is_persistable(&self) -> bool {
371 C::PERSIST
372 }
373
374 fn should_serialize(&self, zalsa: &Zalsa) -> bool {
375 C::PERSIST && self.entries(zalsa).next().is_some()
376 }
377
378 #[cfg(feature = "persistence")]
379 unsafe fn serialize<'db>(
380 &'db self,
381 zalsa: &'db Zalsa,
382 f: &mut dyn FnMut(&dyn erased_serde::Serialize),
383 ) {
384 f(&persistence::SerializeIngredient {
385 zalsa,
386 _ingredient: self,
387 })
388 }
389
390 #[cfg(feature = "persistence")]
391 fn deserialize(
392 &mut self,
393 zalsa: &mut Zalsa,
394 deserializer: &mut dyn erased_serde::Deserializer,
395 ) -> Result<(), erased_serde::Error> {
396 let deserialize = persistence::DeserializeIngredient {
397 zalsa,
398 ingredient: self,
399 };
400
401 serde::de::DeserializeSeed::deserialize(deserialize, deserializer)
402 }
403}
404
405impl<C: Configuration> std::fmt::Debug for IngredientImpl<C> {
406 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
407 f.debug_struct(std::any::type_name::<Self>())
408 .field("index", &self.ingredient_index)
409 .finish()
410 }
411}
412
413#[derive(Debug)]
414pub struct Value<C>
415where
416 C: Configuration,
417{
418 fields: C::Fields,
423
424 revisions: C::Revisions,
426
427 durabilities: C::Durabilities,
429
430 memos: MemoTable,
432}
433
434impl<C> Value<C>
435where
436 C: Configuration,
437{
438 #[cfg(feature = "salsa_unstable")]
443 pub fn fields(&self) -> &C::Fields {
444 &self.fields
445 }
446
447 #[cfg(feature = "salsa_unstable")]
453 unsafe fn memory_usage(&self, memo_table_types: &MemoTableTypes) -> crate::database::SlotInfo {
454 let heap_size = C::heap_size(&self.fields);
455 let memos = unsafe { memo_table_types.attach_memos(&self.memos) };
457
458 crate::database::SlotInfo {
459 debug_name: C::DEBUG_NAME,
460 size_of_metadata: std::mem::size_of::<Self>() - std::mem::size_of::<C::Fields>(),
461 size_of_fields: std::mem::size_of::<C::Fields>(),
462 heap_size_of_fields: heap_size,
463 memos: memos.memory_usage(),
464 }
465 }
466}
467
468pub trait HasBuilder {
469 type Builder;
470}
471
472unsafe impl<C> Slot for Value<C>
474where
475 C: Configuration,
476{
477 #[inline(always)]
478 unsafe fn memos(
479 this: *const Self,
480 _current_revision: Revision,
481 ) -> *const crate::table::memo::MemoTable {
482 unsafe { &raw const (*this).memos }
484 }
485
486 #[inline(always)]
487 fn memos_mut(&mut self) -> &mut crate::table::memo::MemoTable {
488 &mut self.memos
489 }
490}
491
492#[cfg(feature = "persistence")]
493mod persistence {
494 use std::fmt;
495
496 use serde::ser::{SerializeMap, SerializeStruct};
497 use serde::{Deserialize, de};
498
499 use super::{Configuration, IngredientImpl, Value};
500 use crate::Id;
501 use crate::input::singleton::SingletonChoice;
502 use crate::plumbing::Ingredient;
503 use crate::table::memo::MemoTable;
504 use crate::zalsa::Zalsa;
505
506 pub struct SerializeIngredient<'db, C>
507 where
508 C: Configuration,
509 {
510 pub zalsa: &'db Zalsa,
511 pub _ingredient: &'db IngredientImpl<C>,
512 }
513
514 impl<C> serde::Serialize for SerializeIngredient<'_, C>
515 where
516 C: Configuration,
517 {
518 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
519 where
520 S: serde::Serializer,
521 {
522 let Self { zalsa, .. } = self;
523
524 let count = zalsa.table().slots_of::<Value<C>>().count();
525 let mut map = serializer.serialize_map(Some(count))?;
526
527 for (id, value) in zalsa.table().slots_of::<Value<C>>() {
528 map.serialize_entry(&id.as_bits(), value)?;
529 }
530
531 map.end()
532 }
533 }
534
535 impl<C> serde::Serialize for Value<C>
536 where
537 C: Configuration,
538 {
539 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
540 where
541 S: serde::Serializer,
542 {
543 let mut value = serializer.serialize_struct("Value", 3)?;
544
545 let Value {
546 fields,
547 revisions,
548 durabilities,
549 memos: _,
550 } = self;
551
552 value.serialize_field("durabilities", &durabilities)?;
553 value.serialize_field("revisions", &revisions)?;
554 value.serialize_field("fields", &SerializeFields::<C>(fields))?;
555
556 value.end()
557 }
558 }
559
560 struct SerializeFields<'db, C: Configuration>(&'db C::Fields);
561
562 impl<C> serde::Serialize for SerializeFields<'_, C>
563 where
564 C: Configuration,
565 {
566 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
567 where
568 S: serde::Serializer,
569 {
570 C::serialize(self.0, serializer)
571 }
572 }
573
574 pub struct DeserializeIngredient<'db, C>
575 where
576 C: Configuration,
577 {
578 pub zalsa: &'db mut Zalsa,
579 pub ingredient: &'db mut IngredientImpl<C>,
580 }
581
582 impl<'de, C> de::DeserializeSeed<'de> for DeserializeIngredient<'_, C>
583 where
584 C: Configuration,
585 {
586 type Value = ();
587
588 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
589 where
590 D: serde::Deserializer<'de>,
591 {
592 deserializer.deserialize_map(self)
593 }
594 }
595
596 impl<'de, C> de::Visitor<'de> for DeserializeIngredient<'_, C>
597 where
598 C: Configuration,
599 {
600 type Value = ();
601
602 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
603 formatter.write_str("a map")
604 }
605
606 fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
607 where
608 M: de::MapAccess<'de>,
609 {
610 let DeserializeIngredient { zalsa, ingredient } = self;
611
612 while let Some((id, value)) = access.next_entry::<u64, DeserializeValue<C>>()? {
613 let id = Id::from_bits(id);
614 let (page_idx, _) = crate::table::split_id(id);
615
616 let value = Value::<C> {
617 fields: value.fields.0,
618 revisions: value.revisions,
619 durabilities: value.durabilities,
620 memos: unsafe { MemoTable::new(ingredient.memo_table_types()) },
623 };
624
625 zalsa.table_mut().force_page::<Value<C>>(
627 page_idx,
628 ingredient.ingredient_index(),
629 ingredient.memo_table_types(),
630 );
631
632 let allocated_id = ingredient.singleton.with_scope(|| unsafe {
636 zalsa
637 .table()
638 .page(page_idx)
639 .allocate(page_idx, |_| value)
640 .unwrap_or_else(|_| panic!("serialized an invalid `Id`: {id:?}"))
641 .0
642 });
643
644 assert_eq!(
645 allocated_id, id,
646 "values are serialized in allocation order"
647 );
648 }
649
650 Ok(())
651 }
652 }
653
654 #[derive(Deserialize)]
655 #[serde(rename = "Value")]
656 pub struct DeserializeValue<C: Configuration> {
657 durabilities: C::Durabilities,
658 revisions: C::Revisions,
659 #[serde(bound = "C: Configuration")]
660 fields: DeserializeFields<C>,
661 }
662
663 struct DeserializeFields<C: Configuration>(C::Fields);
664
665 impl<'de, C> serde::Deserialize<'de> for DeserializeFields<C>
666 where
667 C: Configuration,
668 {
669 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
670 where
671 D: serde::Deserializer<'de>,
672 {
673 C::deserialize(deserializer)
674 .map(DeserializeFields)
675 .map_err(de::Error::custom)
676 }
677 }
678}