This question already has answers here:
Why is capitalizing the first letter of a string so convoluted in Rust?
(9 answers)
Closed 4 years ago.
Does anyone know a function that changes the first letter of a String to the uppercase equivalent?
Idealy, it would be used as so:
let newfoo = first_letter_to_uppper_case("foobar".to_string()), or
let newfoo = "foobar".to_string().first_letter_to_uppper_case().
If you want a function used as so:
let newfoo = first_letter_to_uppper_case("foobar".to_string())
Try use the following:
fn main() {
println!("{}", first_letter_to_uppper_case("foobar".to_string()));
}
fn first_letter_to_uppper_case (s1: String) -> String {
let mut c = s1.chars();
match c.next() {
None => String::new(),
Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
}
}
If you want it as a function implimented on the string type, like let newfoo = "foobar".to_string().first_letter_to_uppper_case(), try:
pub trait FirstLetterToUppperCase {
fn first_letter_to_uppper_case(self) -> String;
}
impl FirstLetterToUppperCase for String {
fn first_letter_to_uppper_case(self) -> String {
let mut c = self.chars();
match c.next() {
None => String::new(),
Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
}
}
}
fn main() {
println!("{}", "foobar".to_string().first_letter_to_uppper_case());
}
However, these functions do not deal with non-ascii characters very well. For more information, see this answer.
Related
This question already has answers here:
How do I bubble up an error from the closure passed to regex::Regex::replace?
(2 answers)
Closed 2 years ago.
I have a rust function which uses regex to replace string matching a certain rule. I am using the rust regex library, but I can't figure out how to handle error when using the closure.
My app has a custom error handler and I want to map the error returned in this function
pub fn override_from_env(content: &mut String) -> Result<()> {
*content = regex!(r"\B\$\{([A-Z0-9_]*?)\}")
.replace_all(&content, |captures: &Captures| {
let key = captures.get(1).unwrap().as_str();
match ::std::env::var(key) {
Ok(val) => val,
Err(e) => {
Error::EnvVarError(e);
String::from("") // this is not necessary, I want to return the error outside the closure here
}
}
})
.into_owned();
Ok(())
}
I was able to refactor this using capture_iter
pub fn transform_from_env(template: &mut String) -> Result<String> {
let mut content = String::new();
let mut last = 0;
let re = regex!(r"\B\$\{([A-Z0-9_]*?)\}");
for cap in re.captures_iter(&template) {
let range = cap.get(0).unwrap();
content.push_str(&template[last..range.start()]);
let key = cap.get(1).unwrap().as_str();
::std::env::var(key).map(|val| {
content.push_str(&val);
})?;
last = range.end();
}
if content.len() == 0 && template.len() > 0 {
content = template.to_string();
}
Ok(content)
}
This question already has an answer here:
How to get an Option's value or set it if it's empty?
(1 answer)
Closed 2 years ago.
I boiled my code down to these lines:
#[derive(Debug)]
struct Config {
values: Vec<String>,
compiled: Option<Vec<String>>,
}
impl Config {
fn comp_values(&mut self) -> &Vec<String> {
if self.compiled.is_none() {
self.compiled = Some(self.values.clone());
}
self.compiled.as_ref().unwrap()
}
fn comp_values_match(&mut self) -> &Vec<String> {
match self.compiled {
Some(_) => self.compiled.as_ref().unwrap(),
None => {
self.compiled = Some(self.values.clone());
self.compiled.as_ref().unwrap()
}
}
}
}
fn main() {
let mut c = Config {
values: vec![String::from("a"), String::from("b")],
compiled: None,
};
println!("config before: {:?}", c);
println!("compiled: {:?}", c.comp_values());
println!("config after: {:?}", c);
}
What I would like to have is something like:
match self.compiled {
Some(v) => v,
None => {
// assemble v and assign it to self.compiled
v
},
}
just like in the closure chapter in the book. Is it possible in the book it only worked, because u32 implements the Copy trait? If I change the match line to match self.compiled.as_ref() the Some(v) => v, works. In the None arm I then can't assign like self.compiled = ... since I have have the variable 'open' (or referenced with self.compiled.as_ref()) in that block.
Are my assumptions correct? Is the comp_values() method the most elegant solution in that case?
Not a match statement, but I think you are looking for get_or_insert_with.
This question already has answers here:
How do I convert a Vector of bytes (u8) to a string?
(5 answers)
Closed 3 years ago.
I have a Vec<&[u8]> that I want to convert to a String like this:
let rfrce: Vec<&[u8]> = rec.alleles();
for r in rfrce {
// create new String from rfrce
}
I tried this but it is not working since only converting u8 to char is possible, but [u8] to char is not:
let rfrce = rec.alleles();
let mut str = String::from("");
for r in rfrce {
str.push(*r as char);
}
Because r is an array of u8, you need to convert it to a valid &str and use push_str method of String.
use std::str;
fn main() {
let rfrce = vec![&[65,66,67], &[68,69,70]];
let mut str = String::new();
for r in rfrce {
str.push_str(str::from_utf8(r).unwrap());
}
println!("{}", str);
}
Rust Playground
I'd go with TryFrom<u32>:
fn to_string(v: &[&[u8]]) -> Result<String, std::char::CharTryFromError> {
/// Transform a &[u8] to an UTF-8 codepoint
fn su8_to_u32(s: &[u8]) -> Option<u32> {
if s.len() > 4 {
None
} else {
let shift = (0..=32).step_by(8);
let result = s.iter().rev().cloned().zip(shift).map(|(u, shift)| (u as u32) << shift).sum();
Some(result)
}
}
use std::convert::TryFrom;
v.iter().map(|&s| su8_to_u32(s)).try_fold(String::new(), |mut s, u| {
let u = u.unwrap(); //TODO error handling
s.push(char::try_from(u)?);
Ok(s)
})
}
fn main() {
let rfrce: Vec<&[u8]> = vec![&[48][..], &[49][..], &[50][..], &[51][..]];
assert_eq!(to_string(&rfrce), Ok("0123".into()));
let rfrce: Vec<&[u8]> = vec![&[0xc3, 0xa9][..]]; // https://www.utf8icons.com/character/50089/utf-8-character
assert_eq!(to_string(&rfrce), Ok("쎩".into()));
}
This question already has answers here:
How to convert a String into a &'static str
(4 answers)
Closed 7 years ago.
OK, here's my MCVE, right off the bat.
fn do_something (string: &'static str) -> Result<&str, isize> {
Ok(string)
}
fn main() {
let place = Some("hello".to_string());
match place {
Some(input) => {
let place = &input[..];
let something = do_something(place);
}
_ => (),
}
}
I can't seem to figure out a way in which to satisfy do_something. In my actual code, do_something is a library function, so I can't change it's signature.
- Thanks
If you can't change the function's signature, then you either need to use a string literal to create a &'static str or leak memory.
i.e. either do this:
do_something("hello");
or this (bad idea, will probably break, only works on nightly):
let place = Some("hello".to_string());
if let Some(s) = place {
do_something(unsafe { std::mem::transmute(s.into_boxed_str()) });
}
This question already has answers here:
How to convert a String into a &'static str
(4 answers)
Closed 7 years ago.
I'm trying to read input from the user, and then use it as the URL for the POP3 library. When converting the String that I get to a string slice, it doesn't live long enough to be used. This is strange to me for two reasons:
Because everything that uses the POP3 object is inside the same block, so the lifetime of the str slice should be that of the entire block, which would cover everything
I've tried almost every different code configuration I could think of, and to no avail, I get the same error every time.
extern crate pop3;
extern crate smtp;
extern crate openssl;
extern crate libc;
use openssl::ssl::{SslContext, SslMethod};
use pop3::POP3Stream;
use pop3::POP3Result::{POP3Stat, POP3List, POP3Message};
mod readline;
use readline::*;
fn main() {
let place = match readline("URL: ") { // Problem line
Some(input) => { // Problem line
let place: &'static str = &input[..]; // Problem line
let mut email_socket = match POP3Stream::connect(place, 995, Some(SslContext::new(SslMethod::Sslv23).unwrap())) { // Problem line
Ok(s) => s,
Err(e) => panic!("{}", e)
};
match readline("Username: ") {
Some(username) => {
match readline("Password: ") {
Some(password) => { email_socket.login(&*username, &*password); },
None => println!("Please enter a password.")
}
},
None => println!("Please enter a username.")
};
let stat = email_socket.stat();
match stat {
POP3Stat {num_email,
mailbox_size} => println!("num_email: {}, mailbox_size:{}", num_email, mailbox_size),
e => println!("There was an error signing into your server."),
}
let list_all = email_socket.list(None);
match list_all {
POP3List {emails_metadata} => {
for i in emails_metadata.iter() {
println!("message_id: {}, message_size: {}", i.message_id, i.message_size);
}
},
_ => println!("There was an error listing your messages."),
}
let message_25 = email_socket.retr(25);
match message_25 {
POP3Message{raw} => {
for i in raw.iter() {
println!("{}", i);
}
},
_ => println!("There was an error getting your 25th message."),
}
email_socket.quit();
},
None => { println!("Please enter a URL for your server."); }
};
}
The Problem
Your problem boils down to the use of static since the keyword basically says "keep this object around forever". This means that the lifetime of place, without a doubt, will live long after input — forever vs the scope of the block.
fn get() -> Option<String> {
Some("hello world".to_owned())
}
fn main() {
let data = match get() {
Some(input) => { let place : &'static str = &input[..]; },
None => { }
};
}
In the above we try to make place a static reference to a str, other other words; a reference that exists for the entire duration of our program. input on the other hand will definitely not exist for this amount of time, and therefor we get an error diagnostic.
<anon>:7:54: 7:59 error: `input` does not live long enough
<anon>:7 Some(input) => { let place : &'static str = &input[..]; },
The Solution
Remove the use of static, effectively saying that the lifetime of place is that of the block (which is a subset of the lifetime associated with input).
fn get() -> Option<String> {
Some("hello world".to_owned())
}
fn main() {
let data = match get() {
Some(input) => { let place : &str = &input[..]; },
None => { }
};
}
Further Digging
As it turns out, POP3Stream::connect accepts a &'static str as its first argument; this is really bad design since it will only accept string-literals.
impl Pop3Stream {
pub fn connect(host: &'static str, ...) -> Result<POP3Stream> {
...
}
}
https://github.com/mattnenterprise/rust-pop3/blob/master/src/pop3.rs
You can, however, hack your way around the issue by intentionally leaking the resource—effectively making it live "forever". Please note the usage of unsafe, and keep in mind that this is—by language design—considered to be just that.
fn get () -> Option<String> {
Some("hello world".to_owned ())
}
fn connect (host : &'static str) {
/* ... */
}
fn main() {
let data = match get() {
Some(input) => {
let place : &'static str = unsafe {
use std::mem; let x = mem::transmute(&input as &str);
mem::forget (x); x
};
connect(place);
},
None => { }
};
}