/// This file *MUST* be kept in sync with tree-sitter/lib/src/query.c /// It exactly represents the C structures in memory and must produce /// the exact same results as the C tree-sitter library version used. /// /// Yes,... it is not a public API! Here be dragons! /// const std = @import("std"); const Io = std.Io; const cbor = @import("cbor"); const build_options = @import("build_options"); const treez = if (build_options.use_tree_sitter) @import("treez") else @import("treez_dummy.zig"); pub const Slice = extern struct { offset: u32, length: u32, pub fn cborEncode(self: *const @This(), writer: *Io.Writer) !void { return cbor.writeArray(writer, self.*); } pub fn cborExtract(self: *@This(), iter: *[]const u8) cbor.Error!bool { return cbor.matchValue(iter, .{ cbor.extract(&self.offset), cbor.extract(&self.length), }); } }; pub fn Array(T: type) type { return extern struct { contents: ?*T, size: u32, capacity: u32, pub fn cborEncode(self: *const @This(), writer: *Io.Writer) !void { if (self.contents) |contents| { const arr: []T = @as([*]T, @ptrCast(contents))[0..self.size]; try cbor.writeValue(writer, arr); return; } try cbor.writeValue(writer, null); } pub fn cborExtract(self: *@This(), iter: *[]const u8, allocator: std.mem.Allocator) cbor.Error!bool { var iter_ = iter.*; if (cbor.matchValue(&iter_, cbor.null_) catch false) { iter.* = iter_; self.contents = null; self.size = 0; self.capacity = 0; return true; } if (T == u8) { var arr: []const u8 = undefined; if (try cbor.matchValue(iter, cbor.extract(&arr))) { self.contents = @ptrCast(@constCast(arr.ptr)); self.size = @intCast(arr.len); self.capacity = @intCast(arr.len); return true; } return false; } var i: usize = 0; var n = try cbor.decodeArrayHeader(iter); var arr: []T = try allocator.alloc(T, n); while (n > 0) : (n -= 1) { if (comptime cbor.isExtractableAlloc(T)) { if (!(cbor.matchValue(iter, cbor.extractAlloc(&arr[i], allocator)) catch return false)) return false; } else { if (!(cbor.matchValue(iter, cbor.extract(&arr[i])) catch return false)) return false; } i += 1; } self.contents = @ptrCast(@constCast(arr.ptr)); self.size = @intCast(arr.len); self.capacity = @intCast(arr.len); return true; } }; } pub const SymbolTable = extern struct { characters: Array(u8), slices: Array(Slice), pub fn cborEncode(self: *const @This(), writer: *Io.Writer) !void { return cbor.writeArray(writer, self.*); } pub fn cborExtract(self: *@This(), iter: *[]const u8, allocator: std.mem.Allocator) cbor.Error!bool { return cbor.matchValue(iter, .{ cbor.extractAlloc(&self.characters, allocator), cbor.extractAlloc(&self.slices, allocator), }); } }; pub const CaptureQuantifiers = Array(u8); pub const PatternEntry = extern struct { step_index: u16, pattern_index: u16, is_rooted: bool, pub fn cborEncode(self: *const @This(), writer: *Io.Writer) !void { return cbor.writeArray(writer, self.*); } pub fn cborExtract(self: *@This(), iter: *[]const u8) cbor.Error!bool { return cbor.matchValue(iter, .{ cbor.extract(&self.step_index), cbor.extract(&self.pattern_index), cbor.extract(&self.is_rooted), }); } }; pub const QueryPattern = extern struct { steps: Slice, predicate_steps: Slice, start_byte: u32, end_byte: u32, is_non_local: bool, pub fn cborEncode(self: *const @This(), writer: *Io.Writer) !void { return cbor.writeArray(writer, self.*); } pub fn cborExtract(self: *@This(), iter: *[]const u8, allocator: std.mem.Allocator) cbor.Error!bool { return cbor.matchValue(iter, .{ cbor.extractAlloc(&self.steps, allocator), cbor.extractAlloc(&self.predicate_steps, allocator), cbor.extract(&self.start_byte), cbor.extract(&self.end_byte), cbor.extract(&self.is_non_local), }); } }; pub const StepOffset = extern struct { byte_offset: u32, step_index: u16, pub fn cborEncode(self: *const @This(), writer: *Io.Writer) !void { return cbor.writeArray(writer, self.*); } pub fn cborExtract(self: *@This(), iter: *[]const u8) cbor.Error!bool { return cbor.matchValue(iter, .{ cbor.extract(&self.byte_offset), cbor.extract(&self.step_index), }); } }; pub const MAX_STEP_CAPTURE_COUNT = 3; pub const TSSymbol = u16; pub const TSFieldId = u16; pub const QueryStep = extern struct { symbol: TSSymbol, supertype_symbol: TSSymbol, field: TSFieldId, capture_ids: [MAX_STEP_CAPTURE_COUNT]u16, depth: u16, alternative_index: u16, negated_field_list_id: u16, // is_named: u1, // is_immediate: u1, // is_last_child: u1, // is_pass_through: u1, // is_dead_end: u1, // is_inside_alternation: u1, // contains_captures: u1, // root_pattern_guaranteed: u1, flags8: u8, // parent_pattern_guaranteed: u1, // is_missing: u1, flags16: u8, pub fn cborEncode(self: *const @This(), writer: *Io.Writer) !void { return cbor.writeArray(writer, self.*); } pub fn cborExtract(self: *@This(), iter: *[]const u8) cbor.Error!bool { return cbor.matchValue(iter, .{ cbor.extract(&self.symbol), cbor.extract(&self.supertype_symbol), cbor.extract(&self.field), cbor.extract(&self.capture_ids), cbor.extract(&self.depth), cbor.extract(&self.alternative_index), cbor.extract(&self.negated_field_list_id), cbor.extract(&self.flags8), cbor.extract(&self.flags16), }); } }; pub const PredicateStep = extern struct { pub const Type = enum(c_uint) { done, capture, string, }; type: Type, value_id: u32, pub fn cborEncode(self: *const @This(), writer: *Io.Writer) !void { return cbor.writeArray(writer, self.*); } pub fn cborExtract(self: *@This(), iter: *[]const u8) cbor.Error!bool { return cbor.matchValue(iter, .{ cbor.extract(&self.type), cbor.extract(&self.value_id), }); } }; pub const TSQuery = extern struct { captures: SymbolTable, predicate_values: SymbolTable, capture_quantifiers: Array(CaptureQuantifiers), steps: Array(QueryStep), pattern_map: Array(PatternEntry), predicate_steps: Array(PredicateStep), patterns: Array(QueryPattern), step_offsets: Array(StepOffset), negated_fields: Array(TSFieldId), string_buffer: Array(u8), repeat_symbols_with_rootless_patterns: Array(TSSymbol), language: usize, // language: ?*const treez.Language, wildcard_root_pattern_count: u16, pub fn cborEncode(self: *const @This(), writer: *Io.Writer) !void { return cbor.writeArray(writer, self.*); } pub fn cborExtract(self: *@This(), iter: *[]const u8, allocator: std.mem.Allocator) cbor.Error!bool { const result = cbor.matchValue(iter, .{ cbor.extractAlloc(&self.captures, allocator), cbor.extractAlloc(&self.predicate_values, allocator), cbor.extractAlloc(&self.capture_quantifiers, allocator), cbor.extractAlloc(&self.steps, allocator), cbor.extractAlloc(&self.pattern_map, allocator), cbor.extractAlloc(&self.predicate_steps, allocator), cbor.extractAlloc(&self.patterns, allocator), cbor.extractAlloc(&self.step_offsets, allocator), cbor.extractAlloc(&self.negated_fields, allocator), cbor.extractAlloc(&self.string_buffer, allocator), cbor.extractAlloc(&self.repeat_symbols_with_rootless_patterns, allocator), cbor.extract(&self.language), cbor.extract(&self.wildcard_root_pattern_count), }); self.language = 0; return result; } }; pub const SerializeError = error{OutOfMemory}; pub fn toCbor(query: *TSQuery, allocator: std.mem.Allocator) SerializeError![]const u8 { var cb: Io.Writer.Allocating = .init(allocator); defer cb.deinit(); cbor.writeValue(&cb.writer, query.*) catch return error.OutOfMemory; return cb.toOwnedSlice(); } pub const DeserializeError = error{ WriteFailed, OutOfMemory, IntegerTooLarge, IntegerTooSmall, InvalidType, TooShort, InvalidFloatType, InvalidArrayType, InvalidPIntType, InvalidMapType, InvalidUnion, JsonIncompatibleType, InvalidQueryCbor, NotAnObject, BadArrayAllocExtract, }; pub fn fromCbor(cb: []const u8, allocator: std.mem.Allocator) DeserializeError!struct { *TSQuery, *std.heap.ArenaAllocator } { var arena = try allocator.create(std.heap.ArenaAllocator); errdefer allocator.destroy(arena); arena.* = std.heap.ArenaAllocator.init(allocator); errdefer arena.deinit(); const query = try arena.allocator().create(TSQuery); query.* = undefined; var iter: []const u8 = cb; if (!try cbor.matchValue(&iter, cbor.extractAlloc(query, arena.allocator()))) return error.InvalidQueryCbor; return .{ query, arena }; }