     func getTag() throws -> FieldTag? {
         fieldStartP = p
         fieldStartAvailable = available
+        return try getTagWithoutUpdatingFieldStart()
+    }
+
+    // Parse index/type marker that starts each field.
+    // Used during skipping to avoid updating the field start offset.
+    private func getTagWithoutUpdatingFieldStart() throws -> FieldTag? {
         if let t = try getRawVarint() {
             if t < UInt64(UInt32.max) {
                 guard let tag = FieldTag(rawValue: UInt32(truncatingBitPattern: t)) else {


    // Returns tagType for the field being skipped
    // Recursively processes groups; returns the start group marker
    func skipOver(tagType: UInt64) throws {
        if tagType < 8 || tagType > UInt64(UInt32.max) {
            throw ProtobufDecodingError.malformedProtobuf
        }
        switch tagType % 8 {
        case 0:
            if available < 1 {
                throw ProtobufDecodingError.truncatedInput
            }

    func skip() throws -> UnsafeBufferPointer<UInt8> {
        p = fieldStartP
        available = fieldStartAvailable
        guard let tag = try getTagWithoutUpdatingFieldStart() else {
            throw ProtobufDecodingError.truncatedInput
        }
        try skipOver(tag: tag)
        return UnsafeBufferPointer<UInt8>(start: fieldStartP, count: p - fieldStartP)
    }

