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 }