1
0
mirror of https://github.com/danog/ton.git synced 2024-12-03 09:58:01 +01:00
ton/tdfec/test/LibRaptorQ.cpp
2019-09-07 14:33:36 +04:00

158 lines
5.1 KiB
C++

/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "LibRaptorQ.h"
#include "RaptorQ/RaptorQ_v1_hdr.hpp"
namespace RaptorQ = RaptorQ__v1;
namespace td {
namespace fec {
class SlowRaptorQEncoder::Impl {
public:
Impl(BufferSlice data, size_t max_symbol_size)
: encoder_(create_encoder(data.size(), max_symbol_size)), data_(std::move(data)), symbol_size_(max_symbol_size) {
encoder_->set_data(data_.as_slice().ubegin(), data_.as_slice().uend());
}
Symbol gen_symbol(uint32 id) {
BufferSlice symbol_data(symbol_size_);
auto *begin = symbol_data.as_slice().ubegin();
auto *end = symbol_data.as_slice().uend();
encoder_->encode(begin, end, id);
return {id, symbol_data.from_slice(Slice(symbol_data.as_slice().ubegin(), begin))};
}
Parameters get_parameters() const {
return Parameters{encoder_->symbols(), encoder_->symbol_size(), data_.size()};
}
Info get_info() const {
return {1 << 24, computed_ ? encoder_->max_repair() : encoder_->symbols()};
}
void prepare_more_symbols() {
encoder_->compute_sync();
computed_ = true;
}
private:
using Encoder = RaptorQ::Encoder<uint8 *, uint8 *>;
std::unique_ptr<Encoder> encoder_;
BufferSlice data_;
size_t symbol_size_;
bool computed_{false};
static std::unique_ptr<Encoder> create_encoder(size_t data_size, size_t symbol_size) {
auto min_symbols = (data_size + symbol_size - 1) / symbol_size;
RaptorQ::Block_Size block = RaptorQ::Block_Size::Block_10;
for (auto blk : *RaptorQ::blocks) {
// RaptorQ::blocks is a pointer to an array, just scan it to find your
// block.
if (static_cast<uint16>(blk) >= min_symbols) {
block = blk;
break;
}
}
CHECK(static_cast<uint16>(block) >= min_symbols);
return std::make_unique<Encoder>(block, symbol_size);
}
};
class SlowRaptorQDecoder::Impl {
public:
using Decoder = RaptorQ::Decoder<uint8 *, uint8 *>;
Impl(SlowRaptorQEncoder::Parameters parameters)
: decoder_(RaptorQ::Block_Size(parameters.symbols_count), parameters.symbol_size, Decoder::Report::COMPLETE)
, data_size_(parameters.data_size) {
}
bool may_try_decode() const {
return decoder_.can_decode();
}
Result<DataWithEncoder> try_decode(bool need_encoder) {
decoder_.decode_once();
if (!decoder_.ready()) {
return Status::Error("Not ready");
}
BufferSlice data(data_size_);
auto begin = data.as_slice().ubegin();
decoder_.decode_bytes(begin, data.as_slice().uend(), 0, 0);
std::unique_ptr<Encoder> encoder;
if (need_encoder) {
encoder = SlowRaptorQEncoder::create(data.copy(), decoder_.symbol_size());
}
return DataWithEncoder{std::move(data), std::move(encoder)};
}
void add_symbol(Symbol symbol) {
auto begin = symbol.data.as_slice().ubegin();
decoder_.add_symbol(begin, symbol.data.as_slice().uend(), symbol.id);
}
private:
Decoder decoder_;
size_t data_size_;
};
SlowRaptorQEncoder::~SlowRaptorQEncoder() = default;
std::unique_ptr<SlowRaptorQEncoder> SlowRaptorQEncoder::create(BufferSlice data, size_t max_symbol_size) {
return std::make_unique<SlowRaptorQEncoder>(std::move(data), max_symbol_size);
}
SlowRaptorQEncoder::SlowRaptorQEncoder(BufferSlice data, size_t max_symbol_size) {
impl_ = std::make_unique<Impl>(std::move(data), max_symbol_size);
}
Symbol SlowRaptorQEncoder::gen_symbol(uint32 id) {
return impl_->gen_symbol(id);
}
SlowRaptorQEncoder::Parameters SlowRaptorQEncoder::get_parameters() const {
return impl_->get_parameters();
}
Encoder::Info SlowRaptorQEncoder::get_info() const {
return impl_->get_info();
}
void SlowRaptorQEncoder::prepare_more_symbols() {
impl_->prepare_more_symbols();
}
SlowRaptorQDecoder::~SlowRaptorQDecoder() = default;
std::unique_ptr<SlowRaptorQDecoder> SlowRaptorQDecoder::create(SlowRaptorQEncoder::Parameters parameters) {
return std::make_unique<SlowRaptorQDecoder>(std::move(parameters));
}
bool SlowRaptorQDecoder::may_try_decode() const {
return impl_->may_try_decode();
}
Result<DataWithEncoder> SlowRaptorQDecoder::try_decode(bool need_encoder) {
return impl_->try_decode(need_encoder);
}
void SlowRaptorQDecoder::add_symbol(Symbol symbol) {
impl_->add_symbol(std::move(symbol));
}
SlowRaptorQDecoder::SlowRaptorQDecoder(SlowRaptorQEncoder::Parameters parameters) {
impl_ = std::make_unique<Impl>(std::move(parameters));
}
} // namespace fec
} // namespace td