///|
pub(all) struct GetBlock {
option : Byte
suboption : Byte
} derive(Eq, Debug)
///|
pub(all) struct GetRequest {
destination : @frame.MacAddress
source : @frame.MacAddress
xid : Int
blocks : Array[GetBlock]
} derive(Eq)
///|
fn selector_hex_nibble(char : Char) -> Int raise @frame.FrameError {
if char >= '0' && char <= '9' {
char.to_int() - '0'.to_int()
} else if char >= 'a' && char <= 'f' {
10 + char.to_int() - 'a'.to_int()
} else if char >= 'A' && char <= 'F' {
10 + char.to_int() - 'A'.to_int()
} else {
raise @frame.FrameError::InvalidHexText(char.to_string())
}
}
///|
fn parse_selector_hex_byte(text : StringView) -> Byte raise @frame.FrameError {
let trimmed = text.trim()
let body = if trimmed.has_prefix("0x") || trimmed.has_prefix("0X") {
trimmed[2:]
} else {
trimmed
}
guard body.length() > 0 else {
raise @frame.FrameError::InvalidHexText(text.to_owned())
}
let mut value = 0
for char in body {
value = (value << 4) + selector_hex_nibble(char)
}
guard value <= 255 else {
raise @frame.FrameError::InvalidHexText(text.to_owned())
}
value.to_byte()
}
///|
fn make_get_block(option : Byte, suboption : Byte) -> GetBlock {
GetBlock::{ option, suboption }
}
///|
fn named_get_block(selector : String) -> GetBlock? {
match selector {
"all" => Some(make_get_block(dcp_option_all, dcp_suboption_all))
"vendor" | "device-vendor" | "device_vendor" =>
Some(make_get_block(dcp_option_device, dcp_suboption_device_vendor))
"name" | "station-name" | "station_name" | "name-of-station" =>
Some(make_get_block(dcp_option_device, dcp_suboption_name_of_station))
"identity" | "device-id" | "device_id" | "id" =>
Some(make_get_block(dcp_option_device, dcp_suboption_device_id))
"role" | "device-role" | "device_role" =>
Some(make_get_block(dcp_option_device, dcp_suboption_device_role))
"options" | "device-options" | "device_options" =>
Some(make_get_block(dcp_option_device, dcp_suboption_device_options))
"alias" | "alias-name" | "alias_name" =>
Some(make_get_block(dcp_option_device, dcp_suboption_device_alias))
"instance" | "device-instance" | "device_instance" =>
Some(make_get_block(dcp_option_device, dcp_suboption_device_instance))
"oem" | "oem-id" | "oem_device_id" | "oem-device-id" =>
Some(make_get_block(dcp_option_device, dcp_suboption_device_oem_id))
"ip" | "ip-parameter" | "ip_parameter" =>
Some(make_get_block(dcp_option_ip, dcp_suboption_ip_parameter))
"mac" | "mac-address" | "mac_address" =>
Some(make_get_block(dcp_option_ip, dcp_suboption_mac_address))
"full-ip" | "full-ip-suite" | "full_ip_suite" =>
Some(make_get_block(dcp_option_ip, dcp_suboption_full_ip_suite))
"initiative" | "device-initiative" | "device_initiative" =>
Some(
make_get_block(dcp_option_initiative, dcp_suboption_device_initiative),
)
_ => None
}
}
///|
pub fn parse_get_block_selector(
selector : StringView,
) -> GetBlock raise @frame.FrameError {
let trimmed = selector.trim().to_owned()
guard trimmed != "" else {
raise @frame.FrameError::InvalidHexText(selector.to_owned())
}
match named_get_block(trimmed) {
Some(block) => block
None => {
let parts = trimmed.split(":").to_array()
guard parts.length() == 2 else {
raise @frame.FrameError::InvalidHexText(trimmed)
}
make_get_block(
parse_selector_hex_byte(parts[0][:]),
parse_selector_hex_byte(parts[1][:]),
)
}
}
}
///|
pub fn parse_get_request_blocks(
selector_text : StringView,
) -> Array[GetBlock] raise @frame.FrameError {
let blocks : Array[GetBlock] = []
for selector in selector_text.split(",") {
let trimmed = selector.trim().to_owned()
if trimmed != "" {
blocks.push(parse_get_block_selector(trimmed[:]))
}
}
if blocks.is_empty() {
[make_get_block(dcp_option_all, dcp_suboption_all)]
} else {
blocks
}
}
///|
pub fn encode_get_request(request : GetRequest) -> Bytes {
let block_bytes : Array[Byte] = []
for block in request.blocks {
block_bytes.push(block.option)
block_bytes.push(block.suboption)
}
encode_dcp_ethernet_frame(
request.destination,
request.source,
frame_id_get_set,
dcp_service_id_get,
dcp_service_type_request,
request.xid,
0,
Bytes::from_array(block_bytes),
)
}