Rust use different variable value for Cargo profile [duplicate] - rust

This question already has an answer here:
How to check release / debug builds using cfg in Rust?
(1 answer)
Closed yesterday.
This is surprisingly hard to find in the documentation. I want to use a different base_url for my API endpoint for every Cargo profile. So, —-profile=debug will use https://localhost:3000, and —-profile=release will use https://api.cooldomain.io/ or something like that.
Any pointers?

You can set your base_url using #[cfg(debug_assertions)] for debug profiles and using #[cfg(not(debug_assertions))] for non debug profiles.
For example like this
#[cfg(debug_assertions)]
const BASE_URL:&'static str = "http://localhost:3000";
#[cfg(not(debug_assertions))]
const BASE_URL:&'static str = "https://api.cooldomain.io/";
fn main() {
println!("{}",BASE_URL);
}
You can read more about debug_assertions here

Related

Solana Rust program BTreeMap

I have read this article here and I understood that HashMap is not usable in Solana, thus, I need to use BTreeMap.
I am a beginner in Rust and I am having an error with the following code when trying to move from Ethereum to Solana :
pub fn constructor (
let mut DomainsToIndex = BTreeMap::new();
Domains[] pub DomainList;
contractOwner = msg.sender;
firstDomain.name = "empty";
firstDomain.IP = "n/a";
firstDomain.owner = 0;
firstDomain.lockTime = 0;
firstDomain.infoDocumentHash = "n/a";
DomainsToIndex.insert(String::from(firstDomain.name), 0);
DomainList.push(firstDomain);
) -> ProgramResult {
msg!("First domain was added by default");
Ok(())
}
I of course added the import in the top of the file with:
use std::collections::BTreeMap;
The error I receive when using cargo build is the following as per the image presented below:
I presume that I am not doing something right, as I am a newbie in Rust, can you please help out ?
Thanks.
There are a couple of syntactical issues with the code.
Application arguments should be separate from the body and pub without a struct doesn't make sense either.
Unfortunately the documentation of their Rust interface is quite lacking (seems to be mostly "have a look at some examples then find out the rest through trial-and-error"). So I was unable to look up enough information to suggest a reasonably correct version.
Here are a couple of more pointers:
it's not clear what the input to this function is. You're referencing a msg object with a sender member there, but the only equivalent I could identify was the &[AccountInfo] argument which identifies the invoking account.
Alternatively, Solana programs receive a byte array of instruction data which apparently can have any content encoded within them.
I would suggest starting with their Hello World example, playing around with it a bit and continue with your own app once you're more familiar with Rust syntax and Solana best practices.

Is there a way to bind a variable to a request in tower-http / hyper / axum?

I'm trying to add a request id to each tracing event. I can do it with tower_http::trace like this:
#[derive(Clone)]
pub struct RequestSpan;
impl<B> tower_http::trace::MakeSpan<B> for RequestSpan {
fn make_span(&mut self, request: &http::Request<B>) -> tracing::Span {
tracing::error_span!(
"rq",
id = %ulid::Ulid::new().to_string(),
method = %request.method(),
uri = %request.uri(),
version = ?request.version(),
)
}
}
...
let middleware_stack = tower::ServiceBuilder::new()
.layer(TraceLayer::new_for_http().make_span_with(RequestSpan))
It works in the scope of the server, but I also need to pass the request id into an external task queue. Any suggestions?
Custom data can be stored on requests via Extensions. They are accessible via .extensions() and .extensions_mut() on a http::request::Request (which works for hyper and tower-http) or via the same methods on axum::response::RequestParts (which works for axum).
Extensions are primarily used to move data between services/middleware to the route handler and vice-versa. The collection acts like a map with values keyed-off of their type, so if you want to store a Ulid you probably want to wrap it in some more descriptive type like RequestId(Ulid) just to ensure it doesn't conflict with other uses.
See also:
What is the role of a "Extension" in actix-web?
What are Rust's HTTP extensions? (blog)
I've made it into a little crate following a solution from rustlang forum

Using Rust crates for an STM32 microcontroller board

