use crate::PropertyType;
use crate::content::node::NodeState;
use crate::error::Result;
use crate::index::definitions_json_reader::{ParsedNode, ParsedProperty};
use crate::segment::record::RecordIdentifier;
use crate::writer::memory_segments::MemorySegments;
use crate::writer::record_writer::{
ChildNodesToWrite, PropertyToWrite, PropertyValuesToWrite, RecordWriter, SegmentSink,
};
use crate::writer::segment_builder::GarbageCollectionGeneration;
pub(crate) struct MaterializedDefinition {
segments: MemorySegments,
record: RecordIdentifier,
}
impl MaterializedDefinition {
pub(crate) fn node(&self) -> NodeState<'_> {
NodeState::new(&self.segments, self.record)
}
}
pub(crate) fn materialize(parsed: &ParsedNode) -> Result<MaterializedDefinition> {
let mut writer = RecordWriter::new(
MemorySegments::default(),
GarbageCollectionGeneration {
generation: 1,
full_generation: 1,
is_compacted: false,
},
);
let record = write_node(&mut writer, parsed)?;
let segments = writer.finish()?;
Ok(MaterializedDefinition { segments, record })
}
fn write_node<Sink: SegmentSink>(
writer: &mut RecordWriter<Sink>,
parsed: &ParsedNode,
) -> Result<RecordIdentifier> {
let mut children = Vec::new();
for (name, child) in &parsed.children {
let record = write_node(writer, child)?;
children.push((name.clone(), record));
}
let mut properties = Vec::new();
for (name, property) in &parsed.properties {
properties.push(write_property(writer, name, property)?);
}
let children = match children.len() {
0 => ChildNodesToWrite::Zero,
1 => {
let (name, node) = children.remove(0);
ChildNodesToWrite::One { name, node }
}
_ => ChildNodesToWrite::Many(children),
};
writer.write_node(None, &[], &children, &properties)
}
fn write_property<Sink: SegmentSink>(
writer: &mut RecordWriter<Sink>,
name: &str,
property: &ParsedProperty,
) -> Result<PropertyToWrite> {
let mut written = Vec::new();
for value in &property.values {
written.push(if property.property_type == PropertyType::Binary {
writer.write_external_binary_identifier(value)?
} else {
writer.write_string(value)?
});
}
let values = if property.multiple {
PropertyValuesToWrite::Multiple(written)
} else {
PropertyValuesToWrite::Single(written.into_iter().next().ok_or_else(|| {
crate::error::Error::InvalidFormat {
details: format!("{name} is a scalar property with no value"),
}
})?)
};
Ok(PropertyToWrite {
name: name.to_owned(),
property_type: property.property_type,
values,
})
}