memoryd: entries, and the check on every memory write

Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
2026-09-25 16:41:44 -07:00
committed by kyle
parent 178484a981
commit ad5ce5c6e7
6 changed files with 282 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
//! The entries of `memory.md` and `user.md`: text separated by a line holding only `§` (M5a spec,
//! section 3). A file's size is the characters of its entries joined by separator lines, which
//! is what `render` writes, less the final newline.
use proto::memory::SEPARATOR;
/// The entries of a file's text: split at lines that are only `§` (spaces around it allowed),
/// each trimmed, empty ones left out.
pub fn parse(text: &str) -> Vec<String> {
let mut entries: Vec<String> = Vec::new();
let mut current: Vec<&str> = Vec::new();
for line in text.lines() {
if line.trim() == SEPARATOR {
push(&mut entries, &current);
current.clear();
} else {
current.push(line);
}
}
push(&mut entries, &current);
entries
}
fn push(entries: &mut Vec<String>, lines: &[&str]) {
let joined = lines.join("\n");
let trimmed = joined.trim();
if !trimmed.is_empty() {
entries.push(trimmed.to_string());
}
}
/// The entries joined by `\n§\n`, with a final newline; an empty list is an empty file.
pub fn render(entries: &[String]) -> String {
if entries.is_empty() {
return String::new();
}
let joined = entries.join(&format!("\n{SEPARATOR}\n"));
format!("{joined}\n")
}
/// A file's size in characters, the one its limit is measured against.
pub fn size(entries: &[String]) -> usize {
render(entries).trim_end_matches('\n').chars().count()
}