I'm currently trying to learn Rust (for embedded specifically), coming from a background of C for embedded systems and Python.
So far, I've been reading Rust Programming Language and Rust for Embedded, and read a few blog posts on the web.
I want my first project to be a simple "Blinky", where an LED blinks infinitely. I've got an STM32L152CDISCOVERY board with an STM32L152 chip in it (basically same as STM32L151), which is a Cortex M3.
Instead of implementing everything from scratch, I want to leverage existing crates and HALs. I've found two that seem promising: stm32l1 and stm32l1xx-hal. I've tried to read the documentation of each of them and also part of the source code, but I still can't figure out how to use them correctly.
Got a few questions about Rust and about the crates:
I see that stm32l1xx-hal has a dependency on stm32l1. Do I need to add both as a dependency in my Cargo.toml file? Or will that create problems related to ownership?
Is this the correct way to add them? Why is the second one added like that [dependencies.stm32l1]?
[dependencies]
cortex-m-rt = "0.6.10"
cortex-m-semihosting = "0.3.3"
panic-halt = "0.2.0"
stm32l1xx-hal = "0.1.0"
[dependencies.stm32l1]
version = "0.13.0"
features = ["stm32l151", "rt"]
To blink the LD4 (which is connected to PB4 PB6), I've got to enable the GPIOB in the RCC register and then configure the pin to push pull output. By inspecting the documentation of stm32l1xx-hal, I see that there is an RCC struct and a PB4 struct with the method into_push_pull_output. However, I still don't understand how to use these structs: how to import them or how to get an instance of them.
I've seen code examples for stm32l1 but not for stm32l1xx-hal. I know that I can do this:
use stm32l1::{stm32l151};
...
let p = stm32l151::Peripherals::take().unwrap();
p.RCC.ahbenr.modify(|_,w| w.gpiopben().set_bit());
But in the source code of stm32l1xx-hal I see that the RCC part is already done in impl GpioExt for $GPIOX, but I don't know how to get to this "Parts" functionality.
Any help that points me in the right direction is appreciated.
I got some help from a Discord community. The answers were (modified a bit by me):
stm32l1xx-hal already depends on stm32l1 as seen here. There's no need to import it twice. It is enough to add to Cargo.toml:
[dependencies.stm32l1xx-hal]
version = "0.1.0"
default-features = false
features = ["stm32l151", "rt"]
Note that the default-features = false is optional, but without it the compiler was giving me an error.
The syntaxes are equivalent, but as I said above, I only need to add the HAL one. You can add curly braces {} in the first style to add the options, such as:
stm32l1xx-hal = { version = "0.1.0", features = ["stm32l151", "rt"]}
The right code for doing the blinky (which was on PB6, not PB4, sigh) was:
#![no_main]
#![no_std]
use panic_halt as _;
use cortex_m_rt::entry;
use stm32l1xx_hal::delay::Delay;
use stm32l1xx_hal::gpio::GpioExt;
use stm32l1xx_hal::hal::digital::v2::OutputPin;
use stm32l1xx_hal::rcc::{Config, RccExt};
use stm32l1xx_hal::stm32::Peripherals;
use stm32l1xx_hal::stm32::CorePeripherals;
use stm32l1xx_hal::time::MicroSeconds;
#[entry]
fn main() -> ! {
let p = Peripherals::take().unwrap();
let cp = CorePeripherals::take().unwrap();
// Get LED pin PB6
let gpiob = p.GPIOB.split();
let mut led = gpiob.pb6.into_push_pull_output();
// Set up a delay
let rcc = p.RCC.freeze(Config::default());
let mut delay = Delay::new(cp.SYST, rcc.clocks);
loop {
// Turn LED On
led.set_high().unwrap();
delay.delay(MicroSeconds(1_000_000_u32));
// Turn LED Off
led.set_low().unwrap();
delay.delay(MicroSeconds(1_000_000_u32));
}
}
For me, the key was to understand that the split method can be called from the Peripherals because stm32l1xx-hal implemented split for a struct defined in stm32l1. In other words, the HAL crate is not only defining new structs, but also extending functionality for existing structs. I need to wrap my head around trait design patterns.

Installing smtp on rust (versions: rustc and cargo 1.32.0) - multiple "use of unstable library features" [duplicate]

This question already has answers here:
Rust package using unstable library feature 'iter_nth_back'
(1 answer)
use of unstable library feature - how can I fix those?
(1 answer)
"use of unstable library feature 'collections'" using nightly
(3 answers)
Closed 1 year ago.
I am not very good in rust, using version 1.32.0 of rustc and cargo to control a heating system, which works very fine.
Now I try to integrate a simple smtp function, to get information about bad system states via mail. I tried "lettre" from version 0.4 to 10.0 , but all the time I get many errors "use of unstable library feature" concerning "'split_ascii_whitespace', 'try_from', 'alloc', 'maybe_uninit' ...". "lettre" ends in "Could not compile cc". With "mail-smtp" I had similar problems. Is there any solution for this, how can I work with an older version of rustc and cargo, which I need for my control software, without crashing by using new crates?
I used the folllowing code from https://github.com/lettre/lettre#readme:
Cargo.toml:
[dependencies]
lettre = "0.10.0-beta.3" # here I tried also "0.9" down to "0.4"
main.rs:
extern crate lettre;
fn main() {
use lettre::transport::smtp::authentication::Credentials;
use lettre::{Message, SmtpTransport, Transport};
let email = Message::builder()
.from("NoBody <nobody#domain.tld>".parse().unwrap())
.reply_to("Yuin <yuin#domain.tld>".parse().unwrap())
.to("Hei <hei#domain.tld>".parse().unwrap())
.subject("Happy new year")
.body(String::from("Be happy!"))
.unwrap();
let creds = Credentials::new("smtp_username".to_string(), "smtp_password".to_string());
// Open a remote connection to gmail
let mailer = SmtpTransport::relay("smtp.gmail.com")
.unwrap()
.credentials(creds)
.build();
// Send the email
match mailer.send(&email) {
Ok(_) => println!("Email sent successfully!"),
Err(e) => panic!("Could not send email: {:?}", e),
}
}

How can I suppress dead code warnings for a particular platform? [duplicate]

This question already has answers here:
Is it possible to conditionally enable an attribute like `derive`?
(1 answer)
Can I conditionally compile my Rust program for a Windows subsystem?
(1 answer)
Closed 4 years ago.
I have a particular function that is unused on one platform, but I would still like it to be compiled. Is there any way to #[allow(dead_code)] for only a particular configuration?
Here's some example code:
#[ (what do I put here?) ]
fn cross_platform() {
}
#[cfg(windows)]
pub fn windows_only() {
// Do a cross-platform thing
cross_platform();
}
Is there any way to suppress the dead code warning on non-Windows platforms only?

Resources