1use crate::p64_weight::{transcode_safetensor_to_p64, P64TensorIndex, TranscodeReport};
19use crate::render::projection::{project, ProjectionTarget};
20use crate::tensor::buffer_export::{
21 read_tensor_at, tensor_node_count, write_tensor_buffer, TensorBufferHeader,
22};
23use crate::tensor::Tensor10D;
24
25pub const SUBSTRATE_MAGIC: u32 = 0x5342_5551;
27pub const SUBSTRATE_HEADER_BYTES: usize = 40;
29
30#[derive(Debug, Clone, Copy)]
32pub struct SubstrateSections<'a> {
33 pub manifold: &'a [u8],
35 pub weights: &'a [u8],
37}
38
39pub fn compose_substrate(manifold_buf: &[u8], weights_q42: &[u8]) -> Vec<u8> {
41 let manifold_off = SUBSTRATE_HEADER_BYTES;
42 let weights_off = manifold_off + manifold_buf.len();
43 let total = weights_off + weights_q42.len();
44 let mut out = vec![0u8; total];
45 out[0..4].copy_from_slice(&SUBSTRATE_MAGIC.to_le_bytes());
46 out[4..6].copy_from_slice(&1u16.to_le_bytes());
47 out[8..16].copy_from_slice(&(manifold_off as u64).to_le_bytes());
48 out[16..24].copy_from_slice(&(manifold_buf.len() as u64).to_le_bytes());
49 out[24..32].copy_from_slice(&(weights_off as u64).to_le_bytes());
50 out[32..40].copy_from_slice(&(weights_q42.len() as u64).to_le_bytes());
51 out[manifold_off..weights_off].copy_from_slice(manifold_buf);
52 out[weights_off..total].copy_from_slice(weights_q42);
53 out
54}
55
56pub fn read_substrate(buf: &[u8]) -> Result<SubstrateSections<'_>, String> {
58 if buf.len() < SUBSTRATE_HEADER_BYTES {
59 return Err("substrate: too small for header".to_string());
60 }
61 if u32::from_le_bytes(buf[0..4].try_into().unwrap()) != SUBSTRATE_MAGIC {
62 return Err("substrate: bad magic".to_string());
63 }
64 let u64a = |o: usize| u64::from_le_bytes(buf[o..o + 8].try_into().unwrap()) as usize;
65 let (m_off, m_len, w_off, w_len) = (u64a(8), u64a(16), u64a(24), u64a(32));
66 let m_end = m_off
67 .checked_add(m_len)
68 .ok_or("substrate: manifold overflow")?;
69 let w_end = w_off
70 .checked_add(w_len)
71 .ok_or("substrate: weights overflow")?;
72 if m_end > buf.len() || w_end > buf.len() {
73 return Err("substrate: section out of bounds".to_string());
74 }
75 Ok(SubstrateSections {
76 manifold: &buf[m_off..m_end],
77 weights: &buf[w_off..w_end],
78 })
79}
80
81pub fn project_manifold(sections: &SubstrateSections, time: f32) -> Result<Vec<[f32; 3]>, String> {
84 let n = tensor_node_count(sections.manifold).map_err(|e| e.to_string())?;
85 let mut out = Vec::with_capacity(n);
86 for i in 0..n {
87 let t = read_tensor_at(sections.manifold, i).map_err(|e| e.to_string())?;
88 out.push(project(&t, time, ProjectionTarget::Volume3D));
89 }
90 Ok(out)
91}
92
93pub fn load_weights<'a>(sections: &SubstrateSections<'a>) -> Result<P64TensorIndex, String> {
95 P64TensorIndex::from_p64(sections.weights)
96}
97
98pub fn build_model_substrate(
101 geometry: &[Tensor10D],
102 safetensor_src: &[u8],
103) -> Result<(Vec<u8>, TranscodeReport), String> {
104 let mut manifold = vec![0u8; TensorBufferHeader::total_bytes(geometry.len())];
105 write_tensor_buffer(geometry, &mut manifold).map_err(|e| e.to_string())?;
106 let mut weights = Vec::new();
107 let report = transcode_safetensor_to_p64(safetensor_src, 0, &mut weights)?;
108 Ok((compose_substrate(&manifold, &weights), report))
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 fn synth_safetensor(name: &str, nbytes: usize) -> Vec<u8> {
117 let header = serde_json::json!({
118 name: { "dtype": "F16", "shape": [nbytes / 2], "data_offsets": [0, nbytes] }
119 });
120 let hb = serde_json::to_vec(&header).unwrap();
121 let mut out = Vec::new();
122 out.extend_from_slice(&(hb.len() as u64).to_le_bytes());
123 out.extend_from_slice(&hb);
124 out.resize(out.len() + nbytes, 7u8); out
126 }
127
128 #[test]
131 fn renders_a_manifold_that_also_holds_weights() {
132 let geometry = [
134 Tensor10D::new(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
135 Tensor10D::new(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0),
136 Tensor10D::new(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0),
137 ];
138 let model = synth_safetensor("blk.0.weight", 128);
139
140 let (substrate, report) = build_model_substrate(&geometry, &model).unwrap();
142 assert_eq!(report.n_tensors, 1);
143
144 let sections = read_substrate(&substrate).unwrap();
146 assert!(sections.manifold.as_ptr() >= substrate.as_ptr());
147 assert!(sections.weights.as_ptr() > sections.manifold.as_ptr());
148
149 let projected = project_manifold(§ions, 0.0).unwrap();
151 assert_eq!(projected.len(), geometry.len());
152 for (i, p) in projected.iter().enumerate() {
154 let direct = project(&geometry[i], 0.0, ProjectionTarget::Volume3D);
155 assert_eq!(*p, direct);
156 }
157
158 let widx = load_weights(§ions).unwrap();
160 assert_eq!(widx.header.tensor_count, 1);
161 let blob = widx.blob(sections.weights, &widx.entries[0]);
162 assert_eq!(blob.len(), 128);
163 assert!(
164 blob.iter().all(|&b| b == 7u8),
165 "weight bytes survived verbatim"
166 );
167 }
168
169 #[test]
170 fn substrate_round_trips_sections() {
171 let m = vec![1u8, 2, 3, 4];
172 let w = vec![9u8; 10];
173 let s = compose_substrate(&m, &w);
174 let sec = read_substrate(&s).unwrap();
175 assert_eq!(sec.manifold, &m[..]);
176 assert_eq!(sec.weights, &w[..]);
177 }
178}