use crate::ops::security_detection::detector_support::{spans, ByteSpan, DetectionError};
pub const SPEC_TOML: &str = r#"schema_version = 1
id = "security_detection.detect_ipv4"
archetype = "match-bytes-pattern"
display_name = "Detect IPv4"
summary = "Returns offset-length spans for IPv4 addresses with validated octets."
category = "C"
[intrinsic]
wgsl = "security_detection_detect_ipv4"
[signature]
inputs = ["Bytes", "Bytes"]
output = "Bytes"
laws = []
equivalence_classes = ["valid_octets", "octet_overflow", "leading_zero", "t47_cap"]
workgroup_size = [64, 1, 1]
tags = ["security-detection", "ipv4", "ioc", "t47"]
fixtures_dir = "fixtures/"
"#;
pub const REFERENCE_VECTORS_TOML: &str = r#"[[case]]
name = "positive_ipv4"
input = "connect 192.168.1.10:443"
expected_spans = [{ offset = 8, len = 12 }]
[[case]]
name = "negative_octet_overflow"
input = "connect 999.168.1.10"
expected_spans = []
"#;
pub mod lowering {
#[must_use]
pub const fn source() -> &'static str {
r#"@compute @workgroup_size(64)
pub fn detect_ipv4(@builtin(global_invocation_id) gid: vec3<u32>) {
let i = gid.x;
var pos = i;
var parts = 0u;
loop {
let parsed = parse_octet(pos);
if (!parsed.ok || parsed.value > 255u) { return; }
pos = parsed.next;
parts = parts + 1u;
if (parts == 4u) { break; }
if (pos >= input_len || input[pos] != 46u) { return; }
pos = pos + 1u;
}
if (token_boundary(i, pos)) { emit_span(i, pos - i); }
}"#
}
}
pub fn detect_ipv4(input: &[u8]) -> Result<Vec<ByteSpan>, DetectionError> {
spans::ipv4_spans(input)
}
pub mod implementation {
pub use super::detect_ipv4;
pub mod kernel {
pub use super::super::detect_ipv4;
}
pub mod lowering {
pub mod wgsl {
pub use super::super::super::lowering::source;
}
}
}