YU2TA7KA's BLOG ~take one step at a time~

派生開発、組み込み開発周りのこと。

MIMEのパースでハマった話

はじめに

Rust CookbookのParse the MIME type of a HTTP responseでハマったので、その記録です。
rust-lang-nursery.github.io

ソースコード全文をコピペできていなかった

Aboutに説明がありましたが、最初読んでいなかったのでハマりました。
f:id:yuji-tanaak:20191201072824p:plain

利用すべきcrateバージョンがよくわかっていない

crate version
reqwest 0.10.0-alpha.2
mime 1.1.1
error-chain 未記載?

Rust Cookbookの記述
f:id:yuji-tanaak:20191201092922p:plain

crate version
reqwest 0.9.18
mime 0.3.14
error-chain 0.12.1

動作した実装
f:id:yuji-tanaak:20191201101205p:plain

Rust Cookbookの記述に沿うとエラーで、それぞれcrateのドキュメントを検索して記載されているversionに変更しました。reqwest 0.10.0-alpha.2はaysnc/awaitでの実装が必要?

https://docs.rs/reqwest/0.9.18/reqwest/
https://docs.rs/reqwest/0.10.0-alpha.2/reqwest/

おわりに

Rustはドキュメントが丁寧に公開されているため、ありがたいです。ただ、利用crateの(Cargo.tomlに記載すべき)バージョンは気をつけないと今回みたいにハマるなと学びました。

ソースコード

[dependencies]
reqwest = "0.9.18"
mime = "0.3.14"
error-chain = "0.12.1"

#[macro_use]
extern crate error_chain;
extern crate mime;
extern crate reqwest;

use mime::Mime;
use std::str::FromStr;
use reqwest::header::CONTENT_TYPE;


error_chain! {
   foreign_links {
       Reqwest(reqwest::Error);
       Header(reqwest::header::ToStrError);
       Mime(mime::FromStrError);
   }
}

fn main() -> Result<()> {
    let response = reqwest::get("https://www.rust-lang.org/logos/rust-logo-32x32.png")?;

    let headers = response.headers();

    match headers.get(CONTENT_TYPE) {
        None => {
            println!("The response does not contain a Content-Type header.");
        }
        Some(content_type) => {
            let content_type = Mime::from_str(content_type.to_str()?)?;
            let media_type = match (content_type.type_(), content_type.subtype()) {
                (mime::TEXT, mime::HTML) => "a HTML document",
                (mime::TEXT, _) => "a text document",
                (mime::IMAGE, mime::PNG) => "a PNG image",
                (mime::IMAGE, _) => "an image",
                _ => "neither text nor image",
            };

            println!("The reponse contains {}.", media_type);
        }
    };

    Ok(())
}

CrateのバージョンNG時のエラーメッセージ

error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try`
  --> src\main.rs:20:20
   |
20 |     let response = reqwest::get("https://www.rust-lang.org/logos/rust-logo-32x32.png")?;
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl std::future::Future`
   |
   = help: the trait `std::ops::Try` is not implemented for `impl std::future::Future`
   = note: required by `std::ops::Try::into_result`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
error: could not compile `mime`.

To learn more, run the command again with --verbose.