/*
 *  BinaryEncoding handler for .Net.  This class implements
 *	a symmetric encoding that will convert string to byte[]
 *  and byte[] to string without any character set
 *  transliteration.
 *
 *  The contents of this file were written by jimb
 *  at connectedsw.com on Dec 9, 2004.  It is placed in
 *  the Public Domain and may be used as you see fit.
 */
 
using System;
using System.Text;

namespace FirebirdSql.Data.Common;

internal class BinaryEncoding : Encoding
{
	public static string BytesToString(byte[] byteArray)
	{
		// This code isn't great because it requires a double copy,
		// but it requires unsafe code to solve the problem efficiently.
		var charArray = new char[byteArray.GetLength(0)];
		Array.Copy(byteArray, charArray, byteArray.Length);

		return new string(charArray);
	}

	static void Validate(object data, int dataLength, int index, int count)
	{
		if (data == null)
		{
			throw new ArgumentNullException();
		}

		if (index < 0 || count < 0 || dataLength - index < count)
		{
			throw new ArgumentOutOfRangeException();
		}
	}

	public override int GetByteCount(char[] chars, int index, int count)
	{
		Validate(chars, chars.Length, index, count);

		return count;
	}

	public override int GetByteCount(string chars)
	{
		return chars.Length;
	}

	public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int index)
	{
		Validate(chars, chars.Length, charIndex, charCount);

		if (index < 0 || index > bytes.Length)
		{
			throw new ArgumentOutOfRangeException();
		}
		if (bytes.Length - index < charCount)
		{
			throw new ArgumentException();
		}

		var charEnd = charIndex + charCount;
		while (charIndex < charEnd)
		{
			bytes[index++] = (byte)chars[charIndex++];
		}

		return charCount;
	}

	public override int GetBytes(string chars, int charIndex, int charCount, byte[] bytes, int index)
	{
		Validate(chars, chars.Length, charIndex, charCount);

		if (index < 0 || index > bytes.Length)
		{
			throw new ArgumentOutOfRangeException();
		}
		if (bytes.Length - index < charCount)
		{
			throw new ArgumentException();
		}

		var charEnd = charIndex + charCount;
		while (charIndex < charEnd)
		{
			bytes[index++] = (byte)chars[charIndex++];
		}

		return charCount;
	}

	public override int GetCharCount(byte[] bytes, int index, int count)
	{
		Validate(bytes, bytes.Length, index, count);

		return (count);
	}

	public override int GetChars(byte[] bytes, int index, int count, char[] chars, int charIndex)
	{
		Validate(bytes, bytes.Length, index, count);

		if (charIndex < 0 || charIndex > chars.Length)
		{
			throw new ArgumentOutOfRangeException();
		}
		if (chars.Length - charIndex < count)
		{
			throw new ArgumentException();
		}

		var byteEnd = index + count;
		while (index < byteEnd)
		{
			chars[charIndex++] = (char)bytes[index++];
		}

		return count;
	}

	public override string GetString(byte[] bytes)
	{
		return BytesToString(bytes);
	}

	public override string GetString(byte[] bytes, int index, int count)
	{
		Validate(bytes, bytes.Length, index, count);

		return BytesToString(bytes);
	}

	public override int GetMaxByteCount(int charCount)
	{
		return charCount;
	}

	public override int GetMaxCharCount(int count)
	{
		return count;
	}
}
