use std::collections::HashMap;
pub fn parse_note(bytes: &[u8]) -> (HashMap<String, String>, String) {
let text = String::from_utf8_lossy(bytes);
let text = text.as_ref();
if let Some(idx) = text.find("\n\n") {
let head = &text[..idx];
let body = &text[idx + 2..];
if !head.is_empty() {
let mut headers = HashMap::new();
let mut all_headers = true;
for line in head.lines() {
match line.split_once(':') {
Some((k, v)) if is_header_key(k) => {
headers.insert(k.trim().to_lowercase(), v.trim().to_string());
}
_ => {
all_headers = false;
break;
}
}
}
if all_headers && !headers.is_empty() {
return (headers, body.to_string());
}
}
}
(HashMap::new(), text.to_string())
}
fn is_header_key(k: &str) -> bool {
let k = k.trim();
!k.is_empty()
&& k.chars()
.all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')
}
pub fn note_with_registry(registry: &str, body: &str) -> String {
format!("registry: {}\n\n{}", registry.trim(), body.trim())
}
pub fn registry_for_new_note() -> String {
std::env::var("VWH_REGISTRY_URL")
.unwrap_or_else(|_| crate::inspect::DEFAULT_REGISTRY_URL.to_string())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn freeform_note_is_all_body() {
let (h, b) = parse_note(b"just a plain note\nsecond line");
assert!(h.is_empty());
assert_eq!(b, "just a plain note\nsecond line");
}
#[test]
fn registry_header_is_parsed_and_stripped() {
let note = note_with_registry("https://ex.test/reg", "the body");
let (h, b) = parse_note(note.as_bytes());
assert_eq!(h.get("registry").map(String::as_str), Some("https://ex.test/reg"));
assert_eq!(b, "the body");
}
#[test]
fn colon_body_without_blank_line_is_body() {
let (h, b) = parse_note(b"registry: not actually a header");
assert!(h.is_empty());
assert_eq!(b, "registry: not actually a header");
}
}