diff options
Diffstat (limited to 'object/store/packed/internal/ingest/entry.go')
| -rw-r--r-- | object/store/packed/internal/ingest/entry.go | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/object/store/packed/internal/ingest/entry.go b/object/store/packed/internal/ingest/entry.go new file mode 100644 index 00000000..363e213c --- /dev/null +++ b/object/store/packed/internal/ingest/entry.go @@ -0,0 +1,91 @@ +package ingest + +import ( + "fmt" + + objecttype "codeberg.org/lindenii/furgit/object/type" +) + +// scanOneEntry scans one pack entry from stream and appends one record. +func scanOneEntry(state *ingestState, startOffset uint64) (uint64, error) { + state.stream.beginEntryCRC() + + record, err := parseEntryPrefix(state, startOffset) + if err != nil { + return 0, err + } + + payloadStartConsumed := state.stream.consumed + + contentLen, oid, err := drainEntryPayload(state, record) + if err != nil { + return 0, err + } + + consumedInput := state.stream.consumed - payloadStartConsumed + + if contentLen != record.declaredSize { + return 0, &MalformedPackEntryError{ + Offset: startOffset, + Reason: fmt.Sprintf("inflated size mismatch got %d want %d", contentLen, record.declaredSize), + } + } + + endOffset := startOffset + uint64(record.headerLen) + consumedInput + if endOffset > state.stream.consumed { + return 0, &MalformedPackEntryError{ + Offset: startOffset, + Reason: fmt.Sprintf("entry end offset overflow got %d > stream %d", endOffset, state.stream.consumed), + } + } + + record.packedLen = endOffset - startOffset + + record.dataOffset = startOffset + uint64(record.headerLen) + if record.packedLen < uint64(record.headerLen) { + return 0, &MalformedPackEntryError{Offset: startOffset, Reason: "negative payload span"} + } + + crc, err := state.stream.endEntryCRC() + if err != nil { + return 0, err + } + + record.crc32 = crc + + if record.packedType.IsBaseObject() { + record.objectID = oid + record.realType = record.packedType + record.resolved = true + } + + recordIdx := len(state.records) + state.records = append(state.records, record) + + state.offsetToRecord[record.offset] = recordIdx + if record.resolved { + state.objectToRecord[record.objectID] = recordIdx + } + + switch record.packedType { + case objecttype.TypeOfsDelta: + state.ofsDeltas = append(state.ofsDeltas, ofsDeltaRef{ + baseOffset: record.baseOffset, + recordIdx: recordIdx, + }) + case objecttype.TypeRefDelta: + state.refDeltas = append(state.refDeltas, refDeltaRef{ + baseObject: record.baseObject, + recordIdx: recordIdx, + }) + case objecttype.TypeInvalid, + objecttype.TypeCommit, + objecttype.TypeTree, + objecttype.TypeBlob, + objecttype.TypeTag, + objecttype.TypeFuture: + default: + } + + return endOffset, nil +} |
