Skip to main content

concinnity_core/resource/
runtime.rs

1//! Payloads a running world bakes for itself at start.
2//!
3//! A geometry producer the build compiled carries a [`PayloadLocator`] into a
4//! blob section. One the world mints at start has no blob behind it, so its
5//! baked bytes live here and the renderer reads them straight out.
6
7use alloc::vec::Vec;
8
9use crate::ecs::asset_id::AssetId;
10
11/// Mesh payloads baked at world start, each under the asset id of the value
12/// that owns it, in the order they were installed.
13///
14/// Their handles sit in the [`MeshBlock::Runtime`](super::MeshBlock::Runtime)
15/// tail of the shared mesh-source space, past every handle the build assigned,
16/// so the position here is the handle's offset into that tail.
17#[derive(Debug, Clone, Default)]
18pub struct RuntimeMeshPayloads(Vec<(AssetId, Vec<u8>)>);
19
20impl RuntimeMeshPayloads {
21    /// Install `payload` as `id`'s geometry, at the next handle in the tail.
22    pub fn push(&mut self, id: AssetId, payload: Vec<u8>) {
23        self.0.push((id, payload));
24    }
25
26    /// The baked payload for one asset, if the world minted its geometry.
27    pub fn get(&self, id: AssetId) -> Option<&[u8]> {
28        self.0
29            .iter()
30            .find(|(owner, _)| *owner == id)
31            .map(|(_, b)| &b[..])
32    }
33
34    /// The payloads in handle order, each with its owner's id.
35    pub fn iter(&self) -> impl Iterator<Item = (AssetId, &[u8])> {
36        self.0.iter().map(|(id, b)| (*id, &b[..]))
37    }
38
39    /// How many were baked at start.
40    pub fn len(&self) -> usize {
41        self.0.len()
42    }
43
44    /// Whether nothing was baked at start.
45    pub fn is_empty(&self) -> bool {
46        self.0.is_empty()
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53    use alloc::vec;
54
55    #[test]
56    fn a_baked_payload_is_found_by_its_owner_id() {
57        let mut payloads = RuntimeMeshPayloads::default();
58        assert!(payloads.is_empty());
59        payloads.push(AssetId(7), vec![1, 2, 3]);
60        assert_eq!(payloads.get(AssetId(7)), Some(&[1u8, 2, 3][..]));
61        assert_eq!(payloads.get(AssetId(8)), None);
62        assert!(!payloads.is_empty());
63        assert_eq!(payloads.len(), 1);
64    }
65
66    #[test]
67    fn payloads_keep_the_order_they_were_installed_in() {
68        let mut payloads = RuntimeMeshPayloads::default();
69        payloads.push(AssetId(9), vec![1]);
70        payloads.push(AssetId(4), vec![2]);
71        let order: Vec<AssetId> = payloads.iter().map(|(id, _)| id).collect();
72        assert_eq!(order, vec![AssetId(9), AssetId(4)]);
73    }
74}