pub struct OperationLog { /* private fields */ }Expand description
Bounded in-memory operation log providing explicit undo and redo.
Implementations§
Source§impl OperationLog
impl OperationLog
Sourcepub const DEFAULT_MAX_BYTES: usize
pub const DEFAULT_MAX_BYTES: usize
Default aggregate serialized snapshot budget for undo and redo.
Sourcepub fn new(max_entries: usize) -> Result<Self>
pub fn new(max_entries: usize) -> Result<Self>
Creates a log with a non-zero entry bound and default byte budget.
Sourcepub fn new_bounded(max_entries: usize, max_bytes: usize) -> Result<Self>
pub fn new_bounded(max_entries: usize, max_bytes: usize) -> Result<Self>
Creates a log bounded by both entries and aggregate snapshot bytes.
Examples found in repository?
examples/intermediate.rs (line 29)
23fn main() -> Result<(), Box<dyn std::error::Error>> {
24 let limits = ResourceLimits::default();
25 let compiler = Compiler::builder().limits(limits.clone()).build()?;
26 let template = compiler.compile_template_yaml(include_bytes!("intermediate.yml"))?;
27 let data: DataValue = serde_json::from_slice(include_bytes!("intermediate-data.json"))?;
28 let mut document = compiler.bind(&template, &data, &[])?;
29 let mut log = OperationLog::new_bounded(8, 8 * 1024 * 1024)?;
30 let patch = Patch {
31 sequence: 1,
32 operations: vec![PatchOperation::Move {
33 id: ElementId::new("review-marker")?,
34 x: "185mm".parse()?,
35 y: "112mm".parse()?,
36 }],
37 };
38 log.apply(&mut document, &patch, limits.max_patch_operations)?;
39 let fonts = example_fonts()?;
40 let fingerprint = DocumentFingerprint::compute_with_patches(
41 &template,
42 &data,
43 std::slice::from_ref(&patch),
44 None,
45 &fonts,
46 &limits,
47 )?;
48 let engine = LayoutEngine::new(&limits, &fonts, LayoutOptions::default())?;
49 let mut cache = SceneCache::with_byte_capacity(8, 64 * 1024 * 1024)?;
50 let scene = engine.resolve_cached(&document, fingerprint, &mut cache)?;
51 let cached = engine.resolve_cached(&document, fingerprint, &mut cache)?;
52 if !Arc::ptr_eq(&scene, &cached) || scene.pages.len() != 2 {
53 return Err(std::io::Error::other("expected one cached two-page scene").into());
54 }
55
56 let pdf_request = ExportRequest {
57 format: ExportFormat::Pdf,
58 pdf_mode: PdfMode::Editable,
59 ..ExportRequest::default()
60 };
61 let context = ExportContext {
62 limits: &limits,
63 fonts: &fonts,
64 assets: None,
65 };
66 let report = preflight(
67 &scene,
68 &pdf_request,
69 &context,
70 &PreflightOptions {
71 strict: true,
72 ..PreflightOptions::default()
73 },
74 &OperationControl::default(),
75 )?;
76 report.enforce(true)?;
77 let (pdf, pdf_outcome) = export_bytes(&scene, &pdf_request, &context)?;
78 let (html, html_outcome) = export_bytes(
79 &scene,
80 &ExportRequest {
81 format: ExportFormat::Html,
82 html_mode: HtmlMode::Fixed,
83 ..ExportRequest::default()
84 },
85 &context,
86 )?;
87 let (page_one_svg, page_one_outcome) = export_svg_page(&scene, 0, &context)?;
88 let (page_two_svg, page_two_outcome) = export_svg_page(&scene, 1, &context)?;
89
90 let pdf_path = output_path("intermediate.pdf")?;
91 let html_path = output_path("intermediate.html")?;
92 let page_one_path = output_path("intermediate-page-1.svg")?;
93 let page_two_path = output_path("intermediate-page-2.svg")?;
94 let report_path = output_path("intermediate-preflight.json")?;
95 std::fs::write(&pdf_path, pdf)?;
96 std::fs::write(&html_path, html)?;
97 std::fs::write(&page_one_path, page_one_svg)?;
98 std::fs::write(&page_two_path, page_two_svg)?;
99 std::fs::write(&report_path, serde_json::to_vec_pretty(&report)?)?;
100 let inspector = SceneInspector::new(&scene);
101 println!(
102 "pages={} roles={:?}/{:?} undo={} pdf_bytes={} html_bytes={} svg_bytes={}/{}\npdf={}\nhtml={}\npage_1={}\npage_2={}\npreflight={}",
103 scene.pages.len(),
104 inspector.inspect_page(0)?.role,
105 inspector.inspect_page(1)?.role,
106 log.undo_len(),
107 pdf_outcome.bytes_written,
108 html_outcome.bytes_written,
109 page_one_outcome.bytes_written,
110 page_two_outcome.bytes_written,
111 pdf_path.display(),
112 html_path.display(),
113 page_one_path.display(),
114 page_two_path.display(),
115 report_path.display()
116 );
117 Ok(())
118}Sourcepub fn apply(
&mut self,
document: &mut DocumentIr,
patch: &Patch,
max_operations: usize,
) -> Result<()>
pub fn apply( &mut self, document: &mut DocumentIr, patch: &Patch, max_operations: usize, ) -> Result<()>
Applies one atomic patch and records the previous document on success.
Examples found in repository?
examples/intermediate.rs (line 38)
23fn main() -> Result<(), Box<dyn std::error::Error>> {
24 let limits = ResourceLimits::default();
25 let compiler = Compiler::builder().limits(limits.clone()).build()?;
26 let template = compiler.compile_template_yaml(include_bytes!("intermediate.yml"))?;
27 let data: DataValue = serde_json::from_slice(include_bytes!("intermediate-data.json"))?;
28 let mut document = compiler.bind(&template, &data, &[])?;
29 let mut log = OperationLog::new_bounded(8, 8 * 1024 * 1024)?;
30 let patch = Patch {
31 sequence: 1,
32 operations: vec![PatchOperation::Move {
33 id: ElementId::new("review-marker")?,
34 x: "185mm".parse()?,
35 y: "112mm".parse()?,
36 }],
37 };
38 log.apply(&mut document, &patch, limits.max_patch_operations)?;
39 let fonts = example_fonts()?;
40 let fingerprint = DocumentFingerprint::compute_with_patches(
41 &template,
42 &data,
43 std::slice::from_ref(&patch),
44 None,
45 &fonts,
46 &limits,
47 )?;
48 let engine = LayoutEngine::new(&limits, &fonts, LayoutOptions::default())?;
49 let mut cache = SceneCache::with_byte_capacity(8, 64 * 1024 * 1024)?;
50 let scene = engine.resolve_cached(&document, fingerprint, &mut cache)?;
51 let cached = engine.resolve_cached(&document, fingerprint, &mut cache)?;
52 if !Arc::ptr_eq(&scene, &cached) || scene.pages.len() != 2 {
53 return Err(std::io::Error::other("expected one cached two-page scene").into());
54 }
55
56 let pdf_request = ExportRequest {
57 format: ExportFormat::Pdf,
58 pdf_mode: PdfMode::Editable,
59 ..ExportRequest::default()
60 };
61 let context = ExportContext {
62 limits: &limits,
63 fonts: &fonts,
64 assets: None,
65 };
66 let report = preflight(
67 &scene,
68 &pdf_request,
69 &context,
70 &PreflightOptions {
71 strict: true,
72 ..PreflightOptions::default()
73 },
74 &OperationControl::default(),
75 )?;
76 report.enforce(true)?;
77 let (pdf, pdf_outcome) = export_bytes(&scene, &pdf_request, &context)?;
78 let (html, html_outcome) = export_bytes(
79 &scene,
80 &ExportRequest {
81 format: ExportFormat::Html,
82 html_mode: HtmlMode::Fixed,
83 ..ExportRequest::default()
84 },
85 &context,
86 )?;
87 let (page_one_svg, page_one_outcome) = export_svg_page(&scene, 0, &context)?;
88 let (page_two_svg, page_two_outcome) = export_svg_page(&scene, 1, &context)?;
89
90 let pdf_path = output_path("intermediate.pdf")?;
91 let html_path = output_path("intermediate.html")?;
92 let page_one_path = output_path("intermediate-page-1.svg")?;
93 let page_two_path = output_path("intermediate-page-2.svg")?;
94 let report_path = output_path("intermediate-preflight.json")?;
95 std::fs::write(&pdf_path, pdf)?;
96 std::fs::write(&html_path, html)?;
97 std::fs::write(&page_one_path, page_one_svg)?;
98 std::fs::write(&page_two_path, page_two_svg)?;
99 std::fs::write(&report_path, serde_json::to_vec_pretty(&report)?)?;
100 let inspector = SceneInspector::new(&scene);
101 println!(
102 "pages={} roles={:?}/{:?} undo={} pdf_bytes={} html_bytes={} svg_bytes={}/{}\npdf={}\nhtml={}\npage_1={}\npage_2={}\npreflight={}",
103 scene.pages.len(),
104 inspector.inspect_page(0)?.role,
105 inspector.inspect_page(1)?.role,
106 log.undo_len(),
107 pdf_outcome.bytes_written,
108 html_outcome.bytes_written,
109 page_one_outcome.bytes_written,
110 page_two_outcome.bytes_written,
111 pdf_path.display(),
112 html_path.display(),
113 page_one_path.display(),
114 page_two_path.display(),
115 report_path.display()
116 );
117 Ok(())
118}Sourcepub fn undo(&mut self, document: &mut DocumentIr) -> Result<()>
pub fn undo(&mut self, document: &mut DocumentIr) -> Result<()>
Restores the previous successful document state.
Sourcepub fn redo(&mut self, document: &mut DocumentIr) -> Result<()>
pub fn redo(&mut self, document: &mut DocumentIr) -> Result<()>
Reapplies the most recently undone document state.
Sourcepub fn undo_len(&self) -> usize
pub fn undo_len(&self) -> usize
Number of available undo entries.
Examples found in repository?
examples/intermediate.rs (line 106)
23fn main() -> Result<(), Box<dyn std::error::Error>> {
24 let limits = ResourceLimits::default();
25 let compiler = Compiler::builder().limits(limits.clone()).build()?;
26 let template = compiler.compile_template_yaml(include_bytes!("intermediate.yml"))?;
27 let data: DataValue = serde_json::from_slice(include_bytes!("intermediate-data.json"))?;
28 let mut document = compiler.bind(&template, &data, &[])?;
29 let mut log = OperationLog::new_bounded(8, 8 * 1024 * 1024)?;
30 let patch = Patch {
31 sequence: 1,
32 operations: vec![PatchOperation::Move {
33 id: ElementId::new("review-marker")?,
34 x: "185mm".parse()?,
35 y: "112mm".parse()?,
36 }],
37 };
38 log.apply(&mut document, &patch, limits.max_patch_operations)?;
39 let fonts = example_fonts()?;
40 let fingerprint = DocumentFingerprint::compute_with_patches(
41 &template,
42 &data,
43 std::slice::from_ref(&patch),
44 None,
45 &fonts,
46 &limits,
47 )?;
48 let engine = LayoutEngine::new(&limits, &fonts, LayoutOptions::default())?;
49 let mut cache = SceneCache::with_byte_capacity(8, 64 * 1024 * 1024)?;
50 let scene = engine.resolve_cached(&document, fingerprint, &mut cache)?;
51 let cached = engine.resolve_cached(&document, fingerprint, &mut cache)?;
52 if !Arc::ptr_eq(&scene, &cached) || scene.pages.len() != 2 {
53 return Err(std::io::Error::other("expected one cached two-page scene").into());
54 }
55
56 let pdf_request = ExportRequest {
57 format: ExportFormat::Pdf,
58 pdf_mode: PdfMode::Editable,
59 ..ExportRequest::default()
60 };
61 let context = ExportContext {
62 limits: &limits,
63 fonts: &fonts,
64 assets: None,
65 };
66 let report = preflight(
67 &scene,
68 &pdf_request,
69 &context,
70 &PreflightOptions {
71 strict: true,
72 ..PreflightOptions::default()
73 },
74 &OperationControl::default(),
75 )?;
76 report.enforce(true)?;
77 let (pdf, pdf_outcome) = export_bytes(&scene, &pdf_request, &context)?;
78 let (html, html_outcome) = export_bytes(
79 &scene,
80 &ExportRequest {
81 format: ExportFormat::Html,
82 html_mode: HtmlMode::Fixed,
83 ..ExportRequest::default()
84 },
85 &context,
86 )?;
87 let (page_one_svg, page_one_outcome) = export_svg_page(&scene, 0, &context)?;
88 let (page_two_svg, page_two_outcome) = export_svg_page(&scene, 1, &context)?;
89
90 let pdf_path = output_path("intermediate.pdf")?;
91 let html_path = output_path("intermediate.html")?;
92 let page_one_path = output_path("intermediate-page-1.svg")?;
93 let page_two_path = output_path("intermediate-page-2.svg")?;
94 let report_path = output_path("intermediate-preflight.json")?;
95 std::fs::write(&pdf_path, pdf)?;
96 std::fs::write(&html_path, html)?;
97 std::fs::write(&page_one_path, page_one_svg)?;
98 std::fs::write(&page_two_path, page_two_svg)?;
99 std::fs::write(&report_path, serde_json::to_vec_pretty(&report)?)?;
100 let inspector = SceneInspector::new(&scene);
101 println!(
102 "pages={} roles={:?}/{:?} undo={} pdf_bytes={} html_bytes={} svg_bytes={}/{}\npdf={}\nhtml={}\npage_1={}\npage_2={}\npreflight={}",
103 scene.pages.len(),
104 inspector.inspect_page(0)?.role,
105 inspector.inspect_page(1)?.role,
106 log.undo_len(),
107 pdf_outcome.bytes_written,
108 html_outcome.bytes_written,
109 page_one_outcome.bytes_written,
110 page_two_outcome.bytes_written,
111 pdf_path.display(),
112 html_path.display(),
113 page_one_path.display(),
114 page_two_path.display(),
115 report_path.display()
116 );
117 Ok(())
118}Sourcepub const fn used_bytes(&self) -> usize
pub const fn used_bytes(&self) -> usize
Aggregate serialized bytes retained by undo and redo snapshots.
Auto Trait Implementations§
impl Freeze for OperationLog
impl RefUnwindSafe for OperationLog
impl Send for OperationLog
impl Sync for OperationLog
impl Unpin for OperationLog
impl UnsafeUnpin for OperationLog
impl UnwindSafe for OperationLog
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<U, T> ToOwnedObj<U> for Twhere
U: FromObjRef<T>,
impl<U, T> ToOwnedObj<U> for Twhere
U: FromObjRef<T>,
Source§fn to_owned_obj(&self, data: FontData<'_>) -> U
fn to_owned_obj(&self, data: FontData<'_>) -> U
Convert this type into
T, using the provided data to resolve any offsets.