Rust's I/O issue

I've just finished the 4th chapter of 'The Book'. To test my knowledge I was building this project. But, I/O is not working the way it should. I'm trying to figure out problem from my code, but could not.

here's the code:

use std::{
    io::{stdin, stdout, Write},
    vec,
};

fn main() {
    let mut db: Vec<String> = vec![];
    let mut key = String::new();
    let mut value = String::new();
    let mut operation = String::new();
    let operations = (
        String::from("put"),
        String::from("get"),
        String::from("exit"),
    );
    println!(
        "\n\tyour options are {}, {}, {}.\n",
        operations.0, operations.1, operations.2
    );
    loop {
        println!("what do you wanna do?");
        stdin()
            .read_line(&mut operation)
            .expect("colud not parse input");
        let operation = operation.trim();

        if operation == operations.0 {
            println!("enter your key");
            stdin()
                .read_line(&mut key)
                .expect("could not parse the input");
            let key = key.trim();
            println!("enter your value");
            stdin()
                .read_line(&mut value)
                .expect("could not parse the input");
            let value = value.trim();
            store(&mut db, &key, &value);
            println!("\n\tvalue `{1}` stored to key `{0}`\n", key, value);
        } else if operation == operations.1 {
            println!("enter your key");
            stdin()
                .read_line(&mut key)
                .expect("could not parse the input");
            let key = key.trim();
            println!("\n\tthe value of {} is {}\n", key, get(&mut db, &key));
        } else if operation == operations.2 {
            break;
        } else {
            println!("\n\t{} is not a valid option\n", operation);
        }
        stdout().flush().unwrap();
    }
}

fn store(db: &mut Vec<String>, key: &str, value: &str) {
    let new_data = format!("{},{}", key, value);
    db.push(new_data);
}

fn get(db: &mut Vec<String>, key: &str) -> String {
    for data in db {
        if data.split(',').next().expect("error while parsing the key") == key {
            return data
                .split(',')
                .next()
                .expect("error while parsing the value")
                .to_string();
        }
    }
    String::from("404")
}

output:

        your options are put, get, exit.

what do you wanna do?
put
enter your key
name
enter your value
cob

        value `cob` stored to key `name`

what do you wanna do?
exit

        put
exit is not a valid option

what do you wanna do?     
exit

        put
exit
exit is not a valid option

This isn't an I/O issue, there's a hint in the output you pasted

        put
exit is not a valid option

Where is that extra "put" with white space coming from? We can add a print statement to help see what's happening.

+ println!("{:?}", operation.chars().collect::<Vec<_>>());
stdout().flush().unwrap();

That gets us


	your options are put, get, exit.

what do you wanna do?
put
enter your key
a
enter your value
b

	value `b` stored to key `a`

['p', 'u', 't']
what do you wanna do?
get

	put
get is not a valid option

['p', 'u', 't', '\n', 'g', 'e', 't']
what do you wanna do?

That tells us operation isn't getting reset, it's accumulating output from each read. Moving the variable declaration inside the loop fixes that problem.

2 Likes