Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 6 additions & 12 deletions contrib/lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ diesel_mysql_pool = ["databases", "diesel/mysql", "diesel/r2d2"]
postgres_pool = ["databases", "postgres", "r2d2_postgres"]
mysql_pool = ["databases", "mysql", "r2d2_mysql"]
sqlite_pool = ["databases", "rusqlite", "r2d2_sqlite"]
cypher_pool = ["databases", "rusted_cypher", "r2d2_cypher"]
redis_pool = ["databases", "redis", "r2d2_redis"]
mongodb_pool = ["databases", "mongodb", "r2d2-mongodb"]
memcache_pool = ["databases", "memcache", "r2d2-memcache"]

[dependencies]
Expand Down Expand Up @@ -66,16 +64,12 @@ diesel = { version = "1.0", default-features = false, optional = true }
postgres = { version = "0.17", optional = true }
r2d2 = { version = "0.8", optional = true }
r2d2_postgres = { version = "0.16", optional = true }
mysql = { version = "17.0", optional = true }
r2d2_mysql = { version = "17.0", optional = true }
rusqlite = { version = "0.16.0", optional = true }
r2d2_sqlite = { version = "0.8", optional = true }
rusted_cypher = { version = "1", optional = true }
r2d2_cypher = { version = "0.4", optional = true }
redis = { version = "0.13", optional = true }
r2d2_redis = { version = "0.12", optional = true }
mongodb = { version = "0.3.12", optional = true }
r2d2-mongodb = { version = "0.2.0", optional = true }
mysql = { version = "18.0", optional = true }
r2d2_mysql = { version = "18.0", optional = true }
rusqlite = { version = "0.23", optional = true }
r2d2_sqlite = { version = "0.16", optional = true }
redis = { version = "0.15", optional = true }
r2d2_redis = { version = "0.13", optional = true }
memcache = { version = "0.14", optional = true }
r2d2-memcache = { version = "0.5", optional = true }

Expand Down
47 changes: 6 additions & 41 deletions contrib/lib/src/databases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,33 +340,27 @@
//! | Kind | Driver | Version | `Poolable` Type | Feature |
//! |----------|-----------------------|-----------|--------------------------------|------------------------|
//! | MySQL | [Diesel] | `1` | [`diesel::MysqlConnection`] | `diesel_mysql_pool` |
//! | MySQL | [`rust-mysql-simple`] | `17` | [`mysql::Conn`] | `mysql_pool` |
//! | MySQL | [`rust-mysql-simple`] | `18` | [`mysql::Conn`] | `mysql_pool` |
//! | Postgres | [Diesel] | `1` | [`diesel::PgConnection`] | `diesel_postgres_pool` |
//! | Postgres | [Rust-Postgres] | `0.17` | [`postgres::Client`] | `postgres_pool` |
//! | Sqlite | [Diesel] | `1` | [`diesel::SqliteConnection`] | `diesel_sqlite_pool` |
//! | Sqlite | [`Rusqlite`] | `0.16` | [`rusqlite::Connection`] | `sqlite_pool` |
//! | Neo4j | [`rusted_cypher`] | `1` | [`rusted_cypher::GraphClient`] | `cypher_pool` |
//! | Redis | [`redis-rs`] | `0.13` | [`redis::Connection`] | `redis_pool` |
//! | MongoDB | [`mongodb`] | `0.3.12` | [`mongodb::db::Database`] | `mongodb_pool` |
//! | Sqlite | [`Rusqlite`] | `0.23` | [`rusqlite::Connection`] | `sqlite_pool` |
//! | Redis | [`redis-rs`] | `0.15` | [`redis::Connection`] | `redis_pool` |
//! | Memcache | [`memcache`] | `0.14` | [`memcache::Client`] | `memcache_pool` |
//!
//! [Diesel]: https://diesel.rs
//! [`redis::Connection`]: https://docs.rs/redis/0.13.0/redis/struct.Connection.html
//! [`rusted_cypher::GraphClient`]: https://docs.rs/rusted_cypher/1.1.0/rusted_cypher/graph/struct.GraphClient.html
//! [`rusqlite::Connection`]: https://docs.rs/rusqlite/0.16.0/rusqlite/struct.Connection.html
//! [`redis::Connection`]: https://docs.rs/redis/0.15.0/redis/struct.Connection.html
//! [`rusqlite::Connection`]: https://docs.rs/rusqlite/0.23.0/rusqlite/struct.Connection.html
//! [`diesel::SqliteConnection`]: http://docs.diesel.rs/diesel/prelude/struct.SqliteConnection.html
//! [`postgres::Client`]: https://docs.rs/postgres/0.17/postgres/struct.Client.html
//! [`diesel::PgConnection`]: http://docs.diesel.rs/diesel/pg/struct.PgConnection.html
//! [`mysql::Conn`]: https://docs.rs/mysql/17/mysql/struct.Conn.html
//! [`mysql::Conn`]: https://docs.rs/mysql/18/mysql/struct.Conn.html
//! [`diesel::MysqlConnection`]: http://docs.diesel.rs/diesel/mysql/struct.MysqlConnection.html
//! [`redis-rs`]: https://github.com/mitsuhiko/redis-rs
//! [`rusted_cypher`]: https://github.com/livioribeiro/rusted-cypher
//! [`Rusqlite`]: https://github.com/jgallagher/rusqlite
//! [Rust-Postgres]: https://github.com/sfackler/rust-postgres
//! [`rust-mysql-simple`]: https://github.com/blackbeam/rust-mysql-simple
//! [`diesel::PgConnection`]: http://docs.diesel.rs/diesel/pg/struct.PgConnection.html
//! [`mongodb`]: https://github.com/mongodb-labs/mongo-rust-driver-prototype
//! [`mongodb::db::Database`]: https://docs.rs/mongodb/0.3.12/mongodb/db/type.Database.html
//! [`memcache`]: https://github.com/aisk/rust-memcache
//! [`memcache::Client`]: https://docs.rs/memcache/0.14/memcache/struct.Client.html
//!
Expand Down Expand Up @@ -416,15 +410,9 @@ use self::r2d2::ManageConnection;
#[cfg(feature = "sqlite_pool")] pub extern crate rusqlite;
#[cfg(feature = "sqlite_pool")] pub extern crate r2d2_sqlite;

