use super::{ArtifactKey, KeySink, schema};
use crate::stage::Stage;
const VALUE_ABSENT: u8 = 0;
const VALUE_PRESENT: u8 = 1;
type Attr<'a> = (&'a str, Option<&'a str>);
#[must_use]
pub fn source_block_key(kind: &str, attrs: &[Attr<'_>], content: &str) -> ArtifactKey {
let mut sink = KeySink::new(Stage::Source, schema::SOURCE_BLOCK, 0);
sink.feed_str(kind);
sink.feed_u32(attrs.len() as u32);
let mut previous: Option<Attr<'_>> = None;
while let Some(next) = attrs
.iter()
.copied()
.filter(|attr| previous.is_none_or(|previous| *attr > previous))
.min()
{
for _ in attrs.iter().filter(|attr| **attr == next) {
feed_attr(&mut sink, next);
}
previous = Some(next);
}
sink.feed_str(content);
sink.finish()
}
fn feed_attr(sink: &mut KeySink, (name, value): Attr<'_>) {
sink.feed_str(name);
match value {
Some(value) => {
sink.feed_tag(VALUE_PRESENT);
sink.feed_str(value);
}
None => sink.feed_tag(VALUE_ABSENT),
}
}