use diesel::PgConnection; use r2d2; use r2d2_diesel::ConnectionManager; use std::fmt::Display; // An alias to the type for a pool of Diesel PostgreSql connections. pub type Pool = r2d2::Pool>; /// Initializes a database pool. pub fn init_db_pool(dburl: &str) -> Pool { let manager = ConnectionManager::::new(dburl); r2d2::Pool::builder().build(manager).expect("db pool") } use rocket::http::Status; use rocket::request::{self, FlashMessage, FromRequest}; use rocket::{Outcome, Request, State}; use std::ops::Deref; // Connection request guard type: a wrapper around an r2d2 pooled connection. pub struct DbConn(pub r2d2::PooledConnection>); /// Attempts to retrieve a single connection from the managed database pool. If /// no pool is currently managed, fails with an `InternalServerError` status. If /// no connections are available, fails with a `ServiceUnavailable` status. impl<'a, 'r> FromRequest<'a, 'r> for DbConn { type Error = (); fn from_request(request: &'a Request<'r>) -> request::Outcome { let pool = request.guard::>()?; match pool.get() { Ok(conn) => Outcome::Success(DbConn(conn)), Err(_) => Outcome::Failure((Status::ServiceUnavailable, ())), } } } // For the convenience of using an &DbConn as an &SqliteConnection. impl Deref for DbConn { type Target = PgConnection; fn deref(&self) -> &Self::Target { &self.0 } } #[derive(BartDisplay)] #[template = "templates/layout.html"] pub struct Page { pub title: String, pub flash: Option, pub content: T, } macro_rules! implement_responder_for { // Implement a responder for the given template type // // Seems I can't add the lifetime after the matcher, // like this: `$template_type<'a>` // So it will have to be passed in to the argument at // the macro incovation instead. ($template_type:ty) => { impl<'a> ::rocket::response::Responder<'a> for ::utils::Page<$template_type> { fn respond_to( self, _: &::rocket::Request, ) -> Result<::rocket::Response<'static>, ::rocket::http::Status> { ::rocket::Response::build() .header(::rocket::http::ContentType::HTML) .sized_body(::std::io::Cursor::new(format!("{}", &self))) .ok() } } }; }