authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-07 15:05:55+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-07 20:32:27+02:00
logf8dcd3477541aabf3bfb05a1d2c51fa3797c0b48
tree165303454d6b604f8ede5c6de11a17a893605351
parent4fb9c75fc944bbc3242feff653aacd69e17b75dc

TypedValue.print: detect string literals

Closes #4281 Closes #13785

1 files changed, 42 insertions(+), 8 deletions(-)

src/TypedValue.zig+42-8
...@@ -46,6 +46,7 @@ pub fn enumToInt(tv: TypedValue, buffer: *Value.Payload.U64) Value {...@@ -46,6 +46,7 @@ pub fn enumToInt(tv: TypedValue, buffer: *Value.Payload.U64) Value {
46}46}
4747
48const max_aggregate_items = 100;48const max_aggregate_items = 100;
49const max_string_len = 256;
4950
50const FormatContext = struct {51const FormatContext = struct {
51 tv: TypedValue,52 tv: TypedValue,
...@@ -141,10 +142,12 @@ pub fn print(...@@ -141,10 +142,12 @@ pub fn print(
141 .extern_options_type => return writer.writeAll("std.builtin.ExternOptions"),142 .extern_options_type => return writer.writeAll("std.builtin.ExternOptions"),
142 .type_info_type => return writer.writeAll("std.builtin.Type"),143 .type_info_type => return writer.writeAll("std.builtin.Type"),
143144
144 .empty_struct_value, .aggregate => {145 .empty_struct_value => return writer.writeAll(".{}"),
146 .aggregate => {
145 if (level == 0) {147 if (level == 0) {
146 return writer.writeAll(".{ ... }");148 return writer.writeAll(".{ ... }");
147 }149 }
150 const values = val.castTag(.aggregate).?;
148 if (ty.zigTypeTag() == .Struct) {151 if (ty.zigTypeTag() == .Struct) {
149 try writer.writeAll(".{");152 try writer.writeAll(".{");
150 const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items);153 const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items);
...@@ -159,9 +162,9 @@ pub fn print(...@@ -159,9 +162,9 @@ pub fn print(
159 try print(.{162 try print(.{
160 .ty = ty.structFieldType(i),163 .ty = ty.structFieldType(i),
161 .val = switch (ty.containerLayout()) {164 .val = switch (ty.containerLayout()) {
162 .Packed => val.castTag(.aggregate).?.data[i],165 .Packed => values.data[i],
163 else => ty.structFieldValueComptime(i) orelse b: {166 else => ty.structFieldValueComptime(i) orelse b: {
164 const vals = val.castTag(.aggregate).?.data;167 const vals = values.data;
165 break :b vals[i];168 break :b vals[i];
166 },169 },
167 },170 },
...@@ -172,17 +175,31 @@ pub fn print(...@@ -172,17 +175,31 @@ pub fn print(
172 }175 }
173 return writer.writeAll("}");176 return writer.writeAll("}");
174 } else {177 } else {
175 try writer.writeAll(".{ ");
176 const elem_ty = ty.elemType2();178 const elem_ty = ty.elemType2();
177 const len = ty.arrayLen();179 const len = ty.arrayLen();
178 const max_len = std.math.min(len, max_aggregate_items);
179180
181 if (elem_ty.eql(Type.u8, mod)) str: {
182 const max_len = @intCast(usize, std.math.min(len, max_string_len));
183 var buf: [max_string_len]u8 = undefined;
184
185 var i: u32 = 0;
186 while (i < max_len) : (i += 1) {
187 buf[i] = std.math.cast(u8, values.data[i].toUnsignedInt(target)) orelse break :str;
188 }
189
190 const truncated = if (len > max_string_len) " (truncated)" else "";
191 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
192 }
193
194 try writer.writeAll(".{ ");
195
196 const max_len = std.math.min(len, max_aggregate_items);
180 var i: u32 = 0;197 var i: u32 = 0;
181 while (i < max_len) : (i += 1) {198 while (i < max_len) : (i += 1) {
182 if (i != 0) try writer.writeAll(", ");199 if (i != 0) try writer.writeAll(", ");
183 try print(.{200 try print(.{
184 .ty = elem_ty,201 .ty = elem_ty,
185 .val = val.castTag(.aggregate).?.data[i],202 .val = values.data[i],
186 }, writer, level - 1, mod);203 }, writer, level - 1, mod);
187 }204 }
188 if (len > max_aggregate_items) {205 if (len > max_aggregate_items) {
...@@ -372,11 +389,28 @@ pub fn print(...@@ -372,11 +389,28 @@ pub fn print(
372 return writer.writeAll(".{ ... }");389 return writer.writeAll(".{ ... }");
373 }390 }
374 const payload = val.castTag(.slice).?.data;391 const payload = val.castTag(.slice).?.data;
375 try writer.writeAll(".{ ");
376 const elem_ty = ty.elemType2();392 const elem_ty = ty.elemType2();
377 const len = payload.len.toUnsignedInt(target);393 const len = payload.len.toUnsignedInt(target);
378 const max_len = std.math.min(len, max_aggregate_items);
379394
395 if (elem_ty.eql(Type.u8, mod)) str: {
396 const max_len = @intCast(usize, std.math.min(len, max_string_len));
397 var buf: [max_string_len]u8 = undefined;
398
399 var i: u32 = 0;
400 while (i < max_len) : (i += 1) {
401 var elem_buf: Value.ElemValueBuffer = undefined;
402 const elem_val = payload.ptr.elemValueBuffer(mod, i, &elem_buf);
403 buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(target)) orelse break :str;
404 }
405
406 // TODO would be nice if this had a bit of unicode awareness.
407 const truncated = if (len > max_string_len) " (truncated)" else "";
408 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
409 }
410
411 try writer.writeAll(".{ ");
412
413 const max_len = std.math.min(len, max_aggregate_items);
380 var i: u32 = 0;414 var i: u32 = 0;
381 while (i < max_len) : (i += 1) {415 while (i < max_len) : (i += 1) {
382 if (i != 0) try writer.writeAll(", ");416 if (i != 0) try writer.writeAll(", ");