Hello.
In the
first part, we made the simplest prototype that works with PostgreSQL.
In this case, we have registered all the parameters of the connection with the database directly in the code. Let's now put them into the configuration file.
')
I chose
INI as a configuration format — a fairly simple and well-known format.
First of all, we need to find a library for working with INI files.
Here
crates.io , the centralized storage of Rust containers, will help us. We go there, drive in the search "ini", and the very first link leads to the library we need:
rust-ini .
Using it, judging by the example on the main one, is quite simple. Let's try:
Codeextern crate ini; ... use ini::Ini; fn params() -> (ConnectParams, SslMode) { let conf = Ini::load_from_file(".phonebookrc").unwrap(); let general = conf.general_section(); let host = general.get("host").unwrap(); let port = general.get("port").unwrap(); let sslmode = general.get("sslmode").unwrap(); let dbname = general.get("dbname").unwrap(); let user = general.get("user").unwrap(); let pass = general.get("pass").unwrap(); let sslmode_ = match sslmode.as_ref() { "disable" => SslMode::None, "enable" => unimplemented!(), _ => panic!("Wrong sslmode"), }; let params = ConnectParams { target: ConnectTarget::Tcp(host.to_owned()), port: Some(FromStr::from_str(port).unwrap()), user: Some(UserInfo { user: user.to_owned(), password: Some(pass.to_owned()), }), database: Some(dbname.to_owned()), options: vec![], }; (params, sslmode_) } fn main() { let (params, sslmode) = params(); ...
It is worth explaining a few points.
We do
let s = match sslmode.as_ref() {
so that sslmode is not moved inside the match. Otherwise, we could not use it further.
unimplemented! () is a macro that is used to show that certain functionality is not implemented. It causes panic when reaching this line.
panic! () is a macro that directly causes a panic of the current thread. It can be called with a format string and arguments to print your message.
Finally, we create a structure with connection parameters.
let params = ConnectParams {
All fields are initialized, as usual, except for two:
port: Some(FromStr::from_str(port).unwrap()),
Here we use the from_str method from FromStr to parse an integer from a string. This operation returns a Result.
options: vec![],
Here we use the vector initialization macro: it creates a vector, and then does v.push (...) several times.
At the end of the function, we simply write
(params, sslmode_)
to return from it a tuple of 2 elements. Note the absence of a semicolon.
However, if we now try to build a program, we will fail:
$ cargo build
Compiling bufstream v0.1.1
Compiling debug-builders v0.1.0
Compiling gcc v0.3.6
Compiling rustc-serialize v0.3.14
Compiling phf_shared v0.7.3
Compiling libc v0.1.8
Compiling byteorder v0.3.10
Compiling phf v0.7.3
Compiling log v0.3.1
Compiling rand v0.3.8
Compiling rust-ini v0.6.0 (https://github.com/zonyitoo/rust-ini/#0b3a3894)
Compiling time v0.1.26
/home/mkpankov/.multirust/toolchains/stable/cargo/git/checkouts/rust-ini-4a9e7dbb298b5764/master/src/lib.rs:48:1: 48:16 error: # [feature] may not be used the stable release channel
/home/mkpankov/.multirust/toolchains/stable/cargo/git/checkouts/rust-ini-4a9e7dbb298b5764/master/src/lib.rs:48 #! [feature (io)]
^ ~~~~~~~~~~~~~~
error: aborting due to previous error
Compiling rust-crypto v0.2.31
Build failed, waiting for other jobs to finish ...
Could not compile rust-ini.
The compiler says that the “io” feature cannot be used in a stable compiler. Hm
As you can see, “feature (io)” is not used by us, but by rust-ini itself. And in which compiler can it be used then? The answer, of course, is in the unstable Rust.
It is worth noting that at such moments it is easier to go to the chat (at least in
our Russian language ) and ask what is happening and what to do. There is a documentation of the disabled features, but it doesn’t quite keep up with the real state of affairs.
Okay, so what now? Need to reinstall the compiler just for this? Unfortunately, yes, but, fortunately, it needs to be done only once.
Get to
know multirust .
This tool manages compiler versions and allows you to instantly switch between them, and also simplifies updating.
Install it (you should first
remove the already installed Rust):
$ curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sh
Now we can install the compilers themselves and say that our project needs a nightly compiler:
$ multirust update
...
$ cd rust-phonebook
$ multirust override nightly
multirust: using existing install for 'nightly'
multirust: override toolchain for '/home/mkpankov/rust-phonebook.finished' set to 'nightly'
Now we will try to rebuild our project:
$ cargo build
...
Compiling rust-phonebook v0.1.0 (file: ///home/mkpankov/rust-phonebook.finished)
src / main.rs: 10: 5: 10:12 warning: struct field is never used: `id`, # [warn (dead_code)] on by default
src / main.rs: 10 id: i32,
^ ~~~~~~
$
All gathered!
multirust makes the job much more convenient. New projects are still better to start on a stable compiler, and switch only when necessary - the situation with unstable features is such that not all projects need them. And updating of all assemblies is done with it with just one “multirust update” command.
The fly in the ointment is that multirust is not currently running on Windows. But installing several compilers on Windows won't hurt you - they are by default put in different places.
That's all for today. Now you know where to look for libraries, and what to do if they require unstable capabilities.