How can I get password input without showing user input?
fn main() {
println!("Type Your Password");
// I want to hide input here, and do not know how
let input = std::old_io::stdin().read_line().ok().expect("Failed to read line");
println!("{}", input);
}
Update: you can use the rpassword crate. Quoting from the README:
Add the rpassword crate to your Cargo.toml:
[dependencies]
rpassword = "0.0.4"
Then use the read_password() function:
extern crate rpassword;
use rpassword::read_password;
use std::io::Write;
fn main() {
print!("Type a password: ");
std::io::stdout().flush().unwrap();
let password = read_password().unwrap();
println!("The password is: '{}'", password);
}
Old answer
I suspect your best bet is calling some C functions from rust: either getpass (3) or its recommended alternatives (see
Getting a password in C without using getpass). The tricky thing is that it differs by platform, of course (if you get it working, it'd be handy as a crate).
Depending on your requirements, you could also try using ncurses-rs (crate "ncurses"); I haven't tested it but it looks like example 2 might demo turning off echoing input.
Related
How can I get password input without showing user input?
fn main() {
println!("Type Your Password");
// I want to hide input here, and do not know how
let input = std::old_io::stdin().read_line().ok().expect("Failed to read line");
println!("{}", input);
}
Update: you can use the rpassword crate. Quoting from the README:
Add the rpassword crate to your Cargo.toml:
[dependencies]
rpassword = "0.0.4"
Then use the read_password() function:
extern crate rpassword;
use rpassword::read_password;
use std::io::Write;
fn main() {
print!("Type a password: ");
std::io::stdout().flush().unwrap();
let password = read_password().unwrap();
println!("The password is: '{}'", password);
}
Old answer
I suspect your best bet is calling some C functions from rust: either getpass (3) or its recommended alternatives (see
Getting a password in C without using getpass). The tricky thing is that it differs by platform, of course (if you get it working, it'd be handy as a crate).
Depending on your requirements, you could also try using ncurses-rs (crate "ncurses"); I haven't tested it but it looks like example 2 might demo turning off echoing input.
I have a requirement to pass to a procedural macro either a text file or the contents of a text file, such that the procedural macro acts based on the contents of that text file at compile time. That is, the text file configures the output of the macro. The use case for this is the file defining a register map which the macro builds into a library.
The second requirement is that the text file is properly handled by Cargo, such that changes to the text file trigger a recompile in the same way as changes to the source file trigger a recompile.
My initial thought was to create a static string using the include_str! macro. This solves the second requirement but I can't see how to pass that to the macro - at that point I only have the identifier of the string to pass in:
use my_macro_lib::my_macro;
static MYSTRING: &'static str = include_str!("myfile");
my_macro!(MYSTRING); // Not the string itself!
I can pass a string to the macro with the name of the file in a string literal, and open the file inside the macro:
my_macro!("myfile");
At which point I have two problems:
It's not obvious how to get the path of the calling function in order to get the path of the file. I initially thought this would be exposed through the token Span, but it seems in general not (perhaps I'm missing something?).
It's not obvious how to make the file make Cargo trigger a recompile on changes. One idea I had to force this was to add an include_str!("myfile") to the output of the macro, which would hopefully result in the compile being made aware of "myfile", but this is a bit mucky.
Is there some way to do what I'm trying to do? Perhaps either by somehow getting the contents of the string inside the macro that was created outside, or reliably getting the path of the calling rust file (then making Cargo treat changes properly).
As an aside, I've read various places that tell me I can't get access to the contents of variables inside the macro, but it seems to me that this is exactly what the quote macro is doing with #variables. How is this working?
So it turns out this is possible in essentially the way I was hoping with the stable compiler.
If we accept that we need to work relative to the crate root, we can define our paths as such.
Helpfully, inside the macro code, std::env::current_dir() will return the current working directory as the root of the crate containing the call site. This means, even if the macro invocation is inside some crate hierarchy, it will still return a path that is meaningful at the location of the macro invocation.
The following example macro does essentially what I need. For brevity, it's not designed to handle errors properly:
extern crate proc_macro;
use quote::quote;
use proc_macro::TokenStream;
use syn::parse::{Parse, ParseStream, Result};
use syn;
use std;
use std::fs::File;
use std::io::Read;
#[derive(Debug)]
struct FileName {
filename: String,
}
impl Parse for FileName {
fn parse(input: ParseStream) -> Result<Self> {
let lit_file: syn::LitStr = input.parse()?;
Ok(Self { filename: lit_file.value() })
}
}
#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(input as FileName);
let cwd = std::env::current_dir().unwrap();
let file_path = cwd.join(&input.filename);
let file_path_str = format!("{}", file_path.display());
println!("path: {}", file_path.display());
let mut file = File::open(file_path).unwrap();
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap();
println!("contents: {:?}", contents);
let result = quote!(
const FILE_STR: &'static str = include_str!(#file_path_str);
pub fn foo() -> bool {
println!("Hello");
true
}
);
TokenStream::from(result)
}
Which can be invoked with
my_macro!("mydir/myfile");
where mydir is a directory in the root of the invoking crate.
This uses the hack of using an include_str!() in the macro output to cause rebuilds on changes to myfile. This is necessary and does what is expected. I would expect this to be optimised out if it's never actually used.
I'd be interested to know if this approach falls over in any situation.
Relevant to my original question, current nightly implements the source_file() method on Span. This might be a better way to implement the above, but I'd rather stick with stable. The tracking issue for this is here.
Edit:
The above implementation fails when the package is in a workspace, at which point the current working directory is the workspace root, not the crate root. This is easy to work around with something like as follows (inserted between cwd and file_path declarations).
let mut cwd = std::env::current_dir().unwrap();
let cargo_path = cwd.join("Cargo.toml");
let mut cargo_file = File::open(cargo_path).unwrap();
let mut cargo_contents = String::new();
cargo_file.read_to_string(&mut cargo_contents).unwrap();
// Use a simple regex to detect the suitable tag in the toml file. Much
// simpler than using the toml crate and probably good enough according to
// the workspace RFC.
let cargo_re = regex::Regex::new(r"(?m)^\[workspace\][ \t]*$").unwrap();
let workspace_path = match cargo_re.find(&cargo_contents) {
Some(val) => std::env::var("CARGO_PKG_NAME"),
None => "".to_string()
};
let file_path = cwd.join(workspace_path).join(input.filename);
let file_path_str = format!("{}", file_path.display());
Is there a way to print out a complete list of available members of a type or instance in Rust?
For example:
In Python, I can use print(dir(object))
In C, Clang has a Python API that can parse C code and introspect it.
Being unfamiliar with Rust tools, I'm interested to know if there is some way to do this, either at run-time or compile-time, either with compiler features (macros for example), or using external tools.
This question is intentionally broad because the exact method isn't important. It is common in any language to want to find all of a variable's methods/functions. Not knowing Rust well, I'm not limiting the question to specific methods for discovery.
The reason I don't define the exact method is that I assume IDEs will need this information, so there will need to be some kinds of introspection available to support this (eventually). For all I know, Rust has something similar.
I don't think this is a duplicate of Get fields of a struct type in a macro since this answer could include use of external tools (not necessarily macros).
Is there a way to print out a complete list of available members of a type or instance in Rust?
Currently, there is no such built-in API that you can get the fields at runtime. However you can retrieve fields by using two different ways.
Declarative Macros
Procedural Macros
Solution By Using Declarative Macro
macro_rules! generate_struct {
($name:ident {$($field_name:ident : $field_type:ty),+}) => {
struct $name { $($field_name: $field_type),+ }
impl $name {
fn introspect() {
$(
let field_name = stringify!($field_name);
let field_type = stringify!($field_type);
println!("Field Name: {:?} , Field Type: {:?}",field_name,field_type);
)*
}
}
};
}
generate_struct! { MyStruct { num: i32, s: String } }
fn main() {
MyStruct::introspect();
}
This will give you the output:
Field Name: "num" , Field Type: "i32"
Field Name: "s" , Field Type: "String"
Playground
Solution Using Procedural Macro
Since procedural macros are more complicated from the declarative macros, you better to read some references(ref1, ref2, ref3) before starting.
We are going to write a custom derive which is named "Instrospect". To create this custom derive, we need to parse our struct as a TokenStream with the help of syn crate.
#[proc_macro_derive(Introspect)]
pub fn derive_introspect(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemStruct);
// ...
}
Since our input can be parsed as ItemStruct and ItemStruct has the fields() method in it, we can use this to get fields of our struct.
After we get these fields, we can parse them as named and we can print their field name and field type accordingly.
input
.fields
.iter()
.for_each(|field| match field.parse_named() {
Ok(field) => println!("{:?}", field),
Err(_) => println!("Field can not be parsed successfully"),
});
If you want to attach this behavior to your custom derive you can use the following with the help of the quote crate:
let name = &input.ident;
let output = quote! {
impl #name {
pub fn introspect(){
input
.fields
.iter()
.for_each(|field| match field.parse_named() {
Ok(field) => println!("{:?}", field),
Err(_) => println!("Field can not be parsed successfully"),
});
}
}
};
// Return output TokenStream so your custom derive behavior will be attached.
TokenStream::from(output)
Since the behaviour injected to your struct as introspect function, you can call it in your application like following:
#[derive(Introspect)]
struct MyStruct {
num: i32,
text: String
}
MyStruct::introspect();
Note: Since the example you are looking for similar to this question. This Proc Macro Answer and Declarative Macro Answer should give you insight as well
To expand on my comment, you can use rustdoc, the Rust documentation generator, to view almost everything you're asking for (at compile time). rustdoc will show:
Structs (including public members and their impl blocks)
Enums
Traits
Functions
Any documentation comments written by the crate author with /// or //!.
rustdoc also automatically links to the source of each file in the [src] link.
Here is an example of the output of rustdoc.
Standard Library
The standard library API reference is available here and is available for anything in the std namespace.
Crates
You can get documentation for any crate available on crates.io on docs.rs. This automatically generates documentation for each crate every time it is released on crates.io.
Your Project
You can generate documentation for your project with Cargo, like so:
cargo doc
This will also automatically generate documentation for your dependencies (but not the standard library).
I have written a very simple crate which uses procedural macro. It gives you access to members information plus some simple information about struct/enum you use. Information about methods can not be given because procedural macros simply can't get this information, and as far as I know, there are no any methods which may give such information.
I don't think there is anything that will do this out of the box.
It may be possible to write a compiler plugin which can do that by examining the AST.
If you need the field names inside your program then you probably need to use macros. Either wrap your struct definition in macro and pattern match to create some function to get their names, or use procedural macro to derive structs for traits with such functions.
See examples in syn for derived traits. In particular, see syn::Data::Struct which has fields.
According to question of #AlexandreMahdhaoui, I would say: at least on latest Rust versions the proc_macro from accepted answer will not work, because you will need to pass tokens into quote! using "#". So you could try smth like next:
use proc_macro::{TokenStream};
use quote::{quote, ToTokens};
use syn::{parse_macro_input, ItemStruct};
#[proc_macro_derive(Introspect)]
pub fn derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemStruct);
let ident = input.ident;
let field_data = input.fields.iter().map(|f| {
let field_type = f.ty.clone();
format!(
"Name={}, Type={}",
f.ident.clone().unwrap().to_string(),
quote!(#field_type).to_string()
)
}).collect::<Vec<_>>();
let output = quote! {
impl #ident {
pub fn introspect() {
println!("{:#?}", vec![#(#field_data),*]);
}
}
};
TokenStream::from(output)
}
#[derive(Introspect)]
struct Test {
size: u8,
test_field: u8,
}
fn main() {
Test::introspect();
}
Regarding methods, defined in impl I didn't find any info in output, so not sure if it possible. Probably somebody could share in comments ?
I use something like this:
println!("{:?}", variable); // struct, enum whatever
If it's a large type, use the # version:
println!("{:#?}", variable); // struct, enum whatever
How can I get password input without showing user input?
fn main() {
println!("Type Your Password");
// I want to hide input here, and do not know how
let input = std::old_io::stdin().read_line().ok().expect("Failed to read line");
println!("{}", input);
}
Update: you can use the rpassword crate. Quoting from the README:
Add the rpassword crate to your Cargo.toml:
[dependencies]
rpassword = "0.0.4"
Then use the read_password() function:
extern crate rpassword;
use rpassword::read_password;
use std::io::Write;
fn main() {
print!("Type a password: ");
std::io::stdout().flush().unwrap();
let password = read_password().unwrap();
println!("The password is: '{}'", password);
}
Old answer
I suspect your best bet is calling some C functions from rust: either getpass (3) or its recommended alternatives (see
Getting a password in C without using getpass). The tricky thing is that it differs by platform, of course (if you get it working, it'd be handy as a crate).
Depending on your requirements, you could also try using ncurses-rs (crate "ncurses"); I haven't tested it but it looks like example 2 might demo turning off echoing input.
One uses this to send output to stdout:
println!("some output")
I think there is no corresponding macro to do the same for stderr.
After Rust 1.19
As of Rust 1.19, you can use the eprint and eprintln macros:
fn main() {
eprintln!("This is going to standard error!, {}", "awesome");
}
This was originally proposed in RFC 1896.
Before Rust 1.19
You can see the implementation of println! to dive into exactly how it works, but it was a bit overwhelming when I first read it.
You can format stuff to stderr using similar macros though:
use std::io::Write;
let name = "world";
writeln!(&mut std::io::stderr(), "Hello {}!", name);
This will give you a unused result which must be used warning though, as printing to IO can fail (this is not something we usually think about when printing!). We can see that the existing methods simply panic in this case, so we can update our code to do the same:
use std::io::Write;
let name = "world";
let r = writeln!(&mut std::io::stderr(), "Hello {}!", name);
r.expect("failed printing to stderr");
This is a bit much, so let's wrap it back in a macro:
use std::io::Write;
macro_rules! println_stderr(
($($arg:tt)*) => { {
let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
r.expect("failed printing to stderr");
} }
);
fn main() {
let name = "world";
println_stderr!("Hello {}!", name)
}
print! and println! are convenience methods for writing to standard output. There are other macros with the same formatting features available for different tasks:
write! and writeln! to write a formatted string to a &mut Writer
format! to just generate a formatted String
To write to the standard error stream, you can use e.g. writeln! like this:
use std::io::Write;
fn main() {
let mut stderr = std::io::stderr();
writeln!(&mut stderr, "Error!").unwrap();
}
It's done so:
use std::io::Write;
fn main() {
std::io::stderr().write(b"some output\n");
}
You can test it by sending the program output to /dev/null to ensure it works (I ignore the warning):
$ rustc foo.rs && ./foo > /dev/null
foo.rs:4:5: 4:42 warning: unused result which must be used, #[warn(unused_must_use)] on by default
foo.rs:4 io::stderr().write(b"some output\n");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
some output
Similarly, one can do the following for stdout:
use std::io::Write;
fn main() {
std::io::stdout().write(b"some output\n");
}
I think this means println! is just a convenience: it's shorter and it also allows some formatting. As an example of the latter, the following displays 0x400:
println!("0x{:x}", 1024u)
While not answering the precise question, maybe it’s of interest that there’s a log crate which specifies an interface for leveled logging that other crates (e.g. env_logger) can fulfill.
The output of such logging will be sent to stderr, and there are additional benefits for users, such as specifying the log level.
This is how using such a logger could look like:
#[macro_use]
extern crate log;
extern crate env_logger;
fn main() {
env_logger::init().unwrap();
error!("this is printed by default");
}
(Example adapted from http://burntsushi.net/rustdoc/env_logger/index.html#example)
Goal
stderr!("Code {}: Danger, Will Robinson! Danger!", 42);
Notes
The other answers generate an unused import warning with the latest nightly, so here's a modern macro that Just Works TM.
Code
macro_rules! stderr {
($($arg:tt)*) => (
use std::io::Write;
match writeln!(&mut ::std::io::stderr(), $($arg)* ) {
Ok(_) => {},
Err(x) => panic!("Unable to write to stderr (file handle closed?): {}", x),
}
)
}