from rust

This commit is contained in:
Alexander Zhirov 2025-08-31 16:47:55 +03:00
parent 32203fadc0
commit 1f00cff032
Signed by: alexander
GPG key ID: C8D8BE544A27C511
8 changed files with 598 additions and 323 deletions

108
source/xdiff_mmblocks.d Normal file
View file

@ -0,0 +1,108 @@
module xdiff_mmblocks;
import std.exception : enforce;
import xdiff_init : ensureInit, initMmfile;
import xdiff;
final class MMBlocks
{
private:
mmfile_t _inner;
bool _owned = true; // владеем ли блоками?
enum DEFAULT_BSIZE = 8 * 1024;
// Глубокая копия: читаем все блоки и записываем в dst
static void deepCopyAll(mmfile_t* src, MMBlocks dst)
{
enforce(xdl_seek_mmfile(src, 0) == 0, "seek(0) failed");
long sz = 0;
auto p = xdl_mmfile_first(src, &sz);
while (p !is null && sz > 0)
{
auto wrote = xdl_write_mmfile(dst.mmfilePtr(), p, sz);
enforce(wrote == sz, "write failed during deep copy");
p = xdl_mmfile_next(src, &sz);
}
}
public:
this()
{
_inner = initMmfile(DEFAULT_BSIZE);
}
static MMBlocks fromBytes(const(ubyte)[] data)
{
auto b = new MMBlocks;
if (data.length > 0)
{
auto wrote = xdl_write_mmfile(&b._inner, data.ptr, cast(long)data.length);
enforce(wrote == cast(long)data.length, "xdl_write_mmfile wrote less than requested");
}
return b;
}
~this()
{
if (_owned && _inner.head !is null)
xdl_free_mmfile(&_inner);
// обнулим на всякий случай
_inner.head = null; _inner.tail = null;
_inner.rcur = null; _inner.wcur = null;
_inner.fsize = 0; _inner.bsize = 0;
}
// доступ к внутреннему mmfile_t*
mmfile_t* mmfilePtr() @trusted { return &_inner; }
size_t size() { return cast(size_t)xdl_mmfile_size(&_inner); }
bool isCompact() const { return xdl_mmfile_iscompact(cast(mmfile_t*)&_inner) != 0; }
int writeBuf(const(ubyte)[] buf)
{
auto wrote = xdl_write_mmfile(&_inner, buf.ptr, cast(long)buf.length);
return (wrote == cast(long)buf.length) ? 0 : -1;
}
/// Глубокая копия (новое владение)
MMBlocks clone() const
{
auto dst = new MMBlocks;
// deepCopyAll принимает mmfile_t*, поэтому аккуратно снимаем const с заголовка:
deepCopyAll(cast(mmfile_t*)&_inner, dst);
return dst;
}
/// Компактизация через пересборку содержимого
void toCompact()
{
if (isCompact()) return;
auto dst = new MMBlocks;
deepCopyAll(&_inner, dst);
// перехватываем владение содержимым dst
if (_owned && _inner.head !is null)
xdl_free_mmfile(&_inner);
_inner = *dst.mmfilePtr();
dst._owned = false; // dst больше не владеет
dst._inner.head = null; // чтобы финалайзер dst ничего не освободил
dst._inner.tail = null;
dst._inner.rcur = null;
dst._inner.wcur = null;
dst._inner.fsize = 0;
dst._inner.bsize = 0;
}
/// Снять владение (используется при move в MMFile)
void disarm()
{
_owned = false;
_inner.head = null; _inner.tail = null;
_inner.rcur = null; _inner.wcur = null;
_inner.fsize = 0; _inner.bsize = 0;
}
}