mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 01:52:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			167 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			167 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <AK/ByteBuffer.h>
 | |
| #include <AK/Debug.h>
 | |
| #include <AK/DeprecatedString.h>
 | |
| #include <AK/Format.h>
 | |
| #include <LibSQL/Forward.h>
 | |
| #include <LibSQL/Heap.h>
 | |
| 
 | |
| namespace SQL {
 | |
| 
 | |
| class Serializer {
 | |
| public:
 | |
|     Serializer() = default;
 | |
| 
 | |
|     Serializer(RefPtr<Heap> heap)
 | |
|         : m_heap(heap)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     void read_storage(Block::Index block_index)
 | |
|     {
 | |
|         m_buffer = m_heap->read_storage(block_index).release_value_but_fixme_should_propagate_errors();
 | |
|         m_current_offset = 0;
 | |
|     }
 | |
| 
 | |
|     void reset()
 | |
|     {
 | |
|         m_buffer.clear();
 | |
|         m_current_offset = 0;
 | |
|     }
 | |
| 
 | |
|     void rewind()
 | |
|     {
 | |
|         m_current_offset = 0;
 | |
|     }
 | |
| 
 | |
|     template<typename T, typename... Args>
 | |
|     T deserialize_block(Block::Index block_index, Args&&... args)
 | |
|     {
 | |
|         read_storage(block_index);
 | |
|         return deserialize<T>(forward<Args>(args)...);
 | |
|     }
 | |
| 
 | |
|     template<typename T>
 | |
|     void deserialize_block_to(Block::Index block_index, T& t)
 | |
|     {
 | |
|         read_storage(block_index);
 | |
|         return deserialize_to<T>(t);
 | |
|     }
 | |
| 
 | |
|     template<typename T>
 | |
|     void deserialize_to(T& t)
 | |
|     {
 | |
|         if constexpr (IsArithmetic<T>)
 | |
|             memcpy(&t, read(sizeof(T)), sizeof(T));
 | |
|         else
 | |
|             t.deserialize(*this);
 | |
|     }
 | |
| 
 | |
|     void deserialize_to(DeprecatedString& text);
 | |
| 
 | |
|     template<typename T, typename... Args>
 | |
|     NonnullOwnPtr<T> make_and_deserialize(Args&&... args)
 | |
|     {
 | |
|         auto ptr = make<T>(forward<Args>(args)...);
 | |
|         ptr->deserialize(*this);
 | |
|         return ptr;
 | |
|     }
 | |
| 
 | |
|     template<typename T, typename... Args>
 | |
|     NonnullRefPtr<T> adopt_and_deserialize(Args&&... args)
 | |
|     {
 | |
|         auto ptr = adopt_ref(*new T(forward<Args>(args)...));
 | |
|         ptr->deserialize(*this);
 | |
|         return ptr;
 | |
|     }
 | |
| 
 | |
|     template<typename T, typename... Args>
 | |
|     T deserialize(Args&&... args)
 | |
|     {
 | |
|         T t(forward<Args>(args)...);
 | |
|         deserialize_to(t);
 | |
|         return t;
 | |
|     }
 | |
| 
 | |
|     template<typename T>
 | |
|     void serialize(T const& t)
 | |
|     {
 | |
|         if constexpr (IsArithmetic<T>)
 | |
|             write((u8 const*)(&t), sizeof(T));
 | |
|         else
 | |
|             t.serialize(*this);
 | |
|     }
 | |
| 
 | |
|     void serialize(DeprecatedString const&);
 | |
| 
 | |
|     template<typename T>
 | |
|     bool serialize_and_write(T const& t)
 | |
|     {
 | |
|         VERIFY(!m_heap.is_null());
 | |
|         reset();
 | |
|         serialize<T>(t);
 | |
|         m_heap->write_storage(t.block_index(), m_buffer).release_value_but_fixme_should_propagate_errors();
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     [[nodiscard]] size_t offset() const { return m_current_offset; }
 | |
|     u32 request_new_block_index()
 | |
|     {
 | |
|         return m_heap->request_new_block_index();
 | |
|     }
 | |
| 
 | |
|     bool has_block(u32 pointer) const
 | |
|     {
 | |
|         return m_heap->has_block(pointer);
 | |
|     }
 | |
| 
 | |
|     Heap& heap()
 | |
|     {
 | |
|         return *m_heap;
 | |
|     }
 | |
| 
 | |
| 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, DeprecatedString const& prefix)
 | |
|     {
 | |
|         StringBuilder builder;
 | |
|         builder.appendff("{0} {1:04x} | ", prefix, sz);
 | |
|         Vector<DeprecatedString> bytes;
 | |
|         for (auto ix = 0u; ix < sz; ++ix)
 | |
|             bytes.append(DeprecatedString::formatted("{0:02x}", *(ptr + ix)));
 | |
|         StringBuilder bytes_builder;
 | |
|         bytes_builder.join(' ', bytes);
 | |
|         builder.append(bytes_builder.to_deprecated_string());
 | |
|         dbgln(builder.to_deprecated_string());
 | |
|     }
 | |
| 
 | |
|     ByteBuffer m_buffer {};
 | |
|     size_t m_current_offset { 0 };
 | |
|     // FIXME: make this a NonnullRefPtr<Heap> so we can get rid of the null checks
 | |
|     RefPtr<Heap> m_heap { nullptr };
 | |
| };
 | |
| 
 | |
| }
 | 
