Deserialize a universe from bytes (iterative to avoid stack overflow).
(buf: &mut &[u8])
| 100 | |
| 101 | /// Deserialize a universe from bytes (iterative to avoid stack overflow). |
| 102 | pub fn get_univ(buf: &mut &[u8]) -> Result<Arc<Univ>, String> { |
| 103 | let mut work: Vec<GetUnivFrame> = vec![GetUnivFrame::Parse]; |
| 104 | let mut results: Vec<Arc<Univ>> = Vec::new(); |
| 105 | |
| 106 | while let Some(frame) = work.pop() { |
| 107 | match frame { |
| 108 | GetUnivFrame::Parse => { |
| 109 | let tag = Tag2::get(buf)?; |
| 110 | match tag.flag { |
| 111 | Univ::FLAG_ZERO_SUCC => { |
| 112 | if tag.size == 0 { |
| 113 | results.push(Univ::zero()); |
| 114 | } else { |
| 115 | // Parse inner, then wrap in Succs |
| 116 | work.push(GetUnivFrame::WrapSuccs(tag.size)); |
| 117 | work.push(GetUnivFrame::Parse); |
| 118 | } |
| 119 | }, |
| 120 | Univ::FLAG_MAX => { |
| 121 | // Parse a, parse b, then build Max(a, b) |
| 122 | work.push(GetUnivFrame::BuildMax); |
| 123 | work.push(GetUnivFrame::Parse); // b |
| 124 | work.push(GetUnivFrame::Parse); // a |
| 125 | }, |
| 126 | Univ::FLAG_IMAX => { |
| 127 | // Parse a, parse b, then build IMax(a, b) |
| 128 | work.push(GetUnivFrame::BuildIMax); |
| 129 | work.push(GetUnivFrame::Parse); // b |
| 130 | work.push(GetUnivFrame::Parse); // a |
| 131 | }, |
| 132 | Univ::FLAG_VAR => { |
| 133 | results.push(Univ::var(tag.size)); |
| 134 | }, |
| 135 | f => return Err(format!("get_univ: invalid flag {f}")), |
| 136 | } |
| 137 | }, |
| 138 | GetUnivFrame::WrapSuccs(count) => { |
| 139 | let mut result = |
| 140 | results.pop().ok_or("get_univ: missing result for WrapSuccs")?; |
| 141 | for _ in 0..count { |
| 142 | result = Univ::succ(result); |
| 143 | } |
| 144 | results.push(result); |
| 145 | }, |
| 146 | GetUnivFrame::BuildMax => { |
| 147 | let b = results.pop().ok_or("get_univ: missing b for Max")?; |
| 148 | let a = results.pop().ok_or("get_univ: missing a for Max")?; |
| 149 | results.push(Univ::max(a, b)); |
| 150 | }, |
| 151 | GetUnivFrame::BuildIMax => { |
| 152 | let b = results.pop().ok_or("get_univ: missing b for IMax")?; |
| 153 | let a = results.pop().ok_or("get_univ: missing a for IMax")?; |
| 154 | results.push(Univ::imax(a, b)); |
| 155 | }, |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | results.pop().ok_or_else(|| "get_univ: no result".to_string()) |
no test coverage detected