Skip to content

Commit 1ef0fef

Browse files
committed
Support for CAD3 Dense Record types
1 parent 9577f5d commit 1ef0fef

File tree

12 files changed

+227
-65
lines changed

12 files changed

+227
-65
lines changed

convex-core/src/main/java/convex/core/data/ACAD3Record.java

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import convex.core.data.util.BlobBuilder;
44
import convex.core.exceptions.InvalidDataException;
55
import convex.core.lang.RT;
6+
import convex.core.util.Utils;
67

78
/**
89
* Abstract base class for non-CVM CAD3 Records values. These look like countable sequences to CVM code.
@@ -11,43 +12,52 @@
1112
*/
1213
public abstract class ACAD3Record extends ASequence<ACell> {
1314

14-
public ACAD3Record(long count) {
15-
super(count);
16-
}
15+
protected final byte tag;
1716

18-
@Override
19-
public int estimatedEncodingSize() {
20-
return encoding.size();
17+
protected ACAD3Record(byte tag,long count) {
18+
super(count);
19+
this.tag=tag;
2120
}
22-
21+
2322
@Override
2423
public void validateCell() throws InvalidDataException {
25-
// TODO Auto-generated method stub
24+
byte cat=Tag.category(tag);
25+
switch (cat) {
26+
case Tag.DENSE_RECORD_BASE:
27+
case Tag.SPARSE_RECORD_BASE:
28+
break; // seems OK
29+
default: throw new InvalidDataException("Bad tag for CAD3 Record: 0x"+Utils.toHexString(tag),this);
30+
}
2631
}
2732

2833
@Override
2934
public byte getTag() {
30-
return encoding.byteAt(0);
35+
return tag;
3136
}
3237

3338
@Override
3439
public boolean equals(ACell a) {
3540
if (a==null) return false;
36-
if (a.getTag()!=getTag()) return false;
41+
if (a.getTag()!=tag) return false;
3742
return encoding.equals(a.getEncoding());
3843
}
3944

4045
@Override
4146
public int encode(byte[] bs, int pos) {
42-
encoding.getBytes(bs, pos);
43-
return pos+encoding.size();
47+
bs[pos++]=tag;
48+
return encodeRaw(bs,pos);
4449
}
45-
50+
51+
// subclasses must implement getRefCount and getRef
52+
4653
@Override
47-
public int encodeRaw(byte[] bs, int pos) {
48-
encoding.slice(1).getBytes(bs, pos);
49-
return pos+encoding.size()-1;
50-
}
54+
public abstract int getRefCount();
55+
56+
@Override
57+
public abstract Ref<ACell> getRef(int i);
58+
59+
@Override
60+
public abstract ACell updateRefs(IRefFunction func);
5161

5262
@Override
5363
public boolean isCanonical() {

convex-core/src/main/java/convex/core/data/ACell.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ public AString toCVMString(long limit) {
245245
*
246246
* @return The cached blob for this cell, or null if not yet available.
247247
*/
248-
public Blob cachedEncoding() {
248+
public final Blob cachedEncoding() {
249249
return encoding;
250250
}
251251

convex-core/src/main/java/convex/core/data/AMapEntry.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@ public final V setValue(V value) {
5252

5353
@Override
5454
public abstract boolean isCanonical();
55-
56-
5755

5856
@Override
5957
public AVector<ACell> append(ACell value) {

convex-core/src/main/java/convex/core/data/ASequence.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
/**
1818
* Abstract base class for concrete sequential data structure (immutable persistent lists and vectors etc.)
19+
*
20+
* Implements standard java.util.List interface
1921
*
2022
* @param <T> Type of list elements
2123
*/
@@ -169,8 +171,6 @@ public boolean containsKey(ACell key) {
169171
return false;
170172
}
171173

172-
173-
174174
/**
175175
* Gets the element Ref at the specified index
176176
*

convex-core/src/main/java/convex/core/data/DenseRecord.java

Lines changed: 77 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,46 @@
55
import java.util.function.Function;
66

77
import convex.core.data.type.AType;
8+
import convex.core.data.type.Types;
9+
import convex.core.exceptions.BadFormatException;
810

911
public class DenseRecord extends ACAD3Record {
1012

11-
protected AVector<ACell> data;
13+
protected final AVector<ACell> data;
1214

13-
public DenseRecord(long count) {
14-
super(count);
15+
protected DenseRecord(byte tag, AVector<ACell> data) {
16+
super(tag,data.count());
17+
this.data=data;
18+
}
19+
20+
public static DenseRecord create(int tag,AVector<ACell> data) {
21+
if (data==null) return null;
22+
if (Tag.category(tag)!=Tag.DENSE_RECORD_BASE) return null; // not an extension value
23+
24+
return new DenseRecord((byte)tag,data);
25+
}
26+
27+
@Override
28+
public int estimatedEncodingSize() {
29+
return data.estimatedEncodingSize();
30+
}
31+
32+
@Override
33+
public int encodeRaw(byte[] bs, int pos) {
34+
return data.encodeRaw(bs, pos);
35+
}
36+
37+
public static DenseRecord read(byte tag, Blob b, int pos) throws BadFormatException {
38+
AVector<ACell> data=Vectors.read(b, pos);
39+
40+
Blob enc=data.cachedEncoding();
41+
data.attachEncoding(null); // clear invalid encoding
42+
43+
DenseRecord dr=create(tag,data);
44+
if ((enc!=null)&&(enc.byteAt(0)==tag)) {
45+
dr.attachEncoding(enc);
46+
}
47+
return dr;
1548
}
1649

1750
@Override
@@ -34,112 +67,117 @@ public long longLastIndexOf(ACell value) {
3467
return data.longLastIndexOf(value);
3568
}
3669

70+
@SuppressWarnings("unchecked")
3771
@Override
3872
public <R extends ACell> ASequence<R> map(Function<? super ACell, ? extends R> mapper) {
39-
// TODO Auto-generated method stub
40-
return null;
73+
AVector<ACell> rdata=data.map(mapper);
74+
return (ASequence<R>) rdata;
4175
}
4276

4377
@Override
4478
public void forEach(Consumer<? super ACell> action) {
45-
// TODO Auto-generated method stub
46-
79+
data.forEach(action);
4780
}
4881

4982
@Override
5083
public void visitElementRefs(Consumer<Ref<ACell>> f) {
51-
// TODO Auto-generated method stub
52-
84+
data.visitElementRefs(f);
5385
}
5486

5587
@Override
5688
public ASequence<ACell> concat(ASequence<? extends ACell> vals) {
57-
// TODO Auto-generated method stub
58-
return null;
89+
return data.concat(vals);
5990
}
6091

6192
@Override
6293
public ASequence<ACell> next() {
63-
// TODO Auto-generated method stub
64-
return null;
94+
return data.next();
6595
}
6696

6797
@Override
6898
public ASequence<ACell> empty() {
69-
// TODO Auto-generated method stub
70-
return null;
99+
return Vectors.empty();
71100
}
72101

73102
@Override
74103
public ACell get(long index) {
75-
// TODO Auto-generated method stub
76-
return null;
104+
return data.get(index);
77105
}
78106

79107
@Override
80108
public Ref<ACell> getElementRef(long index) {
81-
// TODO Auto-generated method stub
82-
return null;
109+
return data.getElementRef(index);
83110
}
84111

85112
@Override
86113
public ASequence<ACell> assoc(long i, ACell value) {
87-
// TODO Auto-generated method stub
88-
return null;
114+
AVector<ACell> newData=data.assoc(i, value);
115+
return newData;
89116
}
90117

91118
@Override
92119
public ASequence<ACell> conj(ACell value) {
93-
// TODO Auto-generated method stub
94-
return null;
120+
return data.conj(value);
95121
}
96122

97123
@Override
98124
public ASequence<ACell> slice(long start, long end) {
99-
// TODO Auto-generated method stub
100-
return null;
125+
return data.slice(start,end);
101126
}
102127

103128
@Override
104129
public AList<ACell> cons(ACell x) {
105-
// TODO Auto-generated method stub
106-
return null;
130+
return data.cons(x);
107131
}
108132

109133
@Override
110134
public AVector<ACell> subVector(long start, long length) {
111-
// TODO Auto-generated method stub
112-
return null;
135+
return data.subVector(start, length);
113136
}
114137

115138
@Override
116139
protected ListIterator<ACell> listIterator(long l) {
117-
// TODO Auto-generated method stub
118-
return null;
140+
return data.listIterator(l);
119141
}
120142

121143
@Override
122144
public ASequence<ACell> reverse() {
123-
// TODO Auto-generated method stub
124-
return null;
145+
return data.reverse();
125146
}
126147

127148
@Override
128149
public AType getType() {
129-
// TODO Auto-generated method stub
130-
return null;
150+
return Types.CAD3;
131151
}
132152

133153
@Override
134154
public AVector<ACell> toVector() {
135-
// TODO Auto-generated method stub
136-
return null;
155+
return data;
137156
}
138157

139158
@Override
140159
protected <R> void copyToArray(R[] arr, int offset) {
141-
// TODO Auto-generated method stub
142-
160+
data.copyToArray(arr, offset);
143161
}
144162

163+
@Override
164+
public int getRefCount() {
165+
return data.getRefCount();
166+
}
167+
168+
@Override
169+
public Ref<ACell> getRef(int i) {
170+
return data.getRef(i);
171+
}
172+
173+
@Override
174+
public ACell updateRefs(IRefFunction func) {
175+
AVector<ACell> newData=data.updateRefs(func);
176+
if (newData==data) return this;
177+
DenseRecord dr= new DenseRecord(tag,newData);
178+
dr.attachEncoding(getEncoding());
179+
return dr;
180+
}
181+
182+
145183
}

convex-core/src/main/java/convex/core/data/Format.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,11 @@ private static <T extends ACell> T readTransaction(byte tag, Blob b, int pos) th
705705
} else if (tag == Tag.MULTI) {
706706
return (T) Multi.read(b,pos);
707707
}
708-
throw new BadFormatException(badTagMessage(tag));
708+
709+
// Might be a generic Dense Record
710+
DenseRecord dr=DenseRecord.read(tag,b,pos);
711+
if (dr==null) throw new BadFormatException(badTagMessage(tag));
712+
return (T) dr;
709713
}
710714

711715
/**

convex-core/src/main/java/convex/core/data/MapEntry.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
* implementation class for handling entries in Convex maps, and also to support the Java Map.Entry
1616
* interface for compatibility and developer convenience.
1717
*
18-
* From a CVM perspective, a MapEntry is just a regular 2 element Vector. As such, MapEntry is *not* canonical
19-
* and getting the canonical form of a MapEntry requires converting to a Vector
18+
* From a CVM perspective, a MapEntry is just a regular 2 element Vector.
2019
*
2120
* Contains exactly 2 elements, one for key and one for value
2221
*

convex-core/src/main/java/convex/core/data/Tag.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ public class Tag {
6666

6767
// ==========================================
6868
// Sparsely coded record (0xAx)
69+
public static final byte SPARSE_RECORD_BASE = (byte) 0xA0;
70+
6971
public static final byte STATE = (byte) 0xA0;
7072
public static final byte ACCOUNT_STATUS = (byte) 0xA1;
7173
public static final byte PEER_STATUS = (byte) 0xA2;
@@ -98,6 +100,8 @@ public class Tag {
98100

99101
// ==========================================
100102
// Densely coded record (0xDx)
103+
public static final byte DENSE_RECORD_BASE = (byte) 0xD0;
104+
101105
public static final byte INVOKE = (byte) 0xD0;
102106
public static final byte TRANSFER = (byte) 0xD1;
103107
public static final byte CALL = (byte) 0xD2;
@@ -121,6 +125,16 @@ public class Tag {
121125
// Illegal / reserved for special values (0xFx)
122126
public static final byte ILLEGAL = (byte) 0xFF;
123127

128+
129+
/**
130+
* Get the general category for a given Tag (high hex digit)
131+
* @param tag Tag Byte
132+
* @return Category e.g. 0xC0 for coded data
133+
*/
134+
public static byte category(int tag) {
135+
return (byte) (tag&0xF0);
136+
}
137+
124138

125139

126140
}

0 commit comments

Comments
 (0)