1use super::helpers::quote_string;
2use super::NamedShapePathKey;
3use super::Shape;
4use super::ShapeCase;
5use crate::case_enum::Error;
6use std::fmt::{Display, Write as _};
7
8impl Shape {
9 #[must_use]
15 pub fn pretty_print(&self) -> String {
16 self.case.pretty_print()
17 }
18}
19
20impl ShapeCase {
21 #[must_use]
22 #[allow(clippy::too_many_lines)]
23 pub fn pretty_print(&self) -> String {
24 match self {
25 Self::Bool(Some(b)) => b.to_string(),
26 Self::Bool(None) => "Bool".to_string(),
27 Self::String(Some(s)) => quote_string(s.as_str()),
28 Self::String(None) => "String".to_string(),
29 Self::Int(Some(i)) => i.to_string(),
30 Self::Int(None) => "Int".to_string(),
31 Self::Float => "Float".to_string(),
32 Self::Null => "null".to_string(), Self::Unknown => "Unknown".to_string(),
35
36 Self::None => "None".to_string(),
41
42 Self::Array { prefix, tail } => {
43 if prefix.is_empty() {
44 if tail.is_none() {
45 "[]".to_string()
46 } else {
47 format!("List<{}>", tail.pretty_print())
48 }
49 } else {
50 let mut result = "[".to_string();
51 for (i, shape) in prefix.iter().enumerate() {
52 if i > 0 {
53 result.push_str(", ");
54 }
55 result.push_str(&shape.pretty_print());
56 }
57 if !tail.is_none() {
58 let _ = write!(result, ", ...List<{}>", tail.pretty_print());
59 }
60 result.push(']');
61 result
62 }
63 }
64
65 Self::Object { fields, rest } => {
66 if fields.is_empty() && !rest.is_none() {
67 format!("Dict<{}>", rest.pretty_print())
68 } else {
69 let mut result = "{".to_string();
70
71 if !fields.is_empty() {
72 result.push(' ');
73
74 let mut sorted_field_names = fields.keys().collect::<Vec<_>>();
75 sorted_field_names.sort();
76 for (i, field_name) in sorted_field_names.into_iter().enumerate() {
77 if i > 0 {
78 result.push_str(", ");
79 }
80 let _ = write!(
81 result,
82 "{}: {}",
83 field_name,
84 fields[field_name].pretty_print()
85 );
86 }
87 }
88
89 if !rest.is_none() {
90 if !fields.is_empty() {
91 result.push(',');
92 }
93 result.push_str(format!(" ...Dict<{}>", rest.pretty_print()).as_str());
94 }
95
96 if result.starts_with("{ ") {
97 result.push_str(" }");
98 } else {
99 result.push('}');
100 }
101
102 result
103 }
104 }
105
106 Self::One(shapes) => {
107 let mut result = "One<".to_string();
108 for (i, shape) in shapes.iter().enumerate() {
109 if i > 0 {
110 result.push_str(", ");
111 }
112 result.push_str(shape.pretty_print().as_str());
113 }
114 result.push('>');
115
116 if result == "One<>" {
119 "Never".to_string()
120 } else {
121 result
122 }
123 }
124
125 Self::All(shapes) => {
126 let mut result = "All<".to_string();
127 for (i, shape) in shapes.iter().enumerate() {
128 if i > 0 {
129 result.push_str(", ");
130 }
131 result.push_str(shape.pretty_print().as_str());
132 }
133 result.push('>');
134 result
135 }
136
137 Self::Name(name, path) => {
138 let mut dotted_path = name.value.clone();
139 dotted_path.push_str(NamedShapePathKey::path_to_string(path).as_str());
140 dotted_path
141 }
142
143 Self::Error(Error {
144 message, partial, ..
145 }) => {
146 let mut result = format!("Error<{}", quote_string(message.as_str()));
147 if let Some(partial) = partial {
148 let _ = write!(result, ", {}", partial.pretty_print());
149 }
150 result.push('>');
151 result
152 }
153 }
154 }
155}
156
157impl Display for Shape {
158 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159 write!(f, "{}", self.pretty_print())
160 }
161}
162
163impl Display for ShapeCase {
164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165 write!(f, "{}", self.pretty_print())
166 }
167}