Repository: tikv/tikv
File: src/storage/errors.rs (Rust)

Code before:
}

fn ensure_debug_info_for_key_error(err: &mut kvrpcpb::KeyError) -> &mut kvrpcpb::DebugInfo {
    if err.debug_info.is_none() {
        err.set_debug_info(kvrpcpb::DebugInfo::default());
    }
    err.debug_info.as_mut().unwrap()
}

fn add_debug_mvcc_for_key_error(
    err: &mut kvrpcpb::KeyError,
    key: &[u8],
    mvcc_info: Option<types::MvccInfo>,
) {
    if let Some(mut mvcc) = mvcc_info {
        let debug_info = ensure_debug_info_for_key_error(err);
        // remove the values in default CF to reduce the size of the response.
        mvcc.values.clear();
        // set mvcc info to debug_info
        let mut mvcc_debug_info = kvrpcpb::MvccDebugInfo::default();
        mvcc_debug_info.set_key(key.to_owned());
        mvcc_debug_info.set_mvcc(mvcc.into_proto());
        debug_info.mvcc_info.push(mvcc_debug_info);
    }
}

pub fn extract_key_error(err: &Error) -> kvrpcpb::KeyError {
    let mut key_error = kvrpcpb::KeyError::default();
    match err {
        Error(box ErrorInner::Txn(TxnError(box TxnErrorInner::Mvcc(MvccError(
            box MvccErrorInner::KeyIsLocked(info),
        )))))
        | Error(box ErrorInner::Txn(TxnError(box TxnErrorInner::Engine(KvError(
            box KvErrorInner::KeyIsLocked(info),
        )))))
        | Error(box ErrorInner::Kv(KvError(box KvErrorInner::KeyIsLocked(info)))) => {
            key_error.set_locked(info.clone());
        }
        // failed in prewrite or pessimistic lock
        Error(box ErrorInner::Txn(TxnError(box TxnErrorInner::Mvcc(MvccError(
            box MvccErrorInner::WriteConflict {
                start_ts,
                conflict_start_ts,
                conflict_commit_ts,
                key,
                primary,
                reason,
            },
        ))))) => {
            let mut write_conflict = kvrpcpb::WriteConflict::default();
            write_conflict.set_start_ts(start_ts.into_inner());

Review comment (bug):
How about
```suggestion
fn add_debug_mvcc_for_key_error(
    err: mut kvrpcpb::KeyError,
    key: &[u8],
    mvcc_info: Option<types::MvccInfo>,
) -> kvrpcpb::KeyError{
    if let Some(mut mvcc) = mvcc_info {
        let debug_info = err.debug_info.get_or_insert_default();
        // remove the values in default CF to reduce the size of the response.
        mvcc.values.clear();
        // set mvcc info to debug_info
        let mut mvcc_debug_info = kvrpcpb::MvccDebugInfo::default();
        mvcc_debug_info.set_key(key.to_owned());
        mvcc_debug_info.set_mvcc(mvcc.into_proto());
        debug_info.mvcc_info.push(mvcc_debug_info);
    }
    err
}
```

Code after:
}

fn get_or_insert_default_for_key_error_debug_info(
    err: &mut kvrpcpb::KeyError,
) -> &mut kvrpcpb::DebugInfo {
    let debug_info = &mut err.debug_info;
    if debug_info.is_none() {
        debug_info.set_default()
    } else {
        debug_info.as_mut().unwrap()
    }
}

fn add_debug_mvcc_for_key_error(
    err: &mut kvrpcpb::KeyError,
    key: &[u8],
    mvcc_info: Option<types::MvccInfo>,
) {
    if let Some(mut mvcc) = mvcc_info {
        let debug_info = get_or_insert_default_for_key_error_debug_info(err);
        // remove the values in default CF to reduce the size of the response.
        mvcc.values.clear();
        // set mvcc info to debug_info
        let mut mvcc_debug_info = kvrpcpb::MvccDebugInfo::default();
        mvcc_debug_info.set_key(key.to_owned());
        mvcc_debug_info.set_mvcc(mvcc.into_proto());
        debug_info.mvcc_info.push(mvcc_debug_info);
    }
}

pub fn extract_key_error(err: &Error) -> kvrpcpb::KeyError {
    let mut key_error = kvrpcpb::KeyError::default();
    match err {
        Error(box ErrorInner::Txn(TxnError(box TxnErrorInner::Mvcc(MvccError(
            box MvccErrorInner::KeyIsLocked(info),
        )))))
        | Error(box ErrorInner::Txn(TxnError(box TxnErrorInner::Engine(KvError(
            box KvErrorInner::KeyIsLocked(info),
        )))))
        | Error(box ErrorInner::Kv(KvError(box KvErrorInner::KeyIsLocked(info)))) => {
            key_error.set_locked(info.clone());
        }
        // failed in prewrite or pessimistic lock
        Error(box ErrorInner::Txn(TxnError(box TxnErrorInner::Mvcc(MvccError(
            box MvccErrorInner::WriteConflict {
                start_ts,
                conflict_start_ts,
                conflict_commit_ts,
                key,
                primary,
                reason,