Remove "Some" keyword from string println! in rust [duplicate] - rust

This question already has answers here:
How can I pull data out of an Option for independent use?
(3 answers)
Closed 7 months ago.
I want to print out the value of sys.host_name()
let hostname = sys.host_name();
println!("{:?}", hostname);
Output: "Some("arch")"
Expected output: "arch"
How can i print the "raw" string?

It appears (not sure what library you are using) sys.host_name() does not return a string, rather an Option<String>, which implies the function could fail (and return None instead of Some("arch").
println! is printing the full type. If you just wish to print the contained string, you need to extract the string from the Option. One possible way:
let possible_hostname = sys.host_name();
// Check if the hostname is Some or None
if let Some(hostname) = possible_hostname {
println!("{:?}", hostname);
}
else {
println!("hostname could not be determined");
}
If you would prefer your program to just panic if the hostname is None, you can "unwrap" the option:
let hostname = sys.host_name().unwrap();
println!("{:?}", hostname);

Related

How do I extract hex values as strings? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 days ago.
This post was edited and submitted for review 4 days ago.
Improve this question
I am trying to extract a hash value from a function output:
let receipt = do_something();
println!("{receipt:?}");
let receipt_txn_hash = receipt.transaction_hash;
println!("receipt_txn_hash: {}", receipt_txn_hash);
let tx = provider.get_transaction(receipt_txn_hash).await?;
println!("tx: {}\n", serde_json::to_string(&tx)?);
let tx_hash = if let Some(txn) = tx {
txn.hash.to_string()
} else {
"hash_not_found".to_owned() //H256([0; 32])
};
println!("tx.hash: {}\n", &tx_hash);
And it prints out in the terminal:
TransactionReceipt { transaction_hash: 0xd6a0e48e6a0f80ae4467193f40721da1ad53ec854a738ea57d7201619e60f3b7, ... }
receipt_txn_hash: 0xd6a0…f3b7
tx: {"hash":"0xd6a0e48e6a0f80ae4467193f40721da1ad53ec854a738ea57d7201619e60f3b7",...}
tx.hash: 0xd6a0…f3b7
Somehow Rust-Analyzer identifies this receipt has {unknown} type, but tx has Option<Transaction> type.
But still, both the receipt.transaction_hash, tx.hash have been truncated... *why?
How can I get the original complete hash value and return it as a String?
Here are the dependencies:
ethers = { version = "1.0.2", features = ["legacy", "rustls"] }
ethers-solc = { version = "1.0.2", features = ["full"] }
ethers-providers = "1.0.2"
eyre = "0.6.8"
hex = "0.4.3"
reqwest = { version = "0.11.14", default-features = false }
serde_json = "1.0.93"
[Update]
Thanks to the answer below, both receipt_txn_hash and tx_hash are of the type H256.
The Display trait of H256 type is defined here:
https://github.com/paritytech/parity-common/blob/223af1dc6c176e35698aed9285f44e428da0050e/fixed-hash/src/hash.rs#L217
impl $crate::core_::fmt::Display for $name {
fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result {
$crate::core_::write!(f, "0x")?;
for i in &self.0[0..2] {
$crate::core_::write!(f, "{:02x}", i)?;
}
$crate::core_::write!(f, "…")?;
for i in &self.0[$n_bytes - 2..$n_bytes] {
$crate::core_::write!(f, "{:02x}", i)?;
}
Ok(())
}
}
From the Display trait definition above, we know Display trait is causing the truncation.
So we need to modify the Display trait(defined in our dependencies).
But we cannot modify or override the foreign trait definition due to: only traits defined in the current crate can be implemented for types defined outside of the crate. Define and implement a trait or new type instead
So we have to make our local type to modify the foreign trait!
Hence, this question is basically asking how to implement a local type(NewH256), on a foreign trait(fmt::Display)?
Going by a quick search I'm guessing the type is a H256 from here.
This has a Display implementation here which gives you your ellipses.
If you want to show the full hex, you might be best just printing the debug output:
println!("receipt_txn_hash: {:?}", receipt_txn_hash);
If that doesn't work, you can just copy the Display impl and format it however you want.

How to match if string contains? [duplicate]

This question already has an answer here:
How to match on the start of a string?
(1 answer)
Closed 5 months ago.
I have a string variable "distro"
let distro = get_distro().unwrap().name;
The value of this variable is for example "Arch Linux".
Now i want to check in a match, if the variable contains "arch".
match distro.to_lowercase() {
"arch" => //...
}
To use a condition in a match at rust you need to add an if to your match. In this case it would look like
match &distro.to_lowercase() {
x if x.contains("arch") => //...
}
As per I understand you want to check something in the string. For this purpose, match statement is not quite what you are looking for. For string there exists contains method.
Example:
let disto_name = "Arch Linux";
if distro_name.to_ascii_lowercase().contains("arch") {
println!("This is arch linux");
} else {
println!("This is not arch linux");
}
You can do like this:
let distro = get_distro().unwrap().name;
if distro.to_lowercase().as_str().contains("arch") {
println!("0")
}
Playground
Also you can make it simpler, like this:
const DISTRO_NAMES: [&str; 2] = ["arch", "ubuntu"];
fn detector(distro: String) {
for item in DISTRO_NAMES {
if distro.to_lowercase().contains(item) {
println!("the distro is = {item}")
}
}
}
fn main() {
let distro = get_distro().unwrap().name;
detector(distro.to_string())
}
with this solution, you just need to add your distros to the DISTRO_NAMES array.

String match with option in Rust inside Some [duplicate]

This question already has answers here:
How can I pattern match against an Option<String>?
(4 answers)
Closed 8 months ago.
Problem description
I'm trying to match option string with match statement
let option_string = Some(String::from("Bob"));
match option_string {
Some("Mike") => false,
Some("Bob") => true,
_ => false,
}
And, obviously, got an error expected struct 'String, found '&str'.
I tried to change it into string cast
Some("Mike".to_string()) => false
// Or
Some(String::from("Mike")) => false
But faced with a different error: 'fn' calls are not allowed in patterns
The only working way is to place Mike into a variable before Some
let mike = String::from("Mike");
// and in match
Some(mike) => true,
Question
There is a more elegant way to match String but not string literals in match cases with Option value?
I found the answer but it doesn't look elegant enough too. But is it only one possible way to not create extra variables or functions?
let mike = String::from("Mike");
// and in match
Some(mike) => true,
This one is actually a misconception, I'm afraid. Variables are not allowed on the left side of a match expression. Having a name on the left side actually creates a new variable that contains the matched content. So the mike variable in your match clause matches everything and then carries the matched String; it is not the same variable as the outer mike variable.
Pay attention to this code example:
fn main() {
let option_string = Some(String::from("Bob"));
// Note how this line gets the compiler warning "unused variable".
// You could leave this line out completely and it would still
// compile.
let mike = String::from("Mike");
let result = match option_string {
Some(mike) => {
println!("Matched 'Mike': {}", mike);
true
}
_ => false,
};
println!("{:?}", result);
}
Matched 'Mike': Bob
true
In general, you can only match against compile time constants. If you want to compare two variables, you have to use if instead.
Solution
That said, your first example is quite easy to fix:
fn main() {
let option_string = Some(String::from("Bob"));
let result = match option_string.as_deref() {
Some("Mike") => false,
Some("Bob") => true,
_ => false,
};
println!("{:?}", result);
}
true
Note the .as_deref(), which borrows an Option<&str> from the Option<String>, making it compatible with the string literal match expressions.

Pass a temporary/local variable to Err [duplicate]

This question already has answers here:
Proper way to return a new string in Rust
(2 answers)
Return local String as a slice (&str)
(7 answers)
How do you define custom `Error` types in Rust?
(3 answers)
What is the most idiomatic way to merge two error types?
(2 answers)
Closed 2 years ago.
I have this function that sends an HTTP request parses the response and returns a Result:
pub fn get_network_info(&self) -> Result<NetworkInfoResult, &'static str> {
let rpc = JsonRpc::new(
String::from("1.0"),
self.settings.id.clone(),
String::from("getnetworkinfo"),
Vec::new(),
);
let url = format!("http://{}:{}", self.settings.url, self.settings.port);
let req = HttpRequest::new_json_rpc(
url,
rpc,
self.settings.user.clone(),
self.settings.pass.clone(),
);
match req.execute() {
Ok(x) => {
println!("{}", x.content);
let parsed: NetworkInfo = serde_json::from_str(&x.content)
.expect("Failed to parse networkinfo Json response");
if parsed.id != self.settings.id {
Err("RPC Request and Response id didn't match!")
} else {
if parsed.error.is_some() {
Err(&parsed.error.unwrap())
} else {
Ok(parsed.result)
}
}
}
Err(e) => Err(e),
}
}
If the error field is set in the JSON response we want to return an error, in particular the error message inside the response. Otherwise, we return the result field of the parsed response.
The problem which this code is that Err(&parsed.error.unwrap()) doesn't compile. The reason for this is that the lifetime of the variable containing the parsed.error.unwrap() is only within the function, therefore it might not exist anymore in the context of the caller.
My problem is that Err expects a reference to a string, but whatever reference I try to pass would be to a local or temporary variable. How do I work around this issue?
My problem is that Err expects a reference to a string, but whatever reference I try to pass would be to a local or temporary variable. Can anybody help me work around this issue?
The "workaround" is to fix the function's signature. Either return a full-blown String, or if you really need the efficiency return a Cow (so you can return either a String or an &'static str). Since parsed is a local you can't return a reference to it.

