Redundancy in function imports - rust

I think there is some redundancy in my import but I cant really figure out another way to do it
main.rs
mod lib;
use lib::calc::med_calc;
fn main() {
let mut numbers = vec![1,21,22,4,2];
med_calc(& mut numbers)
}
to me it seems weird to declare the lib.rs as a module and only then I can use the structs/functions within. Since I've already declared them as modules and public in lib.rs itself.
lib.rs
pub mod calc {
pub fn med_calc(vector: & mut Vec<u8>){
vector.sort();
println!("{}", vector[vector.len()/2])
}
}
file tree (used in cargo):
src -
|- main.rs
|- lib.rs

When you have both a lib.rs and main.rs file in your project, the lib.rs file creates a library crate that can be accessed via the crate name in your crate's binary source files (like main.rs and bin/*.rs).
For example, if the crate is named rust_tmp, then you can do:
main.rs:
use rust_tmp::calc::med_calc;
fn main() {
let mut numbers = vec![1, 21, 22, 4, 2];
med_calc(&mut numbers)
}
No need for a mod lib;. Actually, a mod lib; is counterproductive to how lib.rs is meant to be used.

Related

Rust bin accessing modules

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;

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;

How to include a public module located in a subfolder

I have the following project where I want to divide some modules into subfolders.
The current file structure is simply:
src/
->main.rs
->cpu/
->cpu.rs
main.rs only contains:
fn main() {
println!("Hello, world!");
let c : cpu::Cpu;
cpu::thing();
}
and cpu/cpu.rs contains a struct declaration and a test function:
pub struct Cpu {
memory : [u8; 16],
}
pub fn thing() -> u8 {
2 // whatever, it's a test
}
How do I include the cpu.rs public functions and structs into main.rs?
No matter what I try, I get an error (could not find `cpu` in the crate root) if I use use crate::cpu::{Cpu, thing};, and using mod cpu; seems to only work on the same directory.
Searching for solutions online is extremely infuriating, since the answers are mixed up between the 2015 and 2018 rust editions, are over-complicated or are done in the same folder.
You forgot to made cpu (folder) a mod itself, you need to include a mod.rs file in the folder structure:
src/
->main.rs
->cpu/
->mod.rs
->cpu.rs
and in mod.rs reexport publicly the inner cpu module:
pub mod cpu;

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