diff --git a/objects.go b/objects.go index 7dc06c6..5ff4f65 100644 --- a/objects.go +++ b/objects.go @@ -45,11 +45,21 @@ func VKeyId(key []byte) rdx.ID { return rdx.IDFromBytes(key[1:]) } +// A class contains a number of fields. Each Field has +// some RDT type. A class can inherit another class. +// New fields can be appended to a class, but never removed. +// Max number of fields is 128, max inheritance depth 32. +// When stored, a class is an append-only sequence of Ts. +// The syntax for each T: "XName", where X is the RDT. +// For the map types, can use "MSS_Name" or similar. type Field struct { - Name string - RdxType byte + Name string + RdxType byte + RdxTypeExt []byte } +type Fields []Field + func (f Field) Valid() bool { for _, l := range f.Name { // has unsafe chars if l < ' ' { @@ -61,8 +71,6 @@ func (f Field) Valid() bool { len(f.Name) > 0 && utf8.ValidString(f.Name)) } -type Fields []Field - func (f Fields) Find(name string) (ndx int) { for i := 0; i < len(f); i++ { if f[i].Name == name { diff --git a/rdx/A.go b/rdx/A.go new file mode 100644 index 0000000..a69a1a4 --- /dev/null +++ b/rdx/A.go @@ -0,0 +1,58 @@ +package rdx + +import "github.com/drpcorg/chotki/protocol" + +// append-only collection of Terms +type LogT []string + +func Amerge(tlvs [][]byte) (merged []byte) { + ih := ItHeap[*AIterator]{} + for _, tlv := range tlvs { + ih.Push(&AIterator{FIRSTIterator{TLV: tlv}}) + } + for ih.Len() > 0 { + merged = append(merged, ih.Next()...) + } + return +} + +func Atlv(log LogT) (tlv []byte) { + for n, t := range log { + bare := FIRSTtlv(int64(n), 0, []byte(t)) + tlv = protocol.AppendHeader(tlv, Term, len(bare)) + tlv = append(tlv, bare...) + } + return +} + +func AnativeT(tlv []byte) (log LogT) { + it := FIRSTIterator{TLV: tlv} + for it.Next() { + if it.lit != Term { + continue + } + log = append(log, string(it.val)) + } + return +} + +type AIterator struct { + FIRSTIterator +} + +func (a *AIterator) Merge(bb SortedIterator) int { + b := bb.(*AIterator) + if a.revz > b.revz { + return MergeBA + } else if a.revz < b.revz { + return MergeAB + } + cmp := FIRSTcompare(a.one, b.one) + if cmp == 0 { + return MergeA + } else if cmp < 0 { + return MergeAB + } else { + return MergeBA + } +} diff --git a/rdx/A_test.go b/rdx/A_test.go new file mode 100644 index 0000000..e59766c --- /dev/null +++ b/rdx/A_test.go @@ -0,0 +1,30 @@ +package rdx + +import ( + "github.com/drpcorg/chotki/protocol" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAmerge(t *testing.T) { + tlv := Atlv(LogT{ + "Ione", + "Stwo", + "Rthree", + }) + tlv2 := Atlv(LogT{ + "Ione", + "Stwo", + "Rthree", + "Tfour", + }) + tlv2b := Amerge(protocol.Records{tlv, tlv2}) + assert.Equal(t, tlv2, tlv2b) + + one := protocol.Record('T', FIRSTtlv(3, 0, []byte("Tfour"))) + tlv3 := Amerge(protocol.Records{tlv, one}) + assert.Equal(t, tlv2, tlv3) + + tlv4 := Amerge(protocol.Records{tlv, one, tlv2, tlv3}) + assert.Equal(t, tlv2, tlv4) +}