Проблемы с жизнью Tuple в ржавчине. - PullRequest
0 голосов
/ 21 октября 2018

Я пытаюсь реализовать простой синтаксический анализатор для потока байтов.

У меня возникают проблемы, когда я хочу повторно использовать объявленную ранее переменную,

fn read_data(asn_data: &mut Cursor<&[u8]>) -> Result<(u8, u8, Vec<u8>), Err> {
    let total_len = asn_data.get_ref().len();

    if total_len < 2 {
        return Err(1);
    }
    let d_type = asn_data.read_u8().unwrap();
    let d_len = asn_data.read_u8().unwrap();

    if (asn_data.position() + d_len as u64) > total_len as u64 {
        return Err(2);
    }

    let mut buf = vec![0; d_len as usize];

    match asn_data.read_exact(&mut buf) {
        Err(e) => Err(e),
        Ok(()) => Ok((d_type, d_len, buf)),
    }

}

fn parse_request(request: &[u8]) -> Option<u8> {

    if request.len() == 0 {
        return None;
    }

    let mut rdr = Cursor::new(request);
    let data_tuple = read_data(&mut rdr).unwrap();
    println!("{:02?}", data_tuple.2);

    rdr = Cursor::new(data_tuple.2.as_slice());
    let data_tuple = read_data(&mut rdr).unwrap();
    println!("{:02x?}", data_tuple.2);

    Some(1)
}

ВФункция parse_request Я хочу повторно использовать переменную rdr, но с кодом, показанным выше, я получаю следующую ошибку при компиляции:

error [E0597]: data_tuple.2 недостаточно долго живет -> src /main.rs:80:23 |80 |rdr = Cursor :: new (data_tuple.2.as_slice ());|^^^^^^^^^^^^ заемное значение не живет достаточно долго ... 104 |} |- data_tuple.2 упал здесь, пока еще одолжил |= примечание: значения в области видимости отбрасываются в обратном порядке их создания

ошибка: прерывание из-за предыдущей ошибки

Однако, если я пишу «let mut», когда я использую2-я переменная rdr, код компилируется и работает нормально ...

let mut rdr = Cursor::new(data_tuple.2.as_slice());

Я не понимаю, почему ... я хочу использовать переменную вместо того, чтобы объявить ее снова ...

Я пытался с некоторыми примерами / проблемами, связанными с переменным временем жизни, но я не получил решение для моего случая ... и решение, которое я нашел, я не понимаю полностью ...

1 Ответ

0 голосов
/ 22 октября 2018

Это не связано с временем жизни кортежа, это просто порядок отбрасывания.

Когда переменные определены в отдельных операторах let в одной и той же области видимости (то есть в одном и том же блоке), онибудет сброшено в обратном порядке.Глядя на ваш код, мы можем видеть:

let mut rdr = Cursor::new(request);
let data_tuple = read_data(&mut rdr).unwrap();

Итак, data_tuple будет отброшено сначала , пока rdr еще жив.Это плохо, потому что rdr должен ссылаться на кортеж.Самым простым решением будет обмен их определений:

let data_tuple: (u8, u8, Vec<u8>);
let mut rdr = Cursor::new(request);
data_tuple = read_data(&mut rdr).unwrap();

Таким образом, rdr будет сначала отброшен, освобождая ссылку на data_tuple и позволяя самому кортежу сбросить.

Упомянутое вами "исправление" работает, потому что каждый оператор let определяет новую переменную , даже если уже используется то же имя , а существующая переменная сразу же забывается.Итак, когда вы пишете:

let mut rdr = Cursor::new(request);
let data_tuple = read_data(&mut rdr).unwrap();
let mut rdr = Cursor::new(data_tuple.2.as_slice());

, второй rdr никак не связан с первым.По сути, это почти то же самое, что объявить две разные переменные, скажем, rdr и rdr2, и использовать rdr2 с этого места до конца функции.

...