These are chat archives for rust-lang/rust

1st
Jul 2017
gavynriebau
@gavynriebau
Jul 01 2017 03:58

Hi all, I'm stuck and hoping someone with more rust experience will be able to help or at least better explain what's going on.

fn xor_dir(entry : &DirEntry, key : &Vec<u8>) {
    info!("Encrypting dir {:?}", entry);

    match fs::read_dir(entry.path()) {
        Ok(entries) => {
            for child in entries {
                if let Ok(child) = child {
                    xor_entry(&child, key);
                }
            }

            if let Some(name) = entry.file_name().to_str() {
                let mut cursor = &mut Cursor::new(name) as &mut Read;
                let encoded_name = cursor.xor(key);
            }
        },
        Err(e) => {
            let mut stderr = io::stderr();
            let _ = stderr.write_fmt(format_args!("Failed to read directory: {}", e));
        }
    }
}

The above code results in this message from the borrow checker (entry.file_name() does not live long enough):

error: borrowed value does not live long enough
   --> src/main.rs:151:33
    |
151 |             if let Some(name) = entry.file_name().to_str() {
    |                                 ^^^^^^^^^^^^^^^^^ does not live long enough
...
155 |         },
    |         - temporary value only lives until here
    |
    = note: borrowed value must be valid for the static lifetime...
error: aborting due to previous error
error: Could not compile `xor`.
To learn more, run the command again with --verbose.

Why does entry.file_name() need to live for longer than it does?
I'm no longer using it after the Cursor::new(name) statement so don't understand why it needs to live longer than that statement?

Denis Lisov
@tanriol
Jul 01 2017 10:04
@gavynriebau What's the signature of cursor.xor?
gavynriebau
@gavynriebau
Jul 01 2017 13:09
fn new(inner: T) -> Cursor<T>

T is a &str type

Any ideas?

Alexey Terekhov
@a1xt
Jul 01 2017 14:53
@gavynriebau entry.file_name() returns OsString that lives only up to the end of if expression. Try to do so:
...
let file_name = entry.file_name();
if let Some(name) = file_name.to_str() {
    let mut cursor = &mut Cursor::new(name) as &mut Read;
    let encoded_name = cursor.xor(key);
}
...
stevensonmt
@stevensonmt
Jul 01 2017 15:14
extern crate regex;

use std::io;
use regex::Regex;

fn main() {
    let mut word = String::new();

    println!("Please enter the word you'd like to translate to pig latin.");

    io::stdin().read_line(&mut word)
        .expect("Failed to read line");

    let word = word.trim();

    string_conversion(word)
}

fn string_conversion(s: &str) {
    let consonants = Regex::new(r"[aeiouAEIOU]").unwrap();
    let first_letter = s.chars().nth(0).unwrap().to_string();
    if consonants.is_match(&first_letter) {
        println!("{:?}", [s, &"hay".to_string()].concat())
    } else {
        let (first, last) = s.split_at(1);
        println!("{:?}", [[last, first].concat(), "ay".to_string()].concat())
    }
}
why does the concat() in the if statement require & while the one in the else arm does not?
Jonas Platte
@jplatte
Jul 01 2017 15:24
@stevensonmt Well you can't have elements of different types in an array. s is a &str and "hay".to_string() is a String, so that wouldn't work. However, I think you should be able to write [s, "hay"].concat() in the first branch.