#pragma once
#include "common/entry_index.h"
#include "root.h"
#include <span>
#include <vector>
namespace whiteout::interfaces {
class WorkerPool;
}
namespace whiteout::storages::casc {
struct OwRootFileEntry {
std::string fileId;
std::array<u8, 16> md5{};
u8 chunkId = 0;
u8 priority = 0;
u8 mPriority = 0;
std::string fileName;
std::string installPath;
};
struct CmfHeader {
u32 buildVersion = 0;
i32 dataCount = 0;
i32 entryCount = 0;
u32 magic = 0;
u8 version = 0;
bool encrypted = false;
};
struct CmfHashData {
u64 guid = 0;
u32 size = 0;
u8 unknown = 0;
std::array<u8, 16> contentKey{};
};
class OwRoot final : public RootManifest {
public:
static std::unique_ptr<OwRoot> parse(std::span<const u8> data, CKeyResolver resolver = nullptr,
interfaces::WorkerPool* pool = nullptr);
static std::unique_ptr<OwRoot> fromManifestEntries(std::vector<OwRootFileEntry> manifestEntries,
CKeyResolver resolver = nullptr,
interfaces::WorkerPool* pool = nullptr);
std::vector<const RootEntry*> findByPath(const std::string& path) const override;
std::vector<const RootEntry*> findByFileDataId(
u32 fileDataId, FileIdHint hint = FileIdHint::None) const override;
bool hasFileDataId(u32, FileIdHint = FileIdHint::None) const override {
return false;
}
std::vector<const RootEntry*> findByGuid(u64 guid) const;
RootFormat format() const override {
return RootFormat::Overwatch;
}
const std::vector<OwRootFileEntry>& manifestEntries() const {
return m_manifestEntries;
}
protected:
const std::vector<RootEntry>& entries() const override {
return m_entries;
}
std::vector<RootEntry>& mutableEntries() override {
return m_entries;
}
private:
std::vector<RootEntry> m_entries;
std::vector<OwRootFileEntry> m_manifestEntries;
EntryIndex<u64> m_byGuid;
EntryIndex<std::string> m_byPath;
void buildIndices();
};
}