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/services/ServiceChain.lvt
namespace Livt.Net
/**
* Identifies the selected fixed handler without runtime component references.
*/
enum ServiceSelection
{
None
First
Second
}
/**
* Deterministic priority chain. Only Ignored falls through to the second handler.
* Owns selection metadata; borrows two independent response services. Neither
* child may be driven separately while the chain owns its lifecycle.
*/
component ServiceChain<F: IResponseService, N: IResponseService> : IResponseService
{
// Fixed handlers and current response selection.
first: F
second: N
selection: ServiceSelection
/**
* Binds idle handlers; the caller constructs their request sources and policies.
*/
new(first: F, second: N)
{
this.first = first
this.second = second
}
/**
* Visits handlers in priority order and retains the selected graph until release.
*/
override fn TryHandle() ServiceResult
{
if (this.selection != ServiceSelection.None) {
return ServiceResult.Busy
}
var result = this.first.TryHandle()
if (result == ServiceResult.Prepared) {
this.selection = ServiceSelection.First;
return result
}
if (result != ServiceResult.Ignored) {
return result
}
result = this.second.TryHandle()
if (result == ServiceResult.Prepared) {
this.selection = ServiceSelection.Second
}
return result
}
/**
* Returns the selected handler for application-specific diagnostics.
*/
public fn GetSelection() ServiceSelection
{
return this.selection
}
/**
* Releases only the selected child after the caller has ended response borrows.
*/
override fn TryReleaseResponse() PacketDataResult
{
var result = PacketDataResult.Invalid
if (this.selection == ServiceSelection.First) {
result = this.first.TryReleaseResponse()
}
elif (this.selection == ServiceSelection.Second) {
result = this.second.TryReleaseResponse()
}
if (result == PacketDataResult.Success) {
this.selection = ServiceSelection.None
}
return result
}
/**
* Reports a selected, published response.
*/
override fn IsReady() bool
{
return this.selection != ServiceSelection.None
}
/**
* Returns the selected complete frame length, or zero with no selection.
*/
override fn GetAvailableLength() int
{
if (this.selection == ServiceSelection.First) {
return this.first.GetAvailableLength()
}
if (this.selection == ServiceSelection.Second) {
return this.second.GetAvailableLength()
}
return 0
}
/**
* Delegates bounded reads to the selected graph. No packet bytes are copied here.
*/
override fn TryRead(index: int, value: out byte) PacketDataResult
{
value = 0x00
if (this.selection == ServiceSelection.First) {
return this.first.TryRead(index, value)
}
if (this.selection == ServiceSelection.Second) {
return this.second.TryRead(index, value)
}
return PacketDataResult.NotReady
}
}