[Solved] Environment Variables

use std::error::Error;
use std::fs;
use std::env;

pub struct Config {
    pub query: String,
    pub filename: String,
    pub case_sensitive: bool,
}

impl Config {
    pub fn new(args: &[String]) -> Result<Config, &'static str> {
        if args.len() < 3 {
            return Err("not enough arguments");
        }

        let query = args[1].clone();
        let filename = args[2].clone();

        let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
        
        println!("{}", case_sensitive);

        Ok(Config { query, filename, case_sensitive })
    }
}

pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
    let contents = fs::read_to_string(config.filename)?;

    let results = if config.case_sensitive {
        search(&config.query, &contents)
    } else {
        search_case_insensitive(&config.query, &contents)
    };

    for line in results {
        println!("{}", line);
    }

    Ok(())
}

pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    let mut results = Vec::new();

    for line in contents.lines() {
        if line.contains(query) {
            results.push(line);
        }
    }

    results
}

pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    let query = query.to_lowercase();
    let mut results = Vec::new();

    for line in contents.lines() {
        if line.to_lowercase().contains(&query) {
            results.push(line);
        }
    }

    results
}

A question to the code above. I use the "env::var" CASE_INSENSITIVE to check if I want to use the case sensitive search function or the case insensitive function to search for a String.

So for example ….. cargo run to poem.txt > output.txt
When I started my IDE fresh (Visual Studio Code) and I compile for the first time, is_err() returns true, because of an Error which follows from not initializing my environment variable yet.

So now I type "set CASE_INSENSITIVE=1" and then "cargo run to poem.txt > output.txt" and everything is fine. But when I want to use the sensitive search function again, I tried "set CASE_INSENSITIVE=0" but that won't work.

So what am I missing here?

Thank you for your help out in front....

Here are all the possible states for your environment variable:

  • either it has not been set and env::var() = Err(_)

  • or it exists and env::var() = Ok(value); then its value can be

    • String::from("1");

    • or String::from("0");

    • or something else (including the empty String!);

It is up to you to decide how you want to map each case to your boolean.

So your current choice,

Maps the case Ok(String::from("0")) to the boolean true.

You most probably meant something along these lines:

/// in case you don't have a logger:
macro_rules! warn {(
    $($args:tt)*
) => (
    eprintln!("<WARNING> {}", format_args!($($args)*))
)}

let case_sensitive: bool =
    env::var("CASE_INSENSITIVE")
        .ok()
        .and_then(|value: String| match &value as &str {
            | "1" => Some(false),
            | "0" | "" => Some(true),
            | _ => {
                warn!("Extraneous CASE_INSENSITIVE={:?}; ignoring it", value);
                None
            },
        })
        .unwrap_or(true)
;
1 Like

Thank you very much, that's exactly what I meant to do!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.