in kll/include/kll_sketch_impl.hpp [477:548]
kll_sketch<T, C, A> kll_sketch<T, C, A>::deserialize(std::istream& is, const SerDe& sd,
const C& comparator, const A& allocator) {
const auto preamble_ints = read<uint8_t>(is);
const auto serial_version = read<uint8_t>(is);
const auto family_id = read<uint8_t>(is);
const auto flags_byte = read<uint8_t>(is);
const auto k = read<uint16_t>(is);
const auto m = read<uint8_t>(is);
read<uint8_t>(is); // skip unused byte
check_m(m);
check_preamble_ints(preamble_ints, flags_byte);
check_serial_version(serial_version);
check_family_id(family_id);
if (!is.good()) throw std::runtime_error("error reading from std::istream");
const bool is_empty(flags_byte & (1 << flags::IS_EMPTY));
if (is_empty) return kll_sketch(k, comparator, allocator);
uint64_t n;
uint16_t min_k;
uint8_t num_levels;
const bool is_single_item(flags_byte & (1 << flags::IS_SINGLE_ITEM)); // used in serial version 2
if (is_single_item) {
n = 1;
min_k = k;
num_levels = 1;
} else {
n = read<uint64_t>(is);
min_k = read<uint16_t>(is);
num_levels = read<uint8_t>(is);
read<uint8_t>(is); // skip unused byte
}
vector_u32 levels(num_levels + 1, 0, allocator);
const uint32_t capacity(kll_helper::compute_total_capacity(k, m, num_levels));
if (is_single_item) {
levels[0] = capacity - 1;
} else {
// the last integer in levels_ is not serialized because it can be derived
read(is, levels.data(), sizeof(levels[0]) * num_levels);
}
levels[num_levels] = capacity;
optional<T> tmp; // space to deserialize min and max
optional<T> min_item;
optional<T> max_item;
if (!is_single_item) {
sd.deserialize(is, &*tmp, 1);
// serde call did not throw, repackage and cleanup
min_item.emplace(*tmp);
(*tmp).~T();
sd.deserialize(is, &*tmp, 1);
// serde call did not throw, repackage and cleanup
max_item.emplace(*tmp);
(*tmp).~T();
}
A alloc(allocator);
auto items_buffer_deleter = [capacity, &alloc](T* ptr) { alloc.deallocate(ptr, capacity); };
std::unique_ptr<T, decltype(items_buffer_deleter)> items_buffer(alloc.allocate(capacity), items_buffer_deleter);
const auto num_items = levels[num_levels] - levels[0];
sd.deserialize(is, &items_buffer.get()[levels[0]], num_items);
// serde call did not throw, repackage with destrtuctors
std::unique_ptr<T, items_deleter> items(items_buffer.release(), items_deleter(levels[0], capacity, allocator));
const bool is_level_zero_sorted = (flags_byte & (1 << flags::IS_LEVEL_ZERO_SORTED)) > 0;
if (is_single_item) {
min_item.emplace(items.get()[levels[0]]);
max_item.emplace(items.get()[levels[0]]);
}
if (!is.good())
throw std::runtime_error("error reading from std::istream");
return kll_sketch(k, min_k, n, num_levels, std::move(levels), std::move(items), capacity,
std::move(min_item), std::move(max_item), is_level_zero_sorted, comparator);
}