Something went wrong. Try again.
Zig parser for the OSM PBF file format. jeff.jcollie.pages/osm.zig
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100// SPDX-FileCopyrightText: © 2026 Jeffrey C. Ollie// SPDX-License-Identifier: MIT
const Way = @This();
const std = @import("std");
const OSMPBF = @import("proto/OSMPBF.pb.zig");
const Timestamp = @import("Timestamp.zig");const stringtable = @import("stringtable.zig");
id: i64,refs: []i64,kvs: std.StringArrayHashMapUnmanaged([]const u8),version: i32,timestamp: Timestamp,changeset: ?i64,uid: ?i32,user_sid: ?[]const u8,visible: ?bool,
pub fn init(gpa: std.mem.Allocator, block: *const OSMPBF.PrimitiveBlock, way: *OSMPBF.Way) !Way { const user_sid = user_sid: { const info = &(way.info orelse break :user_sid null); break :user_sid try stringtable.dupe(gpa, block, info.user_sid); }; errdefer if (user_sid) |v| gpa.free(v);
const kvs = kvs: { var kvs: std.StringArrayHashMapUnmanaged([]const u8) = .empty; errdefer { var it = kvs.iterator(); while (it.next()) |entry| { gpa.free(entry.key_ptr.*); gpa.free(entry.value_ptr.*); } kvs.deinit(gpa); }
for (way.keys, way.vals) |key_index, value_index| { const key = try stringtable.lookup(block, key_index) orelse return error.StringIndexInvalid; const value = try stringtable.dupe(gpa, block, value_index) orelse return error.StringIndexInvalid; const gop = gop: { errdefer gpa.free(value); break :gop try kvs.getOrPut(gpa, key); }; if (gop.found_existing) { gpa.free(gop.value_ptr.*); gop.value_ptr.* = value; } else { gop.key_ptr.* = key: { errdefer gpa.free(value); break :key try gpa.dupe(u8, key); }; gop.value_ptr.* = value; } }
break :kvs kvs; };
return .{ .id = way.id, .refs = refs: { var refs = try gpa.alloc(i64, way.refs.len); var acc: i64 = 0; for (way.refs.items, 0..) |delta, i| { acc += delta; refs[i] = acc; } break :refs refs; }, .version = version: { const info = &(way.info orelse break :version -1); break :version info.version orelse -1; }, .timestamp = timestamp: { const info = &(way.info orelse break :timestamp .{ .timestamp = null, .granularity = block.date_granularity, }); break :timestamp .{ .timestamp = info.timestamp, .granularity = block.date_granularity, }; }, .changeset = changeset: { const info = &(way.info orelse break :changeset null); break :changeset info.changeset; }, .uid = uid: { const info = &(way.info orelse break :uid null); break :uid info.uid; }, .user_sid = user_sid, .kvs = kvs, };}