/*
 * Copyright 2015 - 2025 gary@drinkingtea.net
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <ox/std/serialize.hpp>
#include <ox/std/string.hpp>
#include <ox/std/typetraits.hpp>

#include "alignmentcatcher.hpp"
#include "sizecatcher.hpp"

namespace ox {

struct NativePlatSpec {
	static constexpr std::size_t RomStart = 1024;
	using PtrType = uintptr_t;
	using size_t = std::size_t;

	template<typename T>
	[[nodiscard]]
	static constexpr std::size_t alignOf(const T &v) noexcept {
		if constexpr(ox::is_integral_v<T>) {
			return alignof(T);
		} else if constexpr(ox::is_pointer_v<T>) {
			const PtrType p = 0;
			return alignOf(p);
		} else {
			AlignmentCatcher<NativePlatSpec> c;
			oxAssert(model(c.interface(), &v), "Could not get alignment for type");
			return c.biggestAlignment;
		}
	}

	[[nodiscard]]
	static constexpr auto correctEndianness(auto v) noexcept {
		return v;
	}
};

template<typename PlatSpec, typename T>
[[nodiscard]]
constexpr std::size_t alignOf(const T &v) noexcept {
	if constexpr(ox::is_integral_v<T>) {
		return alignof(T);
	} else if constexpr(ox::is_pointer_v<T>) {
		typename PlatSpec::PtrType p = 0;
		return PlatSpec::alignOf(p);
	} else {
		AlignmentCatcher<PlatSpec> c;
		oxAssert(model(c.interface(), &v), "Could not get alignment for type");
		return c.biggestAlignment;
	}
}

}
