Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 13:58:55 +01:00
parent 4af19165ec
commit 68073add76
12458 changed files with 12350765 additions and 2 deletions

View file

@ -0,0 +1,7 @@
#include "indexer/complex/serdes.hpp"
namespace complex
{
// static
ComplexSerdes::Version const ComplexSerdes::kLatestVersion = Version::V0;
} // namespace complex

View file

@ -0,0 +1,134 @@
#pragma once
#include "indexer/complex/serdes_utils.hpp"
#include "indexer/complex/tree_node.hpp"
#include "coding/reader.hpp"
#include "coding/varint.hpp"
#include "coding/writer.hpp"
#include "base/logging.hpp"
#include "base/stl_helpers.hpp"
#include <string>
#include <vector>
namespace complex
{
class ComplexSerdes
{
public:
using Ids = std::vector<uint32_t>;
enum class Version : uint8_t
{
// There aren't optimized serialization and deserialization. It's experimental verison.
// todo(m.andrianov): Explore better ways for serialization and deserialization.
V0,
};
static Version const kLatestVersion;
template <typename Sink>
static void Serialize(Sink & sink, tree_node::Forest<Ids> const & forest)
{
SerializeLatestVersion(sink);
Serialize(sink, kLatestVersion, forest);
}
template <typename Reader>
static void Deserialize(Reader & reader, tree_node::Forest<Ids> & forest)
{
ReaderSource<decltype(reader)> src(reader);
auto const version = DeserializeVersion(src);
Deserialize(src, version, forest);
}
template <typename Sink>
static void Serialize(Sink & sink, Version version, tree_node::Forest<Ids> const & forest)
{
switch (version)
{
case Version::V0: V0::Serialize(sink, forest); break;
default: UNREACHABLE();
}
}
template <typename Src>
static void Deserialize(Src & src, Version version, tree_node::Forest<Ids> & forest)
{
switch (version)
{
case Version::V0: V0::Deserialize(src, forest); break;
default: UNREACHABLE();
}
}
private:
class V0
{
public:
template <typename Sink>
static void Serialize(Sink & sink, tree_node::Forest<Ids> const & forest)
{
forest.ForEachTree([&](auto const & tree) { Serialize(sink, tree); });
}
template <typename Src>
static void Deserialize(Src & src, tree_node::Forest<Ids> & forest)
{
while (src.Size() > 0)
{
tree_node::types::Ptr<Ids> tree;
Deserialize(src, tree);
forest.Append(tree);
}
}
private:
template <typename Sink>
static void Serialize(Sink & sink, tree_node::types::Ptr<Ids> const & tree)
{
tree_node::PreOrderVisit(tree, [&](auto const & node)
{
coding_utils::WriteCollectionPrimitive(sink, node->GetData());
auto const size = base::checked_cast<coding_utils::CollectionSizeType>(node->GetChildren().size());
WriteVarUint(sink, size);
});
}
template <typename Src>
static void Deserialize(Src & src, tree_node::types::Ptr<Ids> & tree)
{
std::function<void(tree_node::types::Ptr<Ids> &)> deserializeTree;
deserializeTree = [&](auto & tree)
{
Ids ids;
coding_utils::ReadCollectionPrimitive(src, std::back_inserter(ids));
tree = tree_node::MakeTreeNode(std::move(ids));
auto const size = ReadVarUint<coding_utils::CollectionSizeType>(src);
tree_node::types::Ptrs<Ids> children(size);
for (auto & n : children)
{
deserializeTree(n);
n->SetParent(tree);
}
tree->SetChildren(std::move(children));
};
deserializeTree(tree);
}
};
template <typename Sink>
static void SerializeLatestVersion(Sink & sink)
{
WriteToSink(sink, base::Underlying(kLatestVersion));
}
template <typename Src>
static Version DeserializeVersion(Src & src)
{
return static_cast<Version>(ReadPrimitiveFromSource<std::underlying_type_t<Version>>(src));
}
};
} // namespace complex

View file