#[cfg(feature = "cypher_pool")] pub extern crate rusted_cypher;
#[cfg(feature = "cypher_pool")] pub extern crate r2d2_cypher;

#[cfg(feature = "redis_pool")] pub extern crate redis;
#[cfg(feature = "redis_pool")] pub extern crate r2d2_redis;

#[cfg(feature = "mongodb_pool")] pub extern crate mongodb;
#[cfg(feature = "mongodb_pool")] pub extern crate r2d2_mongodb;

#[cfg(feature = "memcache_pool")] pub extern crate memcache;
#[cfg(feature = "memcache_pool")] pub extern crate r2d2_memcache;

Expand Down Expand Up @@ -626,7 +614,6 @@ impl<'a> Display for ConfigError {
/// * `postgres::Connection`
/// * `mysql::Conn`
/// * `rusqlite::Connection`
/// * `rusted_cypher::GraphClient`
/// * `redis::Connection`
///
/// # Implementation Guide
Expand Down Expand Up @@ -790,17 +777,6 @@ impl Poolable for rusqlite::Connection {
}
}

#[cfg(feature = "cypher_pool")]
impl Poolable for rusted_cypher::GraphClient {
type Manager = r2d2_cypher::CypherConnectionManager;
type Error = r2d2::Error;

fn pool(config: DatabaseConfig<'_>) -> Result<r2d2::Pool<Self::Manager>, Self::Error> {
let manager = r2d2_cypher::CypherConnectionManager { url: config.url.to_string() };
r2d2::Pool::builder().max_size(config.pool_size).build(manager)
}
}

#[cfg(feature = "redis_pool")]
impl Poolable for redis::Connection {
type Manager = r2d2_redis::RedisConnectionManager;
Expand All @@ -813,17 +789,6 @@ impl Poolable for redis::Connection {
}
}

#[cfg(feature = "mongodb_pool")]
impl Poolable for mongodb::db::Database {
type Manager = r2d2_mongodb::MongodbConnectionManager;
type Error = DbError<mongodb::Error>;

fn pool(config: DatabaseConfig<'_>) -> Result<r2d2::Pool<Self::Manager>, Self::Error> {
let manager = r2d2_mongodb::MongodbConnectionManager::new_with_uri(config.url).map_err(DbError::Custom)?;
r2d2::Pool::builder().max_size(config.pool_size).build(manager).map_err(DbError::PoolError)
}
}

