// =====================================================================================================================
//  fennec, a free and open source game engine
//  Copyright © 2025 - 2026  Medusa Slockbower
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================

#ifndef FENNEC_LANG_DETAIL_BITS_H
#define FENNEC_LANG_DETAIL_BITS_H

#include <fennec/lang/types.h>

namespace fennec::detail
{

	// helper for bitwise and for 1 byte
	constexpr size_t _bit_and_8(void* dst, const void* src) {
		*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) & *static_cast<const uint8_t*>(src); return 1;
	}

	// helper for bitwise and 2 bytes at once
	constexpr size_t _bit_and_16(void* dst, const void* src) {
		*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) & *static_cast<const uint16_t*>(src); return 2;
	}

	// helper for bitwise and 4 bytes at once
	constexpr size_t _bit_and_32(void* dst, const void* src) {
		*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) & *static_cast<const uint32_t*>(src); return 4;
	}

	// helper for bitwise and 8 bytes at once
	constexpr size_t _bit_and_64(void* dst, const void* src) {
		*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) & *static_cast<const uint64_t*>(src); return 8;
	}

	// helper for selecting size
	constexpr size_t _bit_and(void* dst, const void* src, size_t n) {
		switch (n) {
			case 0:
				return 0;
			case 1:
				return _bit_and_8(dst, src);
			case 2: case 3:
				return _bit_and_16(dst, src);
			case 4: case 5: case 6: case 7:
				return _bit_and_32(dst, src);
			default:
				return _bit_and_64(dst, src);
		}
	}


	// helper for bitwise or for 1 byte
	constexpr size_t _bit_or_8(void* dst, const void* src) {
		*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) | *static_cast<const uint8_t*>(src); return 1;
	}

	// helper for bitwise or 2 bytes at once
	constexpr size_t _bit_or_16(void* dst, const void* src) {
		*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) | *static_cast<const uint16_t*>(src); return 2;
	}

	// helper for bitwise or 4 bytes at once
	constexpr size_t _bit_or_32(void* dst, const void* src) {
		*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) | *static_cast<const uint32_t*>(src); return 4;
	}

	// helper for bitwise or 8 bytes at once
	constexpr size_t _bit_or_64(void* dst, const void* src) {
		*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) | *static_cast<const uint64_t*>(src); return 8;
	}

	// helper for selecting size
	constexpr size_t _bit_or(void* dst, const void* src, size_t n) {
		switch (n) {
			case 0:
				return 0;
			case 1:
				return _bit_or_8(dst, src);
			case 2: case 3:
				return _bit_or_16(dst, src);
			case 4: case 5: case 6: case 7:
				return _bit_or_32(dst, src);
			default:
				return _bit_or_64(dst, src);
		}
	}


	// helper for bitwise and 1 byte
	constexpr size_t _bit_xor_8(void* dst, const void* src) {
		*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) ^ *static_cast<const uint8_t*>(src); return 1;
	}

	// helper for bitwise xor 2 bytes at once
	constexpr size_t _bit_xor_16(void* dst, const void* src) {
		*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) ^ *static_cast<const uint16_t*>(src); return 2;
	}

	// helper for bitwise xor 4 bytes at once
	constexpr size_t _bit_xor_32(void* dst, const void* src) {
		*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) ^ *static_cast<const uint32_t*>(src); return 4;
	}

	// helper for bitwise xor 8 bytes at once
	constexpr size_t _bit_xor_64(void* dst, const void* src) {
		*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) ^ *static_cast<const uint64_t*>(src); return 8;
	}

	// helper for selecting size
	constexpr size_t _bit_xor(void* dst, const void* src, size_t n) {
		switch (n) {
			case 0:
				return 0;
			case 1:
				return _bit_xor_8(dst, src);
			case 2: case 3:
				return _bit_xor_16(dst, src);
			case 4: case 5: case 6: case 7:
				return _bit_xor_32(dst, src);
			default:
				return _bit_xor_64(dst, src);
		}
	}

}

#endif // FENNEC_LANG_DETAIL_BITS_H
