Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions 3 .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"java.configuration.updateBuildConfiguration": "automatic"
}
145 changes: 127 additions & 18 deletions 145 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@ RLP Encoding/Decoding
- declaring your pojo

```java
package org.tdf.rlp;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

public class Node{
// RLP annotation specify the order of field in encoded list
@RLP(0)
public String name;

@RLP(1)
public List<Node> children;

Expand All @@ -32,6 +39,15 @@ public class Node{
children.addAll(nodes);
}

private static class Nested{
@RLP
private List<List<List<String>>> nested;

public Nested() {
}
}


public static void main(String[] args){
Node root = new Node("1");
root.addChildren(Arrays.asList(new Node("2"), new Node("3")));
Expand All @@ -40,15 +56,15 @@ public class Node{
root.children.get(1).addChildren(Arrays.asList(new Node("6"), new Node("7")));

// encode to byte array
byte[] encoded = RLPElement.encode(root).getEncoded();
// encode to rlp element
RLPElement el = RLPElement.encode(root);
byte[] encoded = RLPCodec.encode(root);
// read as rlp tree
RLPElement el = RLPElement.readRLPTree(root);
// decode from byte array
Node root2 = RLPDeserializer.deserialize(encoded, Node.class);
assertTrue(root2.children.get(0).children.get(0).name.equals("4"));
assertTrue(root2.children.get(0).children.get(1).name.equals("5"));
assertTrue(root2.children.get(1).children.get(0).name.equals("6"));
assertTrue(root2.children.get(1).children.get(1).name.equals("7"));
Node root2 = RLPCodec.decode(encoded, Node.class);
el = RLPElement.fromEncoded(encoded);
// decode from rlp element
root2 = el.as(Node.class);
root2 = RLPCodec.decode(el, Node.class);
}

public static void assertTrue(boolean b){
Expand All @@ -60,14 +76,18 @@ public class Node{
- custom encoding/decoding

```java
package org.tdf.rlp;

import java.util.HashMap;
import java.util.Map;