#[cfg(feature = "memcache_pool")]
impl Poolable for memcache::Client {
type Manager = r2d2_memcache::MemcacheConnectionManager;
Expand Down
4 changes: 2 additions & 2 deletions core/http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ private-cookies = ["cookie/private", "cookie/key-expansion"]

[dependencies]
smallvec = "1.0"
percent-encoding = "1"
percent-encoding = "2"
hyper = { version = "0.13.0", default-features = false }
http = "0.2"
mime = "0.3.13"
time = "0.2.11"
indexmap = "1.0"
state = "0.4"
tokio-rustls = { version = "0.12.0", optional = true }
tokio-rustls = { version = "0.14.0", optional = true }
tokio = { version = "0.2.9", features = ["sync", "tcp", "time"] }
cookie = { version = "0.14.0", features = ["percent-encode"] }
pear = "0.1"
Expand Down
2 changes: 1 addition & 1 deletion core/http/src/parse/uri/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::uri::{Uri, Origin, Absolute, Authority};
use crate::parse::indexed::IndexedInput;
use self::parser::{uri, origin, authority_only, absolute_only, rocket_route_origin};

pub use self::tables::is_pchar;
pub use self::tables::{is_pchar, PATH_SET};
pub use self::error::Error;

type RawInput<'a> = IndexedInput<'a, [u8]>;
Expand Down
42 changes: 40 additions & 2 deletions core/http/src/parse/uri/tables.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
use percent_encoding::AsciiSet;

// Generates an AsciiSet from a full character table:
//
// table_to_ascci_set!( ExistingAsciiSet, 0, [ 0, 1, b'x', ... ] );
//
// A 0 or 1 token in the ith position indicates that the ASCII character i
// should be included in the set. Any other literal in the ith position
// indicates that the ASCII character with value i should not be included in the
// set.
//
// The table's last index must be 127 or earlier. All values in the original
// set, up to the end of the passed-in table, are overwritten.
macro_rules! table_to_ascii_set {
($base:expr, $i:expr, [ 0, $($rest:tt,)* ]) => { table_to_ascii_set!($base.add($i), $i+1, [ $($rest,)* ]); };
($base:expr, $i:expr, [ 1, $($rest:tt,)* ]) => { table_to_ascii_set!($base.add($i), $i+1, [ $($rest,)* ]); };
($base:expr, $i:expr, [ $ch:literal, $($rest:tt,)* ]) => { table_to_ascii_set!($base.remove($i), $i+1, [ $($rest,)* ]); };
($base:expr, $i:expr, [ ]) => { $base };
}

// Generates an AsciiSet accompanying a character table. This is
// used to keep `PATH_CHARS` in sync with `PATH_SET`.
//
// The first block is limited to 128 entries, since it is passed
// to table_to_ascii_set!
macro_rules! table_and_asciiset {
(
const $name:ident: [u8; $size:expr] = [ $($block1:tt)* ] [ $($block2:tt)* ];
pub const $setname:ident: AsciiSet;
) => {
const $name: [u8; $size] = [ $($block1)* $($block2)* ] ;
pub const $setname: AsciiSet = table_to_ascii_set!(percent_encoding::CONTROLS, 0, [ $($block1)* ]);
};
}

table_and_asciiset! {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not super happy with this macro invocation (and table_to_ascii_set above). Most of the awkwardness is that AsciiSet's public API only has .add(u8), .remove(u8) and there is no public constructor for an "empty" AsciiSet. The other awkwardness is that you can't call add or remove with any u8 value above 127 apparently due to AsciiSet's bitpacking optimizations.

Some alternatives I thought of:

  • The const_if_match feature as originally proposed in Upgrade percent-encoding to 2.x and base64 to 0.12. #1349, which is stabilized but in one stable release later than we want for 0.5.
  • Have introspection APIs added to AsciiSet, which could make PATH_CHARS unnecessary since AsciiSet could be queried equivalently. AsciiSet's packed representation might lose some performance difference compared to the PATH_CHARS array, however, and we would need to keep a macro like this one anyway.

const PATH_CHARS: [u8; 256] = [
// 0 1 2 3 4 5 6 7 8 9
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // x
Expand All @@ -13,7 +49,7 @@ const PATH_CHARS: [u8; 256] = [
b'Z', 0, 0, 0, 0, b'_', 0, b'a', b'b', b'c', // 9x
b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l', b'm', // 10x
b'n', b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', // 11x
b'x', b'y', b'z', 0, 0, 0, b'~', 0, 0, 0, // 12x
b'x', b'y', b'z', 0, 0, 0, b'~', 0, ] [ 0, 0, // 12x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 13x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 14x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 15x
Expand All @@ -26,8 +62,10 @@ const PATH_CHARS: [u8; 256] = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 22x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 23x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 24x
0, 0, 0, 0, 0, 0 // 25x
0, 0, 0, 0, 0, 0, // 25x
];
pub const PATH_SET: AsciiSet;
}

#[inline(always)]
pub fn is_pchar(c: u8) -> bool {
Expand Down
53 changes: 26 additions & 27 deletions core/http/src/uri/encoding.rs
Original file line number Diff line number Diff line change
@@ -1,65 +1,64 @@
use std::marker::PhantomData;
use std::borrow::Cow;

use percent_encoding::{EncodeSet, utf8_percent_encode};
use percent_encoding::{AsciiSet, utf8_percent_encode};

use crate::uri::{UriPart, Path, Query};
use crate::parse::uri::is_pchar;
use crate::parse::uri::PATH_SET;

#[derive(Clone, Copy)]
#[allow(non_camel_case_types)]
pub struct UNSAFE_ENCODE_SET<P: UriPart>(PhantomData<P>);
pub trait EncodeSet {
const SET: AsciiSet;
}

impl<P: UriPart> Default for UNSAFE_ENCODE_SET<P> {
#[inline(always)]
fn default() -> Self { UNSAFE_ENCODE_SET(PhantomData) }
}

impl EncodeSet for UNSAFE_ENCODE_SET<Path> {
#[inline(always)]
fn contains(&self, byte: u8) -> bool {
!is_pchar(byte) || byte == b'%'
}
const SET: AsciiSet = PATH_SET
.add(b'%');
}

impl EncodeSet for UNSAFE_ENCODE_SET<Query> {
#[inline(always)]
fn contains(&self, byte: u8) -> bool {
(!is_pchar(byte) && (byte != b'?')) || byte == b'%' || byte == b'+'
}
const SET: AsciiSet = PATH_SET
.remove(b'?')
.add(b'%')
.add(b'+');
}

#[derive(Clone, Copy)]
#[allow(non_camel_case_types)]
pub struct ENCODE_SET<P: UriPart>(PhantomData<P>);

impl EncodeSet for ENCODE_SET<Path> {
#[inline(always)]
fn contains(&self, byte: u8) -> bool {
<UNSAFE_ENCODE_SET<Path>>::default().contains(byte) || byte == b'/'
}
const SET: AsciiSet = <UNSAFE_ENCODE_SET<Path>>::SET
.add(b'/');
}

impl EncodeSet for ENCODE_SET<Query> {
#[inline(always)]
fn contains(&self, byte: u8) -> bool {
<UNSAFE_ENCODE_SET<Query>>::default().contains(byte) || match byte {
b'&' | b'=' => true,
_ => false
}
}
const SET: AsciiSet = <UNSAFE_ENCODE_SET<Query>>::SET
.add(b'&')
.add(b'=');
}

#[derive(Default, Clone, Copy)]
#[allow(non_camel_case_types)]
pub struct DEFAULT_ENCODE_SET;

impl EncodeSet for DEFAULT_ENCODE_SET {
#[inline(always)]
fn contains(&self, byte: u8) -> bool {
ENCODE_SET::<Path>(PhantomData).contains(byte) ||
ENCODE_SET::<Query>(PhantomData).contains(byte)
}
// DEFAULT_ENCODE_SET Includes:
// * ENCODE_SET<Path> (and UNSAFE_ENCODE_SET<Path>)
const SET: AsciiSet = <ENCODE_SET<Path>>::SET
// * UNSAFE_ENCODE_SET<Query>
.add(b'%')
.add(b'+')
// * ENCODE_SET<Query>
.add(b'&')
.add(b'=');
}

pub fn unsafe_percent_encode<P: UriPart>(string: &str) -> Cow<'_, str> {
Expand All @@ -71,5 +70,5 @@ pub fn unsafe_percent_encode<P: UriPart>(string: &str) -> Cow<'_, str> {
}

pub fn percent_encode<S: EncodeSet + Default>(string: &str) -> Cow<'_, str> {
utf8_percent_encode(string, S::default()).into()
utf8_percent_encode(string, &S::SET).into()
}
2 changes: 1 addition & 1 deletion examples/raw_sqlite/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ publish = false

[dependencies]
rocket = { path = "../../core/lib" }
rusqlite = "0.16"
rusqlite = "0.23"
2 changes: 1 addition & 1 deletion examples/todo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ diesel_migrations = "1.3"
log = "0.4"

[dev-dependencies]
parking_lot = { version = "0.10", features = ["nightly"] }
parking_lot = "0.11"
rand = "0.7"

[dependencies.rocket_contrib]
Expand Down
2 changes: 1 addition & 1 deletion examples/todo/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rocket::http::{Status, ContentType};
// We use a lock to synchronize between tests so DB operations don't collide.
// For now. In the future, we'll have a nice way to run each test in a DB
// transaction so we can regain concurrency.
static DB_LOCK: Mutex<()> = Mutex::new(());
static DB_LOCK: Mutex<()> = parking_lot::const_mutex(());

macro_rules! run_test {
(|$client:ident, $conn:ident| $block:expr) => ({
Expand Down
2 changes: 0 additions & 2 deletions scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,7 @@ if [ "$1" = "--contrib" ]; then
postgres_pool
mysql_pool
sqlite_pool
cypher_pool
redis_pool
mongodb_pool
memcache_pool
brotli_compression
gzip_compression
Expand Down
18 changes: 6 additions & 12 deletions site/guide/6-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,34 +230,28 @@ Presently, Rocket provides built-in support for the following databases:
| Kind | Driver | Version | `Poolable` Type | Feature |
|----------|-----------------------|-----------|--------------------------------|------------------------|
| MySQL | [Diesel] | `1` | [`diesel::MysqlConnection`] | `diesel_mysql_pool` |
| MySQL | [`rust-mysql-simple`] | `17` | [`mysql::Conn`] | `mysql_pool` |
| MySQL | [`rust-mysql-simple`] | `18` | [`mysql::Conn`] | `mysql_pool` |
| Postgres | [Diesel] | `1` | [`diesel::PgConnection`] | `diesel_postgres_pool` |
| Postgres | [Rust-Postgres] | `0.17` | [`postgres::Client`] | `postgres_pool` |
| Sqlite | [Diesel] | `1` | [`diesel::SqliteConnection`] | `diesel_sqlite_pool` |
| Sqlite | [`Rusqlite`] | `0.16` | [`rusqlite::Connection`] | `sqlite_pool` |
| Neo4j | [`rusted_cypher`] | `1` | [`rusted_cypher::GraphClient`] | `cypher_pool` |
| Redis | [`redis-rs`] | `0.13` | [`redis::Connection`] | `redis_pool` |
| MongoDB | [`mongodb`] | `0.3.12` | [`mongodb::db::Database`] | `mongodb_pool` |
| Sqlite | [`Rusqlite`] | `0.23` | [`rusqlite::Connection`] | `sqlite_pool` |
| Redis | [`redis-rs`] | `0.15` | [`redis::Connection`] | `redis_pool` |
| Memcache | [`memcache`] | `0.14` | [`memcache::Client`] | `memcache_pool` |

[`r2d2`]: https://crates.io/crates/r2d2
[Diesel]: https://diesel.rs
[`redis::Connection`]: https://docs.rs/redis/0.13.0/redis/struct.Connection.html
[`rusted_cypher::GraphClient`]: https://docs.rs/rusted_cypher/1.1.0/rusted_cypher/graph/struct.GraphClient.html
[`rusqlite::Connection`]: https://docs.rs/rusqlite/0.16.0/rusqlite/struct.Connection.html
[`redis::Connection`]: https://docs.rs/redis/0.15.0/redis/struct.Connection.html
[`rusqlite::Connection`]: https://docs.rs/rusqlite/0.23.0/rusqlite/struct.Connection.html
[`diesel::SqliteConnection`]: http://docs.diesel.rs/diesel/prelude/struct.SqliteConnection.html
[`postgres::Client`]: https://docs.rs/postgres/0.17/postgres/struct.Client.html
[`diesel::PgConnection`]: http://docs.diesel.rs/diesel/pg/struct.PgConnection.html
[`mysql::Conn`]: https://docs.rs/mysql/17/mysql/struct.Conn.html
[`mysql::Conn`]: https://docs.rs/mysql/18/mysql/struct.Conn.html
[`diesel::MysqlConnection`]: http://docs.diesel.rs/diesel/mysql/struct.MysqlConnection.html
[`redis-rs`]: https://github.com/mitsuhiko/redis-rs
[`rusted_cypher`]: https://github.com/livioribeiro/rusted-cypher
[`Rusqlite`]: https://github.com/jgallagher/rusqlite
[Rust-Postgres]: https://github.com/sfackler/rust-postgres
[`rust-mysql-simple`]: https://github.com/blackbeam/rust-mysql-simple
[`diesel::PgConnection`]: http://docs.diesel.rs/diesel/pg/struct.PgConnection.html
[`mongodb`]: https://github.com/mongodb-labs/mongo-rust-driver-prototype
[`mongodb::db::Database`]: https://docs.rs/mongodb/0.3.12/mongodb/db/type.Database.html
[`memcache`]: https://github.com/aisk/rust-memcache
[`memcache::Client`]: https://docs.rs/memcache/0.14/memcache/struct.Client.html

Expand Down