use std::borrow::Cow;
use crate::protocol::ProtocolNode;
use anyhow::anyhow;
use wacore_binary::{NodeContentRef, NodeRef};
pub(crate) fn required_child<'a>(
node: &'a NodeRef<'_>,
tag: &str,
) -> Result<&'a NodeRef<'a>, anyhow::Error> {
node.get_optional_child(tag)
.ok_or_else(|| anyhow!("<{tag}> child not found"))
}
pub(crate) fn optional_child<'a>(node: &'a NodeRef<'_>, tag: &str) -> Option<&'a NodeRef<'a>> {
node.get_optional_child(tag)
}
pub(crate) fn required_attr(node: &NodeRef<'_>, key: &str) -> Result<String, anyhow::Error> {
node.get_attr(key)
.map(|v| v.to_string())
.ok_or_else(|| anyhow!("missing required attribute {key}"))
}
pub(crate) fn optional_attr<'a>(node: &'a NodeRef<'_>, key: &str) -> Option<Cow<'a, str>> {
node.attrs().optional_string(key)
}
pub(crate) fn collect_children<T: ProtocolNode>(
node: &NodeRef<'_>,
tag: &str,
) -> Result<Vec<T>, anyhow::Error> {
node.get_children_by_tag(tag)
.map(|child| T::try_from_node_ref(child))
.collect()
}
pub(crate) fn extract_content_bytes(node: Option<&NodeRef<'_>>) -> Vec<u8> {
node.and_then(|n| match n.content.as_ref() {
Some(NodeContentRef::Bytes(b)) => Some(b.to_vec()),
_ => None,
})
.unwrap_or_default()
}
pub(crate) fn extract_content_uint(node: Option<&NodeRef<'_>>) -> u32 {
node.and_then(|n| match n.content.as_ref() {
Some(NodeContentRef::Bytes(b)) => {
let mut buf = [0u8; 4];
let len = b.len().min(4);
buf[4 - len..].copy_from_slice(&b[..len]);
Some(u32::from_be_bytes(buf))
}
_ => None,
})
.unwrap_or(0)
}