tiny.smg.command.rules.render
Defined in command.rules.
API (1)
Actions
Public operations.
Source
Source: tools/smg/src/command/rules/render.zig
zig
const std = @import("std");const pretty_json = @import("pretty").json;const smg = @import("../../root.zig");const output = smg.cli.output;const rich_table = smg.cli.table.rich;const rules_mod = smg.rules;pub fn writeList(allocator: std.mem.Allocator, rule_list: []const rules_mod.Rule, json: bool) !u8 { if (json) { var out: std.Io.Writer.Allocating = .init(allocator); var writer = pretty_json.Writer.init(&out.writer, .minified); try writer.beginArray(); for (rule_list) |rule| try writer.raw(try rules_mod.render(allocator, rule)); try writer.endArray(); try out.writer.writeByte('\n'); return try output.writeOut(out.written()); } if (rule_list.len == 0) return try output.writeOut("No rules defined. Add one with smg rule add.\n"); var out: std.Io.Writer.Allocating = .init(allocator); try writeTable(allocator, &out.writer, rule_list); return try output.writeOut(out.written());}fn writeTable(allocator: std.mem.Allocator, writer: *std.Io.Writer, rule_list: []const rules_mod.Rule) !void { var rows: std.ArrayList(rich_table.Row3) = .empty; for (rule_list) |rule| { try rows.append(allocator, .{ .a = rule.name, .b = rule.type, .c = try constraint(allocator, rule), }); } try rich_table.write3(writer, .{ .a = "Name", .b = "Type", .c = "Constraint" }, rows.items);}fn constraint(allocator: std.mem.Allocator, rule: rules_mod.Rule) ![]const u8 { var value = rule.pattern orelse rule.invariant orelse ""; if (std.mem.eql(u8, rule.type, "quantified")) value = try std.fmt.allocPrint(allocator, "forall {s}: {s}", .{ rule.selector orelse "", rule.assertion orelse "" }); var out: std.Io.Writer.Allocating = .init(allocator); try out.writer.writeAll(try stripMarkup(allocator, value)); if (rule.params.len != 0) { try out.writer.writeAll(" ("); for (rule.params, 0..) |param, index| { if (index != 0) try out.writer.writeAll(", "); try out.writer.print("{s}={s}", .{ param.key, param.value }); } try out.writer.writeByte(')'); } if (rule.allow_empty_target) try out.writer.writeAll(" allow-empty-target"); if (rule.scope) |scope| try out.writer.print(" scope={s}", .{scope}); return try out.toOwnedSlice();}fn stripMarkup(allocator: std.mem.Allocator, value: []const u8) ![]const u8 { var out: std.ArrayList(u8) = .empty; var i: usize = 0; while (i < value.len) : (i += 1) { if (value[i] == '[') { while (i < value.len and value[i] != ']') i += 1; continue; } try out.append(allocator, value[i]); } return try out.toOwnedSlice(allocator);}test "rule table strips rich markup from constraints" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); const rule_list = [_]rules_mod.Rule{.{ .name = "no-db", .type = "deny", .pattern = "app.* -[calls]-> db.*", }}; var out: std.Io.Writer.Allocating = .init(allocator); try writeTable(allocator, &out.writer, &rule_list); try std.testing.expect(std.mem.indexOf(u8, out.written(), "app.* --> db.*") != null); try std.testing.expect(std.mem.indexOf(u8, out.written(), "Constraint") != null);}test "rule table exposes empty-target policy" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); const rule_list = [_]rules_mod.Rule{.{ .name = "no-integration", .type = "deny", .pattern = "pkg -[contains]-> *.integration", .allow_empty_target = true, }}; var out: std.Io.Writer.Allocating = .init(allocator); try writeTable(allocator, &out.writer, &rule_list); try std.testing.expect(std.mem.indexOf(u8, out.written(), "allow-empty-target") != null);}Source: tools/smg/src/command/rules/root.zig:3
zig
pub const render = @import("render.zig");Audit
| Definitions | 2 |
|---|---|
| Public names | 3 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |