#include <cstdint>
#include "db/vlog_reader.h"
#include "leveldb/slice.h"
#include "leveldb/env.h"
#include "util/coding.h"
namespace leveldb{
namespace vlog{
    VReader::VReader(SequentialFile* file) // A file abstraction for reading sequentially through a file
        :file_(file){}
    Status VReader::ReadRecord(uint64_t vfile_offset, std::string* record){
        Status s;
        Slice size_slice;
        char size_buf[11];
        uint64_t rec_size = 0;
        s = file_->SkipFromHead(vfile_offset);  // 将文件的读取位置移动到 vfile_offset
        if(s.ok()) s = file_ -> Read(10, &size_slice, size_buf); // 先把Record 长度读出来, 最长10字节.
        if(s.ok()){
            if(GetVarint64(&size_slice, &rec_size) == false){  // 解析变长整数，得到记录的长度 rec_size
                return Status::Corruption("Failed to decode vlog record size.");
            }
            std::string rec;
            char* c_rec = new char[rec_size];  // 为记录分配一个临时缓冲区
            //TODO: Should delete c_rec?
            rec.resize(rec_size);
            Slice rec_slice;
            s = file_->SkipFromHead(vfile_offset + (size_slice.data() - size_buf)); // 将文件的读取位置移动
            if(!s.ok()) return s;
            s = file_-> Read(rec_size, &rec_slice, c_rec);  // 从文件中读取 rec_size 字节的数据到 c_rec 中，并用 rec_slice 包装这些数据
            if(!s.ok()) return s;
            rec = std::string(c_rec, rec_size);
            *record = std::move(std::string(rec));
        }
        return s;
    }
    Status VReader::ReadKV(uint64_t vfile_offset, std::string* key, std::string* val){
        std::string record_str;
        Status s = ReadRecord(vfile_offset, &record_str);
        if(s.ok()){
            Slice record = Slice(record_str);
            //File the val
            uint64_t key_size;
            bool decode_flag = true;
            decode_flag &= GetVarint64(&record, &key_size);  // 获取键的长度
            if(decode_flag){
                *key = Slice(record.data(), key_size).ToString();  // 从record中截取键值
                record = Slice(record.data() + key_size, record.size() - key_size);  // 截取剩余的record
            }
            uint64_t val_size;
            decode_flag &= GetVarint64(&record, &val_size);  // 获取value的长度
            if(decode_flag) *val = Slice(record.data(), val_size).ToString();  // 截取value的值
            if(!decode_flag || val->size() != record.size()){
                s = Status::Corruption("Failed to decode Record Read From vlog.");
            }
        }
        return s;
    }
}// namespace vlog.
}