cartel_sqlite/engine/conn/
mod.rs1use crate::{api, catalogs};
2use api::{exec, tx};
3use dope_fiber::abi;
4use dope_runtime::client;
5use phase::{Borrow, Live, Phase};
6use std::{marker, mem, ptr};
7
8mod phase;
9pub(crate) mod raw;
10
11#[repr(transparent)]
14pub struct Connection<'app, 'local: 'app, 'd: 'local, I: catalogs::Catalog = catalogs::Empty> {
15 app: client::Bound<'app, 'd, Installed<'local, 'd, I>, ptr::NonNull<Live<'local, 'd, I>>>,
16}
17
18impl<'app, 'local: 'app, 'd: 'local, I: catalogs::Catalog> Connection<'app, 'local, 'd, I> {
19 const LAYOUT: () = {
20 let word = mem::size_of::<usize>();
21 assert!(mem::size_of::<Self>() == word);
22 assert!(mem::align_of::<Self>() == mem::align_of::<usize>());
23 assert!(mem::size_of::<Option<Self>>() == word);
24 };
25
26 fn try_new(
27 context: client::Context<'_, 'app, 'd, Installed<'local, 'd, I>>,
28 ) -> Result<Self, crate::Error> {
29 let (app, bound) = context.into_parts();
30 let phase = unsafe { &*app.get_ref().phase.as_ptr() };
32 let live = match phase {
33 Phase::Live(live) => live,
34 Phase::Closing(_) | Phase::Retiring(_) | Phase::Empty => {
35 return Err(crate::Error::LocalConnectionClosed);
36 }
37 };
38 match live.borrow.get() {
39 Borrow::Vacant => {}
40 Borrow::Borrowed => return Err(crate::Error::LocalConnectionBorrowed),
41 Borrow::Closed | Borrow::Closing => return Err(crate::Error::LocalConnectionClosed),
42 }
43 live.borrow.set(Borrow::Borrowed);
44 Ok(Self {
45 app: bound.bind(ptr::NonNull::from(live)),
46 })
47 }
48
49 fn state(&mut self) -> &mut api::State<'local, 'd, I> {
50 unsafe { &mut *self.app.as_ref().state.get() }
52 }
53
54 pub fn query(&mut self) -> exec::Query<'_, 'local, 'd, I> {
55 self.state().query()
56 }
57
58 pub fn transaction(
59 &mut self,
60 ) -> impl abi::Fiber<'d, Output = Result<tx::Transaction<'_, 'local, 'd, I>, crate::Error>>
61 + use<'_, 'app, 'local, 'd, I> {
62 self.state().transaction()
63 }
64}
65
66impl<I: catalogs::Catalog> Drop for Connection<'_, '_, '_, I> {
67 fn drop(&mut self) {
68 let live = unsafe { self.app.as_ref() };
70 live.borrow.set(live.borrow.get().returned());
71 }
72}
73
74impl<'query, 'app: 'query, 'local: 'app, 'd: 'local, I: catalogs::Catalog>
75 api::IntoQuery<'query, 'local, 'd, I> for &'query mut Connection<'app, 'local, 'd, I>
76{
77 fn into_query(self) -> exec::Query<'query, 'local, 'd, I> {
78 self.query()
79 }
80}
81
82pub struct Installed<'local, 'd: 'local, I: catalogs::Catalog> {
84 phase: ptr::NonNull<Phase<'local, 'd, I>>,
85 ownership: marker::PhantomData<(Phase<'local, 'd, I>, marker::PhantomPinned)>,
86}
87
88impl<'local, 'd: 'local, I: catalogs::Catalog> client::Provider<'d> for Installed<'local, 'd, I> {
89 type Client<'app>
90 = Result<Connection<'app, 'local, 'd, I>, crate::Error>
91 where
92 Self: 'app,
93 'd: 'app;
94
95 fn provide<'app>(context: client::Context<'_, 'app, 'd, Self>) -> Self::Client<'app>
96 where
97 Self: 'app,
98 'd: 'app,
99 {
100 Connection::try_new(context)
101 }
102}
103
104const _: () = Connection::<catalogs::Empty>::LAYOUT;
105
106const _: () = {
107 assert!(mem::size_of::<Installed<'_, '_, catalogs::Empty>>() == mem::size_of::<usize>());
108 assert!(mem::align_of::<Installed<'_, '_, catalogs::Empty>>() == mem::align_of::<usize>());
109};