terminals_core/substrate/
fold.rs1use serde::{Deserialize, Serialize};
8use super::sematon::Sematon;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct FoldedSematon {
14 pub id: String,
15 pub payload_json: String,
16 pub witness_r: f32,
17 pub witness_entropy: f32,
18 pub witness_converged: bool,
19 pub witness_step: u32,
20 pub address_base: u32,
21 pub address_coeff0: u16,
22 pub address_coeff1: u16,
23 pub entropy: f32,
24 pub density: f32,
25 pub impedance: f32,
26 pub shape_hash: u32,
27 pub constructive: bool,
28 pub source: String,
29}
30
31pub fn fold_sematon<T: Clone + Serialize>(sematon: &Sematon<T>) -> FoldedSematon {
33 FoldedSematon {
34 id: sematon.id.clone(),
35 payload_json: serde_json::to_string(&sematon.payload).unwrap_or_default(),
36 witness_r: sematon.witness.r,
37 witness_entropy: sematon.witness.entropy,
38 witness_converged: sematon.witness.converged,
39 witness_step: sematon.witness.step,
40 address_base: sematon.address.base,
41 address_coeff0: sematon.address.coeff0,
42 address_coeff1: sematon.address.coeff1,
43 entropy: sematon.entropy,
44 density: sematon.density,
45 impedance: sematon.impedance,
46 shape_hash: sematon.shape_hash,
47 constructive: sematon.constructive,
48 source: sematon.source.clone(),
49 }
50}
51
52pub fn unfold_sematon<T: Clone + for<'de> Deserialize<'de>>(
54 folded: &FoldedSematon,
55) -> Result<Sematon<T>, String> {
56 let payload: T = serde_json::from_str(&folded.payload_json)
57 .map_err(|e| format!("Failed to deserialize payload: {}", e))?;
58
59 Ok(Sematon {
60 id: folded.id.clone(),
61 payload,
62 witness: super::witness::ConvergenceWitness {
63 r: folded.witness_r,
64 entropy: folded.witness_entropy,
65 converged: folded.witness_converged,
66 step: folded.witness_step,
67 },
68 address: super::graph::PadicAddr {
69 base: folded.address_base,
70 coeff0: folded.address_coeff0,
71 coeff1: folded.address_coeff1,
72 },
73 entropy: folded.entropy,
74 density: folded.density,
75 impedance: folded.impedance,
76 shape_hash: folded.shape_hash,
77 constructive: folded.constructive,
78 source: folded.source.clone(),
79 })
80}
81
82pub fn fold_to_json<T: Clone + Serialize>(sematon: &Sematon<T>) -> String {
84 let folded = fold_sematon(sematon);
85 serde_json::to_string(&folded).unwrap_or_default()
86}
87
88pub fn unfold_from_json<T: Clone + for<'de> Deserialize<'de>>(
90 json: &str,
91) -> Result<Sematon<T>, String> {
92 let folded: FoldedSematon =
93 serde_json::from_str(json).map_err(|e| format!("Failed to parse FoldedSematon: {}", e))?;
94 unfold_sematon(&folded)
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100 use super::super::witness::ConvergenceWitness;
101 use super::super::graph::PadicAddr;
102
103 #[test]
104 fn test_fold_unfold_roundtrip() {
105 let w = ConvergenceWitness {
106 r: 0.95,
107 entropy: 0.3,
108 converged: true,
109 step: 42,
110 };
111 let original = Sematon::new(
112 vec![1.0f32, 2.0, 3.0],
113 w,
114 PadicAddr { base: 3, coeff0: 1, coeff1: 7 },
115 "test-surface",
116 );
117
118 let folded = fold_sematon(&original);
119 let restored: Sematon<Vec<f32>> = unfold_sematon(&folded).unwrap();
120
121 assert_eq!(restored.id, original.id);
122 assert_eq!(restored.payload, original.payload);
123 assert!((restored.witness.r - original.witness.r).abs() < 1e-6);
124 assert_eq!(restored.witness.converged, original.witness.converged);
125 assert_eq!(restored.address.base, original.address.base);
126 assert_eq!(restored.shape_hash, original.shape_hash);
127 assert_eq!(restored.constructive, original.constructive);
128 }
129
130 #[test]
131 fn test_fold_to_json_roundtrip() {
132 let w = ConvergenceWitness { r: 0.8, entropy: 0.5, converged: false, step: 10 };
133 let original = Sematon::new("hello world".to_string(), w, PadicAddr::default(), "test");
134
135 let json = fold_to_json(&original);
136 let restored: Sematon<String> = unfold_from_json(&json).unwrap();
137
138 assert_eq!(restored.payload, "hello world");
139 assert_eq!(restored.id, original.id);
140 }
141
142 #[test]
143 fn test_unfold_bad_json_errors() {
144 let result: Result<Sematon<u32>, _> = unfold_from_json("not valid json");
145 assert!(result.is_err());
146 }
147}