How to access as_secs in SystemTime? "no method named `as_secs` found for enum Result" [duplicate]

This question already has answers here:
Unable to read file contents to string - Result does not implement any method in scope named `read_to_string`
(2 answers)
How can I get the current time in milliseconds?
(7 answers)
Closed 2 years ago.
I'm using std::time::SystemTime. My goal is to make a struct with a field called timestamp and store the time in seconds.
I saw this example which works correctly:
use std::time::SystemTime;
match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
Err(_) => panic!("SystemTime before UNIX EPOCH!"),
}
When I try this code I get an error:
use std::time::SystemTime;
let n = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH);
println!("{}", n.as_secs());
error[E0599]: no method named `as_secs` found for enum `std::result::Result<std::time::Duration, std::time::SystemTimeError>` in the current scope
--> src/main.rs:5:22
|
5 | println!("{}", n.as_secs());
| ^^^^^^^ method not found in `std::result::Result<std::time::Duration, std::time::SystemTimeError>`
What am I doing wrong?
Read the error:
no method named `...` found for type `Result<...>`
So, we look at Result:
Result is a type that represents either success (Ok) or faliure (Err)
See the std::result module for documentation details.
So, we know that SystemTime::duration_since(&self, _) returns a Result, meaning it could possibly have failed. Reading the docs:
Returns an Err if earlier is later than self, and the error contains how far from self the time is.
So, we just have to unwrap, expect, or match on it to get the possibility of an error out:
use std::time::SystemTime;
// Unwrapping
let n = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
.unwrap(); // Will panic if it is not `Ok`.
// Expecting
let n = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
.expect("Invalid time comparison"); // Will panic with error message
// if it is not `Ok`.
// Matching
let n = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH);
match n {
Ok(x) => { /* Use x */ },
Err(e) => { /* Process Error e */ },
}
// Fallibly Destructuring:
let n = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH);
if let Ok(x) = n {
/* Use x */
} else {
/* There was an error. */
}

Resources