Write type-safe metadata to the archive.
Write type-safe metadata to the archive.User-facing API that abstracts JSON serialization format. Components use SerializationMetadata to build metadata without knowledge of underlying format.
SerializationMetadata meta; meta.set("type", "Linear") .set("version", 1) .set("input_features", 128); archive.writeMetadata("meta.json", meta);
module;
#include <memory>
#include <string>
#include <vector>
#include <stdexcept>
#include <utility>
#include <cstdint>
#include <exception>
#include <format>
{
using json = nlohmann::json;
export class ModelArchive
{
public:
explicit ModelArchive(
const std::string& filepath, std::unique_ptr<ArchiveSerializer> serializer,
OpenMode mode )
{
{
throw std::invalid_argument( "ModelArchive requires a non-null serializer" );
}
{
throw std::runtime_error(
std::format(
"ModelArchive: failed to open '{}' for {}", filepath,
archiveModeToString( mode ) ) );
}
}
{
{
try
{
}
catch ( ... )
{
}
}
}
{
}
{
if ( this != &other )
{
{
try
{
}
catch ( ... )
{
}
}
other.closed_ = true;
}
return *this;
}
{
}
{
}
{
}
{
{
return;
}
try
{
}
catch ( const std::exception& e )
{
throw std::runtime_error(
std::format(
"ModelArchive::close failed for '{}': {}",
filepath_, e.what() ) );
}
}
{
std::string s = scope;
while ( !s.empty() && s.front() == '/' ) s.erase( s.begin() );
while ( !s.empty() && s.back() == '/' ) s.pop_back();
if ( !s.empty() )
{
}
}
{
{
throw std::runtime_error( "ModelArchive::popScope: no scope to pop" );
}
}
class ScopedScope
{
public:
{
}
{
{
try
{
}
catch ( ... )
{
}
}
}
{
other.active_ = false;
}
private:
};
bool hasFile(
const std::string& path )
const
{
}
{
}
{
}
void writeMetadata(
const std::string& path,
const SerializationMetadata& metadata )
{
json j = metadata.toJson();
std::string s = j.dump( 2 );
if ( !
serializer_->addData( full, s.data(), s.size() ) )
{
throw std::runtime_error(
std::format( "ModelArchive::writeMetadata failed for path: {}", full ) );
}
}
SerializationMetadata
readMetadata(
const std::string& path )
const
{
if ( sz == 0 )
{
throw std::runtime_error( "ModelArchive::readMetadata missing file: " + full );
}
std::string s( sz, '\0' );
size_t read =
serializer_->extractData( full, s.data(), sz );
if ( read != sz )
{
throw std::runtime_error( "ModelArchive::readMetadata failed to read entire file: " + full );
}
try
{
json j = json::parse( s );
}
catch ( const std::exception& e )
{
throw std::runtime_error( std::string( "ModelArchive::readMetadata parse error: " ) + e.what() );
}
}
void writeBlob(
const std::string& path,
const void* data,
size_t size )
{
if ( !data && size > 0 )
{
throw std::invalid_argument( "ModelArchive::writeBlob: null data with non-zero size" );
}
{
throw std::runtime_error(
std::format( "ModelArchive::writeBlob failed for path: {}", full ) );
}
}
std::vector<uint8_t>
readBlob(
const std::string& path )
const
{
{
throw std::runtime_error(
std::format( "ModelArchive::readBlob: file not found: {}", full ) );
}
if ( sz == 0 )
{
return {};
}
std::vector<uint8_t> buf( sz );
size_t read =
serializer_->extractData( full, buf.data(), sz );
if ( read != sz )
{
throw std::runtime_error(
std::format( "ModelArchive::readBlob: incomplete read from {}", full ) );
}
return buf;
}
size_t readBlobInto(
const std::string& path,
void* buffer,
size_t buffer_size )
const
{
{
throw std::runtime_error(
std::format( "ModelArchive::readBlobInto: file not found: {}", full ) );
}
if ( file_size > buffer_size )
{
throw std::runtime_error(
std::format( "ModelArchive::readBlobInto: buffer too small ({} < {})",
buffer_size, file_size ) );
}
size_t read =
serializer_->extractData( full, buffer, file_size );
if ( read != file_size )
{
throw std::runtime_error(
std::format( "ModelArchive::readBlobInto: incomplete read from {}", full ) );
}
return read;
}
void addMetadata(
const std::string& key,
const std::string& value )
{
}
std::string
getMetadata(
const std::string& key )
const
{
}
private:
static inline const std::vector<std::string>
kAbsoluteRoots = {
"network/",
"components/",
"modules/" };
{
std::string p;
{
if ( i ) p.push_back( '/' );
}
if ( !p.empty() && p.back() != '/' ) p.push_back( '/' );
return p;
}
{
if ( path.empty() ) return false;
if ( path.front() == '/' ) return true;
{
if ( path.rfind( root, 0 ) == 0 ) return true;
}
return false;
}
std::string
scopedPath(
const std::string& path )
const
{
{
return path;
}
}
{
{
throw std::runtime_error(
std::format( "ModelArchive::{}: operation requires {} mode, but archive is in {} mode",
}
}
{
{
throw std::runtime_error(
std::format( "ModelArchive::{}: archive is closed", op ) );
}
}
};
}
bool active_
Definition ModelArchive.ixx:225
ModelArchive & archive_
Definition ModelArchive.ixx:224
~ScopedScope()
Definition ModelArchive.ixx:200
ScopedScope & operator=(const ScopedScope &)=delete
ScopedScope(ModelArchive &archive, const std::string &scope)
Definition ModelArchive.ixx:194
void requireMode(OpenMode expected, const char *op) const
Definition ModelArchive.ixx:523
void addMetadata(const std::string &key, const std::string &value)
Add simple metadata key-value pair.
Definition ModelArchive.ixx:459
std::string filepath_
Definition ModelArchive.ixx:477
std::vector< std::string > scope_stack_
Definition ModelArchive.ixx:480
bool hasFile(const std::string &path) const
Definition ModelArchive.ixx:232
SerializationMetadata readMetadata(const std::string &path) const
Definition ModelArchive.ixx:310
void popScope()
Definition ModelArchive.ixx:182
ModelArchive & operator=(const ModelArchive &)=delete
OpenMode mode_
Definition ModelArchive.ixx:478
ModelArchive(const std::string &filepath, std::unique_ptr< ArchiveSerializer > serializer, OpenMode mode)
Construct archive with serializer and automatically open for specified mode.
Definition ModelArchive.ixx:62
bool isAbsolutePath(const std::string &path) const noexcept
Definition ModelArchive.ixx:500
size_t readBlobInto(const std::string &path, void *buffer, size_t buffer_size) const
Read binary blob directly into provided buffer.
Definition ModelArchive.ixx:422
bool isClosed() const noexcept
Definition ModelArchive.ixx:139
std::vector< uint8_t > readBlob(const std::string &path) const
Read raw binary blob from archive into returned vector.
Definition ModelArchive.ixx:382
static const std::vector< std::string > kAbsoluteRoots
Definition ModelArchive.ixx:482
~ModelArchive()
Destructor automatically closes the serializer.
Definition ModelArchive.ixx:80
std::unique_ptr< ArchiveSerializer > serializer_
Definition ModelArchive.ixx:476
void writeMetadata(const std::string &path, const SerializationMetadata &metadata)
Definition ModelArchive.ixx:274
std::string getMetadata(const std::string &key) const
Retrieve simple metadata value.
Definition ModelArchive.ixx:470
std::string currentPrefix() const
Definition ModelArchive.ixx:484
std::vector< std::string > listFiles() const
Definition ModelArchive.ixx:244
std::string scopedPath(const std::string &path) const
Definition ModelArchive.ixx:513
void close()
Definition ModelArchive.ixx:144
const std::string & getFilepath() const noexcept
Definition ModelArchive.ixx:134
OpenMode getMode() const noexcept
Definition ModelArchive.ixx:129
void writeBlob(const std::string &path, const void *data, size_t size)
Write raw binary blob to archive.
Definition ModelArchive.ixx:354
size_t getFileSize(const std::string &path) const
Definition ModelArchive.ixx:238
bool closed_
Definition ModelArchive.ixx:479
void requireOpen(const char *op) const
Definition ModelArchive.ixx:533
void pushScope(const std::string &scope)
Definition ModelArchive.ixx:170
Definition ArchiveSerializer.ixx:19
OpenMode
Mode indicating whether the archive is used for reading or writing.
Definition OpenMode.ixx:37
@ Write
Definition OpenMode.ixx:39
@ Read
Definition OpenMode.ixx:38
nlohmann::json json
Definition ModelArchive.ixx:27
constexpr std::string_view archiveModeToString(OpenMode mode)
Convert ArchiveMode to string.
Definition OpenMode.ixx:45