Соответствует ли шаблон ржавчины существующей привязке? - PullRequest
2 голосов
/ 28 июня 2019

Я изучаю Rust со вчерашнего дня.Следующий код прост -

use encoding_rs::Encoding;
use std::fs;
use std::fs::File;
use std::io::BufReader;
use std::io::Read;
use std::option::Option;
use std::path::Path;

extern crate encoding_rs;
extern crate encoding_rs_io;

fn main() {
    let mut reader = BufReader::new(file);
    let mut bom: [u8; 3] = [0; 3];

    // read BOM
    if let Ok(_) = reader.read_exact(&mut bom) {
        // sniff BOM

        // Because Rust disallows NULLs, hence I declare `Option<&Encoding>` to store the result of encoding.
        let mut enc: Option<&Encoding> = None;
        match Encoding::for_bom(&bom) {
            Some((encoding, _)) => {
                // <-- Some((enc, _))
                enc = Some(encoding);
            }
            None => {
                if let Some(encoding) = Encoding::for_label("UTF-8".as_bytes()) {
                    enc = Some(encoding);
                }
            }
        }

        if let Some(encoding) = enc {
            println!("{:?}", encoding);
        }
    }
}

Он открывает текстовый файл и пытается проанализировать его кодировку, анализируя BOM (Byte Order Marker).Если Encoding::for_bom не возвращает кодировку, код будет использовать UTF-8 по умолчанию.

Мне не нравится unwrap(), потому что он всегда предполагает, что есть верный результат

Мой вопрос: есть ли способ сопоставления с образцом и помещения результата непосредственно в существующую изменяемую привязку?

например, Изменить Some((encoding, _)) на Some((enc, _)), следовательно, мне не нужна строка enc = Some(encoding)

Ответы [ 2 ]

5 голосов
/ 28 июня 2019

Многие ржавые конструкции могут использоваться в качестве выражений, то есть они могут возвращать значение.Поэтому, если каждая ветвь вашего соответствия возвращает значение одного и того же типа, вы можете назначить его непосредственно в переменную.Он не должен быть изменяемым, если вы не планируете изменить его позже.

let mut reader = BufReader::new(file);
let mut bom: [u8; 3] = [0; 3];

if let Ok(_) = reader.read_exact(&mut bom) {
    let enc = match Encoding::for_bom(&bom) {
        Some((encoding, _)) => Some(encoding),
        None => Encoding::for_label("UTF-8".as_bytes()),
    };

    if let Some(encoding) = enc {
        println!("{:?}", encoding);
    }
}
1 голос
/ 28 июня 2019

Я бы использовал комбинацию map и or_else:

let enc = Encoding::for_bom (&bom)
        .map (|t| t.0)
        .or_else (|| Encoding::for_label ("UTF-8".as_bytes()));

Или (более четко, но немного дольше):

let enc = Encoding::for_bom (&bom)
        .map (|(e, _)| e)
        .or_else (|| Encoding::for_label ("UTF-8".as_bytes()));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...