diff --git a/indexes/index-cid-to-subset-offset-and-size.go b/indexes/index-cid-to-subset-offset-and-size.go index a071eaf4..e0450739 100644 --- a/indexes/index-cid-to-subset-offset-and-size.go +++ b/indexes/index-cid-to-subset-offset-and-size.go @@ -3,6 +3,7 @@ package indexes import ( "context" "fmt" + "io" "os" "path/filepath" @@ -130,3 +131,76 @@ func (w *CidToSubsetOffsetAndSize_Writer) Close() error { } return w.index.Close() } + +func (w *CidToSubsetOffsetAndSize_Writer) GetFilePath() string { + return w.finalPath +} + +type CidToSubsetOffsetAndSize_Reader struct { + file io.Closer + meta *Metadata + index *compactindexsized.DB +} + +func Open_CidToSubsetOffsetAndSize(file string) (*CidToSubsetOffsetAndSize_Reader, error) { + reader, err := os.Open(file) + if err != nil { + return nil, fmt.Errorf("failed to open index file: %w", err) + } + + return OpenWithReader_CidToSubsetOffsetAndSize(reader) +} + +func OpenWithReader_CidToSubsetOffsetAndSize(reader ReaderAtCloser) (*CidToSubsetOffsetAndSize_Reader, error) { + index, err := compactindexsized.Open(reader) + if err != nil { + return nil, fmt.Errorf("failed to open index: %w", err) + } + meta, err := getDefaultMetadata(index) + if err != nil { + return nil, err + } + if !IsValidNetwork(meta.Network) { + return nil, fmt.Errorf("invalid network") + } + if meta.RootCid == cid.Undef { + return nil, fmt.Errorf("root cid is undefined") + } + if err := meta.AssertIndexKind(Kind_CidToSubsetOffsetAndSize); err != nil { + return nil, err + } + return &CidToSubsetOffsetAndSize_Reader{ + file: reader, + meta: meta, + index: index, + }, nil +} + +func (r *CidToSubsetOffsetAndSize_Reader) Get(cid_ cid.Cid) (*SubsetOffsetAndSize, error) { + if cid_ == cid.Undef { + return nil, fmt.Errorf("cid is undefined") + } + key := cid_.Bytes() + value, err := r.index.Lookup(key) + if err != nil { + return nil, err + } + soas := &SubsetOffsetAndSize{} + if err := soas.FromBytes(value); err != nil { + return nil, err + } + return soas, nil +} + +func (r *CidToSubsetOffsetAndSize_Reader) Close() error { + return r.file.Close() +} + +// Meta returns the metadata for the index. +func (r *CidToSubsetOffsetAndSize_Reader) Meta() *Metadata { + return r.meta +} + +func (r *CidToSubsetOffsetAndSize_Reader) Prefetch(b bool) { + r.index.Prefetch(b) +} diff --git a/indexes/subset-offset-and-size.go b/indexes/subset-offset-and-size.go new file mode 100644 index 00000000..34ec83f6 --- /dev/null +++ b/indexes/subset-offset-and-size.go @@ -0,0 +1,21 @@ +package indexes + +import "errors" + +type SubsetOffsetAndSize struct { + Subset uint64 // uint24, 3 bytes, max 16.7 MB (megabytes) + Offset uint64 // uint48, 6 bytes, max 281.5 TB (terabytes) + Size uint64 // uint24, 3 bytes, max 16.7 MB (megabytes) +} + +// FromBytes parses the offset and size from a byte slice. +func (soas *SubsetOffsetAndSize) FromBytes(buf []byte) error { + if len(buf) != IndexValueSize_CidToSubsetOffsetAndSize { + return errors.New("invalid byte slice length") + } + _ = buf[IndexValueSize_CidToSubsetOffsetAndSize-1] // bounds check hint to compiler + soas.Subset = uint64(BtoUint24(buf[:3])) + soas.Offset = BtoUint48(buf[3:9]) + soas.Size = uint64(BtoUint24(buf[9:])) + return nil +}