I am using a macro hex! that accepts only string literals.
I have a value returned from a function and stored in a variable. I cannot hard-code the values and call this function. So, how can I call the hex! macro with a variable?
This is my working code:
let account: AccountId32 = hex_literal::hex!["d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"].into();
and this is the code where I am facing the error:
let account_id = "d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d";
let account: AccountId32 = hex_literal::hex!(&account_id).into();
The error is:
error: proc-macro derive panicked
--> src/examples/example_substratekitties.rs:49:32
|
49 | let account: AccountId32 = hex_literal::hex!(&account_id).into();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: message: expected one string literal
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
All the examples of the hex! macro only demonstrate it with string literals.
You cannot. It is literally impossible. A literal is something where the value is written verbatim in the source code of the program.
Don't use that macro because it doesn't do what you want (emphasis mine):
This crate provides hex! macro for converting hexadecimal string literal to byte array at compile time.
Perhaps you want the hex crate?
See also:
What is the difference between literals and non-literals, other than the fact that non-literals go into the heap?
What does the word "literal" mean?
How can I convert a hex string to a u8 slice?
Converting a hexadecimal string to a decimal integer
Decimal number to hexadecimal string
How to convert hex string to a float in Rust?
How do I convert a string to hex in Rust?
Show u8 slice in hex representation
Related
Why can I not use str here?
let question: &str = "why";
What's the difference between str and &str?
I get that & denotes a reference, but I'm confused about what &str is referencing.
A str is a sequence of UTF-8 encoded bytes of unknown length, somewhere in memory.
Because its size is not known at compile time, it can't be put on the stack directly, instead, a reference must be used.
A string literal (i.e. the "why" syntax) creates a space in the data segment of the binary, and returns a reference to that location, which is an &str (in particular, an &'static str, because it is never dropped).
If you write let question: str = "why";, this won't compile for the same reason: let i: i32 = &123; won't compile.
P.S. ("hello") is not a tuple, it is just a &str in brackets. If you want to make a tuple with a single element, add a trailing comma: let hello: (&str,) = ("hello",);
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.
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
Python has the unichr() (or chr() in Python 3) function that takes an integer and returns a character with the Unicode code point of that number. Does Rust have an equivalent function?
Sure, though it is a built-in operator as:
let c: char = 97 as char;
println!("{}", c); // prints "a"
Note that as operator works only for u8 numbers, something else will cause a compilation error:
let c: char = 97u32 as char; // error: only `u8` can be cast as `char`, not `u32`
If you need a string (to fully emulate the Python function), use to_string():
let s: String = (97 as char).to_string();
There is also the char::from_u32 function:
use std::char;
let c: Option<char> = char::from_u32(97);
It returns an Option<char> because not every number is a valid Unicode code point - the only valid numbers are 0x0000 to 0xD7FF and from 0xE000 to 0x10FFFF. This function is applicable to a larger set of values than as char and can convert numbers larger than one byte, providing you access to the whole range of Unicode code points.
I've compiled a set of examples on the Playground.
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.