@ -0,0 +1,34 @@
#pragma once
#include "coding/reader.hpp"
#include "coding/varint.hpp"
#include "base/assert.hpp"
#include "base/checked_cast.hpp"
namespace coding_utils
{
// Type of collection size. Used for reading and writing collections.
using CollectionSizeType = uint64_t;
// WriteCollectionPrimitive writes collection. It uses WriteToSink function.
template <typename Sink, typename Cont>
void WriteCollectionPrimitive(Sink & sink, Cont const & container)
{
auto const contSize = base::checked_cast<CollectionSizeType>(container.size());
WriteVarUint(sink, contSize);
for (auto value : container)
WriteToSink(sink, value);
}
// ReadCollectionPrimitive reads collection. It uses ReadPrimitiveFromSource function.
template <typename Source, typename OutIt>
void ReadCollectionPrimitive(Source & src, OutIt it)
{
using ValueType = typename OutIt::container_type::value_type;
auto size = ReadVarUint<CollectionSizeType>(src);
while (size--)
*it++ = ReadPrimitiveFromSource<ValueType>(src);
}
} // namespace coding_utils

View file

@ -0,0 +1,308 @@
#pragma once
#include <algorithm>
#include <limits>
#include <memory>
#include <sstream>
#include <type_traits>
#include <utility>
#include <vector>
#include "base/control_flow.hpp"
#include "base/stl_helpers.hpp"
namespace tree_node
{
template <typename Data>
class TreeNode;
namespace types
{
template <typename Data>
using Ptr = std::shared_ptr<TreeNode<Data>>;
template <typename Data>
using WeakPtr = std::weak_ptr<TreeNode<Data>>;
template <typename Data>
using Ptrs = std::vector<Ptr<Data>>;
} // namespace types
template <typename Data>
class TreeNode
{
public:
using Ptr = types::Ptr<Data>;
using WeakPtr = types::WeakPtr<Data>;
using Ptrs = types::Ptrs<Data>;
explicit TreeNode(Data && data) : m_data(std::forward<Data>(data)) {}
bool HasChildren() const { return !m_children.empty(); }
Ptrs const & GetChildren() const { return m_children; }
void AddChild(Ptr const & child) { m_children.push_back(child); }
void AddChildren(Ptrs && children) { std::move(std::begin(children), std::end(children), std::end(m_children)); }
void SetChildren(Ptrs && children) { m_children = std::move(children); }
void RemoveChildren() { m_children.clear(); }
template <typename Fn>
void RemoveChildrenIf(Fn && fn)
{
base::EraseIf(m_children, std::forward<Fn>(fn));
}
bool HasParent() const { return m_parent.lock() != nullptr; }
Ptr GetParent() const { return m_parent.lock(); }
void SetParent(Ptr const & parent) { m_parent = parent; }
Data & GetData() { return m_data; }
Data const & GetData() const { return m_data; }
private:
Data m_data;
Ptrs m_children;
WeakPtr m_parent;
};
template <typename Data>
decltype(auto) MakeTreeNode(Data && data)
{
return std::make_shared<TreeNode<Data>>(std::forward<Data>(data));
}
template <typename Data>
void Link(types::Ptr<Data> const & node, types::Ptr<Data> const & parent)
{
parent->AddChild(node);
node->SetParent(parent);
}
template <typename Data>
void Unlink(types::Ptr<Data> const & node, types::Ptr<Data> const & parent)
{
parent->RemoveChildrenIf([&](auto const & n) { return n == node; });
node->SetParent(nullptr);
}
template <typename Data>
size_t GetDepth(types::Ptr<Data> node)
{
size_t depth = 0;
while (node)
{
node = node->GetParent();
++depth;
}
return depth;
}
template <typename Data, typename Fn>
void PreOrderVisit(types::Ptr<Data> const & node, Fn && fn)
{
base::ControlFlowWrapper<Fn> wrapper(std::forward<Fn>(fn));
std::function<base::ControlFlow(types::Ptr<Data> const &)> preOrderVisitDetail;
preOrderVisitDetail = [&](auto const & node)
{
if (wrapper(node) == base::ControlFlow::Break)
return base::ControlFlow::Break;
for (auto const & ch : node->GetChildren())
if (preOrderVisitDetail(ch) == base::ControlFlow::Break)
return base::ControlFlow::Break;
return base::ControlFlow::Continue;
};
preOrderVisitDetail(node);
}
template <typename Data, typename Fn>
void PostOrderVisit(types::Ptr<Data> const & node, Fn && fn)
{
base::ControlFlowWrapper<Fn> wrapper(std::forward<Fn>(fn));
std::function<base::ControlFlow(types::Ptr<Data> const &)> postOrderVisitDetail;
postOrderVisitDetail = [&](auto const & node)
{
for (auto const & ch : node->GetChildren())
if (postOrderVisitDetail(ch) == base::ControlFlow::Break)
return base::ControlFlow::Break;
return wrapper(node);
};
postOrderVisitDetail(node);
}
template <typename Data, typename Fn>
void ForEach(types::Ptr<Data> const & node, Fn && fn)
{
PreOrderVisit(node, [&](auto const & node) { fn(node->GetData()); });
}
template <typename Data, typename Fn>
decltype(auto) FindIf(types::Ptr<Data> const & node, Fn && fn)
{
types::Ptr<Data> res = nullptr;
PreOrderVisit(node, [&](auto const & node)
{
if (fn(node->GetData()))
{
res = node;
return base::ControlFlow::Break;
}
return base::ControlFlow::Continue;
});
return res;
}
template <typename Data>
size_t Size(types::Ptr<Data> const & node)
{
size_t size = 0;
PreOrderVisit(node, [&](auto const &) { ++size; });
return size;
}
template <typename Data>
decltype(auto) GetRoot(types::Ptr<Data> node)
{
while (node->HasParent())
node = node->GetParent();
return node;
}
template <typename Data>
decltype(auto) GetPathToRoot(types::Ptr<Data> node)
{
types::Ptrs<Data> path;
while (node)
{
path.emplace_back(node);
node = node->GetParent();
}
return path;
}
template <typename Data, typename Fn>
types::Ptr<typename std::invoke_result<Fn, Data const &>::type> TransformToTree(types::Ptr<Data> const & node, Fn && fn)
{
auto n = MakeTreeNode(fn(node->GetData()));
for (auto const & ch : node->GetChildren())
n->AddChild(TransformToTree(ch, fn));
return n;
}
template <typename Data>
bool IsEqual(types::Ptr<Data> const & lhs, types::Ptr<Data> const & rhs)
{
if (!(lhs->GetData() == rhs->GetData()))
return false;
auto const & lhsCh = lhs->GetChildren();
auto const & rhsCh = rhs->GetChildren();
if (lhsCh.size() != rhsCh.size())
return false;
for (size_t i = 0; i < lhsCh.size(); ++i)
if (!IsEqual(lhsCh[i], rhsCh[i]))
return false;
return true;
}
template <typename Data, typename Fn>
size_t CountIf(types::Ptr<Data> const & node, Fn && fn)
{
size_t count = 0;
PreOrderVisit(node, [&](auto const & node)
{
if (fn(node->GetData()))
++count;
});
return count;
}
template <typename Data>
void Print(types::Ptr<Data> const & node, std::ostream & stream, std::string prefix = "", bool isTail = true)
{
stream << prefix;
if (isTail)
{
stream << "└───";
prefix += " ";
}
else
{
stream << "├───";
prefix += "";
}
auto str = DebugPrint(node->GetData());
std::replace(std::begin(str), std::end(str), '\n', '|');
stream << str << '\n';
auto const & children = node->GetChildren();
size_t size = children.size();
for (size_t i = 0; i < size; ++i)
Print(children[i], stream, prefix, i == size - 1 /* isTail */);
}
template <typename Data>
std::string DebugPrint(types::Ptr<Data> const & node)
{
std::stringstream stream;
Print(node, stream);
return stream.str();
}
template <typename Data>
class Forest
{
public:
bool operator==(Forest<Data> const & other) const
{
auto const size = Size();
if (size != other.Size())
return false;
for (size_t i = 0; i < size; ++i)
if (!IsEqual(m_trees[i], other.m_trees[i]))
return false;
return true;
}
bool operator!=(Forest<Data> const & other) const { return !(*this == other); }
void Append(types::Ptr<Data> const & tree) { m_trees.emplace_back(tree); }
size_t Size() const { return m_trees.size(); }
template <typename Fn>
void ForEachTree(Fn && fn) const
{
base::ControlFlowWrapper<Fn> wrapper(std::forward<Fn>(fn));
for (auto const & tree : m_trees)
if (wrapper(tree) == base::ControlFlow::Break)
return;
}
private:
types::Ptrs<Data> m_trees;
};
template <typename Data, typename Fn>
decltype(auto) FindIf(Forest<Data> const & forest, Fn && fn)
{
types::Ptr<Data> res = nullptr;
forest.ForEachTree([&](auto const & tree)
{
res = FindIf(tree, fn);
return res ? base::ControlFlow::Break : base::ControlFlow::Continue;
});
return res;
}
template <typename Data>
std::string DebugPrint(Forest<Data> const & forest)
{
std::stringstream stream;
forest.ForEachTree([&](auto const & tree) { stream << DebugPrint(tree) << '\n'; });
return stream.str();
}
} // namespace tree_node