как извлечь поля из структуры в перечислении (неопровержимый шаблон if-let) - PullRequest
0 голосов
/ 10 июля 2020

Я пытаюсь создать клиентскую библиотеку S3, но, поскольку существует множество действий (API_Operations) , я решил использовать enum для определения всех возможных действий в надежде, что может быть больше легко поддерживать (какие-либо советы / комментарии / отзывы?) , например, это фрагмент enum Actions::ListObjectsV2 для перечисления содержимого корзины:

pub enum Actions {
    // missing options, POC for now 
    ListObjectsV2 {
        continuation_token: Option<String>,
        delimiter: Option<String>,
        fetch_owner: Option<bool>,
        prefix: Option<String>,
        start_after: Option<String>,
    },
}

Используется с чем-то вроде это:

let s3 = S3::new(&bucket, &credentials, &region);
let action = Actions::ListObjectsV2 {
    continuation_token: None,
    delimiter: None,
    fetch_owner: None,
    prefix: Some(String::from("foo")),
    start_after: None,
};

if let Ok(objects) = s3.list_objects(action).await {
    println!("objects: {:#?}", objects);
}

Метод s3.list_objects(action) выглядит так:

pub async fn list_objects(
    &self,
    action: Actions,
) -> Result<ListBucketResult, Box<dyn error::Error>> {
    let mut url = Url::parse(&format!("https://{}/{}", self.host, self.bucket))?;
    url.query_pairs_mut().append_pair("list-type", "2");

    if let Actions::ListObjectsV2 {
        continuation_token,
        delimiter,
        fetch_owner,
        prefix,
        start_after,
    } = action.clone()
    {
        if let Some(token) = continuation_token {
            url.query_pairs_mut()
                .append_pair("continuation-token", &token);
        }
        if let Some(delimiter) = delimiter {
            url.query_pairs_mut().append_pair("delimiter", &delimiter);
        }
        if fetch_owner.is_some() {
            url.query_pairs_mut().append_pair("fetch-owner", "true");
        }
        if let Some(prefix) = prefix {
            url.query_pairs_mut().append_pair("prefix", &prefix);
        }
        if let Some(sa) = start_after {
            url.query_pairs_mut().append_pair("start-after", &sa);
        }
    }
...

Он работает, но я получаю это предупреждение: неопровержимый шаблон if-let

warning: irrefutable if-let pattern
  --> src/s3/mod.rs:49:9
   |
49 | /         if let Actions::ListObjectsV2 {
50 | |             continuation_token,
51 | |             delimiter,
52 | |             fetch_owner,
...  |
72 | |             }
73 | |         }
   | |_________^
   |
   = note: `#[warn(irrefutable_let_patterns)]` on by default

Я мог бы удалить предупреждение, добавив в этот блок:

 #[allow(irrefutable_let_patterns)]

Но вместо этого я хотел бы знать, есть ли лучшие способы исправить это, я попробовал некоторые варианты из этого post (https://users.rust-lang.org/t/how-do-i-get-rid-of-this-pattern-of-extracting-a-value-from-an-enum/12555/7), но я не могу понять, как реализовать этот шаблон: impl From<> for Option<>

Есть идеи?

...