Livt packages

Livt.Net

Version 1.4.1

Ethernet, IPv4, TCP, UDP, ARP, TFTP, and Telnet networking components for Livt hardware.

Published files (163)

src/packet/PacketRegion.lvt

namespace Livt.Net

/**
 * Bounded, read-only view of a published source; no payload copy.
 * Close this region and all descendants before releasing/reusing its source.
 * The source is a fixed constructor dependency, not a runtime-owned handle.
 */
component PacketRegion<S: IPacketData> : IPacketData
{
	// Borrowed fixed provider; the caller coordinates its publication lifetime.
	source: S

	// Opened region bounds relative to the source, valid only while opened.
	offset: int
	length: int
	opened: bool

	/**
	 * Borrows a fixed source and starts closed; construction performs no source reads.
	 */
	new(source: S)
	{
		this.source = source
		offset = 0
		length = 0
		opened = false
	}

	/**
	 * Opens offset..offset+length within the published source; both are byte counts.
	 * Failure leaves a closed region, except Busy preserves an already open region.
	 * An empty region is valid. The caller retains the source until TryClose.
	 */
	public fn TryOpen(offset: int, length: int) PacketDataResult
	{
		if (opened) {
			return PacketDataResult.Busy
		}

		if (!source.IsReady()) {
			return PacketDataResult.NotReady
		}

		var available = source.GetAvailableLength()

		if (offset < 0 || length < 0 || offset > available) {
			return PacketDataResult.Invalid
		}

		if (length > available - offset) {
			return PacketDataResult.Invalid
		}

		this.offset = offset
		this.length = length
		opened = true
		return PacketDataResult.Success
	}

	/**
	 * Reports whether this region is open and its borrowed source remains ready.
	 */
	override fn IsReady() bool
	{
		if (!opened) {
			return false
		}

		return source.IsReady()
	}

	/**
	 * Returns the opened region length in bytes, or zero while unavailable.
	 */
	override fn GetAvailableLength() int
	{
		if (!this.IsReady()) {
			return 0
		}

		return length
	}

	/**
	 * Reads index in 0..length-1 relative to the opened region. Returns NotReady
	 * when unavailable, Invalid outside the region, or the source result.
	 * The output is data only on Success; keep the source stable throughout the call.
	 */
	override fn TryRead(index: int, value: out byte) PacketDataResult
	{
		value = 0x00

		if (!this.IsReady()) {
			return PacketDataResult.NotReady
		}

		if (index < 0 || index >= length) {
			return PacketDataResult.Invalid
		}

		var readValue: byte = 0x00
		var result = source.TryRead(offset + index, readValue)
		value = readValue
		return result
	}

	/**
	 * Closes the region without releasing its borrowed source. Returns Invalid
	 * if already closed. First close descendants and finish outstanding reads.
	 */
	public fn TryClose() PacketDataResult
	{
		if (!opened) {
			return PacketDataResult.Invalid
		}

		opened = false
		offset = 0
		length = 0
		return PacketDataResult.Success
	}
}