github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/repo/serialize.go (about)

     1  package repo
     2  
     3  import (
     4  	flatbuffers "github.com/google/flatbuffers/go"
     5  	"github.com/qri-io/qri/profile"
     6  	reporef "github.com/qri-io/qri/repo/ref"
     7  	repofb "github.com/qri-io/qri/repo/repo_fbs"
     8  )
     9  
    10  // RefList is a list of refs
    11  type RefList []reporef.DatasetRef
    12  
    13  // Len returns the length of refs. Used for sort.Interface
    14  func (rs RefList) Len() int { return len(rs) }
    15  
    16  // Less returns true if i comes before j. Used for sort.Interface
    17  func (rs RefList) Less(i, j int) bool { return rs[i].Peername+rs[i].Name < rs[j].Peername+rs[j].Name }
    18  
    19  // Swap flips the positions of i and j. Used for sort.Interface
    20  func (rs RefList) Swap(i, j int) { rs[i], rs[j] = rs[j], rs[i] }
    21  
    22  // FlatbufferBytes turns refs into a byte slice of flatbuffer data
    23  func FlatbufferBytes(rs RefList) []byte {
    24  	builder := flatbuffers.NewBuilder(0)
    25  	count := len(rs)
    26  
    27  	offsets := make([]flatbuffers.UOffsetT, count)
    28  	for i, l := range rs {
    29  		offsets[i] = MarshalFlatbuffer(l, builder)
    30  	}
    31  
    32  	repofb.RepoStartRefsVector(builder, count)
    33  	for i := count - 1; i >= 0; i-- {
    34  		builder.PrependUOffsetT(offsets[i])
    35  	}
    36  	refsvo := builder.EndVector(count)
    37  
    38  	repofb.ReflistStart(builder)
    39  	repofb.ReflistAddRefs(builder, refsvo)
    40  	off := repofb.ReflistEnd(builder)
    41  
    42  	builder.Finish(off)
    43  	return builder.FinishedBytes()
    44  }
    45  
    46  // UnmarshalRefsFlatbuffer turns a repo flatbuffer into a list of refs
    47  func UnmarshalRefsFlatbuffer(data []byte) (ls RefList, err error) {
    48  	repoFb := repofb.GetRootAsReflist(data, 0)
    49  	dec := &repofb.DatasetRef{}
    50  	ls = make(RefList, repoFb.RefsLength())
    51  	for i := 0; i < repoFb.RefsLength(); i++ {
    52  		repoFb.Refs(dec, i)
    53  		r, err := UnmarshalFlatbuffer(dec)
    54  		if err != nil {
    55  			return nil, err
    56  		}
    57  		ls[i] = r
    58  	}
    59  
    60  	return ls, nil
    61  }
    62  
    63  // MarshalFlatbuffer writes a ref to a builder
    64  func MarshalFlatbuffer(r reporef.DatasetRef, builder *flatbuffers.Builder) flatbuffers.UOffsetT {
    65  	peername := builder.CreateString(r.Peername)
    66  	profileID := builder.CreateString(r.ProfileID.Encode())
    67  	name := builder.CreateString(r.Name)
    68  	path := builder.CreateString(r.Path)
    69  	fsiPath := builder.CreateString(r.FSIPath)
    70  
    71  	repofb.DatasetRefStart(builder)
    72  	repofb.DatasetRefAddPeername(builder, peername)
    73  	repofb.DatasetRefAddProfileID(builder, profileID)
    74  	repofb.DatasetRefAddName(builder, name)
    75  	repofb.DatasetRefAddPath(builder, path)
    76  	repofb.DatasetRefAddFsiPath(builder, fsiPath)
    77  	repofb.DatasetRefAddPublished(builder, r.Published)
    78  	return repofb.DatasetRefEnd(builder)
    79  }
    80  
    81  // UnmarshalFlatbuffer decodes a job from a flatbuffer
    82  func UnmarshalFlatbuffer(rfb *repofb.DatasetRef) (r reporef.DatasetRef, err error) {
    83  	r = reporef.DatasetRef{
    84  		Peername:  string(rfb.Peername()),
    85  		Name:      string(rfb.Name()),
    86  		Path:      string(rfb.Path()),
    87  		FSIPath:   string(rfb.FsiPath()),
    88  		Published: rfb.Published(),
    89  	}
    90  
    91  	if pidstr := string(rfb.ProfileID()); pidstr != "" {
    92  		r.ProfileID, err = profile.IDB58Decode(pidstr)
    93  	}
    94  
    95  	return r, err
    96  }