kubectl-style plaintext rendering.
(root: &str, rest: &[&str], rs: &RootSchema, obj: &SchemaObject)
| 259 | |
| 260 | /// kubectl-style plaintext rendering. |
| 261 | fn render_plaintext(root: &str, rest: &[&str], rs: &RootSchema, obj: &SchemaObject) -> String { |
| 262 | let mut out = String::new(); |
| 263 | let full_path = if rest.is_empty() { |
| 264 | root.to_string() |
| 265 | } else { |
| 266 | format!("{}.{}", root, rest.join(".")) |
| 267 | }; |
| 268 | out.push_str(&format!("KIND: {}\n", root)); |
| 269 | out.push_str(&format!("FIELD PATH: {}\n", full_path)); |
| 270 | if let Some(ty) = describe_type(obj) { |
| 271 | out.push_str(&format!("TYPE: {}\n", ty)); |
| 272 | } |
| 273 | out.push('\n'); |
| 274 | |
| 275 | let desc = obj |
| 276 | .metadata |
| 277 | .as_ref() |
| 278 | .and_then(|m| m.description.as_deref()) |
| 279 | .unwrap_or("(no description)"); |
| 280 | out.push_str("DESCRIPTION:\n"); |
| 281 | for line in wrap(desc, 78) { |
| 282 | out.push_str(&format!(" {}\n", line)); |
| 283 | } |
| 284 | out.push('\n'); |
| 285 | |
| 286 | // For container types (arrays, maps), transparently unwrap to the element |
| 287 | // type and render its fields/variants. So `reply.evidence` (array of |
| 288 | // Evidence) renders the Evidence variants; `state.steps` |
| 289 | // (map<string, StepState>) renders the StepState fields. |
| 290 | let target = unwrap_container(rs, obj); |
| 291 | |
| 292 | // Fields (if it's an object). |
| 293 | if let Some(props) = target.object.as_ref() { |
| 294 | if !props.properties.is_empty() { |
| 295 | out.push_str("FIELDS:\n"); |
| 296 | let required: std::collections::HashSet<&String> = props.required.iter().collect(); |
| 297 | for (name, schema) in &props.properties { |
| 298 | if let Schema::Object(po) = schema { |
| 299 | let resolved = resolve(rs, po); |
| 300 | // Prefer the field's own type label (may carry the ref name |
| 301 | // via allOf/anyOf wrapping); fall back to the resolved type. |
| 302 | let ty = describe_type(po) |
| 303 | .or_else(|| describe_type(resolved)) |
| 304 | .unwrap_or_else(|| "<unknown>".into()); |
| 305 | let req_mark = if required.contains(name) { " (required)" } else { "" }; |
| 306 | out.push_str(&format!(" {} <{}>{}\n", name, ty, req_mark)); |
| 307 | let pdesc = po |
| 308 | .metadata |
| 309 | .as_ref() |
| 310 | .and_then(|m| m.description.as_deref()) |
| 311 | .or_else(|| resolved.metadata.as_ref().and_then(|m| m.description.as_deref())) |
| 312 | .unwrap_or(""); |
| 313 | if !pdesc.is_empty() { |
| 314 | for line in wrap(pdesc, 76) { |
| 315 | out.push_str(&format!(" {}\n", line)); |
| 316 | } |
| 317 | } |
| 318 | out.push('\n'); |
no test coverage detected
searching dependent graphs…