verde/internal/
db.rs

1use std::{
2	any::TypeId,
3	borrow::Borrow,
4	cell::{Cell, RefCell},
5	hash::Hash,
6	mem::MaybeUninit,
7};
8
9use rustc_hash::{FxHashMap, FxHashSet};
10
11use crate::{
12	internal::{
13		storage::{interned, tracked, ErasedId, ErasedQueryId, Route, RoutingTable, RoutingTableBuilder},
14		Query,
15		Storage,
16	},
17	span,
18	Id,
19	Interned,
20	Pushable,
21	Tracked,
22};
23
24/// A database. This trait provides most of the functionality of the concrete database type.
25pub trait Db {
26	#[doc(hidden)]
27	fn init_routing(table: &mut RoutingTableBuilder)
28	where
29		Self: Sized;
30
31	#[doc(hidden)]
32	fn routing_table(&self) -> &RoutingTable;
33
34	#[doc(hidden)]
35	fn storage_struct(&self, storage: u16) -> &dyn Storage;
36}
37
38#[doc(hidden)]
39pub struct ErasedVec {
40	bytes: [u8; std::mem::size_of::<Vec<()>>()],
41}
42
43impl ErasedVec {
44	fn new<T>() -> Self {
45		let mut bytes = [0; std::mem::size_of::<Vec<()>>()];
46		unsafe {
47			std::ptr::write(bytes.as_mut_ptr() as *mut Vec<T>, Vec::new());
48		}
49		Self { bytes }
50	}
51
52	unsafe fn as_mut<T>(&mut self) -> &mut Vec<T> { unsafe { &mut *(self.bytes.as_mut_ptr() as *mut Vec<T>) } }
53
54	pub(crate) unsafe fn into_inner<T>(self) -> Vec<T> {
55		// This transmute saves if the size of `Vec<T>` is ever different from `Vec<()>`.
56		unsafe { std::mem::transmute(self.bytes) }
57	}
58}
59
60/// A context into the database. Used by query functions to access the database.
61pub struct Ctx<'a> {
62	pub(crate) db: &'a dyn Db,
63	pub(crate) dependencies: RefCell<MaybeUninit<FxHashSet<(ErasedId, u64)>>>,
64	pub(crate) pushed: RefCell<MaybeUninit<FxHashMap<TypeId, (ErasedVec, &'static str)>>>,
65	pub(crate) curr_query: ErasedQueryId,
66	dead: Cell<bool>,
67}
68
69impl<'a> Ctx<'a> {
70	fn new(db: &'a dyn Db, curr_query: ErasedQueryId) -> Self {
71		Self {
72			db,
73			dependencies: RefCell::new(MaybeUninit::new(FxHashSet::default())),
74			pushed: RefCell::new(MaybeUninit::new(FxHashMap::default())),
75			curr_query,
76			dead: Cell::new(false),
77		}
78	}
79
80	/// Insert a tracked value. Useful for returning tracked values other than the query output. These values *must*
81	/// influence query output comparision in some way (such as being stored in it) - since changes to `insert`ed values
82	/// are not tracked as outputs.
83	///
84	/// Unlike `set_input` called on the database, these values must be unique across only this query type, not
85	/// globally.
86	/// ```rust
87	/// # use verde::{query, Tracked, Ctx, Id, storage, db};
88	/// #[derive(Tracked, Eq, PartialEq)]
89	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
90	/// struct S {
91	/// 	#[id]
92	/// 	id: u32,
93	/// 	value: u32,
94	/// }
95	///
96	/// # #[storage]
97	/// # struct Storage(S, String, foo);
98	/// # #[db]
99	/// # struct Database(Storage);
100	/// #[query]
101	/// fn foo(ctx: &Ctx, id: Id<S>) -> S {
102	/// 	let s = ctx.get(id);
103	/// 	let s2 = ctx.insert(S { id: 0, value: 1 }); // Turns out to be same as the return value!
104	/// 	S {
105	/// 		id: s.id,
106	/// 		value: s.value + 1,
107	/// 	}
108	/// }
109	///
110	/// # let mut db = Database::default();
111	/// # let db = &mut db as &mut dyn verde::Db;
112	/// let id = db.set_input(S { id: 0, value: 0 });
113	/// db.execute(|ctx| foo(ctx, id));
114	/// ```
115	pub fn insert<T: Tracked>(&self, value: T) -> Id<T> { self.db.insert(self.curr_query.route, value) }
116
117	/// Get a reference to the value `id` points to.
118	/// ```rust
119	/// # use verde::{query, Tracked, Ctx, Id, storage, db};
120	/// #[derive(Tracked, Eq, PartialEq)]
121	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
122	/// struct S {
123	/// 	#[id]
124	/// 	id: u32,
125	/// 	value: u32,
126	/// }
127	///
128	/// # #[storage]
129	/// # struct Storage(S, foo);
130	/// # #[db]
131	/// # struct Database(Storage);
132	/// #[query]
133	/// fn foo(ctx: &Ctx, id: Id<S>) -> S {
134	/// 	let s = ctx.get(id);
135	/// 	assert_eq!(s.value, 0);
136	/// 	S {
137	/// 		id: s.id,
138	/// 		value: s.value + 1,
139	/// 	}
140	/// }
141	///
142	/// # let mut db = Database::default();
143	/// # let db = &mut db as &mut dyn verde::Db;
144	/// let id = db.set_input(S { id: 0, value: 0 });
145	/// db.execute(|ctx| foo(ctx, id));
146	/// ```
147	pub fn get<T: Tracked>(&self, id: Id<T>) -> tracked::Get<'_, T> {
148		let id = id.get();
149		span!(
150			enter trace,
151			"fetching value",
152			ty = std::any::type_name::<T>(),
153			id = id.index
154		);
155		unsafe {
156			let gen = self.get_generation(id);
157			self.dependencies
158				.try_borrow_mut()
159				.expect("Cannot call `get` within a `map` scope")
160				.assume_init_mut()
161				.insert((id, gen));
162		}
163		let storage = self
164			.db
165			.storage_struct(id.route.storage)
166			.tracked_storage(id.route.index)
167			.unwrap();
168		unsafe { storage.get(id.index) }
169	}
170
171	/// Get a reference to the value `id` points to.
172	/// ```rust
173	/// # use verde::{query, Tracked, Ctx, Id, storage, db};
174	/// #[derive(Tracked, Eq, PartialEq)]
175	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
176	/// struct S {
177	/// 	#[id]
178	/// 	id: u32,
179	/// 	value: u32,
180	/// }
181	///
182	/// # #[storage]
183	/// # struct Storage(S, String, foo);
184	/// # #[db]
185	/// # struct Database(Storage);
186	/// #[query]
187	/// fn foo(ctx: &Ctx, id: Id<S>, id2: Id<String>) -> S {
188	/// 	let s = ctx.get(id);
189	/// 	let i = ctx.geti(id2);
190	/// 	assert_eq!(*i, "Hello");
191	/// 	S {
192	/// 		id: s.id,
193	/// 		value: s.value + 1,
194	/// 	}
195	/// }
196	///
197	/// # let mut db = Database::default();
198	/// # let db = &mut db as &mut dyn verde::Db;
199	/// let id = db.set_input(S { id: 0, value: 0 });
200	/// let id2 = db.add("Hello".to_string());
201	/// db.execute(|ctx| foo(ctx, id, id2));
202	/// ```
203	pub fn geti<T: Interned>(&self, id: Id<T>) -> interned::Get<'_, T> { self.db.geti(id) }
204
205	/// Intern a value.
206	/// ```rust
207	/// # use verde::{query, Tracked, Ctx, Id, storage, db};
208	/// #[derive(Tracked, Eq, PartialEq)]
209	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
210	/// struct S {
211	/// 	#[id]
212	/// 	id: u32,
213	/// 	value: u32,
214	/// }
215	///
216	/// # #[storage]
217	/// # struct Storage(S, String, foo);
218	/// # #[db]
219	/// # struct Database(Storage);
220	/// #[query]
221	/// fn foo(ctx: &Ctx, id: Id<S>) -> S {
222	/// 	let s = ctx.get(id);
223	/// 	let id2 = ctx.add("Hello".to_string());
224	/// 	let i = ctx.geti(id2);
225	/// 	assert_eq!(*i, "Hello");
226	/// 	S {
227	/// 		id: s.id,
228	/// 		value: s.value + 1,
229	/// 	}
230	/// }
231	///
232	/// # let mut db = Database::default();
233	/// # let db = &mut db as &mut dyn verde::Db;
234	/// let id = db.set_input(S { id: 0, value: 0 });
235	/// db.execute(|ctx| foo(ctx, id));
236	/// ```
237	pub fn add<T: Interned>(&self, value: T) -> Id<T> { self.db.add(value) }
238
239	/// Intern a value through a reference.
240	/// ```rust
241	/// # use verde::{query, Tracked, Ctx, Id, storage, db};
242	/// #[derive(Tracked, Eq, PartialEq)]
243	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
244	/// struct S {
245	/// 	#[id]
246	/// 	id: u32,
247	/// 	value: u32,
248	/// }
249	///
250	/// # #[storage]
251	/// # struct Storage(S, String, foo);
252	/// # #[db]
253	/// # struct Database(Storage);
254	/// #[query]
255	/// fn foo(ctx: &Ctx, id: Id<S>) -> S {
256	/// 	let s = ctx.get(id);
257	/// 	let id2 = ctx.add_ref("Hello");
258	/// 	let i = ctx.geti(id2);
259	/// 	assert_eq!(*i, "Hello");
260	/// 	S {
261	/// 		id: s.id,
262	/// 		value: s.value + 1,
263	/// 	}
264	/// }
265	///
266	/// # let mut db = Database::default();
267	/// # let db = &mut db as &mut dyn verde::Db;
268	/// let id = db.set_input(S { id: 0, value: 0 });
269	/// db.execute(|ctx| foo(ctx, id));
270	/// ```
271	pub fn add_ref<T, U>(&self, value: &U) -> Id<T>
272	where
273		U: ToOwned<Owned = T> + Hash + Eq + ?Sized,
274		T: Borrow<U> + Interned,
275	{
276		self.db.add_ref(value)
277	}
278
279	/// Push a value to the database from this query.
280	/// Get a reference to the value `id` points to.
281	/// ```rust
282	/// # use verde::{query, Tracked, Pushable, Ctx, Id, storage, db};
283	/// #[derive(Tracked, Eq, PartialEq)]
284	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
285	/// struct S {
286	/// 	#[id]
287	/// 	id: u32,
288	/// 	value: u32,
289	/// }
290	///
291	/// #[derive(Pushable, Eq, PartialEq, Debug)]
292	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
293	/// struct P {
294	/// 	value: u32,
295	/// }
296	///
297	/// # #[storage]
298	/// # struct Storage(S, P, foo);
299	/// # #[db]
300	/// # struct Database(Storage);
301	/// #[query]
302	/// fn foo(ctx: &Ctx, id: Id<S>) -> S {
303	/// 	let s = ctx.get(id);
304	/// 	ctx.push(P { value: s.value + 1 });
305	/// 	S {
306	/// 		id: s.id,
307	/// 		value: s.value + 1,
308	/// 	}
309	/// }
310	///
311	/// # let mut db = Database::default();
312	/// # let db = &mut db as &mut dyn verde::Db;
313	/// let id = db.set_input(S { id: 0, value: 0 });
314	/// db.execute(|ctx| foo(ctx, id));
315	/// assert_eq!(db.get_all::<P>().next(), Some(&P { value: 1 }));
316	/// ```
317	pub fn push<T: Pushable>(&self, value: T) {
318		let name = std::any::type_name::<T>();
319		span!(enter trace, "push", ty = name);
320		let mut borrowed = self
321			.pushed
322			.try_borrow_mut()
323			.expect("Cannot call `push` within a `map` scope");
324		let map = unsafe { borrowed.assume_init_mut() };
325		let vec = map.entry(TypeId::of::<T>()).or_insert((ErasedVec::new::<T>(), name));
326		unsafe {
327			vec.0.as_mut().push(value);
328		}
329	}
330
331	#[doc(hidden)]
332	pub fn start_query<T: Query>(&self, input: T::Input) -> Ctx<'_> {
333		span!(enter trace, "initialize query", query = std::any::type_name::<T>());
334
335		let route = self.db.routing_table().route::<T>();
336		let storage = self
337			.db
338			.storage_struct(route.storage)
339			.query_storage(route.index)
340			.unwrap();
341		unsafe {
342			let index = storage.start_query::<T>(input);
343			let curr_query = ErasedQueryId { route, index };
344			Ctx::new(self.db, curr_query)
345		}
346	}
347
348	#[doc(hidden)]
349	pub fn end_query<T: Query>(&self, f: impl FnOnce() -> T::Output) -> Id<T::Output> {
350		assert!(!self.dead.get(), "Query has already been ended");
351		self.dead.set(true);
352
353		let query = self.db.routing_table().route::<T>();
354		let storage = self
355			.db
356			.storage_struct(query.storage)
357			.query_storage(query.index)
358			.unwrap();
359		let ret = unsafe { storage.execute::<T>(self, f) };
360
361		// Commit the pushed values to the database (if there are any, we don't know)
362		let borrowed = self
363			.pushed
364			.try_borrow_mut()
365			.expect("Cannot end query within a `map` scope");
366		for (id, (vec, name)) in unsafe { borrowed.assume_init_read() } {
367			let route = self.db.routing_table().route_for(id, name);
368			let storage = self
369				.db
370				.storage_struct(route.storage)
371				.pushable_storage(route.index)
372				.unwrap();
373			unsafe { storage.push(self.curr_query, vec) }
374		}
375
376		ret
377	}
378
379	pub(crate) fn get_generation(&self, id: ErasedId) -> u64 {
380		span!(
381			enter trace,
382			"fetching generation",
383			ty = self.db.routing_table().name(id.route),
384			id = id.index
385		);
386		let storage = self
387			.db
388			.storage_struct(id.route.storage)
389			.tracked_storage(id.route.index)
390			.unwrap();
391		storage.get_generation(id.index)
392	}
393}
394
395impl dyn Db + '_ {
396	/// Set an input value.
397	/// ```rust
398	/// # use verde::{Tracked, Ctx, Id, storage, db};
399	/// #[derive(Tracked, Eq, PartialEq, Debug)]
400	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
401	/// struct S {
402	/// 	#[id]
403	/// 	id: u32,
404	/// 	value: u32,
405	/// }
406	///
407	/// # #[storage]
408	/// # struct Storage(S);
409	/// # #[db]
410	/// # struct Database(Storage);
411	///
412	/// # let mut db = Database::default();
413	/// # let db = &mut db as &mut dyn verde::Db;
414	/// let id = db.set_input(S { id: 0, value: 0 });
415	/// let s = db.get(id);
416	/// assert_eq!(*s, S { id: 0, value: 0 });
417	/// ```
418	pub fn set_input<T: Tracked>(&self, value: T) -> Id<T> { self.insert(Route::input(), value) }
419
420	/// Get a reference to the value `id` points to.
421	/// ```rust
422	/// # use verde::{Tracked, Ctx, Id, storage, db};
423	/// #[derive(Tracked, Eq, PartialEq, Debug)]
424	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
425	/// struct S {
426	/// 	#[id]
427	/// 	id: u32,
428	/// 	value: u32,
429	/// }
430	///
431	/// # #[storage]
432	/// # struct Storage(S);
433	/// # #[db]
434	/// # struct Database(Storage);
435	///
436	/// # let mut db = Database::default();
437	/// # let db = &mut db as &mut dyn verde::Db;
438	/// let id = db.set_input(S { id: 0, value: 0 });
439	/// let s = db.get(id);
440	/// assert_eq!(*s, S { id: 0, value: 0 });
441	/// ```
442	pub fn get<T: Tracked>(&self, id: Id<T>) -> tracked::Get<'_, T> {
443		let id = id.get();
444		span!(
445			enter trace,
446			"fetching value",
447			ty = std::any::type_name::<T>(),
448			id = id.index
449		);
450		let storage = self
451			.storage_struct(id.route.storage)
452			.tracked_storage(id.route.index)
453			.unwrap();
454		unsafe { storage.get(id.index) }
455	}
456
457	/// Get a reference to the value `id` points to.
458	/// ```rust
459	/// # use verde::{Interned, Ctx, Id, storage, db};
460	///
461	/// # #[storage]
462	/// # struct Storage(String);
463	/// # #[db]
464	/// # struct Database(Storage);
465	///
466	/// # let mut db = Database::default();
467	/// # let db = &mut db as &mut dyn verde::Db;
468	/// let id = db.add("Hello".to_string());
469	/// let s = db.geti(id);
470	/// assert_eq!(*s, "Hello");
471	/// ```
472	pub fn geti<T: Interned>(&self, id: Id<T>) -> interned::Get<'_, T> {
473		let id = id.get();
474		span!(
475			enter trace,
476			"fetching value",
477			ty = std::any::type_name::<T>(),
478			id = id.index
479		);
480		let storage = self
481			.storage_struct(id.route.storage)
482			.interned_storage(id.route.index)
483			.unwrap();
484		unsafe { storage.get(id.index) }
485	}
486
487	/// Intern a value.
488	/// ```rust
489	/// # use verde::{Interned, Ctx, Id, storage, db};
490	///
491	/// # #[storage]
492	/// # struct Storage(String);
493	/// # #[db]
494	/// # struct Database(Storage);
495	///
496	/// # let mut db = Database::default();
497	/// # let db = &mut db as &mut dyn verde::Db;
498	/// let id = db.add("Hello".to_string());
499	/// let s = db.geti(id);
500	/// assert_eq!(*s, "Hello");
501	/// ```
502	pub fn add<T: Interned>(&self, value: T) -> Id<T> {
503		let span = span!(
504			trace,
505			"inserting value",
506			ty = std::any::type_name::<T>(),
507			id = tracing::field::Empty
508		);
509		#[allow(clippy::let_unit_value)]
510		let _e = span.enter();
511		let route = self.routing_table().route::<T>();
512		let storage = self
513			.storage_struct(route.storage)
514			.interned_storage(route.index)
515			.unwrap();
516		let id = unsafe { storage.insert(value) };
517		span.record("id", id);
518		Id::new(id, route)
519	}
520
521	/// Intern a value through a reference.
522	/// ```rust
523	/// # use verde::{Interned, Ctx, Id, storage, db};
524	///
525	/// # #[storage]
526	/// # struct Storage(String);
527	/// # #[db]
528	/// # struct Database(Storage);
529	///
530	/// # let mut db = Database::default();
531	/// # let db = &mut db as &mut dyn verde::Db;
532	/// let id = db.add_ref("Hello");
533	/// let s = db.geti(id);
534	/// assert_eq!(*s, "Hello");
535	/// ```
536	pub fn add_ref<T, U>(&self, value: &U) -> Id<T>
537	where
538		U: ToOwned<Owned = T> + Hash + Eq + ?Sized,
539		T: Borrow<U> + Interned,
540	{
541		let span = span!(
542			trace,
543			"inserting value",
544			ty = std::any::type_name::<T>(),
545			id = tracing::field::Empty
546		);
547		#[allow(clippy::let_unit_value)]
548		let _e = span.enter();
549		let route = self.routing_table().route::<T>();
550		let storage = self
551			.storage_struct(route.storage)
552			.interned_storage(route.index)
553			.unwrap();
554		let id = unsafe { storage.insert_ref(value) };
555		span.record("id", id);
556		Id::new(id, route)
557	}
558
559	/// Get all pushed `T`s.
560	/// ```rust
561	/// # use verde::{query, Tracked, Pushable, Ctx, Id, storage, db};
562	/// #[derive(Tracked, Eq, PartialEq)]
563	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
564	/// struct S {
565	/// 	#[id]
566	/// 	id: u32,
567	/// 	value: u32,
568	/// }
569	///
570	/// #[derive(Pushable, Eq, PartialEq, Debug)]
571	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
572	/// struct P {
573	/// 	value: u32,
574	/// }
575	///
576	/// # #[storage]
577	/// # struct Storage(S, P, foo);
578	/// # #[db]
579	/// # struct Database(Storage);
580	/// #[query]
581	/// fn foo(ctx: &Ctx, id: Id<S>) -> S {
582	/// 	let s = ctx.get(id);
583	/// 	ctx.push(P { value: s.value + 1 });
584	/// 	S {
585	/// 		id: s.id,
586	/// 		value: s.value + 1,
587	/// 	}
588	/// }
589	///
590	/// # let mut db = Database::default();
591	/// # let db = &mut db as &mut dyn verde::Db;
592	/// let id = db.set_input(S { id: 0, value: 0 });
593	/// db.execute(|ctx| foo(ctx, id));
594	/// assert_eq!(db.get_all::<P>().next(), Some(&P { value: 1 }));
595	/// ```
596	pub fn get_all<T: Pushable>(&self) -> impl Iterator<Item = &'_ T> {
597		let route = self.routing_table().route::<T>();
598		let storage = self
599			.storage_struct(route.storage)
600			.pushable_storage(route.index)
601			.unwrap();
602		unsafe { storage.get_all() }
603	}
604
605	/// Get all pushed `T`s from the query `Q`.
606	/// ```rust
607	/// # use verde::{query, Tracked, Pushable, Ctx, Id, storage, db};
608	/// #[derive(Tracked, Eq, PartialEq)]
609	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
610	/// struct S {
611	/// 	#[id]
612	/// 	id: u32,
613	/// 	value: u32,
614	/// }
615	///
616	/// #[derive(Pushable, Eq, PartialEq, Debug)]
617	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
618	/// struct P {
619	/// 	value: u32,
620	/// }
621	///
622	/// # #[storage]
623	/// # struct Storage(S, P, foo, boo);
624	/// # #[db]
625	/// # struct Database(Storage);
626	/// #[query]
627	/// fn foo(ctx: &Ctx, id: Id<S>) -> S {
628	/// 	let s = ctx.get(id);
629	/// 	ctx.push(P { value: s.value + 1 });
630	/// 	S {
631	/// 		id: s.id,
632	/// 		value: s.value + 1,
633	/// 	}
634	/// }
635	///
636	/// #[query]
637	/// fn boo(ctx: &Ctx, id: Id<S>) -> S {
638	/// 	let s = ctx.get(id);
639	/// 	ctx.push(P { value: s.value + 1 });
640	/// 	S {
641	/// 		id: s.id,
642	/// 		value: s.value + 1,
643	/// 	}
644	/// }
645	///
646	/// # let mut db = Database::default();
647	/// # let db = &mut db as &mut dyn verde::Db;
648	/// let id = db.set_input(S { id: 0, value: 0 });
649	/// let id2 = db.set_input(S { id: 0, value: 1 });
650	/// db.execute(|ctx| foo(ctx, id));
651	/// db.execute(|ctx| boo(ctx, id));
652	/// assert_eq!(db.get_query::<boo, P>().next(), Some(&P { value: 2 }));
653	/// ```
654	pub fn get_query<Q: Query, T: Pushable>(&self) -> impl Iterator<Item = &'_ T> {
655		let route = self.routing_table().route::<T>();
656		let query = self.routing_table().route::<Q>();
657		let storage = self
658			.storage_struct(route.storage)
659			.pushable_storage(route.index)
660			.unwrap();
661		unsafe { storage.get_query(query) }
662	}
663
664	/// Execute a closure in the context of the database.
665	/// ```rust
666	/// # use verde::{query, Tracked, Ctx, Id, storage, db};
667	/// #[derive(Tracked, Eq, PartialEq)]
668	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
669	/// struct S {
670	/// 	#[id]
671	/// 	id: u32,
672	/// 	value: u32,
673	/// }
674	///
675	/// # #[storage]
676	/// # struct Storage(S, foo);
677	/// # #[db]
678	/// # struct Database(Storage);
679	/// #[query]
680	/// fn foo(ctx: &Ctx, id: Id<S>) -> S {
681	/// 	let s = ctx.get(id);
682	/// 	assert_eq!(s.value, 0);
683	/// 	S {
684	/// 		id: s.id,
685	/// 		value: s.value + 1,
686	/// 	}
687	/// }
688	///
689	/// # let mut db = Database::default();
690	/// # let db = &mut db as &mut dyn verde::Db;
691	/// let id = db.set_input(S { id: 0, value: 0 });
692	/// db.execute(|ctx| foo(ctx, id));
693	/// ```
694	pub fn execute<R>(&self, f: impl FnOnce(&Ctx) -> R) -> R {
695		let ctx = Ctx::new(
696			self,
697			ErasedQueryId {
698				route: Route::input(),
699				index: 0,
700			},
701		);
702		f(&ctx)
703	}
704}
705impl dyn Db + Send + Sync + '_ {
706	/// Set an input value.
707	/// ```rust
708	/// # use verde::{Tracked, Ctx, Id, storage, db};
709	/// #[derive(Tracked, Eq, PartialEq, Debug)]
710	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
711	/// struct S {
712	/// 	#[id]
713	/// 	id: u32,
714	/// 	value: u32,
715	/// }
716	///
717	/// # #[storage]
718	/// # struct Storage(S);
719	/// # #[db]
720	/// # struct Database(Storage);
721	///
722	/// # let mut db = Database::default();
723	/// # let db = &mut db as &mut dyn verde::Db;
724	/// let id = db.set_input(S { id: 0, value: 0 });
725	/// let s = db.get(id);
726	/// assert_eq!(*s, S { id: 0, value: 0 });
727	/// ```
728	pub fn set_input<T: Tracked>(&self, value: T) -> Id<T> { (self as &dyn Db).set_input(value) }
729
730	/// Get a reference to the value `id` points to.
731	/// ```rust
732	/// # use verde::{Tracked, Ctx, Id, storage, db};
733	/// #[derive(Tracked, Eq, PartialEq, Debug)]
734	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
735	/// struct S {
736	/// 	#[id]
737	/// 	id: u32,
738	/// 	value: u32,
739	/// }
740	///
741	/// # #[storage]
742	/// # struct Storage(S);
743	/// # #[db]
744	/// # struct Database(Storage);
745	///
746	/// # let mut db = Database::default();
747	/// # let db = &mut db as &mut dyn verde::Db;
748	/// let id = db.set_input(S { id: 0, value: 0 });
749	/// let s = db.get(id);
750	/// assert_eq!(*s, S { id: 0, value: 0 });
751	/// ```
752	pub fn get<T: Tracked>(&self, id: Id<T>) -> tracked::Get<'_, T> { (self as &dyn Db).get(id) }
753
754	/// Get a reference to the value `id` points to.
755	/// ```rust
756	/// # use verde::{Interned, Ctx, Id, storage, db};
757	///
758	/// # #[storage]
759	/// # struct Storage(String);
760	/// # #[db]
761	/// # struct Database(Storage);
762	///
763	/// # let mut db = Database::default();
764	/// # let db = &mut db as &mut dyn verde::Db;
765	/// let id = db.add("Hello".to_string());
766	/// let s = db.geti(id);
767	/// assert_eq!(*s, "Hello");
768	/// ```
769	pub fn geti<T: Interned>(&self, id: Id<T>) -> interned::Get<'_, T> { (self as &dyn Db).geti(id) }
770
771	/// Intern a value.
772	/// ```rust
773	/// # use verde::{Interned, Ctx, Id, storage, db};
774	///
775	/// # #[storage]
776	/// # struct Storage(String);
777	/// # #[db]
778	/// # struct Database(Storage);
779	///
780	/// # let mut db = Database::default();
781	/// # let db = &mut db as &mut dyn verde::Db;
782	/// let id = db.add("Hello".to_string());
783	/// let s = db.geti(id);
784	/// assert_eq!(*s, "Hello");
785	/// ```
786	pub fn add<T: Interned>(&self, value: T) -> Id<T> { (self as &dyn Db).add(value) }
787
788	/// Intern a value through a reference.
789	/// ```rust
790	/// # use verde::{Interned, Ctx, Id, storage, db};
791	///
792	/// # #[storage]
793	/// # struct Storage(String);
794	/// # #[db]
795	/// # struct Database(Storage);
796	///
797	/// # let mut db = Database::default();
798	/// # let db = &mut db as &mut dyn verde::Db;
799	/// let id = db.add_ref("Hello");
800	/// let s = db.geti(id);
801	/// assert_eq!(*s, "Hello");
802	/// ```
803	pub fn add_ref<T, U>(&self, value: &U) -> Id<T>
804	where
805		U: ToOwned<Owned = T> + Hash + Eq + ?Sized,
806		T: Borrow<U> + Interned,
807	{
808		(self as &dyn Db).add_ref(value)
809	}
810
811	/// Get all pushed `T`s.
812	/// ```rust
813	/// # use verde::{query, Tracked, Pushable, Ctx, Id, storage, db};
814	/// #[derive(Tracked, Eq, PartialEq)]
815	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
816	/// struct S {
817	/// 	#[id]
818	/// 	id: u32,
819	/// 	value: u32,
820	/// }
821	///
822	/// #[derive(Pushable, Eq, PartialEq, Debug)]
823	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
824	/// struct P {
825	/// 	value: u32,
826	/// }
827	///
828	/// # #[storage]
829	/// # struct Storage(S, P, foo);
830	/// # #[db]
831	/// # struct Database(Storage);
832	/// #[query]
833	/// fn foo(ctx: &Ctx, id: Id<S>) -> S {
834	/// 	let s = ctx.get(id);
835	/// 	ctx.push(P { value: s.value + 1 });
836	/// 	S {
837	/// 		id: s.id,
838	/// 		value: s.value + 1,
839	/// 	}
840	/// }
841	///
842	/// # let mut db = Database::default();
843	/// # let db = &mut db as &mut dyn verde::Db;
844	/// let id = db.set_input(S { id: 0, value: 0 });
845	/// db.execute(|ctx| foo(ctx, id));
846	/// assert_eq!(db.get_all::<P>().next(), Some(&P { value: 1 }));
847	/// ```
848	pub fn get_all<T: Pushable>(&self) -> impl Iterator<Item = &'_ T> { (self as &dyn Db).get_all() }
849
850	/// Get all pushed `T`s from the query `Q`.
851	/// ```rust
852	/// # use verde::{query, Tracked, Pushable, Ctx, Id, storage, db};
853	/// #[derive(Tracked, Eq, PartialEq)]
854	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
855	/// struct S {
856	/// 	#[id]
857	/// 	id: u32,
858	/// 	value: u32,
859	/// }
860	///
861	/// #[derive(Pushable, Eq, PartialEq, Debug)]
862	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
863	/// struct P {
864	/// 	value: u32,
865	/// }
866	///
867	/// # #[storage]
868	/// # struct Storage(S, P, foo, boo);
869	/// # #[db]
870	/// # struct Database(Storage);
871	/// #[query]
872	/// fn foo(ctx: &Ctx, id: Id<S>) -> S {
873	/// 	let s = ctx.get(id);
874	/// 	ctx.push(P { value: s.value + 1 });
875	/// 	S {
876	/// 		id: s.id,
877	/// 		value: s.value + 1,
878	/// 	}
879	/// }
880	///
881	/// #[query]
882	/// fn boo(ctx: &Ctx, id: Id<S>) -> S {
883	/// 	let s = ctx.get(id);
884	/// 	ctx.push(P { value: s.value + 1 });
885	/// 	S {
886	/// 		id: s.id,
887	/// 		value: s.value + 1,
888	/// 	}
889	/// }
890	///
891	/// # let mut db = Database::default();
892	/// # let db = &mut db as &mut dyn verde::Db;
893	/// let id = db.set_input(S { id: 0, value: 0 });
894	/// let id2 = db.set_input(S { id: 0, value: 1 });
895	/// db.execute(|ctx| foo(ctx, id));
896	/// db.execute(|ctx| boo(ctx, id));
897	/// assert_eq!(db.get_query::<boo, P>().next(), Some(&P { value: 2 }));
898	/// ```
899	pub fn get_query<Q: Query, T: Pushable>(&self) -> impl Iterator<Item = &'_ T> {
900		(self as &dyn Db).get_query::<Q, T>()
901	}
902
903	/// Execute a closure in the context of the database.
904	/// ```rust
905	/// # use verde::{query, Tracked, Ctx, Id, storage, db};
906	/// #[derive(Tracked, Eq, PartialEq)]
907	/// # #[cfg_attr(feature = "serde", derive(verde::serde::Serialize, verde::serde::Deserialize))]
908	/// struct S {
909	/// 	#[id]
910	/// 	id: u32,
911	/// 	value: u32,
912	/// }
913	///
914	/// # #[storage]
915	/// # struct Storage(S, foo);
916	/// # #[db]
917	/// # struct Database(Storage);
918	/// #[query]
919	/// fn foo(ctx: &Ctx, id: Id<S>) -> S {
920	/// 	let s = ctx.get(id);
921	/// 	assert_eq!(s.value, 0);
922	/// 	S {
923	/// 		id: s.id,
924	/// 		value: s.value + 1,
925	/// 	}
926	/// }
927	///
928	/// # let mut db = Database::default();
929	/// # let db = &mut db as &mut dyn verde::Db;
930	/// let id = db.set_input(S { id: 0, value: 0 });
931	/// db.execute(|ctx| foo(ctx, id));
932	/// ```
933	pub fn execute<R>(&self, f: impl FnOnce(&Ctx) -> R) -> R { (self as &dyn Db).execute(f) }
934}
935
936impl dyn Db + '_ {
937	pub(crate) fn insert<T: Tracked>(&self, query: Route, value: T) -> Id<T> {
938		let span = span!(
939			trace,
940			"inserting value",
941			ty = std::any::type_name::<T>(),
942			id = tracing::field::Empty
943		);
944		#[allow(clippy::let_unit_value)]
945		let _e = span.enter();
946		let route = self.routing_table().route::<T>();
947		let storage = self.storage_struct(route.storage).tracked_storage(route.index).unwrap();
948		let id = unsafe { storage.insert(value, query) };
949		span.record("id", id);
950		Id::new(id, route)
951	}
952}
953
954impl Db for Ctx<'_> {
955	fn init_routing(_: &mut RoutingTableBuilder) {
956		panic!("Cannot call `init_routing` on a `Ctx`");
957	}
958
959	fn routing_table(&self) -> &RoutingTable { self.db.routing_table() }
960
961	fn storage_struct(&self, storage: u16) -> &dyn Storage { self.db.storage_struct(storage) }
962}