TITANIUM_FUNCTION(Buffer, copy)
	{
		if (arguments.size() < 2) {
			HAL::detail::ThrowRuntimeError("Titanium::Buffer::copy", "Buffer::copy: Too few argument");
		}

		ENSURE_OBJECT_AT_INDEX(sourceBuffer, 0);
		ENSURE_UINT_AT_INDEX(offset, 1);
		ENSURE_OPTIONAL_UINT_AT_INDEX(sourceOffset, 2, 0);
		ENSURE_OPTIONAL_UINT_AT_INDEX(sourceLength, 3, 0);

		const auto buffer = sourceBuffer.GetPrivate<Buffer>();
		if (buffer) {
			if (sourceLength == 0) {
				sourceLength = static_cast<std::uint32_t>(buffer->get_data().size());
			}
		} else {
			HAL::detail::ThrowRuntimeError("Titanium::Buffer::copy", "Buffer::copy: Unable to get Buffer");
		}

		if (get_length() <= offset || buffer->get_length() < sourceOffset + sourceLength) {
			HAL::detail::ThrowRuntimeError("Titanium::Buffer::insert", "Buffer::insert: Invalid argument");
		}

		return get_context().CreateNumber(copy(buffer, offset, sourceOffset, sourceLength));
	}
	TITANIUM_FUNCTION(Buffer, append)
	{
		if (arguments.size() == 0) {
			HAL::detail::ThrowRuntimeError("Titanium::Buffer::append", "Buffer::append: Too few argument");
		}

		ENSURE_OBJECT_AT_INDEX(sourceBuffer, 0);
		ENSURE_OPTIONAL_UINT_AT_INDEX(sourceOffset, 1, 0);
		ENSURE_OPTIONAL_UINT_AT_INDEX(sourceLength, 2, 0);

		const auto buffer = sourceBuffer.GetPrivate<Buffer>();
		if (buffer) {
			if (sourceLength == 0) {
				sourceLength = static_cast<std::uint32_t>(buffer->get_length());
			}
		} else {
			HAL::detail::ThrowRuntimeError("Titanium::Buffer::append", "Buffer::append: Unable to get Buffer");
		}

		if (buffer->get_length() < sourceOffset + sourceLength) {
			HAL::detail::ThrowRuntimeError("Titanium::Buffer::append", "Buffer::append: Invalid argument");
		}

		return get_context().CreateNumber(append(buffer, sourceOffset, sourceLength));
	}
	TITANIUM_FUNCTION(IOStream, read)
	{
		ENSURE_OBJECT_AT_INDEX(buffer_object, 0);
		ENSURE_OPTIONAL_UINT_AT_INDEX(offset, 1, 0);
		const auto buffer = buffer_object.GetPrivate<Buffer>();
		if (buffer == nullptr) {
			HAL::detail::ThrowRuntimeError("Titanium::IOStream::read", "Titanium::IOStream::read: Invalid arguments");
		}
		ENSURE_OPTIONAL_UINT_AT_INDEX(length, 2, buffer->get_length());
		return get_context().CreateNumber(read(buffer, offset, length));
	}
			TITANIUM_FUNCTION(UDP, start)
			{
				ENSURE_OPTIONAL_UINT_AT_INDEX(port, 0, 0);
				ENSURE_OPTIONAL_STRING_AT_INDEX(host, 1, "");
				start(port, host);
				return get_context().CreateUndefined();
			}
	TITANIUM_FUNCTION(Buffer, fill)
	{
		if (arguments.size() < 1) {
			HAL::detail::ThrowRuntimeError("Titanium::Buffer::fill", "Buffer::fill: Too few argument");
		}

		ENSURE_UINT_AT_INDEX(fillByte, 0);
		ENSURE_OPTIONAL_UINT_AT_INDEX(offset, 1, 0);
		ENSURE_OPTIONAL_UINT_AT_INDEX(length, 2, get_length());

		if (get_length() < offset + length) {
			HAL::detail::ThrowRuntimeError("Titanium::Buffer::fill", "Buffer::fill: Invalid argument");
		}

		fill(fillByte, offset, length);
		return get_context().CreateUndefined();
	}
	TITANIUM_FUNCTION(Buffer, clone)
	{
		ENSURE_OPTIONAL_UINT_AT_INDEX(offset, 0, 0);
		ENSURE_OPTIONAL_UINT_AT_INDEX(length, 1, get_length());

		if (get_length() < offset + length) {
			HAL::detail::ThrowRuntimeError("Titanium::Buffer::clone", "Buffer::clone: Invalid argument");
		}

		const auto buffer = clone(offset, length);
		
		if (buffer) {
			return buffer->get_object();
		} else {
			return get_context().CreateNull();
		}
	}
			TITANIUM_FUNCTION(UDP, sendString)
			{
				ENSURE_OPTIONAL_UINT_AT_INDEX(port, 0, 0);
				ENSURE_OPTIONAL_STRING_AT_INDEX(host, 1, "");
				ENSURE_OPTIONAL_STRING_AT_INDEX(data, 2, "");

				sendString(port, host, data);
				return get_context().CreateUndefined();
			}
			TITANIUM_FUNCTION(UDP, sendBytes)
			{
				ENSURE_OPTIONAL_UINT_AT_INDEX(port, 0, 0);
				ENSURE_OPTIONAL_STRING_AT_INDEX(host, 1, "");
				ENSURE_OPTIONAL_ARRAY_AT_INDEX(js_data, 2);

				std::vector<std::uint8_t> data;
				const auto length = js_data.GetLength();
				for (uint32_t i = 0; i < length; i++) {
					data.push_back(static_cast<std::uint8_t>(static_cast<std::uint32_t>(js_data.GetProperty(i))));
				}

				sendBytes(port, host, data);
				return get_context().CreateUndefined();
			}