Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to match a file extension represented as an OsStr?

Tags:

string

rust

I am trying to match against a file extension:

let file_path = std::path::Path::new("index.html");
let content_type = match file_path.extension() {
    None => "",
    Some(os_str) => match os_str {
        "html" => "text/html",
        "css" => "text/css",
        "js" => "application/javascript",
    },
};

The compiler says:

error[E0308]: mismatched types
 --> src/main.rs:6:13
  |
6 |             "html" => "text/html",
  |             ^^^^^^ expected struct `std::ffi::OsStr`, found str
  |
  = note: expected type `&std::ffi::OsStr`
             found type `&'static str`
like image 703
Boiethios Avatar asked Feb 07 '17 22:02

Boiethios


People also ask

What does the return length of an osstr mean?

Returns the length of this OsStr. Note that this does not return the number of bytes in the string in OS string form. The length returned is that of the underlying storage used by OsStr .

What is the difference between &&osstr and osstring?

&OsStr is to OsString as & str is to String: the former in each pair are borrowed references; the latter are owned strings. See the module’s toplevel documentation about conversions for a discussion on the traits which OsStr implements for conversions from/to native representations. pub fn new <S: AsRef < OsStr > + ? Sized > (s: & S) -> & OsStr

What is ‘file format and extension of don’t match’ error?

The ‘File Format and Extension of Don’t Match’ error appear when the user tries to open certain files in Excel. Even if the user clicks on Yes to open it, all previously saved information on that file will be gone.

How to find common file name extensions in Windows 10?

Common file name extensions in Windows. 1 In the search box on the taskbar, type file explorer, and in the search results, select File Explorer. 2 In File Explorer under View, in the Show/hide group, select the File name extensions check box.


2 Answers

OsStr and OsString exist precisely because filenames are not UTF-8. A Rust string literal is UTF-8. That means you must deal with converting between the two representations.

One solution is to give up the match and use if-else statements. See Stargateur's answer for an example.

You can also convert the extension to a string. Since the extension might not be UTF-8, this returns another Option:

fn main() {
    let file_path = std::path::Path::new("index.html");
    let content_type = match file_path.extension() {
        None => "",
        Some(os_str) => {
            match os_str.to_str() {
                Some("html") => "text/html",
                Some("css") => "text/css",
                Some("js") => "application/javascript",
                _ => panic!("You forgot to specify this case!"),
            }
        }
    };
}

If you want all cases to use an empty string as the fallback, you can do something like:

use std::ffi::OsStr;

fn main() {
    let file_path = std::path::Path::new("index.html");
    let content_type = match file_path.extension().and_then(OsStr::to_str) {
        Some("html") => "text/html",
        Some("css") => "text/css",
        Some("js") => "application/javascript",
        _ => "",
    };
}

Or if you want to use None as the fallback:

use std::ffi::OsStr;

fn main() {
    let file_path = std::path::Path::new("index.html");

    let content_type = file_path.extension().and_then(OsStr::to_str).and_then(|ext| {
        match ext {
            "html" => Some("text/html"),
            "css" => Some("text/css"),
            "js" => Some("application/javascript"),
            _ => None,
        }
    });
}
like image 145
Shepmaster Avatar answered Oct 22 '22 22:10

Shepmaster


You could use PartialEq<str> trait for OsStr.

fn main() {
    let file_path = std::path::Path::new("index.html");
    let content_type = match file_path.extension() {
        None => "",
        Some(os_str) => {
            if os_str == "html" {
                "text/html"
            } else if os_str == "css" {
                "text/css"
            } else if os_str == "js" {
                "application/javascript"
            } else {
                ""
            }
        }
    };
    println!("{:?}", content_type);
}
like image 44
Stargateur Avatar answered Oct 23 '22 00:10

Stargateur