public class Main{
public static class MapEncoderDecoder implements RLPEncoder<Map<String, String>>, RLPDecoder<Map<String, String>> {
@Override
public Map<String, String> decode(RLPElement element) {
RLPList list = element.getAsList();
public Map<String, String> decode(RLPElement list) {
Map<String, String> map = new HashMap<>(list.size() / 2);
for (int i = 0; i < list.size(); i += 2) {
map.put(list.get(i).getAsItem().getString(), list.get(i+1).getAsItem().getString());
map.put(list.get(i).asString(), list.get(i+1).asString());
}
return map;
}
Expand Down Expand Up @@ -101,15 +121,16 @@ public class Main{
Map<String, String> m = new HashMap<>();
m.put("a", "1");
m.put("b", "2");
byte[] encoded = RLPElement.encode(new MapWrapper(m)).getEncoded();
MapWrapper decoded = RLPDeserializer.deserialize(encoded, MapWrapper.class);
byte[] encoded = RLPCodec.encode(new MapWrapper(m));
MapWrapper decoded = RLPCodec.decode(encoded, MapWrapper.class);
assertTrue(decoded.map.get("a").equals("1"));
}

public static void assertTrue(boolean b){
if(!b) throw new RuntimeException("assertion failed");
}
}

```

- supports List and POJO only for rlp is ordered while set is no ordered, generic list could be nested to any deepth
Expand All @@ -123,6 +144,7 @@ public class Nested{
}
}
```

```java
public class Main{
public static void main(String[] args){
Expand All @@ -131,10 +153,97 @@ public class Main{
nested.nested.add(new ArrayList<>());
nested.nested.get(0).add(new ArrayList<>());
nested.nested.get(0).get(0).addAll(Arrays.asList("aaa", "bbb"));
byte[] encoded = RLPElement.encode(nested).getEncoded();
nested = RLPDeserializer.deserialize(encoded, Nested.class);
assertTrue(nested.nested.get(0).get(0).get(0).equals("aaa"));
assertTrue(nested.nested.get(0).get(0).get(1).equals("bbb"));
byte[] encoded = RLPCodec.encode(nested);
nested = RLPCodec.decode(encoded, Nested.class);
assert nested.nested.get(0).get(0).get(0).equals("aaa");
assert nested.nested.get(0).get(0).get(1).equals("bbb");
}
}
```

- encoding/decoding of Set/Map

```java
public class Main{

private static class ByteArraySetWrapper {
@RLP
@RLPDecoding(as = TreeSet.class)
@RLPEncoding(contentOrdering = BytesComparator.class)
private Set<byte[]> bytesSet;
}

private static class BytesComparator implements Comparator<byte[]> {
@Override
public int compare(byte[] o1, byte[] o2) {
return new BigInteger(1, o1).compareTo(new BigInteger(1, o2));
}
}

public static class MapWrapper2 {
@RLP
@RLPDecoding(as = TreeMap.class)
@RLPEncoding(keyOrdering = StringComparator.class)
public Map<String, Map<String, String>> map = new HashMap<>();
}

private static class StringComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
}

public static void main(String[] args){
ByteArraySetWrapper wrapper =
RLPList.of(RLPList.of(RLPItem.fromLong(1), RLPItem.fromLong(2))).as(ByteArraySetWrapper.class);
assert wrapper.bytesSet instanceof TreeSet;

wrapper = new ByteArraySetWrapper();
wrapper.bytesSet = new HashSet<>();
wrapper.bytesSet.add(new byte[]{1});
wrapper.bytesSet.add(new byte[]{2});
wrapper.bytesSet.add(new byte[]{3});
wrapper.bytesSet.add(new byte[]{4});
wrapper.bytesSet.add(new byte[]{5});
boolean sorted = true;
int i = 0;
for (byte[] b : wrapper.bytesSet) {
if (new BigInteger(1, b).compareTo(BigInteger.valueOf(i + 1)) != 0) {
sorted = false;
break;
}
i++;
}
assert !sorted;
RLPElement el = RLPElement.readRLPTree(wrapper).get(0);
for (int j = 0; j < el.size(); j++) {
assert new BigInteger(1, el.get(j).asBytes()).compareTo(BigInteger.valueOf(j + 1)) == 0;
}

MapWrapper2 wrapper2 = new MapWrapper2();
wrapper2.map.put("1", new HashMap<>());
wrapper2.map.put("22", new HashMap<>());
wrapper2.map.put("sss", new HashMap<>());
wrapper2.map.get("sss").put("aaa", "bbb");
hasSorted = true;
i = 1;
for (String k : wrapper2.map.keySet()) {
if (k.length() != i) {
hasSorted = false;
break;
}
i++;
}
assert !hasSorted;
byte[] encoded = RLPCodec.encode(wrapper2);
el = RLPElement.readRLPTree(wrapper2);
for (int j = 0; j < 3; j++) {
assert el.get(0).get(j * 2).asString().length() == j + 1;
}
MapWrapper2 decoded = RLPCodec.decode(encoded, MapWrapper2.class);
assert decoded.map instanceof TreeMap;
assert decoded.map.get("sss").get("aaa").equals("bbb");
}
}
```
Expand Down
2 changes: 1 addition & 1 deletion 2 build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {
}

group 'org.tdf'
version '1.0.7'
version '1.1.7'

sourceCompatibility = 1.8

Expand Down
28 changes: 28 additions & 0 deletions 28 src/main/java/org/tdf/rlp/CollectionContainer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.tdf.rlp;

import java.util.Collection;

class CollectionContainer implements Container {
Class<? extends Collection> collectionType;

public ContainerType getContainerType() {
return ContainerType.COLLECTION;
}

Container contentType;

@Override
public Class<?> asRawType() {
throw new RuntimeException("not a raw type");
}

@Override
public CollectionContainer asCollectionContainer() {
return this;
}

@Override
public MapContainer asMapContainer() {
throw new RuntimeException("not a map container");
}
}
78 changes: 78 additions & 0 deletions 78 src/main/java/org/tdf/rlp/Container.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package org.tdf.rlp;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;

interface Container {
ContainerType getContainerType();

Class<?> asRawType();

CollectionContainer asCollectionContainer();

MapContainer asMapContainer();

static Container resolveField(Field field) {
Container container = resolveContainerofGeneric(field.getGenericType());
Class clazz = null;
if (field.isAnnotationPresent(RLPDecoding.class)) {
clazz = field.getAnnotation(RLPDecoding.class).as();
}

if(clazz == null || clazz == Void.class) return container;
if(container.getContainerType() == ContainerType.RAW)
throw new RuntimeException("@RLPDecoding.as is used on collection or map type");
if(!field.getType().isAssignableFrom(clazz))
throw new RuntimeException("cannot assign " + clazz + " as " + field.getType());
if(container.getContainerType() == ContainerType.COLLECTION){
container.asCollectionContainer().collectionType = clazz;
}
if(container.getContainerType() == ContainerType.MAP){
container.asMapContainer().mapType = clazz;
}
return container;
}

static Container resolveContainerOfNoGeneric(Class clazz){
if(Collection.class.isAssignableFrom(clazz)){
CollectionContainer con = new CollectionContainer();
con.contentType = new Raw(RLPElement.class);
con.collectionType = clazz;
return con;
}
if(Map.class.isAssignableFrom(clazz)){
MapContainer con = new MapContainer();
con.keyType = new Raw(RLPElement.class);
con.valueType = new Raw(RLPElement.class);
con.mapType = clazz;
return con;
}
return new Raw(clazz);
}

static Container resolveContainerofGeneric(Type type) {
if (!(type instanceof ParameterizedType)) {
Class clazz = (Class<?>) type;
return resolveContainerOfNoGeneric(clazz);
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Class clazz = (Class) parameterizedType.getRawType();
if (Collection.class.isAssignableFrom(clazz)) {
CollectionContainer con = new CollectionContainer();
con.contentType = resolveContainerofGeneric(parameterizedType.getActualTypeArguments()[0]);
con.collectionType = clazz;
return con;
}
if (Map.class.isAssignableFrom(clazz)) {
MapContainer con = new MapContainer();
con.keyType = resolveContainerofGeneric(parameterizedType.getActualTypeArguments()[0]);
con.valueType = resolveContainerofGeneric(parameterizedType.getActualTypeArguments()[1]);
con.mapType = clazz;
return con;
}
return resolveContainerOfNoGeneric(clazz);
}
}
7 changes: 7 additions & 0 deletions 7 src/main/java/org/tdf/rlp/ContainerType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.tdf.rlp;

public enum ContainerType {
RAW,
COLLECTION,
MAP
}
2 changes: 1 addition & 1 deletion 2 src/main/java/org/tdf/rlp/LazyByteArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import java.util.Arrays;

// reduce byte array copy by lazy loading
class LazyByteArray {
final class LazyByteArray {
private byte[] data;
private int offset;
private int limit;
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.