(v: Val, s: &Spec, ty: u8, heap: &HeapPool)
| 198 | } |
| 199 | |
| 200 | fn format_float(v: Val, s: &Spec, ty: u8, heap: &HeapPool) -> Result<String, &'static str> { |
| 201 | let f = require_float(v, heap)?; |
| 202 | let prec = s.precision.unwrap_or(6); |
| 203 | |
| 204 | /* NaN/inf go through unchanged (emits "nan"/"inf" before padding). */ |
| 205 | if f.is_nan() { |
| 206 | let body = if ty == b'F' { "NAN" } else { "nan" }; |
| 207 | return Ok(pad_string(s, body)); |
| 208 | } |
| 209 | if f.is_infinite() { |
| 210 | let mut out = String::new(); |
| 211 | let sign_ch = sign_char(f.is_sign_negative(), s.sign); |
| 212 | if let Some(c) = sign_ch { out.push(c); } |
| 213 | out.push_str(if ty == b'F' { "INF" } else { "inf" }); |
| 214 | return Ok(pad_aligned(s, &out, sign_ch.map(|_| 1).unwrap_or(0))); |
| 215 | } |
| 216 | |
| 217 | let mag = f.abs(); |
| 218 | let body = match ty { |
| 219 | b'f' | b'F' => fixed(mag, prec), |
| 220 | // e/g delegate to Rust's f64 formatter; round-half-to-even applies only to `f`. |
| 221 | b'e' => format_with_e(mag, prec, false), |
| 222 | b'E' => format_with_e(mag, prec, true), |
| 223 | // `g/G`: pick `e` for very small/large, `f` otherwise. |
| 224 | b'g' | b'G' => { |
| 225 | let upper = ty == b'G'; |
| 226 | let exp = if mag == 0.0 { 0 } else { ffloor(flog10(mag)) as i32 }; |
| 227 | // rule: -4 <= exp < precision uses fixed; else scientific. |
| 228 | let p = prec.max(1); |
| 229 | if exp < -4 || exp >= p as i32 { |
| 230 | format_with_e(mag, p.saturating_sub(1), upper) |
| 231 | } else { |
| 232 | let dec = (p as i32 - 1 - exp).max(0) as usize; |
| 233 | let out = fixed(mag, dec); |
| 234 | if upper { out.to_uppercase() } else { out } |
| 235 | } |
| 236 | } |
| 237 | _ => unreachable!(), |
| 238 | }; |
| 239 | let body = if s.sep != 0 { add_thousands_float(&body, s.sep) } else { body }; |
| 240 | let sign_ch = sign_char(f.is_sign_negative(), s.sign); |
| 241 | let mut left = String::new(); |
| 242 | if let Some(c) = sign_ch { left.push(c); } |
| 243 | left.push_str(&body); |
| 244 | Ok(pad_aligned(s, &left, sign_ch.map(|_| 1).unwrap_or(0))) |
| 245 | } |
| 246 | |
| 247 | fn format_with_e(mag: f64, prec: usize, upper: bool) -> String { |
| 248 | // Rust emits "3.14e0"; expects "e+00", inject the sign and pad exponent to >=2 digits. |
no test coverage detected