I have the following code:
#[database("pg_db")]
struct PgDbConn(diesel::PgConnection);
fn main() {
rocket::ignite()
.attach(PgDbConn::fairing())
.mount("/", routes![find_one, find_all])
.launch();
}
#[get("/<id>", format = "json")]
fn find_one(conn: PgDbConn, id: i32) -> Result<Json<Person>, NotFound<String>> {
let one: QueryResult<Person> = person.find(id).first(&*conn);
...
I would like to know how my PgDbConn
struct ends up as a connection. My question is about the referencing and dereferencing in &*conn
. Can someone please explain the mechanism in detail?
Let's have a look at (part of) the implementation of the database
attribute macro:
Ok(quote! {
//...
impl ::std::ops::Deref for #guard_type {
type Target = #conn_type;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl ::std::ops::DerefMut for #guard_type {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
})
#guard_type
is PgDbConn
and #conn_type
is diesel::PgConnection
in your example, so the produced code looks like this:
impl ::std::ops::Deref for PgDbConn {
type Target = diesel::PgConnection;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl ::std::ops::DerefMut for PgDbConn {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
With Deref
and DerefMut
, you can implement dereference for your own types, in this case PgDbConn
. Now, you can write *conn
to get a diesel::PgConnection
from your PgDbConn
. However, you want a reference to diesel::PgConnection
. To get a reference, you have to again reference the dereferenced PgDbConn
, so the end result is &*conn
.