/* * Copyright (c) 2021, Jan de Visser * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include namespace SQL { class Serializer { public: Serializer() = default; Serializer(RefPtr heap) : m_heap(heap) { } void get_block(u32 pointer) { VERIFY(m_heap.ptr() != nullptr); auto buffer_or_error = m_heap->read_block(pointer); if (buffer_or_error.is_error()) VERIFY_NOT_REACHED(); m_buffer = buffer_or_error.value(); m_current_offset = 0; } void reset() { m_buffer.clear(); m_current_offset = 0; } void rewind() { m_current_offset = 0; } template T deserialize_block(u32 pointer, Args&&... args) { get_block(pointer); return deserialize(forward(args)...); } template void deserialize_block_to(u32 pointer, T& t) { get_block(pointer); return deserialize_to(t); } template void deserialize_to(T& t) { if constexpr (IsArithmetic) memcpy(&t, read(sizeof(T)), sizeof(T)); else t.deserialize(*this); } void deserialize_to(String& text); template NonnullOwnPtr make_and_deserialize(Args&&... args) { auto ptr = make(forward(args)...); ptr->deserialize(*this); return ptr; } template NonnullRefPtr adopt_and_deserialize(Args&&... args) { auto ptr = adopt_ref(*new T(forward(args)...)); ptr->deserialize(*this); return ptr; } template T deserialize(Args&&... args) { T t(forward(args)...); deserialize_to(t); return t; } template void serialize(T const& t) { if constexpr (IsArithmetic) write((u8 const*)(&t), sizeof(T)); else t.serialize(*this); } void serialize(String const&); template bool serialize_and_write(T const& t) { VERIFY(m_heap.ptr() != nullptr); reset(); serialize(t); m_heap->add_to_wal(t.pointer(), m_buffer); return true; } [[nodiscard]] size_t offset() const { return m_current_offset; } u32 new_record_pointer() { VERIFY(m_heap.ptr() != nullptr); return m_heap->new_record_pointer(); } bool has_block(u32 pointer) const { VERIFY(m_heap.ptr() != nullptr); return pointer < m_heap->size(); } Heap& heap() { VERIFY(m_heap.ptr() != nullptr); return *(m_heap.ptr()); } private: void write(u8 const* ptr, size_t sz) { if constexpr (SQL_DEBUG) dump(ptr, sz, "(out) =>"); m_buffer.append(ptr, sz); m_current_offset += sz; } u8 const* read(size_t sz) { auto buffer_ptr = m_buffer.offset_pointer(m_current_offset); if constexpr (SQL_DEBUG) dump(buffer_ptr, sz, "<= (in)"); m_current_offset += sz; return buffer_ptr; } static void dump(u8 const* ptr, size_t sz, String const& prefix) { StringBuilder builder; builder.appendff("{0} {1:04x} | ", prefix, sz); Vector bytes; for (auto ix = 0u; ix < sz; ++ix) { bytes.append(String::formatted("{0:02x}", *(ptr + ix))); } StringBuilder bytes_builder; bytes_builder.join(' ', bytes); builder.append(bytes_builder.to_string()); dbgln(builder.to_string()); } ByteBuffer m_buffer {}; size_t m_current_offset { 0 }; RefPtr m_heap { nullptr }; }; }