pub struct UnsavedFs {
pub meta: WorldMeta,
pub worlds: HashMap<usize, UnsavedWorld>,
pub prefabs: IndexMap<String, Vec<u8>>,
}Expand description
All of the dynamic data needed to serialize a world
Fields§
§meta: WorldMetaMeta/
worlds: HashMap<usize, UnsavedWorld>World/
prefabs: IndexMap<String, Vec<u8>>Prefabs/ - embedded prefab archives, root-relative path → raw bytes.
Implementations§
Source§impl UnsavedFs
impl UnsavedFs
Sourcepub fn to_pending(self) -> Result<BrPendingFs, BrError>
pub fn to_pending(self) -> Result<BrPendingFs, BrError>
Examples found in repository?
examples/write_fixtures.rs (line 380)
365fn spawner_world() -> World {
366 // Prefab-embedding fixture: an outer prefab whose spawner gate references
367 // an inner single-brick prefab embedded at Prefabs/Uploads/<BLAKE3>.brz.
368 // Single grid, single chunk, one insertion-ordered prefab map entry —
369 // fully deterministic. The inner archive is written raw (no zstd) so the
370 // embedded bytes are cross-language reproducible.
371 let mut inner = World::new();
372 inner.meta.bundle.description = "Inner prefab".to_string();
373 inner.bricks.push(Brick {
374 position: (0, 0, 6).into(),
375 color: (255, 0, 0).into(),
376 ..Default::default()
377 });
378 inner.make_prefab();
379 let inner_bytes = {
380 let pending = inner.to_unsaved().unwrap().to_pending().unwrap();
381 let mut buf = Vec::new();
382 pending
383 .to_brz_data(None)
384 .unwrap()
385 .write(&mut buf, None)
386 .unwrap();
387 buf
388 };
389
390 let mut world = World::new();
391 world.register_all_components();
392 world.meta.bundle.description = "Spawner fixture".to_string();
393 let prefab_path = world.add_prefab(inner_bytes);
394 world.bricks.push(
395 Brick {
396 asset: brdb::BrickType::str("B_1x1_Gate_Exec_PrefabSpawner"),
397 position: (0, 0, 1).into(),
398 ..Default::default()
399 }
400 .with_component(
401 assets::LiteralComponent::new("BrickComponentType_WireGraph_Exec_PrefabSpawner")
402 .with_data([(
403 "Prefab",
404 Box::new(prefab_path) as Box<dyn AsBrdbValue>,
405 )]),
406 ),
407 );
408 world.make_prefab();
409 world
410}
411
412fn hash_archive(path: &PathBuf) -> Result<BTreeMap<String, serde_json::Value>, Box<dyn std::error::Error>> {
413 fn collect(fs: &BrFs, prefix: &str, out: &mut Vec<(String, Option<i64>)>) {
414 match fs {
415 BrFs::Root(children) => for (n, c) in children { collect(c, n, out); },
416 BrFs::Folder(_, children) => for (n, c) in children {
417 collect(c, &format!("{prefix}/{n}"), out);
418 },
419 BrFs::File(f) => out.push((prefix.to_string(), f.content_id)),
420 }
421 }
422 let reader = Brz::open(path)?.into_reader();
423 let reader = &*reader;
424 let mut files = Vec::new();
425 collect(&reader.get_fs()?, "", &mut files);
426 let mut out = BTreeMap::new();
427 for (p, content_id) in files {
428 let content = match content_id {
429 Some(id) => reader.find_blob(id)?.read()?,
430 None => Vec::new(),
431 };
432 out.insert(p, serde_json::json!({
433 "blake3": blake3::hash(&content).to_hex().to_string(),
434 "len": content.len(),
435 }));
436 }
437 Ok(out)
438}
439
440fn main() -> Result<(), Box<dyn std::error::Error>> {
441 let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("fixtures");
442 fs::create_dir_all(dir.join("schemas"))?;
443
444 let mut hashes = BTreeMap::new();
445 for (name, world) in [
446 ("brick", brick_world()),
447 ("features", features_world()),
448 ("chunks", chunks_world()),
449 ("wires", wires_world()),
450 ("components", components_world()),
451 ("entities", entities_world()),
452 ("spawner", spawner_world()),
453 ] {
454 let pending = world.to_unsaved()?.to_pending()?;
455 // raw variant: no zstd anywhere — byte-comparable across languages
456 let raw_path = dir.join(format!("{name}_raw.brz"));
457 let mut f = fs::File::create(&raw_path)?;
458 pending.clone().to_brz_data(None)?.write(&mut f, None)?;
459 // compressed variant: zstd level 14 (matches Brz::save)
460 let mut f = fs::File::create(dir.join(format!("{name}.brz")))?;
461 pending.to_brz_data(Some(14))?.write(&mut f, Some(14))?;
462
463 // .brdb variant: content parity only (the .brdb container is not
464 // byte-deterministic across runs).
465 let db_path = dir.join(format!("{name}.brdb"));
466 let _ = fs::remove_file(&db_path);
467 Brdb::create(&db_path)?.save("Fixture", &world)?;
468
469 hashes.insert(name.to_string(), hash_archive(&raw_path)?);
470 }
471 fs::write(dir.join("hashes.json"), serde_json::to_string_pretty(&hashes)?)?;
472
473 // The nine embedded schemas as binary msgpack (the exact bytes the
474 // writer embeds as *.schema files inside archives).
475 for (name, schema) in [
476 ("BRSavedGlobalDataSoA", schemas::global_data_schema()),
477 ("BRSavedOwnerTableSoA", schemas::owners_schema()),
478 ("BRSavedBrickChunkIndexSoA", schemas::bricks_chunk_index_schema()),
479 ("BRSavedBrickChunkSoA", schemas::bricks_chunks_schema()),
480 ("BRSavedWireChunkSoA", schemas::bricks_wires_schema()),
481 ("BRSavedComponentChunkSoA", schemas::bricks_components_schema_min()),
482 ("BRSavedComponentChunkSoA_max", schemas::bricks_components_schema_max()),
483 ("BRSavedEntityChunkIndexSoA", schemas::entities_chunk_index_schema()),
484 ("BRSavedEntityChunkSoA", schemas::entities_chunks_schema()),
485 ] {
486 fs::write(dir.join(format!("schemas/{name}.bin")), schema.to_bytes()?)?;
487 }
488 eprintln!("fixtures written to {}", dir.display());
489 Ok(())
490}Auto Trait Implementations§
impl !RefUnwindSafe for UnsavedFs
impl !UnwindSafe for UnsavedFs
impl Freeze for UnsavedFs
impl Send for UnsavedFs
impl Sync for UnsavedFs
impl Unpin for UnsavedFs
impl UnsafeUnpin for UnsavedFs
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