#pragma once
#include "common/entry_index.h"
#include "root.h"
#include "tvfs_root.h"
#include <memory>
#include <span>
#include <string>
#include <vector>
namespace whiteout::interfaces {
class WorkerPool;
}
namespace whiteout::storages::casc {
using EKeyReader = std::function<std::vector<u8>(std::span<const u8, 16> eKey)>;
class D4Root final : public RootManifest {
public:
static std::unique_ptr<D4Root> create(std::unique_ptr<TvfsRoot> tvfs, const EKeyReader& reader,
interfaces::WorkerPool* pool = nullptr);
std::vector<const RootEntry*> findByPath(const std::string& path) const override;
std::vector<const RootEntry*> findByNormalizedPath(
const std::string& normalizedPath) const override;
bool hasPath(const std::string& normalizedPath) const override;
std::vector<const RootEntry*> findByFileDataId(
u32 fileDataId, FileIdHint hint = FileIdHint::None) const override;
RootFormat format() const override {
return RootFormat::Diablo4;
}
void enumerateUnder(const std::string& normalizedPrefix,
std::function<bool(const RootEntry&)> callback) const override;
protected:
const std::vector<RootEntry>& entries() const override;
std::vector<RootEntry>& mutableEntries() override;
private:
std::unique_ptr<TvfsRoot> m_tvfs;
std::vector<RootEntry> m_entries;
EntryIndex<std::string> m_byPath;
EntryIndex<u32> m_bySnoId;
void buildIndex(interfaces::WorkerPool* pool);
};
}