use super::{ChunkNode, Document, DocumentState, PayloadInput, RawChunkPolicy};
use crate::{
ChunkFlags, ChunkId, ChunkType, EditError, EncodedFrames, Font, Meta, Palette, Scene,
TryEditError,
};
pub struct DocumentChunkMut<'document, 'source> {
document: &'document mut Document<'source>,
index: usize,
}
impl<'document, 'source> DocumentChunkMut<'document, 'source> {
pub(super) fn new(document: &'document mut Document<'source>, index: usize) -> Self {
Self { document, index }
}
pub fn id(&self) -> ChunkId {
self.node().id
}
pub fn chunk_type(&self) -> ChunkType {
self.node().chunk_type
}
pub fn flags(&self) -> ChunkFlags {
self.node().flags
}
pub fn set_type(
&mut self,
chunk_type: ChunkType,
policy: RawChunkPolicy,
) -> Result<(), EditError> {
self.document.set_type_at(self.index, chunk_type, policy)
}
pub fn set_flags(
&mut self,
flags: ChunkFlags,
policy: RawChunkPolicy,
) -> Result<(), EditError> {
self.document.set_flags_at(self.index, flags, policy)
}
pub fn set_raw_policy(&mut self, policy: RawChunkPolicy) -> Result<(), EditError> {
self.document.set_raw_policy_at(self.index, policy)
}
pub fn replace_raw(
&mut self,
payload: PayloadInput<'source>,
policy: RawChunkPolicy,
) -> Result<(), EditError> {
self.document.replace_raw_at(self.index, payload, policy)
}
pub fn replace_image(
&mut self,
image: &(impl crate::image::ImageSource + ?Sized),
) -> Result<(), EditError> {
let id = self.id();
self.document.replace_image(id, image)
}
pub fn replace_encoded_image(
&mut self,
image: &crate::image::EncodedImageAsset<'_>,
) -> Result<(), EditError> {
let id = self.id();
self.document.replace_encoded_image(id, image)
}
pub fn replace_font(&mut self, font: &Font) -> Result<(), EditError> {
let id = self.id();
self.document.replace_font(id, font)
}
pub fn edit_font(&mut self, edit: impl FnOnce(&mut Font)) -> Result<(), EditError> {
let id = self.id();
self.document.edit_font(id, edit)
}
pub fn try_edit_font<E>(
&mut self,
edit: impl FnOnce(&mut Font) -> Result<(), E>,
) -> Result<(), TryEditError<E>> {
let id = self.id();
self.document.try_edit_font(id, edit)
}
pub fn replace_vector(&mut self, scene: &Scene) -> Result<(), EditError> {
let id = self.id();
self.document.replace_vector(id, scene)
}
pub fn edit_vector(&mut self, edit: impl FnOnce(&mut Scene)) -> Result<(), EditError> {
let id = self.id();
self.document.edit_vector(id, edit)
}
pub fn try_edit_vector<E>(
&mut self,
edit: impl FnOnce(&mut Scene) -> Result<(), E>,
) -> Result<(), TryEditError<E>> {
let id = self.id();
self.document.try_edit_vector(id, edit)
}
pub fn replace_meta(&mut self, meta: &Meta) -> Result<(), EditError> {
let id = self.id();
self.document.replace_meta(id, meta)
}
pub fn edit_meta(&mut self, edit: impl FnOnce(&mut Meta)) -> Result<(), EditError> {
let id = self.id();
self.document.edit_meta(id, edit)
}
pub fn try_edit_meta<E>(
&mut self,
edit: impl FnOnce(&mut Meta) -> Result<(), E>,
) -> Result<(), TryEditError<E>> {
let id = self.id();
self.document.try_edit_meta(id, edit)
}
pub fn replace_palette(&mut self, palette: &Palette) -> Result<(), EditError> {
let id = self.id();
self.document.replace_palette(id, palette)
}
pub fn edit_palette(&mut self, edit: impl FnOnce(&mut Palette)) -> Result<(), EditError> {
let id = self.id();
self.document.edit_palette(id, edit)
}
pub fn try_edit_palette<E>(
&mut self,
edit: impl FnOnce(&mut Palette) -> Result<(), E>,
) -> Result<(), TryEditError<E>> {
let id = self.id();
self.document.try_edit_palette(id, edit)
}
pub fn replace_frames(&mut self, frames: EncodedFrames) -> Result<(), EditError> {
let id = self.id();
self.document.replace_frames(id, frames)
}
fn node(&self) -> &ChunkNode<'source> {
let DocumentState::Chunk(chunks) = &self.document.state else {
unreachable!("mutable chunk handles are only created for CHUNK documents");
};
&chunks.chunks[self.index]
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{MetaEntry, MetaValueRef};
#[test]
fn typed_replacement_and_callbacks_stay_scoped_to_the_handle() {
let mut original = Meta::new();
original.push(MetaEntry::text("name", "before")).unwrap();
let mut document = Document::new();
let id = document.push_meta(&original).unwrap();
let mut replacement = Meta::new();
replacement.push(MetaEntry::text("name", "after")).unwrap();
{
let mut chunk = document.get_mut(id).unwrap();
chunk.replace_meta(&replacement).unwrap();
chunk
.edit_meta(|meta| meta.push(MetaEntry::text("kind", "asset")).unwrap())
.unwrap();
assert_eq!(
chunk.try_edit_meta(|_| Err::<(), _>("stop")),
Err(TryEditError::Callback("stop"))
);
}
let view = document.meta(id).unwrap();
assert_eq!(view.len(), 2);
assert_eq!(
view.get_first("name").unwrap().value,
MetaValueRef::Text("after")
);
assert_eq!(
view.get_first("kind").unwrap().value,
MetaValueRef::Text("asset")
);
}
}