<commit_before>
#include "channel_codec_wrapper.h"
#include "channel_codec/channel_codec.h"
#include "errorlogger/generic_eeprom_errorlogger.h"
#include "global.h"
#include "rpcruntime_decoded_function_call.h"
#include "rpcruntime_decoder.h"
#include "rpcruntime_encoded_function_call.h"
#include "rpcruntime_transfer.h"

#include <iterator>
#include <map>

using Wrapper_instances = std::map<channel_codec_instance_t *, Channel_codec_wrapper *>;
GLOBAL(Wrapper_instances, wrapper_instances)

Channel_codec_wrapper::Channel_codec_wrapper(const RPCRuntimeDecoder &decoder)
	: decoder(&decoder)
	, cci(std::make_unique<channel_codec_instance_t>()) {
	transfers.emplace_back(*decoder.get_description(), &decoder);
	channel_init_instance(cci.get(), input_buffer, sizeof input_buffer, output_buffer, sizeof output_buffer);
	global::detail::getwrapper_instances()[cci.get()] = this;
}

Channel_codec_wrapper::~Channel_codec_wrapper() {
	channel_uninit_instance(cci.get());
}

void Channel_codec_wrapper::add_data(const std::vector<unsigned char> &buffer) {
	for (auto &c : buffer) {
		channel_push_byte_to_RPC(cci.get(), c);
	}
}

void Channel_codec_wrapper::add_data(const unsigned char *data, std::size_t size) {
	add_data({data, data + size});
}

bool Channel_codec_wrapper::transfer_complete() const {
	return transfers.front().is_complete();
}

RPCRuntimeDecodedFunctionCall Channel_codec_wrapper::pop() {
	return pop_completed_transfer().decode();
}

RPCRuntimeTransfer Channel_codec_wrapper::pop_completed_transfer()
{
	if (transfers.front().is_complete() == false) {
		throw std::runtime_error("Tried to pop from an incomplete transfer");
	}
	auto transfer = std::move(transfers.front());
	transfers.pop_front();
	return transfer;
}

const RPCRuntimeDecoder *Channel_codec_wrapper::get_decoder() const {
	return decoder;
}

void Channel_codec_wrapper::reset_current_transfer() {
	transfers.back().reset();
}

std::vector<unsigned char> Channel_codec_wrapper::encode(const RPCRuntimeEncodedFunctionCall &call) {
	encoded_data.clear();
	const auto &data = call.encode();
	channel_start_message_from_RPC(cci.get(), data.size());
	for (auto &byte : data) {
		channel_push_byte_from_RPC(cci.get(), byte);
	}
	channel_commit_from_RPC(cci.get());
	return std::move(encoded_data);
}

void push_data(Channel_codec_wrapper &ccw, const unsigned char *data, std::size_t size) {<commit_msg>Fixed crash in destruction of moved-from channel_codec_wrapper.<commit_after>
#include "channel_codec_wrapper.h"
#include "channel_codec/channel_codec.h"
#include "errorlogger/generic_eeprom_errorlogger.h"
#include "global.h"
#include "rpcruntime_decoded_function_call.h"
#include "rpcruntime_decoder.h"
#include "rpcruntime_encoded_function_call.h"
#include "rpcruntime_transfer.h"

#include <iterator>
#include <map>

using Wrapper_instances = std::map<channel_codec_instance_t *, Channel_codec_wrapper *>;
GLOBAL(Wrapper_instances, wrapper_instances)

Channel_codec_wrapper::Channel_codec_wrapper(const RPCRuntimeDecoder &decoder)
	: decoder(&decoder)
	, cci(std::make_unique<channel_codec_instance_t>()) {
	transfers.emplace_back(*decoder.get_description(), &decoder);
	channel_init_instance(cci.get(), input_buffer, sizeof input_buffer, output_buffer, sizeof output_buffer);
	global::detail::getwrapper_instances()[cci.get()] = this;
}

Channel_codec_wrapper::~Channel_codec_wrapper() {
	if (cci != nullptr) {
		channel_uninit_instance(cci.get());
	}
}

void Channel_codec_wrapper::add_data(const std::vector<unsigned char> &buffer) {
	for (auto &c : buffer) {
		channel_push_byte_to_RPC(cci.get(), c);
	}
}

void Channel_codec_wrapper::add_data(const unsigned char *data, std::size_t size) {
	add_data({data, data + size});
}

bool Channel_codec_wrapper::transfer_complete() const {
	return transfers.front().is_complete();
}

RPCRuntimeDecodedFunctionCall Channel_codec_wrapper::pop() {
	return pop_completed_transfer().decode();
}

RPCRuntimeTransfer Channel_codec_wrapper::pop_completed_transfer() {
	if (transfers.front().is_complete() == false) {
		throw std::runtime_error("Tried to pop from an incomplete transfer");
	}
	auto transfer = std::move(transfers.front());
	transfers.pop_front();
	return transfer;
}

const RPCRuntimeDecoder *Channel_codec_wrapper::get_decoder() const {
	return decoder;
}

void Channel_codec_wrapper::reset_current_transfer() {
	transfers.back().reset();
}

std::vector<unsigned char> Channel_codec_wrapper::encode(const RPCRuntimeEncodedFunctionCall &call) {
	encoded_data.clear();
	const auto &data = call.encode();
	channel_start_message_from_RPC(cci.get(), data.size());
	for (auto &byte : data) {
		channel_push_byte_from_RPC(cci.get(), byte);
	}
	channel_commit_from_RPC(cci.get());
	return std::move(encoded_data);
}

void push_data(Channel_codec_wrapper &ccw, const unsigned char *data, std::size_t size) {
{'fraction_non_alphanumeric': 0.13029989658738367, 'fraction_numerical': 0.0, 'mean_word_length': 8.48235294117647, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2633079', 'n_tokens_mistral': 1618, 'n_tokens_neox': 1581, 'n_words': 275}