Unwrap_or need String or &str in rust? - rust

I am trying to parse an environment value; using std::env as follows
let environment = env::var("SENSIBULL_ENVIRONMENT").unwrap();
This returns a string to the variable environment. If I want to pass a default value, then I have to use the below code
let environment = env::var("SENSIBULL_ENVIRONMENT").unwrap_or("development".into());
but I was expecting to do it like
let environment = env::var("SENSIBULL_ENVIRONMENT").unwrap_or("development");
as mentioned in the Rust example
But then it shows error String expected but found &str
Why is that error not happening in the example code?

In Rust, string literals are of type &str, and environment variables are of type String. Essentially, &strs have a fixed size, while Strings can be dynamically changed and resized (read more here). unwrap_or requires that the alternate value be of the same type as the option value, which means that you must provide a String to match the type of the environment variable. That's why you have to call .into to convert it to a string. In their example, the option uses a string literal, which is also of type &str, so there are no errors.

Related

include_bytes macro won't take argument, even if it is of type &'static str

I was using glium, and tried to make a struct to make using textures easier. Problem is, the function I am using to initialize the struct takes an &'static str as an argument, but the include_bytes!() macro won't take it, and the compiler is saying that the argument must be a string literal.
Here's the dysfunctional code:
fn load(path : String, format : ImageFormat, display : glium::Display) -> Image{
let image = image::load(Cursor::new(&include_bytes!(path)[..]),
format).unwrap().to_rgba8();
let image_dimensions = image.dimensions();
let image = glium::texture::RawImage2d::from_raw_rgba_reversed(&image.into_raw(), image_dimensions);
let _opengl_texture = glium::texture::CompressedSrgbTexture2d::new(&display, image).unwrap();
return Image{opengl_texture : _opengl_texture}
}
I tried using String and converting it in multiple ways, but it still didn't work.
The include_bytes! macro is for loading data from a file at compile-time and embedding it in the executable. Therefore the path must be known at compile-time via a string literal. Your path variable is only known at run-time.
Perhaps you wanted std::fs::read instead?

How can I return a String Vector?

How can I return a String Vector in Rust? I tried:
fn test_vec() -> Vec<&str> {
vec!("foo", "bar")
}
The compiler says something about lifetimes, but I'm not sure my problem is really about lifetimes:
src/main.rs:9:22: 9:26 error: missing lifetime specifier [E0106]
I'm a bit lost, I think I misunderstood (or forgot to learn) something.
A &str is not a String. It is a "string slice", meaning a kind of pointer into a String or something equivalent that is stored somewhere else. In your case you are using string literals (using quotes gives you string literals). String literals are of the type &'static str, because they are stored in the same place where the compiled code is stored and thus are available for the 'static lifetime, which means for (at least) the entire runtime of your program.
So the easy fix is to have your method return that specific type: &'static str.
The compiler cannot infer a lifetime for the returned reference, because your function does not take any arguments of reference type. The only way the compiler will infer a lifetime in a function's signature, is by assuming that if you are returning a reference, it needs to live shorter than the argument it's referring to. There's more information in The Book

Use write! macro with a string instead of a string literal

I've written the following function:
fn print_error(text: &str) {
let mut t = term::stdout().unwrap();
t.fg(term::color::RED).unwrap();
(write!(t, text)).unwrap();
assert!(t.reset().unwrap());
}
It should take the string and print it out on the console in red.
When I try to to compile, the compiler says:
error: format argument must be a string literal.
--> src/main.rs:4:16
|
4 | (write!(t, text)).unwrap();
| ^^^^
After a lot of searching, I've found out that I'm able to replace the text variable with e.g. "text" and it will work because it's a string literal, which the write! macro needs.
How could I use the write! macro with a string instead of a string literal? Or is there a better way to colourize the terminal output?
Just use write!(t, "{}", text).
I think you're missing the thrust of the error message. write! has two mandatory arguments:
A location to write to.
A format string.
The second parameter is not just any arbitrary string, it's the format string.
See also:
println! error: expected a literal / format argument must be a string literal

How do I convert from an integer to a string?

I am unable to compile code that converts a type from an integer to a string. I'm running an example from the Rust for Rubyists tutorial which has various type conversions such as:
"Fizz".to_str() and num.to_str() (where num is an integer).
I think the majority (if not all) of these to_str() function calls have been deprecated. What is the current way to convert an integer to a string?
The errors I'm getting are:
error: type `&'static str` does not implement any method in scope named `to_str`
error: type `int` does not implement any method in scope named `to_str`
Use to_string() (running example here):
let x: u32 = 10;
let s: String = x.to_string();
println!("{}", s);
You're right; to_str() was renamed to to_string() before Rust 1.0 was released for consistency because an allocated string is now called String.
If you need to pass a string slice somewhere, you need to obtain a &str reference from String. This can be done using & and a deref coercion:
let ss: &str = &s; // specifying type is necessary for deref coercion to fire
let ss = &s[..]; // alternatively, use slicing syntax
The tutorial you linked to seems to be obsolete. If you're interested in strings in Rust, you can look through the strings chapter of The Rust Programming Language.

What is the third argument to std::int::to_str_bytes?

In Rust programming language - I am trying to convert an integer into the string representation and so I write something like:
use std::int::to_str_bytes;
...
to_str_bytes(x, 10);
...but it says that I have to specify a third argument.The documentation is here: http://static.rust-lang.org/doc/master/std/int/fn.to_str_bytes.html , but I am not clever enough to understand what it expects as the third argument.
Using x.to_str() as in Njol's answer is the straightforward way to get a string representation of an integer. However, x.to_str() returns an owned (and therefore heap-allocated) string (~str). As long as you don't need to store the resulting string permanently, you can avoid the expense of an extra heap allocation by allocating the string representation on the stack. This is exactly the point of the std::int::to_str_bytes function - to provide a temporary string representation of a number.
The third argument, of type f: |v: &[u8]| -> U, is a closure that takes a byte slice (I don't think Rust has stack-allocated strings). You use it like this:
let mut f = std::io::stdout();
let result = std::int::to_str_bytes(100, 16, |v| {
f.write(v);
Some(())
});
to_str_bytes returns whatever the closure does, in this case Some(()).
int seems to implement ToStr: http://static.rust-lang.org/doc/master/std/to_str/trait.ToStr.html
so you should be able to simply use x.to_str() or to_str(x)

Resources