#[macro_export]
macro_rules! feed_id {
($hex:expr) => {{
#[allow(
clippy::allow_attributes,
clippy::allow_attributes_without_reason,
clippy::panic,
clippy::arithmetic_side_effects
)]
const fn hex_char_to_byte(c: u8) -> u8 {
match c {
b'0'..=b'9' => c - b'0',
b'a'..=b'f' => c - b'a' + 10,
b'A'..=b'F' => c - b'A' + 10,
_ => panic!("Invalid hex character"),
}
}
#[allow(
clippy::allow_attributes,
clippy::allow_attributes_without_reason,
clippy::panic,
clippy::arithmetic_side_effects
)]
const fn parse_feed_id(hex: &str) -> PythFeedId {
let hex_bytes = hex.as_bytes();
let (start_offset, expected_len) =
if hex_bytes.len() == 66 && hex_bytes[0] == b'0' && hex_bytes[1] == b'x' {
(2, 66)
} else if hex_bytes.len() == 64 {
(0, 64)
} else {
panic!("Feed ID must be 64 hex characters or 66 with 0x prefix")
};
if hex_bytes.len() != expected_len {
panic!("Invalid hex string length");
}
let mut result = [0u8; 32];
let mut i = 0;
while i < 32 {
let high = hex_char_to_byte(hex_bytes[start_offset + i * 2]);
let low = hex_char_to_byte(hex_bytes[start_offset + i * 2 + 1]);
result[i] = (high << 4) | low;
i += 1;
}
result
}
const HEX: &str = $hex;
const RESULT: PythFeedId = parse_feed_id(HEX);
RESULT
}};
}
#[macro_export]
macro_rules! filter_supported_tokens {
($vis:vis $name:ident, $field:ident) => {
#[allow(clippy::allow_attributes, clippy::allow_attributes_without_reason, clippy::arithmetic_side_effects)]
$vis const $name: [Token; {
let mut c = 0usize;
let mut i = 0usize;
while i < SUPPORTED_TOKENS.len() {
if SUPPORTED_TOKENS[i].$field.is_some() { c += 1; }
i += 1;
}
c
}] = {
const N: usize = {
let mut c = 0usize;
let mut i = 0usize;
while i < SUPPORTED_TOKENS.len() {
if SUPPORTED_TOKENS[i].$field.is_some() { c += 1; }
i += 1;
}
c
};
let mut out = [SUPPORTED_TOKENS[0]; N];
let mut j = 0usize;
let mut i = 0usize;
while i < SUPPORTED_TOKENS.len() {
if SUPPORTED_TOKENS[i].$field.is_some() {
out[j] = SUPPORTED_TOKENS[i];
j += 1;
}
i += 1;
}
out
};
};
}