pub const VERSION_FLAG: &str = "--version";
pub const SCHEMA_FLAG: &str = "--schema";
pub const SHEP_PROTOCOL_KEY: &str = "shep-protocol";
pub const SHEP_CHANNEL_KEY: &str = "shep-channel";
pub const DOG_NAME_VAR: &str = "SHEP_DOG_NAME";
pub const SECRET_KEY: &str = "x-shep-secret";
pub const SHEEP_SCHEMA_KEY: &str = "x-shep-sheep";
#[derive(Debug, PartialEq, Eq)]
pub struct DogVersion {
pub version: String,
pub protocol: Option<u32>,
pub channel: bool,
}
#[must_use]
pub fn parse_version_answer(text: &str) -> Option<DogVersion> {
let mut lines = text.lines();
let version = lines.next()?.split_whitespace().next_back()?.to_string();
let mut protocol = None;
let mut channel = false;
for line in lines {
let Some((key, value)) = line.split_once(':') else {
continue;
};
match key.trim() {
SHEP_PROTOCOL_KEY => protocol = value.trim().parse().ok(),
SHEP_CHANNEL_KEY => channel = value.trim() == "true",
_ => {}
}
}
Some(DogVersion {
version,
protocol,
channel,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_output_is_no_answer() {
assert_eq!(parse_version_answer(""), None);
}
#[test]
fn a_bad_protocol_number_reads_as_unknown_not_a_fault() {
assert_eq!(
parse_version_answer("shep-otel 0.1.3\nshep-protocol: two\n"),
Some(DogVersion {
version: "0.1.3".to_string(),
protocol: None,
channel: false,
})
);
}
#[test]
fn a_dog_asks_for_the_channel_with_true_and_nothing_else() {
let asks = |line: &str| {
parse_version_answer(&format!("shep-otel 0.1.3\n{line}\n"))
.unwrap()
.channel
};
assert!(asks("shep-channel: true"));
assert!(
asks("shep-channel:true"),
"the space is optional, as it is for the protocol"
);
assert!(!asks("shep-channel: false"));
assert!(!asks("shep-channel: yes"), "only `true` asks");
assert!(!asks("shep-channel: TRUE"), "the value is case-sensitive");
assert!(!asks("x-shep-channel: true"), "the key is exact");
assert!(!asks("shep-protocol: 11"), "no line is no ask");
}
#[test]
fn a_channel_ask_does_not_need_a_stated_protocol() {
assert_eq!(
parse_version_answer("shep-otel 0.1.3\nshep-channel: true\n"),
Some(DogVersion {
version: "0.1.3".to_string(),
protocol: None,
channel: true,
})
);
}
}