Rust bin accessing modules - rust

Problem
Cannot access ServerConnection which is in /src/gameclient/server_connection.rs from /src/bin/client.rs.
I dont have any lib.rs nor main.rs all binaries are in /src/bin/
Project structure
Cargo.toml
...
[[bin]]
name = "server"
path = "src/bin/server.rs"
[[bin]]
name = "client"
path = "src/bin/client.rs"
...
/src/gameclient/mod.rs
rust-analyzer already complains here with:
file not included in module tree
pub mod player_instance;
pub use crate::gameclient::player_instance::PlayerInstance;
pub mod server_connection;
pub use crate::gameclient::server_connection::ServerConnection;
/src/gameclient/server_connection/ServerConnection
...
pub struct ServerConnection {
pub server_endpoint: url::Url,
}
pub impl ServerConnection {
pub fn connect(&self) {
...

Pitaj gave the correct answer already.
Just for completeness.
/src/bin/client.rs
adding this at the very top makes me get rid of lib.rs.
#[path = "../gameclient/mod.rs"]
mod gameclient;

Related

Rust project workspace improvement accessibility

Problem
Is there a cleaner way to name imports from member projects then this:
(1) libs/src/messages/server_message.rs
...
let states = libs::messages::server_message::ServerMessage::Welcome(id);
...
e.g. this without changing the source code:
...
let states = libs::messages::ServerMessage::Welcome(id);
...
Project setup
Following workspaces approach.
My project looks like this
(2) Cargo.toml
...
[workspace]
members = [
"libs",
]
[dependencies]
libs = { path = "libs" }
...
(3) libs/src/libs.rs
pub mod messages;
(4) libs/src/messages/mod.rs
pub mod client_message;
pub mod remote_state;
pub mod server_message;
pub mod state;
(5) libs/src/messages/server_message.rs
...
pub enum ServerMessage {
Welcome(usize),
Goodbye(usize),
Update(Vec<RemoteState>),
}
...
Only changes required
(4) libs/src/messages/mod.rs
...
mod server_message;
pub use crate::messages::server_message::ServerMessage;
...
I could then use following import
(1) libs/src/messages/server_message.rs
let states = libs::messages::ServerMessage::Welcome(id);

Why do I get "expected struct file1::A found struct file2::A" error when using a struct in multiple files?

I am trying to share a struct between two files, but I am getting an error.
I have the following folder structure:
src/
Models/
Login.rs
Routes/
LoginRoute.rs
Services/
LoginService.rs
main.rs
In Login.rs I have:
#[derive(Serialize, Deserialize, Debug)]
pub struct UserLoginResponse {
id: i32,
username: String,
token: String
}
In LoginRoute.rs I have:
#[path = "../Models/Login.rs"]
pub mod Login;
#[path = "../Services/LoginService.rs"]
pub mod LoginService;
#[post("/login", format = "application/json", data = "<user>")]
pub async fn login(user: String) -> Json<Login::UserLoginResponse> {
if let Ok(sk) = LoginService::callAuthenticate(user).await {
return sk
......
In LoginService.rs I have:
#[path = "../Models/Login.rs"]
pub mod Login;
pub async fn callAuthenticate(user: String)-> Result<Json<Login::UserLoginResponse>, Error> {
...
let userLoginResponse :Login::UserLoginResponse = Login::UserLoginResponse::new(1, "admin".to_string(), api_reponse.return_result);
Ok(Json(userLoginResponse))
}
I am getting error in LoginRoute.rs on the return sk line:
expected struct 'LoginRoute::Login::UserLoginResponse', found struct 'LoginService::Login:UserLoginResponse'
Please do not use the #[path = ...] attribute for your typical organization; it should only be used in obscure cases. Each time you do mod something, you are declaring a new module. Even if two modules point to the same file due to #[path = ...], they will be distinct.
So you have multiple UserLoginResponse structs declared:
one at crate::LoginRoute::Login::UserLoginResponse
one at crate::LoginService::Login:UserLoginResponse
and maybe another if you've also declared Login in main.rs.
Since they're in distinct modules, the Rust compiler sees them as different types, which is not what you want.
Just use the idiomatic way of declaring modules. If you want to keep your existing folder structure without intermediate mod.rs files, you can declare them all in main.rs like so:
mod Models {
pub mod Login;
}
mod Routes {
pub mod LoginRoute;
}
mod Services {
pub mod LoginService;
}
And then access them elsewhere via crate::Models::Login and whatnot.
See:
How do I import from a sibling module?
You've probably already run into warnings from the compiler trying to encourage a specific style: "module [...] should have a snake case name". Idiomatic file structure would typically look like this:
src/
models/
login.rs
mod.rs
routes/
login_route.rs
mod.rs
services/
login_service.rs
mod.rs
main.rs
Where main.rs would have:
mod models;
mod routes;
mod services;
And src/models/mod.rs (for example) would have:
pub mod login;

The trait `std::convert::From<cli::Opts>` is not implemented

I try to create a simple application parsing command line arguments using clap library and converting them to a Config custom structure. I implemented From trait for my structure, however, when I try to call from function, I receive the following error:
the trait bound `minimal_example::Config: std::convert::From<cli::Opts>` is not satisfied
the following implementations were found:
<minimal_example::Config as std::convert::From<minimal_example::cli::Opts>>
required by `std::convert::From::from`
Here is the code:
main.rs:
mod cli;
use clap::Clap;
use minimal_example::Config;
fn main() {
println!("Hello, world!");
let opts = cli::Opts::parse();
let config = Config::from(opts);
}
cli.rs:
use clap::{Clap, crate_version};
/// This doc string acts as a help message when the user runs '--help'
/// as do all doc strings on fields
#[derive(Clap)]
#[clap(version = crate_version!(), author = "Yury")]
pub struct Opts {
/// Simple option
pub opt: String,
}
lib.rs:
mod cli;
pub struct Config {
pub opt: String,
}
impl From<cli::Opts> for Config {
fn from(opts: cli::Opts) -> Self {
Config {
opt: opts.opt,
}
}
}
cargo.toml:
[package]
name = "minimal_example"
version = "0.1.0"
authors = ["Yury"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = {version="3.0.0-beta.2", features=["wrap_help"]}
What am I doing wrong?
You have added mod cli to both lib.rs and main.rs.
They are different from the standpoint of each other.
Rust modules confusion when there is main.rs and lib.rs
may help in understanding that.
That's what the error says. It's satisfied for std::convert::From<minimal_example::cli::Opts> but not for std::convert::From<cli::Opts>.
A simple fix:
main.rs
mod cli;
use clap::Clap;
use minimal_example::Config;
impl From<cli::Opts> for Config {
fn from(opts: cli::Opts) -> Self {
Config {
opt: opts.opt,
}
}
}
fn main() {
println!("Hello, world!");
let opts = cli::Opts::parse();
let config = Config::from(opts);
}
Now std::convert::From<cli::Opts> is implemented for Config.
How you actually want to place all this depends on your package architecture.

How do I access exported functions inside a crate's "tests" directory?

How do I access my libraries exported functions inside the create's "tests" directory?
src/relations.rs:
#![crate_type = "lib"]
mod relations {
pub fn foo() {
println!("foo");
}
}
tests/test.rs:
use relations::foo;
#[test]
fn first() {
foo();
}
$ cargo test
Compiling relations v0.0.1 (file:///home/chris/github/relations)
/home/chris/github/relations/tests/test.rs:1:5: 1:14 error: unresolved import `relations::foo`. Maybe a missing `extern crate relations`?
/home/chris/github/relations/tests/test.rs:1 use relations::foo;
^~~~~~~~~
If I add the suggested extern crate relations, the error is:
/home/chris/github/relations/tests/test.rs:2:5: 2:19 error: unresolved import `relations::foo`. There is no `foo` in `relations`
/home/chris/github/relations/tests/test.rs:2 use relations::foo;
^~~~~~~~~~~~~~
I want to test my relations in this separate tests/test.rs file. How can I solve these use issues?
Your problem is that, first, mod relations is not public so it is not visible outside of the crate, and second, you don't import your crate in tests.
If you build your program with Cargo, then the crate name will be the one you defined in Cargo.toml. For example, if Cargo.toml looks like this:
[package]
name = "whatever"
authors = ["Chris"]
version = "0.0.1"
[lib]
name = "relations" # (1)
And src/lib.rs file contains this:
pub mod relations { // (2); note the pub modifier
pub fn foo() {
println!("foo");
}
}
Then you can write this in tests/test.rs:
extern crate relations; // corresponds to (1)
use relations::relations; // corresponds to (2)
#[test]
fn test() {
relations::foo();
}
The solution was to specify a crate_id at the top of src/relations.rs:
#![crate_id = "relations"]
#![crate_type = "lib"]
pub fn foo() {
println!("foo");
}
This seems to declare that all the contained code is part of a "relations" module, though I'm still not sure how this is different to the earlier mod block.

Deriving Encodable trait in a module not working

I have a main.rs file and a logging module inside logging.rs file. My file layout is:
.
├── Cargo.toml
├── src
│ ├── logging.rs
│ └── main.rs
The contents of my main.rs
mod logging;
fn main(){}
The contents of logging.rs
extern crate serialize;
use self::serialize::{json, Encoder, Encodable};
#[deriving(Encodable)]
pub struct Person {
pub age: i32
}
However this does not compile. The error is:
error: failed to resolve. Did you mean `self::serialize`?
/Users/valentin/../src/logging.rs:7 #[deriving(Encodable)]
Three questions:
Why does not it compile?
Why does moving the struct and use directive to main.rs makes it compile?
Why does changing serialize::Encodable to Show trait makes it compile even inside logging module?
However
If I add
extern crate serialize;
use self::serialize::{json, Encoder, Encodable};
to main.rs, it all starts compiling.
This is very confusing, the fourth questions is why isn't it sufficient to have only one extern crate + use serialize::.. inside logging module?
Let’s look at the code that’s generated, with rustc main.rs --pretty expanded:
#![feature(phase)]
#![no_std]
#![feature(globs)]
#[phase(plugin, link)]
extern crate std = "std";
extern crate rt = "native";
use std::prelude::*;
mod logging {
extern crate serialize;
use std::prelude::*;
use self::serialize::{json, Encoder, Encodable};
pub struct Person {
pub age: i32,
}
#[automatically_derived]
impl <__S: ::serialize::Encoder<__E>, __E>
::serialize::Encodable<__S, __E> for Person {
fn encode(&self, __arg_0: &mut __S) ->
::std::result::Result<(), __E> {
match *self {
Person { age: ref __self_0_0 } =>
__arg_0.emit_struct("Person", 1u, |_e| {
return _e.emit_struct_field("age", 0u,
|_e|
(*__self_0_0).encode(_e));
}),
}
}
}
}
fn main() { }
This demonstrates that the #[deriving(Encodable)]expands to stuff involving the paths ::serialize::*; that is, the item serialize from the crate root.
Now, extern crate serialize; from inside mod logging means that the path to serialize is ::logging::serialize, which is also accessible as self::serialize inside the module; there is no ::serialize.
The solution is moving the extern crate serialize; into the crate root. (This is where all extern crate definitions should be.) This is what fixed it for you, not the use self::serialize::{json, Encoder, Encodable};.

Resources