├── .editorconfig ├── .github └── workflows │ └── maven.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── TODO.md ├── doc ├── img │ ├── large.png │ ├── medium.png │ ├── small.png │ ├── smartbuf-packet.png │ └── smartbuf-stream.png └── index_zh.md ├── pom.xml └── src ├── main └── java │ └── com │ └── github │ └── smartbuf │ ├── SmartBuf.java │ ├── SmartPacket.java │ ├── SmartStream.java │ ├── Type.java │ ├── converter │ ├── BeanInfo.java │ ├── Codec.java │ ├── CodecFactory.java │ ├── Converter.java │ ├── ConverterMap.java │ ├── ConverterMethod.java │ ├── ConverterPipeline.java │ ├── RealConverterMethod.java │ ├── TranConverterMethod.java │ └── codec │ │ ├── ArrayCodec.java │ │ ├── AtomicCodec.java │ │ ├── AwtCodec.java │ │ ├── BufferCodec.java │ │ ├── CollectionCodec.java │ │ ├── IOCodec.java │ │ ├── JavaxCodec.java │ │ ├── JodaCodec.java │ │ ├── LangCodec.java │ │ ├── MapCodec.java │ │ ├── MathCodec.java │ │ ├── NetCodec.java │ │ ├── NumberCodec.java │ │ ├── PrimaryCodec.java │ │ ├── ReferenceCodec.java │ │ ├── SqlCodec.java │ │ ├── StringCodec.java │ │ ├── ThrowableCodec.java │ │ ├── TimeCodec.java │ │ └── UtilCodec.java │ ├── exception │ ├── CircleReferenceException.java │ ├── InvalidDataException.java │ ├── InvalidStructException.java │ ├── InvalidVersionException.java │ ├── MismatchModeException.java │ ├── NoShortestPipelineException.java │ ├── OutOfSpaceException.java │ ├── SmartBufClosedException.java │ ├── UnexpectedReadException.java │ └── UnexpectedSequenceException.java │ ├── node │ ├── Node.java │ ├── NodeCodec.java │ ├── NodeType.java │ ├── array │ │ ├── ArrayNode.java │ │ ├── BooleanArrayNode.java │ │ ├── ByteArrayNode.java │ │ ├── DoubleArrayNode.java │ │ ├── FloatArrayNode.java │ │ ├── IntArrayNode.java │ │ ├── LongArrayNode.java │ │ └── ShortArrayNode.java │ └── basic │ │ ├── BooleanNode.java │ │ ├── DoubleNode.java │ │ ├── FloatNode.java │ │ ├── ObjectNode.java │ │ ├── StringNode.java │ │ ├── SymbolNode.java │ │ └── VarintNode.java │ ├── reflect │ ├── BeanField.java │ ├── BeanReader.java │ ├── BeanReaderBuilder.java │ ├── BeanWriter.java │ ├── BeanWriterBuilder.java │ ├── TypeRef.java │ ├── XField.java │ ├── XType.java │ ├── XTypeFactory.java │ └── XTypeUtils.java │ ├── transport │ ├── Array.java │ ├── Const.java │ ├── IDAllocator.java │ ├── Input.java │ ├── InputBuffer.java │ ├── InputDataPool.java │ ├── InputMetaPool.java │ ├── Output.java │ ├── OutputBuffer.java │ ├── OutputDataPool.java │ └── OutputMetaPool.java │ └── utils │ ├── ASMUtils.java │ ├── ArrayUtils.java │ ├── CodecUtils.java │ ├── NumberUtils.java │ ├── ReflectUtils.java │ ├── TimeUtils.java │ └── UTF8Utils.java └── test ├── java └── com │ └── github │ └── smartbuf │ ├── SmartPacketTest.java │ ├── SmartStreamTest.java │ ├── World.java │ ├── benchmark │ ├── Runner.java │ ├── TestBenchmark.java │ ├── large │ │ ├── Large.java │ │ ├── LargeDeserBenchmark.java │ │ ├── LargeSerialBenchmark.java │ │ ├── LargeTest.java │ │ └── TrendModel.java │ ├── medium │ │ ├── Medium.java │ │ ├── MediumDeserBenchmark.java │ │ ├── MediumSerialBenchmark.java │ │ ├── MediumTest.java │ │ └── UserModel.java │ ├── small │ │ ├── Small.java │ │ ├── SmallDeserBenchmark.java │ │ ├── SmallSerialBenchmark.java │ │ ├── SmallTest.java │ │ └── UserModel.java │ └── tiny │ │ ├── Tiny.java │ │ └── TinyTest.java │ ├── converter │ ├── CodecFactoryTest.java │ ├── CodecTest.java │ ├── ConverterMapTest.java │ ├── ConverterMethodTest.java │ ├── ConverterPipelineTest.java │ └── codec │ │ ├── ArrayCodecTest.java │ │ ├── AtomicCodecTest.java │ │ ├── AwtCodecTest.java │ │ ├── BufferCodecTest.java │ │ ├── CollectionCodecTest.java │ │ ├── IOCodecTest.java │ │ ├── JavaxCodecTest.java │ │ ├── JodaCodecTest.java │ │ ├── LangCodecTest.java │ │ ├── MapCodecTest.java │ │ ├── MathCodecTest.java │ │ ├── NetCodecTest.java │ │ ├── NumberCodecTest.java │ │ ├── PrimaryCodecTest.java │ │ ├── ReferenceCodecTest.java │ │ ├── SqlCodecTest.java │ │ ├── StringCodecTest.java │ │ ├── ThrowableCodecTest.java │ │ ├── TimeCodecTest.java │ │ └── UtilCodecTest.java │ ├── model │ └── MessageOuterClass.java │ ├── node │ ├── NodeCodecTest.java │ └── NodeTest.java │ ├── reflect │ ├── BeanReaderBenchmark.java │ ├── BeanReaderBuilderTest.java │ ├── BeanReaderTest.java │ ├── BeanWriterBuilderTest.java │ ├── BeanWriterTest.java │ ├── GenericModel.java │ ├── TypeRefTest.java │ ├── TypeTest.java │ ├── XTypeFactoryTest.java │ ├── XTypeTest.java │ └── XTypeUtilsTest.java │ ├── transport │ ├── ArrayTest.java │ ├── BufferTest.java │ ├── DataPoolTest.java │ ├── IDAllocatorTest.java │ ├── IOArrayTest.java │ ├── IOExpireTest.java │ ├── IOFullTest.java │ ├── IOObjectTest.java │ ├── IOSliceTest.java │ ├── IOTest.java │ ├── MetaPoolTest.java │ └── OutputTest.java │ └── utils │ ├── ASMUtilsTest.java │ ├── ArrayUtilsTest.java │ ├── NumberUtilsTest.java │ ├── ReflectUtilsTest.java │ ├── TimeUtilsTest.java │ └── UTF8UtilsTest.java └── resources ├── large.json ├── logback.xml └── proto ├── large.proto ├── medium.proto ├── message.proto ├── small.proto └── tiny.proto /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset = utf-8 3 | end_of_line = lf 4 | indent_style = space 5 | indent_size = 4 6 | insert_final_newline = true 7 | 8 | [*.yml] 9 | indent_size = 2 10 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | name: Java CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v1 15 | - name: Set up JDK 1.8 16 | uses: actions/setup-java@v1 17 | with: 18 | java-version: 1.8 19 | - name: Build with Maven 20 | run: mvn -B package --file pom.xml 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | target/ 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | sudo: false # faster builds 3 | install: true 4 | script: mvn clean test 5 | 6 | after_success: 7 | - bash <(curl -s https://codecov.io/bash) -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | 1. Support self-reference 2 | -------------------------------------------------------------------------------- /doc/img/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartbuf/smartbuf-java/c069efc25b376852e377bf4d83d8637d9b354ef6/doc/img/large.png -------------------------------------------------------------------------------- /doc/img/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartbuf/smartbuf-java/c069efc25b376852e377bf4d83d8637d9b354ef6/doc/img/medium.png -------------------------------------------------------------------------------- /doc/img/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartbuf/smartbuf-java/c069efc25b376852e377bf4d83d8637d9b354ef6/doc/img/small.png -------------------------------------------------------------------------------- /doc/img/smartbuf-packet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartbuf/smartbuf-java/c069efc25b376852e377bf4d83d8637d9b354ef6/doc/img/smartbuf-packet.png -------------------------------------------------------------------------------- /doc/img/smartbuf-stream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartbuf/smartbuf-java/c069efc25b376852e377bf4d83d8637d9b354ef6/doc/img/smartbuf-stream.png -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/SmartStream.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf; 2 | 3 | import com.github.smartbuf.reflect.TypeRef; 4 | 5 | import java.io.IOException; 6 | 7 | /** 8 | * SmartStream provides an easy way to use "smartbuf" protocol in stream-mode, 9 | * It's similar to {@link SmartPacket}, but support the context concept. 10 | *

11 | * SmartStream is not thread-safe, you have to use it in single thread and orderly. 12 | * Otherwise, it will go into error. 13 | * 14 | * @author sulin 15 | * @since 2019-10-25 14:40:52 16 | */ 17 | public final class SmartStream { 18 | 19 | public final SmartBuf buf; 20 | 21 | /** 22 | * Initialize SmartStream 23 | */ 24 | public SmartStream() { 25 | this.buf = new SmartBuf(true); 26 | } 27 | 28 | /** 29 | * Use stream-mode to serialize the specified object into byte[]. 30 | * 31 | * @param obj The object need to serialize 32 | * @return Serialization result 33 | * @throws IOException if an I/O error occurs. 34 | */ 35 | public byte[] serialize(Object obj) throws IOException { 36 | return buf.write(obj); 37 | } 38 | 39 | /** 40 | * Use stream-mode to deserialize byte[] into an object of the specified class. 41 | * 42 | * @param data Binary data in packet-mode format 43 | * @param tClz The specified class to convert 44 | * @param Template of target class 45 | * @return Deserialization result 46 | * @throws IOException if an I/O error occurs. 47 | */ 48 | public T deserialize(byte[] data, Class tClz) throws IOException { 49 | return buf.read(data, tClz); 50 | } 51 | 52 | /** 53 | * Use stream-mode to deserialize byte[] into an object of the specified type, 54 | * could used for supporting generic type. 55 | * 56 | * @param data Binary data in packet-mode format 57 | * @param tRef The specified type to convert 58 | * @param Template of target type 59 | * @return Deserialization result 60 | * @throws IOException if an I/O error occurs. 61 | */ 62 | public T deserialize(byte[] data, TypeRef tRef) throws IOException { 63 | return buf.read(data, tRef); 64 | } 65 | 66 | /** 67 | * Close this instance, would close the underlying SmartBuf instance. 68 | */ 69 | public void close() { 70 | buf.close(); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/Type.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf; 2 | 3 | import java.util.Collection; 4 | 5 | /** 6 | * Redefine some common data types to use switch replacing if/else 7 | * 8 | * @author sulin 9 | * @since 2019-11-10 12:21:55 10 | */ 11 | public enum Type { 12 | 13 | Z, 14 | B, 15 | S, 16 | I, 17 | J, 18 | F, 19 | D, 20 | C, 21 | 22 | BOOLEAN, 23 | BYTE, 24 | SHORT, 25 | INTEGER, 26 | LONG, 27 | FLOAT, 28 | DOUBLE, 29 | CHAR, 30 | STRING, 31 | SYMBOL, 32 | 33 | ARRAY, 34 | ARRAY_BOOL, 35 | ARRAY_BYTE, 36 | ARRAY_SHORT, 37 | ARRAY_INT, 38 | ARRAY_LONG, 39 | ARRAY_FLOAT, 40 | ARRAY_DOUBLE, 41 | ARRAY_CHAR, 42 | COLLECTION, 43 | OBJECT, 44 | UNKNOWN; 45 | 46 | /** 47 | * Get Type instance by the specified class 48 | * 49 | * @param cls Original class 50 | * @return Redefined Type 51 | */ 52 | public static Type valueOf(Class cls) { 53 | if (cls == boolean.class) { 54 | return Z; 55 | } else if (cls == Boolean.class) { 56 | return BOOLEAN; 57 | } else if (cls == float.class) { 58 | return F; 59 | } else if (cls == Float.class) { 60 | return FLOAT; 61 | } else if (cls == double.class) { 62 | return D; 63 | } else if (cls == Double.class) { 64 | return DOUBLE; 65 | } else if (cls == byte.class) { 66 | return B; 67 | } else if (cls == Byte.class) { 68 | return BYTE; 69 | } else if (cls == short.class) { 70 | return S; 71 | } else if (cls == Short.class) { 72 | return SHORT; 73 | } else if (cls == int.class) { 74 | return I; 75 | } else if (cls == Integer.class) { 76 | return INTEGER; 77 | } else if (cls == long.class) { 78 | return J; 79 | } else if (cls == Long.class) { 80 | return LONG; 81 | } else if (cls == char.class) { 82 | return C; 83 | } else if (cls == Character.class) { 84 | return CHAR; 85 | } else if (CharSequence.class.isAssignableFrom(cls)) { 86 | return STRING; 87 | } else if (Enum.class.isAssignableFrom(cls)) { 88 | return SYMBOL; 89 | } else if (Collection.class.isAssignableFrom(cls)) { 90 | return COLLECTION; 91 | } else if (cls.isArray()) { 92 | if (cls == boolean[].class) { 93 | return ARRAY_BOOL; 94 | } else if (cls == byte[].class) { 95 | return ARRAY_BYTE; 96 | } else if (cls == short[].class) { 97 | return ARRAY_SHORT; 98 | } else if (cls == int[].class) { 99 | return ARRAY_INT; 100 | } else if (cls == long[].class) { 101 | return ARRAY_LONG; 102 | } else if (cls == float[].class) { 103 | return ARRAY_FLOAT; 104 | } else if (cls == double[].class) { 105 | return ARRAY_DOUBLE; 106 | } else if (cls == char[].class) { 107 | return ARRAY_CHAR; 108 | } else { 109 | return ARRAY; 110 | } 111 | } else { 112 | return UNKNOWN; 113 | } 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/BeanInfo.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter; 2 | 3 | import com.github.smartbuf.reflect.BeanWriter; 4 | 5 | /** 6 | * BeanInfo helps convert map or objectnode to T 7 | * 8 | * @author sulin 9 | * @since 2019-11-11 17:59:11 10 | */ 11 | public final class BeanInfo { 12 | 13 | private final BeanWriter writer; 14 | private final Object[] values; 15 | 16 | public BeanInfo(BeanWriter writer, Object[] values) { 17 | this.writer = writer; 18 | this.values = values; 19 | } 20 | 21 | public BeanWriter getWriter() { 22 | return writer; 23 | } 24 | 25 | public Object[] getValues() { 26 | return values; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/Codec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter; 2 | 3 | import com.github.smartbuf.reflect.XType; 4 | 5 | import java.lang.reflect.Type; 6 | 7 | /** 8 | * Codec's base class. 9 | * 10 | * @author sulin 11 | * @since 2019-05-12 16:01:19 12 | */ 13 | public abstract class Codec { 14 | 15 | private CodecFactory factory; 16 | 17 | /** 18 | * Setup {@link CodecFactory} which owns this codec instance. 19 | * 20 | * @param factory The CodecFactory owns this 21 | */ 22 | public void setFactory(CodecFactory factory) { 23 | this.factory = factory; 24 | } 25 | 26 | /** 27 | * Proxy of {@link CodecFactory#toXType(Type)} 28 | * 29 | * @param type The original java type 30 | * @return The parsed xtype, which contains generic info 31 | */ 32 | protected final XType toXType(Type type) { 33 | return factory.toXType(type); 34 | } 35 | 36 | /** 37 | * Proxy of {@link CodecFactory#doConvert(Object, XType)} 38 | * 39 | * @param src The source object, could be null 40 | * @param tgtType The target type 41 | * @return New object which is instance of tgtType 42 | */ 43 | protected final Object convert(Object src, XType tgtType) { 44 | return factory.doConvert(src, tgtType); 45 | } 46 | 47 | /** 48 | * Proxy of {@link CodecFactory#doConvert(Object, XType)} 49 | * 50 | * @param src The source object, could be null 51 | * @param clz The target java class 52 | * @param clz's template type 53 | * @return new object which is instance of clz 54 | */ 55 | @SuppressWarnings("unchecked") 56 | protected final T convert(Object src, Class clz) { 57 | return (T) factory.doConvert(src, toXType(clz)); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/Converter.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | import static java.lang.annotation.ElementType.*; 9 | 10 | /** 11 | * Data converter 12 | * 13 | * @author sulin 14 | * @since 2019-07-11 14:24:09 15 | */ 16 | @Documented 17 | @Retention(RetentionPolicy.RUNTIME) 18 | @Target(value = {METHOD}) 19 | public @interface Converter { 20 | 21 | /** 22 | * Indicate this converter accept null or not, 23 | * which means null shouldn't be passed into converter. 24 | * 25 | * @return default false 26 | */ 27 | boolean nullable() default false; 28 | 29 | /** 30 | * Indicate this converter is extensible or not, 31 | * which means converter support target-class's subclass 32 | * 33 | * @return default false 34 | */ 35 | boolean extensible() default false; 36 | 37 | /** 38 | * Indicate this converter's distance, used for dfs. 39 | * 40 | * @return default 100 41 | */ 42 | int distance() default 100; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/ConverterMethod.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter; 2 | 3 | import com.github.smartbuf.reflect.XType; 4 | import lombok.Getter; 5 | 6 | /** 7 | * ConverterMethod represent a method for converting data from srcClass to tgtClass 8 | * 9 | * @author sulin 10 | * @since 2019-08-01 20:41:42 11 | */ 12 | @Getter 13 | public abstract class ConverterMethod { 14 | 15 | private final Class srcClass; 16 | private final Class tgtClass; 17 | 18 | public ConverterMethod(Class srcClass, Class tgtClass) { 19 | this.srcClass = srcClass; 20 | this.tgtClass = tgtClass; 21 | } 22 | 23 | /** 24 | * Convert the data to target instance 25 | * 26 | * @param data Source data 27 | * @param tgtType Target Type 28 | * @return target instance 29 | */ 30 | public abstract Object convert(Object data, XType tgtType); 31 | 32 | /** 33 | * The distance in map, which used for shortest calculation. 34 | * 35 | * @return Distance 36 | */ 37 | public abstract int getDistance(); 38 | 39 | /** 40 | * This method is extensible or not. 41 | * 42 | * @return extensible 43 | */ 44 | public abstract boolean isExtensible(); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/RealConverterMethod.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter; 2 | 3 | import com.github.smartbuf.reflect.XType; 4 | import lombok.extern.slf4j.Slf4j; 5 | 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * ConvertMethod, Must match `[S] S convert(T t, Class[S] clz)` 10 | * 11 | * @author sulin 12 | * @since 2019-06-06 12:19:53 13 | */ 14 | @Slf4j 15 | public final class RealConverterMethod extends ConverterMethod { 16 | 17 | protected Codec codec; 18 | protected boolean hasTypeArg; 19 | protected Converter annotation; 20 | protected Method method; 21 | 22 | RealConverterMethod(Class srcClass, Class tgtClass) { 23 | super(srcClass, tgtClass); 24 | } 25 | 26 | /** 27 | * Create RealConverterMethod by Codec and Method 28 | * 29 | * @param codec Codec instance 30 | * @param method Method reference 31 | * @return RealConverterMethod 32 | */ 33 | public static RealConverterMethod valueOf(Codec codec, Method method) { 34 | Class[] argTypes = method.getParameterTypes(); 35 | Class rtType = method.getReturnType(); 36 | Converter annotation = method.getAnnotation(Converter.class); 37 | if (annotation == null) { 38 | log.debug("ignore method that don't have @Converter: {}", method); 39 | return null; 40 | } 41 | if (method.isVarArgs()) { 42 | log.debug("ignore varargs method: {}", method); 43 | return null; 44 | } 45 | if (rtType == void.class || rtType == Void.class) { 46 | log.debug("ignore method by void return: {}", method); 47 | return null; // ignore void return 48 | } 49 | if (argTypes.length != 1 && argTypes.length != 2) { 50 | log.debug("ignore method by argument count: {}", method); 51 | return null; 52 | } 53 | if (argTypes.length == 2 && argTypes[1] != XType.class) { 54 | log.debug("ignore method by the second argument!=Type: {}", method); 55 | return null; 56 | } 57 | RealConverterMethod result = new RealConverterMethod(argTypes[0], rtType); 58 | result.annotation = annotation; 59 | result.method = method; 60 | result.codec = codec; 61 | result.hasTypeArg = argTypes.length == 2; 62 | return result; 63 | } 64 | 65 | @Override 66 | public Object convert(Object data, XType tgtType) { 67 | if (!annotation.nullable() && data == null) { 68 | return null; 69 | } 70 | if (data != null && !this.getSrcClass().isAssignableFrom(data.getClass())) { 71 | throw new IllegalArgumentException("data type unmatched: " + this.getSrcClass() + ", " + data.getClass()); 72 | } 73 | try { 74 | if (hasTypeArg) { 75 | return method.invoke(codec, data, tgtType); 76 | } else { 77 | return method.invoke(codec, data); 78 | } 79 | } catch (Exception e) { 80 | throw new IllegalStateException("invoke codec failed.", e); 81 | } 82 | } 83 | 84 | @Override 85 | public int getDistance() { 86 | return annotation.distance(); 87 | } 88 | 89 | @Override 90 | public boolean isExtensible() { 91 | return annotation.extensible(); 92 | } 93 | 94 | public boolean isHasTypeArg() { 95 | return hasTypeArg; 96 | } 97 | 98 | @Override 99 | public String toString() { 100 | return String.format("[%s]", method.toString()); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/TranConverterMethod.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter; 2 | 3 | import com.github.smartbuf.reflect.XType; 4 | 5 | /** 6 | * Simple convert data from subclass to class 7 | * 8 | * @author sulin 9 | * @since 2019-08-01 20:13:39 10 | */ 11 | public final class TranConverterMethod extends ConverterMethod { 12 | 13 | public TranConverterMethod(Class srcClass, Class tgtClass) { 14 | super(srcClass, tgtClass); 15 | } 16 | 17 | @Override 18 | public Object convert(Object data, XType tgtType) { 19 | return data; 20 | } 21 | 22 | @Override 23 | public int getDistance() { 24 | return 1 << 4; 25 | } 26 | 27 | @Override 28 | public boolean isExtensible() { 29 | return false; 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return String.format("[%s->%s]", getSrcClass().getName(), getTgtClass().getName()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/codec/AtomicCodec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.Codec; 4 | import com.github.smartbuf.converter.Converter; 5 | import com.github.smartbuf.reflect.XType; 6 | 7 | import java.util.concurrent.atomic.*; 8 | 9 | /** 10 | * Codec for java.util.concurrent.atomic package. 11 | * 12 | * @author sulin 13 | * @since 2019-07-25 12:00:54 14 | */ 15 | public final class AtomicCodec extends Codec { 16 | 17 | @Converter 18 | public AtomicBoolean toAtomicBoolean(Boolean b) { 19 | return new AtomicBoolean(b); 20 | } 21 | 22 | @Converter 23 | public Boolean toBoolean(AtomicBoolean ab) { 24 | return ab.get(); 25 | } 26 | 27 | @Converter 28 | public AtomicIntegerArray toAtomicIntegerArray(int[] arr) { 29 | return new AtomicIntegerArray(arr); 30 | } 31 | 32 | @Converter 33 | public int[] toIntegerArray(AtomicIntegerArray aia) { 34 | int[] result = new int[aia.length()]; 35 | for (int i = 0; i < result.length; i++) { 36 | result[i] = aia.get(i); 37 | } 38 | return result; 39 | } 40 | 41 | @Converter 42 | public AtomicInteger toAtomicInteger(Integer i) { 43 | return new AtomicInteger(i); 44 | } 45 | 46 | @Converter 47 | public Integer toInteger(AtomicInteger ai) { 48 | return ai.get(); 49 | } 50 | 51 | @Converter 52 | public AtomicLongArray toAtomicLongArray(long[] arr) { 53 | return new AtomicLongArray(arr); 54 | } 55 | 56 | @Converter 57 | public long[] toLongArray(AtomicLongArray ala) { 58 | long[] result = new long[ala.length()]; 59 | for (int i = 0; i < result.length; i++) { 60 | result[i] = ala.get(i); 61 | } 62 | return result; 63 | } 64 | 65 | @Converter 66 | public AtomicLong toAtomicLong(Long l) { 67 | return new AtomicLong(l); 68 | } 69 | 70 | @Converter 71 | public Long toLong(AtomicLong al) { 72 | return al.get(); 73 | } 74 | 75 | @Converter 76 | public AtomicReference toAtomicReference(Object obj, XType type) { 77 | XType refType = type.getParameterizedType(); 78 | if (refType.isPure() && refType.getRawType().isAssignableFrom(obj.getClass())) { 79 | return new AtomicReference<>(obj); // compatible 80 | } 81 | return new AtomicReference<>(convert(obj, refType)); 82 | } 83 | 84 | @Converter(extensible = true) 85 | public Object toObject(AtomicReference ref, XType type) { 86 | Object data = ref.get(); 87 | return convert(data, type); 88 | } 89 | 90 | @Converter 91 | public DoubleAdder toDoubleAdder(Double d) { 92 | DoubleAdder addr = new DoubleAdder(); 93 | addr.add(d); 94 | return addr; 95 | } 96 | 97 | @Converter 98 | public Double toDouble(DoubleAdder adder) { 99 | return adder.doubleValue(); 100 | } 101 | 102 | @Converter 103 | public LongAdder toLongAdder(Long l) { 104 | LongAdder adder = new LongAdder(); 105 | adder.add(l); 106 | return adder; 107 | } 108 | 109 | @Converter 110 | public Long toLong(LongAdder adder) { 111 | return adder.longValue(); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/codec/AwtCodec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.Codec; 4 | import com.github.smartbuf.converter.Converter; 5 | 6 | import java.awt.*; 7 | import java.util.HashMap; 8 | import java.util.LinkedHashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * Codec for `java.awt` package, support Point/Dimension/Rectangle/Font/Color/etc. 13 | * 14 | * @author sulin 15 | * @since 2019-07-25 14:28:03 16 | */ 17 | @SuppressWarnings({"MagicConstant"}) 18 | public final class AwtCodec extends Codec { 19 | 20 | private final String FONT_NAME = "name"; 21 | private final String FONT_STYLE = "style"; 22 | private final String FONT_SIZE = "size"; 23 | private final String POINT_X = "x"; 24 | private final String POINT_Y = "y"; 25 | private final String DIMENSION_WIDTH = "width"; 26 | private final String DIMENSION_HEIGHT = "height"; 27 | 28 | @Converter 29 | public Font toFont(Map map) { 30 | String name = convert(map.get(FONT_NAME), String.class); 31 | Integer style = convert(map.get(FONT_STYLE), Integer.class); 32 | Integer size = convert(map.get(FONT_SIZE), Integer.class); 33 | if (style == null) { 34 | style = Font.PLAIN; 35 | } 36 | if (size == null) { 37 | size = 12; 38 | } 39 | return new Font(name, style, size); 40 | } 41 | 42 | @Converter 43 | public Map toMap(Font font) { 44 | Map map = new LinkedHashMap<>(); 45 | map.put(FONT_NAME, font.getName()); 46 | map.put(FONT_STYLE, font.getStyle()); 47 | map.put(FONT_SIZE, font.getSize()); 48 | 49 | return map; 50 | } 51 | 52 | /* 53 | * Convert Color to String, like #00112233 54 | */ 55 | @Converter 56 | public String toString(Color c) { 57 | return String.format("#%02x%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()); 58 | } 59 | 60 | /* 61 | * Convert String to Color, support like #001122 or #00112233 62 | */ 63 | @Converter 64 | public Color toColor(String s) { 65 | int value = Integer.decode(s); 66 | if (s.length() == 9 && s.charAt(0) == '#') { 67 | return new Color(value >> 24 & 0xFF, value >> 16 & 0xFF, value >> 8 & 0xFF, value & 0xFF); 68 | } 69 | return new Color((value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF); 70 | } 71 | 72 | @Converter 73 | public Map toMap(Point point) { 74 | Map map = new HashMap<>(); 75 | map.put(POINT_X, (int) point.getX()); 76 | map.put(POINT_Y, (int) point.getY()); 77 | return map; 78 | } 79 | 80 | @Converter 81 | public Point toPoint(Map map) { 82 | Integer x = convert(map.get(POINT_X), Integer.class); 83 | Integer y = convert(map.get(POINT_Y), Integer.class); 84 | return new Point(x, y); 85 | } 86 | 87 | @Converter 88 | public Map toMap(Dimension dimension) { 89 | Map map = new HashMap<>(); 90 | map.put(DIMENSION_WIDTH, (int) dimension.getWidth()); 91 | map.put(DIMENSION_HEIGHT, (int) dimension.getHeight()); 92 | return map; 93 | } 94 | 95 | @Converter 96 | public Dimension toDimension(Map map) { 97 | Integer width = convert(map.get(DIMENSION_WIDTH), Integer.class); 98 | Integer height = convert(map.get(DIMENSION_HEIGHT), Integer.class); 99 | return new Dimension(width, height); 100 | } 101 | 102 | @Converter 103 | public Map toMap(Rectangle rect) { 104 | Map map = new HashMap<>(); 105 | map.put(POINT_X, (int) rect.getX()); 106 | map.put(POINT_Y, (int) rect.getY()); 107 | map.put(DIMENSION_WIDTH, (int) rect.getWidth()); 108 | map.put(DIMENSION_HEIGHT, (int) rect.getHeight()); 109 | return map; 110 | } 111 | 112 | @Converter 113 | public Rectangle toRectangle(Map map) { 114 | Integer x = convert(map.get(POINT_X), Integer.class); 115 | Integer y = convert(map.get(POINT_Y), Integer.class); 116 | Integer width = convert(map.get(DIMENSION_WIDTH), Integer.class); 117 | Integer height = convert(map.get(DIMENSION_HEIGHT), Integer.class); 118 | return new Rectangle(x, y, width, height); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/codec/BufferCodec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.Converter; 4 | import com.github.smartbuf.converter.Codec; 5 | 6 | import java.nio.*; 7 | 8 | /** 9 | * Codec for java.nio.Buffer, and correlated class 10 | * 11 | * @author sulin 12 | * @since 2019-07-25 17:32:41 13 | */ 14 | public final class BufferCodec extends Codec { 15 | 16 | @Converter 17 | public byte[] toByteArray(ByteBuffer buf) { 18 | byte[] arr = new byte[buf.remaining()]; 19 | buf.get(arr, 0, arr.length); 20 | return arr; 21 | } 22 | 23 | @Converter 24 | public ByteBuffer toByteBuffer(byte[] bs) { 25 | return ByteBuffer.wrap(bs); 26 | } 27 | 28 | @Converter 29 | public char[] toCharArray(CharBuffer buf) { 30 | char[] arr = new char[buf.remaining()]; 31 | buf.get(arr, 0, arr.length); 32 | return arr; 33 | } 34 | 35 | @Converter 36 | public CharBuffer toCharBuffer(char[] chars) { 37 | return CharBuffer.wrap(chars); 38 | } 39 | 40 | @Converter 41 | public CharBuffer toCharBuffer(ByteBuffer buf) { 42 | return buf.asCharBuffer(); 43 | } 44 | 45 | @Converter 46 | public float[] toFloatArray(FloatBuffer buf) { 47 | float[] arr = new float[buf.remaining()]; 48 | buf.get(arr, 0, arr.length); 49 | return arr; 50 | } 51 | 52 | @Converter 53 | public FloatBuffer toFloatBuffer(float[] floats) { 54 | return FloatBuffer.wrap(floats); 55 | } 56 | 57 | @Converter 58 | public FloatBuffer toFloatBuffer(ByteBuffer buf) { 59 | return buf.asFloatBuffer(); 60 | } 61 | 62 | @Converter 63 | public double[] toDoubleArray(DoubleBuffer buf) { 64 | double[] arr = new double[buf.remaining()]; 65 | buf.get(arr, 0, arr.length); 66 | return arr; 67 | } 68 | 69 | @Converter 70 | public DoubleBuffer toDoubleBuffer(double[] doubles) { 71 | return DoubleBuffer.wrap(doubles); 72 | } 73 | 74 | @Converter 75 | public DoubleBuffer toDoubleBuffer(ByteBuffer buf) { 76 | return buf.asDoubleBuffer(); 77 | } 78 | 79 | @Converter 80 | public short[] toShortArray(ShortBuffer buf) { 81 | short[] arr = new short[buf.remaining()]; 82 | buf.get(arr, 0, arr.length); 83 | return arr; 84 | } 85 | 86 | @Converter 87 | public ShortBuffer toShortBuffer(short[] shorts) { 88 | return ShortBuffer.wrap(shorts); 89 | } 90 | 91 | @Converter 92 | public ShortBuffer toShortBuffer(ByteBuffer buf) { 93 | return buf.asShortBuffer(); 94 | } 95 | 96 | @Converter 97 | public int[] toIntArray(IntBuffer buf) { 98 | int[] arr = new int[buf.remaining()]; 99 | buf.get(arr, 0, arr.length); 100 | return arr; 101 | } 102 | 103 | @Converter 104 | public IntBuffer toIntBuffer(int[] ints) { 105 | return IntBuffer.wrap(ints); 106 | } 107 | 108 | @Converter 109 | public IntBuffer toIntBuffer(ByteBuffer buf) { 110 | return buf.asIntBuffer(); 111 | } 112 | 113 | @Converter 114 | public long[] toLongArray(LongBuffer buf) { 115 | long[] arr = new long[buf.remaining()]; 116 | buf.get(arr, 0, arr.length); 117 | return arr; 118 | } 119 | 120 | @Converter 121 | public LongBuffer toLongBuffer(long[] longs) { 122 | return LongBuffer.wrap(longs); 123 | } 124 | 125 | @Converter 126 | public LongBuffer toLongBuffer(ByteBuffer buf) { 127 | return buf.asLongBuffer(); 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/codec/IOCodec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.Codec; 4 | import com.github.smartbuf.converter.Converter; 5 | import com.github.smartbuf.reflect.XType; 6 | 7 | import java.io.*; 8 | import java.nio.CharBuffer; 9 | import java.nio.charset.Charset; 10 | 11 | /** 12 | * Codec for `java.io` and `java.nio` packages. 13 | * 14 | * @author sulin 15 | * @since 2019-07-25 14:40:12 16 | */ 17 | public final class IOCodec extends Codec { 18 | 19 | @Converter 20 | public Charset toCharset(String s) { 21 | return Charset.forName(s); 22 | } 23 | 24 | @Converter 25 | public String toString(Charset c) { 26 | return c.name(); 27 | } 28 | 29 | @Converter 30 | public String toString(File file) { 31 | return file.toString(); 32 | } 33 | 34 | @Converter 35 | public byte[] toByteArray(InputStream is) throws IOException { 36 | ByteArrayOutputStream output = new ByteArrayOutputStream(); 37 | byte[] buffer = new byte[1024]; 38 | for (int n; (n = is.read(buffer)) >= 0; ) { 39 | output.write(buffer, 0, n); 40 | } 41 | return output.toByteArray(); 42 | } 43 | 44 | @Converter 45 | public InputStream toInputStream(byte[] bytes, XType type) { 46 | Class clz = type.getRawType(); 47 | if (clz.isAssignableFrom(ByteArrayInputStream.class)) { 48 | return new ByteArrayInputStream(bytes); 49 | } 50 | if (clz.isAssignableFrom(BufferedInputStream.class)) { 51 | return new BufferedInputStream(new ByteArrayInputStream(bytes)); 52 | } 53 | if (clz.isAssignableFrom(DataInputStream.class)) { 54 | return new DataInputStream(new ByteArrayInputStream(bytes)); 55 | } 56 | throw new UnsupportedOperationException("unsupported type: " + clz); 57 | } 58 | 59 | @Converter 60 | public String toString(Readable reader) throws IOException { 61 | StringBuilder sb = new StringBuilder(); 62 | CharBuffer buf = CharBuffer.allocate(1024); 63 | while (reader.read(buf) >= 0) { 64 | buf.flip(); 65 | while (buf.hasRemaining()) { 66 | sb.append(buf.get()); 67 | } 68 | buf.clear(); 69 | } 70 | return sb.toString(); 71 | } 72 | 73 | @Converter 74 | public Readable toReadable(String s, XType type) { 75 | Class clz = type.getRawType(); 76 | if (clz.isAssignableFrom(StringReader.class)) { 77 | return new StringReader(s); 78 | } 79 | if (clz.isAssignableFrom(CharArrayReader.class)) { 80 | return new CharArrayReader(s.toCharArray()); 81 | } 82 | if (clz.isAssignableFrom(BufferedReader.class)) { 83 | return new BufferedReader(new StringReader(s)); 84 | } 85 | 86 | throw new UnsupportedOperationException("Unsupported Readable: " + clz); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/codec/JavaxCodec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.Codec; 4 | import com.github.smartbuf.converter.Converter; 5 | 6 | import javax.xml.datatype.XMLGregorianCalendar; 7 | import java.util.Calendar; 8 | 9 | /** 10 | * Codec for javax.xml package. 11 | * 12 | * @author sulin 13 | * @since 2019-05-13 18:25:17 14 | */ 15 | public final class JavaxCodec extends Codec { 16 | 17 | @Converter 18 | public Calendar toCalendar(XMLGregorianCalendar calendar) { 19 | return calendar.toGregorianCalendar(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/codec/JodaCodec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.Codec; 4 | import com.github.smartbuf.converter.Converter; 5 | import org.joda.time.*; 6 | import org.joda.time.format.DateTimeFormat; 7 | import org.joda.time.format.DateTimeFormatter; 8 | 9 | import java.util.TimeZone; 10 | 11 | /** 12 | * Codec for `org.joda.time` package. 13 | *

14 | * https://blog.joda.org/2014/11/converting-from-joda-time-to-javatime.html 15 | * 16 | * @author sulin 17 | * @since 2019-07-26 11:56:20 18 | */ 19 | public final class JodaCodec extends Codec { 20 | 21 | @Converter 22 | public LocalDateTime toLocalDateTime(java.time.LocalDateTime dt) { 23 | return new LocalDateTime(dt.getYear(), dt.getMonthValue(), dt.getDayOfMonth(), 24 | dt.getHour(), dt.getMinute(), dt.getSecond(), dt.getNano() / 1000000); 25 | } 26 | 27 | @Converter 28 | public java.time.LocalDateTime toLocalDateTime(LocalDateTime dt) { 29 | return java.time.LocalDateTime.of(dt.getYear(), dt.getMonthOfYear(), dt.getDayOfMonth(), 30 | dt.getHourOfDay(), dt.getMinuteOfHour(), dt.getSecondOfMinute(), dt.getMillisOfSecond() * 1000000); 31 | } 32 | 33 | @Converter 34 | public DateTime toDateTime(LocalDateTime ldt) { 35 | return ldt.toDateTime(); 36 | } 37 | 38 | @Converter 39 | public LocalDateTime toLocalDateTime(DateTime dt) { 40 | return dt.toLocalDateTime(); 41 | } 42 | 43 | @Converter 44 | public LocalDate toLocalDate(java.time.LocalDate ldt) { 45 | return new LocalDate(ldt.getYear(), ldt.getMonthValue(), ldt.getDayOfMonth()); 46 | } 47 | 48 | @Converter 49 | public java.time.LocalDate toLocalDate(LocalDate date) { 50 | return java.time.LocalDate.of(date.getYear(), date.getMonthOfYear(), date.getDayOfMonth()); 51 | } 52 | 53 | @Converter 54 | public LocalTime toLocalTime(java.time.LocalTime time) { 55 | return LocalTime.fromMillisOfDay(time.toNanoOfDay() / 1000000L); 56 | } 57 | 58 | @Converter 59 | public java.time.LocalTime toLocalTime(LocalTime time) { 60 | return java.time.LocalTime.ofNanoOfDay(time.getMillisOfDay() * 1000000L); 61 | } 62 | 63 | @Converter 64 | public Duration toDuration(java.time.Duration d) { 65 | return Duration.millis(d.toMillis()); 66 | } 67 | 68 | @Converter 69 | public java.time.Duration toDuration(Duration d) { 70 | return java.time.Duration.ofMillis(d.getMillis()); 71 | } 72 | 73 | @Converter 74 | public Instant toInstant(java.time.Instant instant) { 75 | return Instant.ofEpochMilli(instant.toEpochMilli()); 76 | } 77 | 78 | @Converter 79 | public java.time.Instant toInstant(Instant instant) { 80 | return java.time.Instant.ofEpochMilli(instant.getMillis()); 81 | } 82 | 83 | @Converter 84 | public TimeZone toTimeZone(DateTimeZone zone) { 85 | return zone.toTimeZone(); 86 | } 87 | 88 | @Converter 89 | public DateTimeZone toDateTimeZone(TimeZone zone) { 90 | return DateTimeZone.forTimeZone(zone); 91 | } 92 | 93 | @Converter 94 | public String toString(DateTimeFormatter formatter) { 95 | throw new UnsupportedOperationException(); 96 | } 97 | 98 | @Converter 99 | public DateTimeFormatter toDateTimeFormatter(String str) { 100 | return DateTimeFormat.forPattern(str); 101 | } 102 | 103 | @Converter 104 | public Period toPeriod(String str) { 105 | return Period.parse(str); 106 | } 107 | 108 | @Converter 109 | public String toString(Period period) { 110 | return period.toString(); 111 | } 112 | 113 | @Converter 114 | public Interval toInterval(String str) { 115 | return Interval.parse(str); 116 | } 117 | 118 | @Converter 119 | public String toString(Interval interval) { 120 | return interval.toString(); 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/codec/MathCodec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.Converter; 4 | import com.github.smartbuf.converter.Codec; 5 | 6 | import java.math.BigDecimal; 7 | import java.math.BigInteger; 8 | 9 | /** 10 | * Codec for java.math package, include BigDecimal and BigInteger. 11 | * 12 | * @author sulin 13 | * @since 2019-07-25 12:17:16 14 | */ 15 | public final class MathCodec extends Codec { 16 | 17 | @Converter 18 | public BigDecimal toBigDecimal(String s) { 19 | return new BigDecimal(s); 20 | } 21 | 22 | @Converter 23 | public String toString(BigDecimal bd) { 24 | return bd.toPlainString(); 25 | } 26 | 27 | @Converter 28 | public BigInteger toBigInteger(String s) { 29 | return new BigInteger(s); 30 | } 31 | 32 | @Converter 33 | public String toString(BigInteger bi) { 34 | return bi.toString(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/codec/NetCodec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.Codec; 4 | import com.github.smartbuf.converter.Converter; 5 | 6 | import java.net.*; 7 | 8 | /** 9 | * Codec for `java.net` package 10 | * 11 | * @author sulin 12 | * @since 2019-07-25 20:44:11 13 | */ 14 | public final class NetCodec extends Codec { 15 | 16 | @Converter 17 | public URI toURI(String s) { 18 | return URI.create(s); 19 | } 20 | 21 | @Converter 22 | public String toString(URI uri) { 23 | return uri.toString(); 24 | } 25 | 26 | @Converter 27 | public URL toURL(String s) throws MalformedURLException { 28 | return new URL(s); 29 | } 30 | 31 | @Converter 32 | public String toString(URL url) { 33 | return url.toString(); 34 | } 35 | 36 | /* 37 | * Convert String to InetAddress, support Inet4Address and Inet6Address 38 | */ 39 | @Converter(extensible = true) 40 | public InetAddress toInetAddress(String s) throws UnknownHostException { 41 | int off = s.indexOf('/'); 42 | if (off >= 0) { 43 | String hostname = s.substring(0, off); 44 | String address = s.substring(off + 1); 45 | s = hostname.length() == 0 ? address : hostname; 46 | } 47 | return InetAddress.getByName(s); 48 | } 49 | 50 | /* 51 | * Convert InetAddress to String, support Inet4Address and Inet6Address 52 | */ 53 | @Converter 54 | public String toString(InetAddress addr) { 55 | return addr.getHostAddress(); 56 | } 57 | 58 | @Converter 59 | public InetSocketAddress toInetSocketAddress(String s) { 60 | String host, port = null; 61 | int off = s.indexOf(':'); 62 | if (off > 0) { 63 | host = s.substring(0, off); 64 | port = s.substring(off + 1); 65 | } else { 66 | host = s; 67 | } 68 | InetAddress addr = convert(host, InetAddress.class); 69 | if (port == null) { 70 | return new InetSocketAddress(addr, 0); 71 | } 72 | return new InetSocketAddress(addr, Integer.parseInt(port)); 73 | } 74 | 75 | @Converter 76 | public String toString(InetSocketAddress addr) { 77 | return addr.getHostString() + ":" + addr.getPort(); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/codec/NumberCodec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.Codec; 4 | import com.github.smartbuf.converter.Converter; 5 | 6 | import java.text.DecimalFormat; 7 | 8 | /** 9 | * Codec for Number and its descendants, include Boolean 10 | * 11 | * @author sulin 12 | * @since 2019-05-13 18:14:18 13 | */ 14 | public final class NumberCodec extends Codec { 15 | 16 | private static final DecimalFormat F_F = new DecimalFormat("0.#######"); 17 | private static final DecimalFormat D_F = new DecimalFormat("0.################"); 18 | 19 | @Converter 20 | public Long toLong(String s) { 21 | return Long.parseLong(s); 22 | } 23 | 24 | @Converter 25 | public String toString(Long l) { 26 | return l.toString(); 27 | } 28 | 29 | @Converter 30 | public Short toShort(Long l) { 31 | return l.shortValue(); 32 | } 33 | 34 | @Converter 35 | public Long toLong(Short s) { 36 | return s.longValue(); 37 | } 38 | 39 | @Converter 40 | public Integer toInteger(Long l) { 41 | return l.intValue(); 42 | } 43 | 44 | @Converter 45 | public Long toLong(Integer i) { 46 | return i.longValue(); 47 | } 48 | 49 | @Converter 50 | public Float toFloat(Double d) { 51 | return d.floatValue(); 52 | } 53 | 54 | @Converter 55 | public Float toFloat(String s) { 56 | return Float.parseFloat(s); 57 | } 58 | 59 | @Converter 60 | public Double toDouble(Float f) { 61 | return f.doubleValue(); 62 | } 63 | 64 | @Converter 65 | public String toString(Float f) { 66 | return F_F.format(f); 67 | } 68 | 69 | @Converter 70 | public Double toDouble(String s) { 71 | return Double.parseDouble(s); 72 | } 73 | 74 | @Converter 75 | public Double toDouble(Long l) { 76 | return l.doubleValue(); 77 | } 78 | 79 | @Converter 80 | public Long toLong(Double d) { 81 | return d.longValue(); 82 | } 83 | 84 | @Converter 85 | public String toString(Double d) { 86 | return D_F.format(d); 87 | } 88 | 89 | @Converter 90 | public Byte toByte(Long l) { 91 | return l.byteValue(); 92 | } 93 | 94 | @Converter 95 | public Long toLong(Byte b) { 96 | return b.longValue(); 97 | } 98 | 99 | @Converter 100 | public Boolean toBoolean(Long l) { 101 | // Convert Integer to Boolean; 0 => false; !0 => true 102 | return l != 0; 103 | } 104 | 105 | @Converter 106 | public Long toLong(Boolean b) { 107 | return b ? 1L : 0L; 108 | } 109 | 110 | @Converter 111 | public Boolean toBoolean(String s) { 112 | return Boolean.valueOf(s); 113 | } 114 | 115 | @Converter 116 | public String toString(Boolean b) { 117 | return b.toString(); 118 | } 119 | 120 | @Converter 121 | public Character toCharacter(Long i) { 122 | return (char) i.intValue(); 123 | } 124 | 125 | @Converter 126 | public Long toInteger(Character c) { 127 | return (long) (int) c; 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/codec/PrimaryCodec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.Codec; 4 | import com.github.smartbuf.converter.Converter; 5 | 6 | /** 7 | * Codec for primary data type 8 | * 9 | * @author sulin 10 | * @since 2019-08-05 19:44:37 11 | */ 12 | public final class PrimaryCodec extends Codec { 13 | 14 | @Converter 15 | public boolean toBoolean(Boolean b) { 16 | return b; 17 | } 18 | 19 | @Converter 20 | public Boolean toBoolean(boolean b) { 21 | return b; 22 | } 23 | 24 | @Converter 25 | public byte toByte(Byte b) { 26 | return b; 27 | } 28 | 29 | @Converter 30 | public Byte toByte(byte b) { 31 | return b; 32 | } 33 | 34 | @Converter 35 | public short toShort(Short s) { 36 | return s; 37 | } 38 | 39 | @Converter 40 | public Short toShort(short s) { 41 | return s; 42 | } 43 | 44 | @Converter 45 | public int toInt(Integer i) { 46 | return i; 47 | } 48 | 49 | @Converter 50 | public Integer toInteger(int i) { 51 | return i; 52 | } 53 | 54 | @Converter 55 | public long toLong(Long l) { 56 | return l; 57 | } 58 | 59 | @Converter 60 | public Long toLong(long l) { 61 | return l; 62 | } 63 | 64 | @Converter 65 | public float toFloat(Float f) { 66 | return f; 67 | } 68 | 69 | @Converter 70 | public Float toFloat(float f) { 71 | return f; 72 | } 73 | 74 | @Converter 75 | public double toDouble(Double d) { 76 | return d; 77 | } 78 | 79 | @Converter 80 | public Double toDouble(double d) { 81 | return d; 82 | } 83 | 84 | @Converter 85 | public char toChar(Character c) { 86 | return c; 87 | } 88 | 89 | @Converter 90 | public Character toCharacter(char c) { 91 | return c; 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/codec/ReferenceCodec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.Codec; 4 | import com.github.smartbuf.converter.Converter; 5 | import com.github.smartbuf.reflect.XType; 6 | 7 | import java.lang.ref.Reference; 8 | import java.lang.ref.SoftReference; 9 | import java.lang.ref.WeakReference; 10 | 11 | /** 12 | * Reference's codec 13 | * 14 | * @author sulin 15 | * @since 2019-05-13 18:39:05 16 | */ 17 | public final class ReferenceCodec extends Codec { 18 | 19 | @Converter(extensible = true) 20 | public Reference toReference(Object obj, XType type) { 21 | XType paramType = type.getParameterizedType(); 22 | Object value; 23 | if (paramType.isPure() && paramType.getRawType().isAssignableFrom(obj.getClass())) { 24 | value = obj; // compatible 25 | } else { 26 | value = convert(obj, paramType); // convert 27 | } 28 | // build reference 29 | Class refClass = type.getRawType(); 30 | if (refClass == SoftReference.class || refClass == Reference.class) { 31 | return new SoftReference<>(value); 32 | } 33 | if (refClass == WeakReference.class) { 34 | return new WeakReference<>(value); 35 | } 36 | throw new IllegalArgumentException("Unsupport Reference: " + refClass); 37 | } 38 | 39 | @Converter(extensible = true) 40 | public Object toObject(Reference ref, XType type) { 41 | Object obj = ref.get(); 42 | if (type.isPure() && type.getRawType().isInstance(obj)) { 43 | return obj; 44 | } 45 | return convert(obj, type); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/codec/SqlCodec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.Codec; 4 | import com.github.smartbuf.converter.Converter; 5 | 6 | import javax.sql.rowset.serial.SerialBlob; 7 | import javax.sql.rowset.serial.SerialClob; 8 | import java.io.InputStream; 9 | import java.io.Reader; 10 | import java.sql.*; 11 | 12 | /** 13 | * Codec for `java.sql` package 14 | * 15 | * @author sulin 16 | * @since 2019-07-25 20:49:12 17 | */ 18 | public final class SqlCodec extends Codec { 19 | 20 | @Converter 21 | public Blob toBlob(byte[] bytes) throws SQLException { 22 | return new SerialBlob(bytes); 23 | } 24 | 25 | @Converter 26 | public InputStream toInputStream(Blob b) throws SQLException { 27 | return b.getBinaryStream(); 28 | } 29 | 30 | @Converter 31 | public Clob toClob(String str) throws SQLException { 32 | return new SerialClob(str.toCharArray()); 33 | } 34 | 35 | @Converter 36 | public Reader toReader(Clob c) throws SQLException { 37 | return c.getCharacterStream(); 38 | } 39 | 40 | @Converter 41 | public Date toDate(Long time) { 42 | return new Date(time); 43 | } 44 | 45 | @Converter 46 | public Long toLong(Date date) { 47 | return date.getTime(); 48 | } 49 | 50 | @Converter 51 | public Time toTime(Long time) { 52 | return new Time(time); 53 | } 54 | 55 | @Converter 56 | public Long toLong(Time time) { 57 | return time.getTime(); 58 | } 59 | 60 | @Converter 61 | public Timestamp toTimestamp(Long time) { 62 | return new Timestamp(time); 63 | } 64 | 65 | @Converter 66 | public Long toLong(Timestamp t) { 67 | return t.getTime(); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/converter/codec/StringCodec.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.Codec; 4 | import com.github.smartbuf.converter.Converter; 5 | 6 | import java.text.StringCharacterIterator; 7 | 8 | /** 9 | * String's codec 10 | * 11 | * @author sulin 12 | * @since 2019-05-13 18:14:25 13 | */ 14 | public final class StringCodec extends Codec { 15 | 16 | @Converter 17 | public String toString(StringBuffer sb) { 18 | return sb.toString(); 19 | } 20 | 21 | @Converter 22 | public StringBuffer toStringBuffer(String s) { 23 | return new StringBuffer(s); 24 | } 25 | 26 | @Converter 27 | public String toString(StringBuilder sb) { 28 | return sb.toString(); 29 | } 30 | 31 | @Converter 32 | public StringBuilder toStringBuilder(String s) { 33 | return new StringBuilder(s); 34 | } 35 | 36 | @Converter(distance = 101) 37 | public Character toCharacter(String s) { 38 | if (s.length() != 1) { 39 | throw new UnsupportedOperationException("Convert string to char failed, string.length > 0: " + s); 40 | } 41 | return s.charAt(0); 42 | } 43 | 44 | @Converter(distance = 101) 45 | public String toString(Character c) { 46 | return c.toString(); 47 | } 48 | 49 | @Converter 50 | public String toString(char[] chars) { 51 | return new String(chars); 52 | } 53 | 54 | @Converter 55 | public char[] toCharArray(String s) { 56 | return s.toCharArray(); 57 | } 58 | 59 | @Converter 60 | public String toString(byte[] bytes) { 61 | return new String(bytes); 62 | } 63 | 64 | @Converter 65 | public byte[] toByteArray(String s) { 66 | return s.getBytes(); 67 | } 68 | 69 | @Converter 70 | public String toString(StringCharacterIterator sc) { 71 | StringBuilder sb = new StringBuilder(); 72 | char c = sc.first(); 73 | while (c != StringCharacterIterator.DONE) { 74 | sb.append(c); 75 | c = sc.next(); 76 | } 77 | return sb.toString(); 78 | } 79 | 80 | @Converter 81 | public StringCharacterIterator toStringCharacterIterator(String s) { 82 | return new StringCharacterIterator(s); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/exception/CircleReferenceException.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.exception; 2 | 3 | /** 4 | * CircularReferenceException represents that the specified object has circular reference problem, 5 | * which causes it's no serializable. 6 | * 7 | * @author sulin 8 | * @since 2019-10-22 20:55:29 9 | */ 10 | public class CircleReferenceException extends RuntimeException { 11 | 12 | public CircleReferenceException(String message) { 13 | super(message); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/exception/InvalidDataException.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.exception; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * InvalidDataException indicates the specified data-id is invalid. 7 | * 8 | * @author sulin 9 | * @since 2019-11-08 11:34:08 10 | */ 11 | public class InvalidDataException extends IOException { 12 | 13 | public InvalidDataException(String message) { 14 | super(message); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/exception/InvalidStructException.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.exception; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * InvalidStructException indicates that the specified struct-id is invalid. 7 | * 8 | * @author sulin 9 | * @since 2019-11-08 14:18:56 10 | */ 11 | public class InvalidStructException extends IOException { 12 | 13 | public InvalidStructException(String message) { 14 | super(message); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/exception/InvalidVersionException.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.exception; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * InvalidVersionException indicates the specified data has an invalid version 7 | * 8 | * @author sulin 9 | * @since 2019-10-22 17:17:44 10 | */ 11 | public class InvalidVersionException extends IOException { 12 | 13 | public InvalidVersionException(int expectedVer, int ver) { 14 | super("Expect " + Integer.toHexString(expectedVer) + ", but received " + Integer.toHexString(ver)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/exception/MismatchModeException.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.exception; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * MismatchModeException indicates the `mode` flag didn't match between input and output. 7 | * 8 | * @author sulin 9 | * @since 2019-10-22 16:49:56 10 | */ 11 | public class MismatchModeException extends IOException { 12 | 13 | public MismatchModeException(boolean localEnableStream) { 14 | super(localEnableStream ? 15 | "expect stream mode, but data has no-stream mode flag" : 16 | "expect no-stream mode, but data has stream mode flag"); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/exception/NoShortestPipelineException.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.exception; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | 5 | /** 6 | * NoShortestPipelineException indicates the {@link CodecFactory} 7 | * can't decide the shortest codec-pipeline to use. 8 | * 9 | * @author sulin 10 | * @since 2019-11-11 21:47:21 11 | */ 12 | public class NoShortestPipelineException extends RuntimeException { 13 | 14 | public NoShortestPipelineException(String message) { 15 | super(message); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/exception/OutOfSpaceException.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.exception; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * OutOfSpaceException indicates that the data to write is too big to handle. 7 | * 8 | * @author sulin 9 | * @since 2019-10-27 15:55:25 10 | */ 11 | public class OutOfSpaceException extends IOException { 12 | 13 | public OutOfSpaceException(String message) { 14 | super(message); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/exception/SmartBufClosedException.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.exception; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * SmartBufClosedException indicates the closed SmartBuf instance are reused. 7 | * 8 | * @author sulin 9 | * @since 2019-10-28 17:22:11 10 | */ 11 | public class SmartBufClosedException extends IOException { 12 | 13 | public SmartBufClosedException(String message) { 14 | super(message); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/exception/UnexpectedReadException.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.exception; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * UnexpectedReadException indicates Input run into some unexpected data. 7 | * 8 | * @author sulin 9 | * @since 2019-10-22 17:10:07 10 | */ 11 | public class UnexpectedReadException extends IOException { 12 | 13 | public UnexpectedReadException(String message) { 14 | super(message); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/exception/UnexpectedSequenceException.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.exception; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * UnexpectedSequenceException indicates the sequence of input data is unexpected, 7 | * Maybe packet-lost occured, in this case, should reset all input/output context. 8 | * 9 | * @author sulin 10 | * @since 2019-10-22 17:00:39 11 | */ 12 | public class UnexpectedSequenceException extends IOException { 13 | 14 | public UnexpectedSequenceException(long local, long seq) { 15 | super("The sequence of schema-area is unexpected, expect " + local + ", but received " + seq); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/Node.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node; 2 | 3 | /** 4 | * Base class of Node, and provider some common features. 5 | * 6 | * @author sulin 7 | * @since 2019-05-08 20:33:51 8 | */ 9 | public abstract class Node { 10 | 11 | /** 12 | * Get this Node's value 13 | * 14 | * @return Node's real value 15 | */ 16 | public abstract Object value(); 17 | 18 | /** 19 | * Get this Node's datatype 20 | * 21 | * @return Node's real type 22 | */ 23 | public abstract NodeType type(); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/NodeType.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node; 2 | 3 | /** 4 | * NodeType represents datatype of {@link Node}, 5 | * it could help use switch to optimize a little performance. 6 | * 7 | * @author sulin 8 | * @since 2019-11-10 12:12:51 9 | */ 10 | public enum NodeType { 11 | UNKNOWN, 12 | 13 | BOOLEAN, 14 | VARINT, 15 | FLOAT, 16 | DOUBLE, 17 | STRING, 18 | SYMBOL, 19 | OBJECT, 20 | 21 | ARRAY, 22 | ARRAY_BOOLEAN, 23 | ARRAY_BYTE, 24 | ARRAY_SHORT, 25 | ARRAY_INT, 26 | ARRAY_LONG, 27 | ARRAY_FLOAT, 28 | ARRAY_DOUBLE 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/array/ArrayNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.array; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | 6 | import java.util.Collection; 7 | 8 | /** 9 | * ArrayNode represents unknown data's array 10 | * 11 | * @author sulin 12 | * @since 2019-11-03 14:54:55 13 | */ 14 | public final class ArrayNode extends Node { 15 | 16 | private final Collection data; 17 | 18 | public ArrayNode(Collection data) { 19 | this.data = data; 20 | } 21 | 22 | @Override 23 | public Object value() { 24 | return data; 25 | } 26 | 27 | @Override 28 | public NodeType type() { 29 | return NodeType.ARRAY; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/array/BooleanArrayNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.array; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | 6 | /** 7 | * BooleanArrayNode represents boolean[] 8 | * 9 | * @author sulin 10 | * @since 2019-11-03 14:46:34 11 | */ 12 | public final class BooleanArrayNode extends Node { 13 | 14 | private final boolean[] data; 15 | 16 | public BooleanArrayNode(boolean[] data) { 17 | this.data = data; 18 | } 19 | 20 | @Override 21 | public Object value() { 22 | return data; 23 | } 24 | 25 | @Override 26 | public NodeType type() { 27 | return NodeType.ARRAY_BOOLEAN; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/array/ByteArrayNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.array; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | 6 | /** 7 | * ByteArrayNode represents byte[] 8 | * 9 | * @author sulin 10 | * @since 2019-11-03 14:46:42 11 | */ 12 | public final class ByteArrayNode extends Node { 13 | 14 | private final byte[] data; 15 | 16 | public ByteArrayNode(byte[] data) { 17 | this.data = data; 18 | } 19 | 20 | @Override 21 | public Object value() { 22 | return data; 23 | } 24 | 25 | @Override 26 | public NodeType type() { 27 | return NodeType.ARRAY_BYTE; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/array/DoubleArrayNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.array; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | 6 | /** 7 | * DoubleArrayNode represents double[] 8 | * 9 | * @author sulin 10 | * @since 2019-11-03 14:47:29 11 | */ 12 | public final class DoubleArrayNode extends Node { 13 | 14 | private final double[] data; 15 | 16 | public DoubleArrayNode(double[] data) { 17 | this.data = data; 18 | } 19 | 20 | @Override 21 | public Object value() { 22 | return data; 23 | } 24 | 25 | @Override 26 | public NodeType type() { 27 | return NodeType.ARRAY_DOUBLE; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/array/FloatArrayNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.array; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | 6 | /** 7 | * FloatArrayNode represents float[] 8 | * 9 | * @author sulin 10 | * @since 2019-11-03 14:47:16 11 | */ 12 | public final class FloatArrayNode extends Node { 13 | 14 | private final float[] data; 15 | 16 | public FloatArrayNode(float[] data) { 17 | this.data = data; 18 | } 19 | 20 | @Override 21 | public Object value() { 22 | return data; 23 | } 24 | 25 | @Override 26 | public NodeType type() { 27 | return NodeType.ARRAY_FLOAT; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/array/IntArrayNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.array; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | 6 | /** 7 | * IntArrayNode represents int[] 8 | * 9 | * @author sulin 10 | * @since 2019-11-03 14:46:58 11 | */ 12 | public final class IntArrayNode extends Node { 13 | 14 | private final int[] data; 15 | 16 | public IntArrayNode(int[] data) { 17 | this.data = data; 18 | } 19 | 20 | @Override 21 | public Object value() { 22 | return data; 23 | } 24 | 25 | @Override 26 | public NodeType type() { 27 | return NodeType.ARRAY_INT; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/array/LongArrayNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.array; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | 6 | /** 7 | * LongArrayNode represents long[] 8 | * 9 | * @author sulin 10 | * @since 2019-11-03 14:47:09 11 | */ 12 | public final class LongArrayNode extends Node { 13 | 14 | private final long[] data; 15 | 16 | public LongArrayNode(long[] data) { 17 | this.data = data; 18 | } 19 | 20 | @Override 21 | public Object value() { 22 | return data; 23 | } 24 | 25 | @Override 26 | public NodeType type() { 27 | return NodeType.ARRAY_LONG; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/array/ShortArrayNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.array; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | 6 | /** 7 | * ShortArrayNode represents short[] 8 | * 9 | * @author sulin 10 | * @since 2019-11-03 14:46:51 11 | */ 12 | public final class ShortArrayNode extends Node { 13 | 14 | private final short[] data; 15 | 16 | public ShortArrayNode(short[] data) { 17 | this.data = data; 18 | } 19 | 20 | @Override 21 | public Object value() { 22 | return data; 23 | } 24 | 25 | @Override 26 | public NodeType type() { 27 | return NodeType.ARRAY_SHORT; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/basic/BooleanNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.basic; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | 6 | /** 7 | * BooleanNode represents boolean and Boolean. 8 | * 9 | * @author sulin 10 | * @since 2019-05-08 21:00:07 11 | */ 12 | public final class BooleanNode extends Node { 13 | 14 | public final static BooleanNode TRUE = new BooleanNode(); 15 | public final static BooleanNode FALSE = new BooleanNode(); 16 | 17 | private BooleanNode() { 18 | } 19 | 20 | public static BooleanNode valueOf(boolean b) { 21 | return b ? TRUE : FALSE; 22 | } 23 | 24 | public static BooleanNode valueOf(Boolean b) { 25 | return valueOf(b.booleanValue()); 26 | } 27 | 28 | @Override 29 | public Object value() { 30 | return this == TRUE; 31 | } 32 | 33 | @Override 34 | public NodeType type() { 35 | return NodeType.BOOLEAN; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/basic/DoubleNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.basic; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | 6 | /** 7 | * DoubleNode represents double and Double. 8 | * 9 | * @author sulin 10 | * @since 2019-05-08 21:00:27 11 | */ 12 | public final class DoubleNode extends Node { 13 | 14 | public final static DoubleNode ZERO = new DoubleNode(0); 15 | 16 | private final double value; 17 | 18 | private DoubleNode(double value) { 19 | this.value = value; 20 | } 21 | 22 | public static DoubleNode valueOf(double d) { 23 | if (d == 0) { 24 | return ZERO; 25 | } 26 | return new DoubleNode(d); 27 | } 28 | 29 | public static DoubleNode valueOf(Double d) { 30 | return valueOf(d.doubleValue()); 31 | } 32 | 33 | @Override 34 | public Object value() { 35 | return value; 36 | } 37 | 38 | @Override 39 | public NodeType type() { 40 | return NodeType.DOUBLE; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/basic/FloatNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.basic; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | 6 | /** 7 | * FloatNode represents float and Float. 8 | * 9 | * @author sulin 10 | * @since 2019-05-08 21:00:21 11 | */ 12 | public final class FloatNode extends Node { 13 | 14 | public final static FloatNode ZERO = new FloatNode(0); 15 | 16 | private final float value; 17 | 18 | private FloatNode(float value) { 19 | this.value = value; 20 | } 21 | 22 | public static FloatNode valueOf(float f) { 23 | if (f == 0) { 24 | return ZERO; 25 | } 26 | return new FloatNode(f); 27 | } 28 | 29 | public static FloatNode valueOf(Float f) { 30 | return valueOf(f.floatValue()); 31 | } 32 | 33 | @Override 34 | public Object value() { 35 | return value; 36 | } 37 | 38 | @Override 39 | public NodeType type() { 40 | return NodeType.FLOAT; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/basic/ObjectNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.basic; 2 | 3 | import com.github.smartbuf.Type; 4 | import com.github.smartbuf.node.Node; 5 | import com.github.smartbuf.node.NodeType; 6 | 7 | /** 8 | * ObjectNode represents JavaBean or Map. 9 | * 10 | * @author sulin 11 | * @since 2019-05-08 21:02:12 12 | */ 13 | public final class ObjectNode extends Node { 14 | 15 | public final static ObjectNode EMPTY = new ObjectNode(true, new String[0], new Object[0]); 16 | 17 | /** 18 | * Stable object's keys must be ordered 19 | */ 20 | private final boolean stable; 21 | 22 | private final String[] keys; 23 | private final Object[] fields; 24 | private final Type[] types; 25 | 26 | public ObjectNode(boolean stable, String[] keys, Object[] values) { 27 | this.stable = stable; 28 | this.keys = keys; 29 | this.fields = values; 30 | this.types = null; 31 | } 32 | 33 | public ObjectNode(boolean stable, String[] keys, Object[] values, Type[] types) { 34 | this.stable = stable; 35 | this.keys = keys; 36 | this.fields = values; 37 | this.types = types; 38 | } 39 | 40 | public boolean isStable() { 41 | return stable; 42 | } 43 | 44 | public String[] keys() { 45 | return keys; 46 | } 47 | 48 | public Object[] values() { 49 | return fields; 50 | } 51 | 52 | public Type[] types() { 53 | return types; 54 | } 55 | 56 | @Override 57 | public Object value() { 58 | return this; 59 | } 60 | 61 | @Override 62 | public NodeType type() { 63 | return NodeType.OBJECT; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/basic/StringNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.basic; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | 6 | /** 7 | * StringNode represents String. 8 | * 9 | * @author sulin 10 | * @since 2019-05-08 21:00:34 11 | */ 12 | public final class StringNode extends Node { 13 | 14 | public final static StringNode EMPTY = new StringNode(""); 15 | 16 | private final String value; 17 | 18 | private StringNode(String value) { 19 | this.value = value; 20 | } 21 | 22 | public static StringNode valueOf(String str) { 23 | if (str.isEmpty()) { 24 | return EMPTY; 25 | } 26 | return new StringNode(str); 27 | } 28 | 29 | @Override 30 | public Object value() { 31 | return value; 32 | } 33 | 34 | @Override 35 | public NodeType type() { 36 | return NodeType.STRING; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/basic/SymbolNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.basic; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | 6 | /** 7 | * SymbolNode represents constant String or Enum etc. 8 | * 9 | * @author sulin 10 | * @since 2019-06-04 20:23:31 11 | */ 12 | public final class SymbolNode extends Node { 13 | 14 | private String data; 15 | 16 | private SymbolNode(String data) { 17 | this.data = data; 18 | } 19 | 20 | public static SymbolNode valueOf(String str) { 21 | return new SymbolNode(str); 22 | } 23 | 24 | public static SymbolNode valueOf(Enum en) { 25 | return new SymbolNode(en.name()); // don't need cache 26 | } 27 | 28 | @Override 29 | public Object value() { 30 | return data; 31 | } 32 | 33 | @Override 34 | public NodeType type() { 35 | return NodeType.SYMBOL; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/node/basic/VarintNode.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node.basic; 2 | 3 | import com.github.smartbuf.node.Node; 4 | import com.github.smartbuf.node.NodeType; 5 | import com.github.smartbuf.utils.NumberUtils; 6 | 7 | /** 8 | * VarintNode represents all number like byte/short/int/long. 9 | * 10 | * @author sulin 11 | * @since 2019-05-08 21:00:46 12 | */ 13 | public final class VarintNode extends Node { 14 | 15 | private final static VarintNode[] TABLE = new VarintNode[256]; 16 | 17 | static { 18 | for (int i = 0; i < TABLE.length; i++) { 19 | TABLE[i] = new VarintNode(NumberUtils.uintToInt(i)); 20 | } 21 | } 22 | 23 | private final long value; 24 | 25 | private VarintNode(long value) { 26 | this.value = value; 27 | } 28 | 29 | public static VarintNode valueOf(byte b) { 30 | return valueOf((long) b); 31 | } 32 | 33 | public static VarintNode valueOf(Byte b) { 34 | return valueOf(b.byteValue()); 35 | } 36 | 37 | public static VarintNode valueOf(short s) { 38 | return valueOf((long) s); 39 | } 40 | 41 | public static VarintNode valueOf(Short s) { 42 | return valueOf(s.shortValue()); 43 | } 44 | 45 | public static VarintNode valueOf(int i) { 46 | return valueOf((long) i); 47 | } 48 | 49 | public static VarintNode valueOf(Integer i) { 50 | return valueOf(i.intValue()); 51 | } 52 | 53 | public static VarintNode valueOf(long l) { 54 | long ul = NumberUtils.intToUint(l); 55 | if (ul >= 0 && ul < TABLE.length) { 56 | return TABLE[(int) ul]; 57 | } 58 | return new VarintNode(l); 59 | } 60 | 61 | public static VarintNode valueOf(Long l) { 62 | return valueOf(l.longValue()); 63 | } 64 | 65 | @Override 66 | public Object value() { 67 | return value; 68 | } 69 | 70 | @Override 71 | public NodeType type() { 72 | return NodeType.VARINT; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/reflect/BeanField.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.reflect; 2 | 3 | import com.github.smartbuf.Type; 4 | 5 | import java.lang.reflect.Field; 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * BeanField represents an field which support getter or setter 10 | * 11 | * @author sulin 12 | * @since 2019-10-29 15:46:00 13 | */ 14 | public final class BeanField { 15 | 16 | final String name; 17 | final Class cls; 18 | final Type type; 19 | 20 | Field field; 21 | Method getter; 22 | Method setter; 23 | 24 | public BeanField(String name, Class cls) { 25 | this.name = name; 26 | this.cls = cls; 27 | this.type = Type.valueOf(cls); 28 | } 29 | 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | public Type getType() { 35 | return type; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/reflect/BeanReader.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.reflect; 2 | 3 | import com.github.smartbuf.Type; 4 | 5 | /** 6 | * BeanReader provides {@link #getValues} for normal pojos. 7 | * 8 | * @author sulin 9 | * @since 2019-11-08 18:01:40 10 | */ 11 | public final class BeanReader { 12 | 13 | static String API_NAME = API.class.getName().replace('.', '/'); 14 | 15 | final API api; 16 | final BeanField[] fields; 17 | final String[] fieldNames; 18 | final Type[] fieldTypes; 19 | 20 | BeanReader(API api, BeanField[] fields) { 21 | this.api = api; 22 | this.fields = fields; 23 | this.fieldNames = new String[fields.length]; 24 | this.fieldTypes = new Type[fields.length]; 25 | for (int i = 0; i < fields.length; i++) { 26 | BeanField field = fields[i]; 27 | this.fieldNames[i] = field.getName(); 28 | this.fieldTypes[i] = field.getType(); 29 | } 30 | } 31 | 32 | /** 33 | * Get all readable field's names of this reader 34 | * 35 | * @return All readable field's names 36 | */ 37 | public String[] getFieldNames() { 38 | return fieldNames; 39 | } 40 | 41 | /** 42 | * Get all readable field's types of this reader 43 | * 44 | * @return All readable field's types 45 | */ 46 | public Type[] getFieldTypes() { 47 | return fieldTypes; 48 | } 49 | 50 | /** 51 | * Get all values of the specified object's properties. 52 | * 53 | * @param t The specified object to get values 54 | * @return t's all values 55 | */ 56 | public Object[] getValues(Object t) { 57 | Object[] result = new Object[fieldNames.length]; 58 | api.getAll(t, result); 59 | return result; 60 | } 61 | 62 | public interface API { 63 | /** 64 | * Fetch all properties of the specified object by predefined fields and their order 65 | * 66 | * @param o The Object to access, its getter will be called in predefined order 67 | * @param values The array to accept getter's result 68 | */ 69 | void getAll(Object o, Object[] values); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/reflect/BeanWriter.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.reflect; 2 | 3 | /** 4 | * BeanWriter provides {@link #setValues} for normal pojos. 5 | * 6 | * @author sulin 7 | * @since 2019-11-08 17:52:09 8 | */ 9 | public final class BeanWriter { 10 | 11 | static String API_NAME = API.class.getName().replace('.', '/'); 12 | 13 | private final API api; 14 | private final BeanField[] fields; 15 | 16 | public BeanWriter(API api, BeanField[] fields) { 17 | this.api = api; 18 | this.fields = fields; 19 | } 20 | 21 | /** 22 | * Get all fields of this reader 23 | * 24 | * @return All fields 25 | */ 26 | public BeanField[] getFields() { 27 | return fields; 28 | } 29 | 30 | /** 31 | * Set all values of the specified object' properties 32 | * 33 | * @param t The specified object to set values 34 | * @param values all values to setup 35 | */ 36 | public void setValues(Object t, Object[] values) { 37 | if (values == null || values.length != fields.length) { 38 | throw new IllegalArgumentException("invalid values"); 39 | } 40 | api.setAll(t, values); 41 | } 42 | 43 | public interface API { 44 | /** 45 | * Setup all properties of the specified object by predefined fields and their order 46 | * 47 | * @param o The Object to access, its setter will be called in predefined order 48 | * @param values The values which need to set into object 49 | */ 50 | void setAll(Object o, Object[] values); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/reflect/TypeRef.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.reflect; 2 | 3 | import java.lang.reflect.ParameterizedType; 4 | import java.lang.reflect.Type; 5 | 6 | /** 7 | * Comment copied from `fastjson`: 8 | *

9 | * Represents a generic type {@code T}. Java doesn't yet provide a way to 10 | * represent generic types, so this class does. Forces clients to create a 11 | * subclass of this class which enables retrieval the type information even at 12 | * runtime. 13 | * 14 | * @author sulin 15 | * @since 2019-07-22 15:38:53 16 | */ 17 | public abstract class TypeRef { 18 | 19 | private final Type type; 20 | 21 | /** 22 | * Constructs a new type literal. Derives represented class from type parameter. 23 | *

24 | * If caller didnt specify generic type, throw exception directly. 25 | */ 26 | protected TypeRef() { 27 | Type superClass = getClass().getGenericSuperclass(); 28 | if (superClass instanceof ParameterizedType) { 29 | type = ((ParameterizedType) superClass).getActualTypeArguments()[0]; 30 | } else { 31 | throw new IllegalArgumentException("Must specify TypeRef's parameterized type"); 32 | } 33 | } 34 | 35 | /** 36 | * Gets underlying {@code Type} instance. 37 | * 38 | * @return The underlying java type 39 | */ 40 | public Type getType() { 41 | return type; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/reflect/XField.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.reflect; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | /** 6 | * XField represents a field of class, with clear generic type. 7 | * 8 | * @author sulin 9 | * @since 2019-07-15 20:42:17 10 | */ 11 | public final class XField { 12 | 13 | /** 14 | * Field's name 15 | */ 16 | private String name; 17 | /** 18 | * Java's reflect field 19 | */ 20 | private Field field; 21 | /** 22 | * Field's clear type 23 | */ 24 | private XType type; 25 | 26 | public String getName() { 27 | return name; 28 | } 29 | 30 | public void setName(String name) { 31 | this.name = name; 32 | } 33 | 34 | public Field getField() { 35 | return field; 36 | } 37 | 38 | public void setField(Field field) { 39 | this.field = field; 40 | } 41 | 42 | public XType getType() { 43 | return type; 44 | } 45 | 46 | public void setType(XType type) { 47 | this.type = type; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/reflect/XTypeUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.reflect; 2 | 3 | import java.lang.ref.Reference; 4 | import java.lang.reflect.Type; 5 | import java.util.Collection; 6 | import java.util.Map; 7 | 8 | /** 9 | * This is a convenience utils for XTypeFactory, use common Classes as Stop-Classes by default. 10 | * 11 | * @author sulin 12 | * @since 2019-07-22 14:46:05 13 | */ 14 | public final class XTypeUtils { 15 | 16 | // Global default XTypeFactory 17 | private static final XTypeFactory factory = new XTypeFactory().addStopClass( 18 | Object[].class, 19 | Boolean.class, 20 | Number.class, 21 | CharSequence.class, 22 | Collection.class, 23 | Map.class, 24 | Reference.class 25 | ); 26 | 27 | private XTypeUtils() { 28 | } 29 | 30 | /** 31 | * Convert Type to XType, all generic types should be resolved. 32 | * 33 | * @param type Standard type like Class/ParameterizedType/GenericArrayType/etc... 34 | * @return XType instance 35 | */ 36 | public static XType toXType(Type type) { 37 | return factory.toXType(type); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/transport/Array.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.transport; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * Array like T[], but support more features like auto-scale 7 | * 8 | * @author sulin 9 | * @since 2019-09-26 14:21:44 10 | */ 11 | @SuppressWarnings("unchecked") 12 | public final class Array { 13 | 14 | private int size; 15 | private T[] data; 16 | 17 | /** 18 | * Add new object into the final offset of this List 19 | * 20 | * @param val New object of T 21 | * @return New item's offset 22 | */ 23 | public int add(T val) { 24 | int pos = this.size; 25 | this.put(pos, val); 26 | return pos; 27 | } 28 | 29 | /** 30 | * Put value into the specified offset of this List 31 | * 32 | * @param pos The specified offset 33 | * @param val New instance of T 34 | */ 35 | public void put(int pos, T val) { 36 | if (data == null) { 37 | data = (T[]) new Object[4]; 38 | } 39 | if (pos >= data.length) { 40 | T[] newArr = (T[]) new Object[data.length * 2]; 41 | System.arraycopy(data, 0, newArr, 0, data.length); 42 | data = newArr; 43 | } 44 | if (pos >= this.size) { 45 | size = pos + 1; 46 | } 47 | data[pos] = val; 48 | } 49 | 50 | /** 51 | * Get T value from the specified offset 52 | * 53 | * @param offset The specified offset to fetch 54 | * @return Value at offsetd 55 | */ 56 | public T get(int offset) { 57 | return data[offset]; 58 | } 59 | 60 | /** 61 | * Return real size of this array 62 | * 63 | * @return real size of this array 64 | */ 65 | public int size() { 66 | return size; 67 | } 68 | 69 | /** 70 | * Return capacity of this array 71 | * 72 | * @return capacity of this array 73 | */ 74 | public int cap() { 75 | return data == null ? 0 : data.length; 76 | } 77 | 78 | /** 79 | * Clear this array, don't need release reference, only reset position 80 | */ 81 | public void clear() { 82 | size = 0; 83 | } 84 | 85 | @Override 86 | public boolean equals(Object obj) { 87 | if (!(obj instanceof Array)) { 88 | return false; 89 | } 90 | Array objArr = (Array) obj; 91 | if (objArr.size != size) { 92 | return false; 93 | } 94 | for (int i = 0; i < size; i++) { 95 | if (!Objects.deepEquals(data[i], objArr.data[i])) { 96 | return false; 97 | } 98 | } 99 | return true; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/transport/Const.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.transport; 2 | 3 | /** 4 | * Constants that shared between input and output 5 | * 6 | * @author sulin 7 | * @since 2019-10-02 16:42:24 8 | */ 9 | interface Const { 10 | 11 | byte VER = 0b0001_0000; 12 | byte VER_STREAM = 0b0000_1000; 13 | byte VER_HAS_DATA = 0b0000_0100; 14 | byte VER_HAS_META = 0b0000_0010; 15 | byte VER_HAS_SEQ = 0b0000_0001; 16 | 17 | byte FLAG_META_NAME_TMP = 1 << 1; 18 | byte FLAG_META_NAME_ADDED = 2 << 1; 19 | byte FLAG_META_NAME_EXPIRED = 3 << 1; 20 | byte FLAG_META_STRUCT_TMP = 4 << 1; 21 | byte FLAG_META_STRUCT_ADDED = 5 << 1; 22 | byte FLAG_META_STRUCT_EXPIRED = 6 << 1; 23 | byte FLAG_META_STRUCT_REFERRED = 7 << 1; 24 | 25 | byte FLAG_DATA_FLOAT = 1 << 1; 26 | byte FLAG_DATA_DOUBLE = 2 << 1; 27 | byte FLAG_DATA_VARINT = 3 << 1; 28 | byte FLAG_DATA_STRING = 4 << 1; 29 | byte FLAG_DATA_SYMBOL_ADDED = 5 << 1; 30 | byte FLAG_DATA_SYMBOL_EXPIRED = 6 << 1; 31 | 32 | byte CONST_NULL = 0x00; 33 | byte CONST_FALSE = 0x01; 34 | byte CONST_TRUE = 0x02; 35 | byte CONST_ZERO_ARRAY = 0x03; 36 | 37 | byte TYPE_CONST = -1; 38 | byte TYPE_VARINT = 0; 39 | byte TYPE_FLOAT = 1; 40 | byte TYPE_DOUBLE = 2; 41 | byte TYPE_STRING = 3; 42 | byte TYPE_SYMBOL = 4; 43 | byte TYPE_OBJECT = 5; 44 | byte TYPE_ARRAY = 6; 45 | byte TYPE_NARRAY = 7; 46 | 47 | byte TYPE_NARRAY_BOOL = 1 << 3 | TYPE_NARRAY; 48 | byte TYPE_NARRAY_BYTE = 2 << 3 | TYPE_NARRAY; 49 | byte TYPE_NARRAY_SHORT = 3 << 3 | TYPE_NARRAY; 50 | byte TYPE_NARRAY_INT = 4 << 3 | TYPE_NARRAY; 51 | byte TYPE_NARRAY_LONG = 5 << 3 | TYPE_NARRAY; 52 | byte TYPE_NARRAY_FLOAT = 6 << 3 | TYPE_NARRAY; 53 | byte TYPE_NARRAY_DOUBLE = 7 << 3 | TYPE_NARRAY; 54 | 55 | byte TYPE_SLICE_NULL = 0x00; 56 | byte TYPE_SLICE_BOOL = 0x01; 57 | byte TYPE_SLICE_FLOAT = 0x02; 58 | byte TYPE_SLICE_DOUBLE = 0x03; 59 | byte TYPE_SLICE_BYTE = 0x04; 60 | byte TYPE_SLICE_SHORT = 0x05; 61 | byte TYPE_SLICE_INT = 0x06; 62 | byte TYPE_SLICE_LONG = 0x07; 63 | byte TYPE_SLICE_STRING = 0x08; 64 | byte TYPE_SLICE_SYMBOL = 0x09; 65 | byte TYPE_SLICE_OBJECT = 0x0A; 66 | byte TYPE_SLICE_UNKNOWN = 0x0B; 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/transport/IDAllocator.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.transport; 2 | 3 | import com.github.smartbuf.utils.ArrayUtils; 4 | 5 | /** 6 | * allocate [0, max] id 7 | * 8 | * @author sulin 9 | * @since 2019-04-29 17:37:20 10 | */ 11 | public final class IDAllocator { 12 | 13 | /** 14 | * The next incremental id, if no reuseIds, it should be used at next time. 15 | */ 16 | private int nextId; 17 | /** 18 | * The real count of reuseIds. 19 | */ 20 | private int reuseCount; 21 | /** 22 | * The id was released. 23 | */ 24 | private int[] reuseIds; 25 | 26 | /** 27 | * Acquire an unique and incremental id, if have released id, use it first. 28 | * 29 | * @return Unique and incremental id 30 | */ 31 | public int acquire() { 32 | if (reuseCount == 0) { 33 | return nextId++; 34 | } 35 | return this.reuseIds[--reuseCount]; 36 | } 37 | 38 | /** 39 | * Release the specified id, It will be used in high priority. 40 | * 41 | * @param id ID was released 42 | */ 43 | public void release(int id) { 44 | if (id >= nextId) { 45 | throw new IllegalArgumentException(id + " is not acquired"); 46 | } 47 | if (reuseIds == null) { 48 | reuseIds = new int[4]; 49 | } else if (reuseCount >= reuseIds.length) { 50 | int[] tmp = new int[reuseIds.length * 2]; 51 | System.arraycopy(reuseIds, 0, tmp, 0, reuseIds.length); 52 | this.reuseIds = tmp; 53 | } 54 | this.reuseIds[this.reuseCount] = id; 55 | ArrayUtils.descFastSort(this.reuseIds, 0, this.reuseCount); 56 | 57 | this.reuseCount++; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/utils/ArrayUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.utils; 2 | 3 | import java.lang.reflect.Array; 4 | 5 | /** 6 | * Some utils for array, meanly sort 7 | * 8 | * @author sulin 9 | * @since 2019-10-02 15:16:34 10 | */ 11 | public final class ArrayUtils { 12 | 13 | private ArrayUtils() { 14 | } 15 | 16 | /** 17 | * Fast-Sort arithmetic which support descend sort for int[] 18 | * 19 | * @param arr Source array 20 | * @param from start offset, include 21 | * @param to end offset, include 22 | */ 23 | public static void descFastSort(final int[] arr, final int from, final int to) { 24 | if (to - from < 1) { 25 | return; 26 | } 27 | int low = from; 28 | int high = to; 29 | int baseVal = arr[low]; 30 | 31 | while (low < high) { 32 | for (; high > low; high--) { 33 | if (arr[high] > baseVal) { 34 | arr[low] = arr[high]; 35 | low++; 36 | break; 37 | } 38 | } 39 | for (; high > low; low++) { 40 | if (arr[low] < baseVal) { 41 | arr[high] = arr[low]; 42 | high--; 43 | break; 44 | } 45 | } 46 | } 47 | 48 | arr[low] = baseVal; 49 | if (low - from > 1) { 50 | descFastSort(arr, from, low - 1); 51 | } 52 | if (to - low > 1) { 53 | descFastSort(arr, low + 1, to); 54 | } 55 | } 56 | 57 | /** 58 | * Fast-Sort arithmetic which support descend sort for long[] 59 | * 60 | * @param arr Source array 61 | * @param from start offset, include 62 | * @param to end offset, include 63 | */ 64 | public static void descFastSort(final long[] arr, final int from, final int to) { 65 | if (to - from < 1) { 66 | return; 67 | } 68 | int low = from; 69 | int high = to; 70 | long baseVal = arr[low]; 71 | 72 | while (low < high) { 73 | for (; high > low; high--) { 74 | if (arr[high] > baseVal) { 75 | arr[low] = arr[high]; 76 | low++; 77 | break; 78 | } 79 | } 80 | for (; high > low; low++) { 81 | if (arr[low] < baseVal) { 82 | arr[high] = arr[low]; 83 | high--; 84 | break; 85 | } 86 | } 87 | } 88 | 89 | arr[low] = baseVal; 90 | if (low - from > 1) { 91 | descFastSort(arr, from, low - 1); 92 | } 93 | if (to - low > 1) { 94 | descFastSort(arr, low + 1, to); 95 | } 96 | } 97 | 98 | /** 99 | * put value into array's specified position, execute expansion automatically. 100 | * 101 | * @param arr Source array 102 | * @param pos Put position 103 | * @param val New item 104 | * @param T 105 | * @return Put result 106 | */ 107 | @SuppressWarnings("unchecked") 108 | public static T[] put(T[] arr, int pos, T val) { 109 | if (arr == null) { 110 | arr = (T[]) new Object[4]; 111 | } 112 | if (arr.length <= pos) { 113 | T[] newArr = (T[]) Array.newInstance(arr.getClass().getComponentType(), arr.length * 2); 114 | System.arraycopy(arr, 0, newArr, 0, arr.length); 115 | arr = newArr; 116 | } 117 | arr[pos] = val; 118 | return arr; 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/utils/CodecUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.utils; 2 | 3 | import com.github.smartbuf.converter.Codec; 4 | import com.github.smartbuf.converter.CodecFactory; 5 | import com.github.smartbuf.converter.ConverterPipeline; 6 | import com.github.smartbuf.node.NodeCodec; 7 | import com.github.smartbuf.reflect.TypeRef; 8 | import com.github.smartbuf.reflect.XType; 9 | 10 | import java.lang.reflect.Type; 11 | 12 | /** 13 | * CodecUtils wraps an global {@link CodecFactory} and provides some useful features. 14 | * 15 | * @author sulin 16 | * @since 2019-11-09 20:19:49 17 | */ 18 | public final class CodecUtils { 19 | 20 | private static final CodecFactory factory = new CodecFactory(); 21 | 22 | static { 23 | factory.installCodec(NodeCodec.class); 24 | } 25 | 26 | private CodecUtils() { 27 | } 28 | 29 | /** 30 | * Install new {@link Codec} into the default CodecFactory 31 | * 32 | * @param codec The new codec implementation 33 | */ 34 | public static void installCodec(Codec codec) { 35 | factory.installCodec(codec); 36 | } 37 | 38 | /** 39 | * Convert the specified object to instance of the specified class 40 | * 41 | * @param src source data 42 | * @param clz target class 43 | * @param Target template type 44 | * @return instance of the specified class 45 | */ 46 | public static T convert(Object src, Class clz) { 47 | return factory.convert(src, clz); 48 | } 49 | 50 | /** 51 | * Convert the specified object to the specified type 52 | * 53 | * @param src Source data 54 | * @param type Target type 55 | * @param Target's real type 56 | * @return instance of the specified type 57 | */ 58 | public static T convert(Object src, TypeRef type) { 59 | return convert(src, type.getType()); 60 | } 61 | 62 | /** 63 | * Convert the specified object to the specified type 64 | * 65 | * @param src Source data 66 | * @param type Target type, suport generic type 67 | * @param Target's real type 68 | * @return instance of the specified type 69 | */ 70 | @SuppressWarnings("unchecked") 71 | public static T convert(Object src, Type type) { 72 | return (T) factory.convert(src, type); 73 | } 74 | 75 | /** 76 | * Convert the specified {@link Type} into {@link XType} 77 | * 78 | * @param type original type 79 | * @return type's XType instance 80 | */ 81 | public static XType toXType(Type type) { 82 | return factory.toXType(type); 83 | } 84 | 85 | /** 86 | * Get a pipeline which could convert srcClass's instance into tgtClass's instance 87 | * 88 | * @param srcClass Source Class 89 | * @param tgtClass Target Class 90 | * @return The final pipeline 91 | */ 92 | public static ConverterPipeline getPipeline(Class srcClass, Class tgtClass) { 93 | return factory.getPipeline(srcClass, tgtClass); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/utils/NumberUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.utils; 2 | 3 | /** 4 | * NumberUtils provides some useful features for number convert operation. 5 | * 6 | * @author sulin 7 | * @since 2019-04-27 16:03:53 8 | */ 9 | public final class NumberUtils { 10 | 11 | private NumberUtils() { 12 | } 13 | 14 | public static long intToUint(long l) { 15 | return (l << 1) ^ (l >> 63); 16 | } 17 | 18 | public static long uintToInt(long l) { 19 | return (l >>> 1) ^ -(l & 1); 20 | } 21 | 22 | public static int floatToBits(float f) { 23 | return Float.floatToRawIntBits(f); 24 | } 25 | 26 | public static float bitsToFloat(int i) { 27 | return Float.intBitsToFloat(i); 28 | } 29 | 30 | public static long doubleToBits(double d) { 31 | return Double.doubleToRawLongBits(d); 32 | } 33 | 34 | public static double bitsToDouble(long l) { 35 | return Double.longBitsToDouble(l); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/utils/TimeUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.utils; 2 | 3 | import java.lang.management.ManagementFactory; 4 | 5 | /** 6 | * Some time utils for convenience or performance 7 | * 8 | * @author sulin 9 | * @since 2019-10-08 21:02:56 10 | */ 11 | public final class TimeUtils { 12 | 13 | public static int INTERVAL = 500; 14 | 15 | static final long UP_TIME = ManagementFactory.getRuntimeMXBean().getStartTime(); 16 | static final Thread TIMER_THREAD; 17 | 18 | private static long now; 19 | private static long uptime; 20 | 21 | static { 22 | TIMER_THREAD = new Thread(() -> { 23 | while (true) { 24 | flush(); 25 | try { 26 | Thread.sleep(INTERVAL); 27 | } catch (InterruptedException ignored) { 28 | } 29 | } 30 | }); 31 | TIMER_THREAD.setName("TimeUtils-Timer"); 32 | TIMER_THREAD.setDaemon(true); 33 | TIMER_THREAD.start(); 34 | flush(); 35 | } 36 | 37 | private TimeUtils() { 38 | } 39 | 40 | /** 41 | * Fetch current second from 1970.1.1, this is faster and fuzzier 42 | * 43 | * @return Now second 44 | */ 45 | public static long fastNow() { 46 | return now; 47 | } 48 | 49 | /** 50 | * Fetch current second from uptime, this is faster and fuzzier 51 | * 52 | * @return Uptime second 53 | */ 54 | public static long fastUpTime() { 55 | return uptime; 56 | } 57 | 58 | private static void flush() { 59 | long ms = System.currentTimeMillis(); 60 | now = ms; 61 | uptime = ms - UP_TIME; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/github/smartbuf/utils/UTF8Utils.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.utils; 2 | 3 | import java.nio.charset.Charset; 4 | 5 | /** 6 | * UTF8Utils wraps encode and decode functions for utf-8 charset, 7 | * it provides higher performance to convert String as byte[] 8 | * 9 | * @author sulin 10 | * @since 2019-11-05 19:51:53 11 | */ 12 | public final class UTF8Utils { 13 | 14 | public static final byte REPL = 63; 15 | 16 | private UTF8Utils() { 17 | } 18 | 19 | /** 20 | * Encode the speicifed CharSequence into byte[], it works like {@link String#getBytes(Charset)} 21 | * 22 | * @param cs The original string to encode 23 | * @return Encoding result 24 | */ 25 | public static byte[] encode(CharSequence cs) { 26 | byte[] buf = new byte[cs.length() * 3]; 27 | int size = encode(cs, buf, 0); 28 | byte[] result = new byte[size]; 29 | System.arraycopy(buf, 0, result, 0, size); 30 | return result; 31 | } 32 | 33 | /** 34 | * Use UTF-8 encode the specified {@link CharSequence} to bytes, and write them into the specified buf 35 | * 36 | * @param str The original string to encode 37 | * @param buf The buffer to accept encoding result 38 | * @param bufOffset buf's write offset 39 | * @return Final position of writing 40 | */ 41 | public static int encode(CharSequence str, byte[] buf, int bufOffset) { 42 | int charOff = 0; 43 | int charNum = str.length(); 44 | 45 | // encode the beginning ascii chars [0, 128) 46 | for (char c; charOff < charNum; charOff++) { 47 | if ((c = str.charAt(charOff)) >= 128) { 48 | break; 49 | } 50 | buf[bufOffset++] = (byte) c; 51 | } 52 | 53 | while (charOff < charNum) { 54 | char c = str.charAt(charOff++); 55 | if (c < 128) { 56 | buf[bufOffset++] = (byte) c; 57 | } else if (c < 2048) { 58 | buf[bufOffset++] = (byte) (192 | c >> 6); 59 | buf[bufOffset++] = (byte) (128 | c & 63); 60 | } else if (Character.isSurrogate(c)) { 61 | 62 | int code = parse(str, c, charOff - 1, charNum); 63 | if (code < 0) { 64 | buf[bufOffset++] = REPL; 65 | } else { 66 | buf[bufOffset++] = (byte) (240 | code >> 18); 67 | buf[bufOffset++] = (byte) (128 | code >> 12 & 63); 68 | buf[bufOffset++] = (byte) (128 | code >> 6 & 63); 69 | buf[bufOffset++] = (byte) (128 | code & 63); 70 | ++charOff; 71 | } 72 | } else { 73 | buf[bufOffset++] = (byte) (224 | c >> 12); 74 | buf[bufOffset++] = (byte) (128 | c >> 6 & 63); 75 | buf[bufOffset++] = (byte) (128 | c & 63); 76 | } 77 | } 78 | 79 | return bufOffset; 80 | } 81 | 82 | /** 83 | * surrogate char parser, mainly copied from {@link sun.nio.cs.Surrogate.Parser#parse} 84 | */ 85 | private static int parse(CharSequence cs, char c, int pos, int limit) { 86 | int character; 87 | if (Character.isHighSurrogate(c)) { 88 | if (limit - pos < 2) { 89 | return -1; 90 | } else { 91 | char var5 = cs.charAt(pos + 1); 92 | if (Character.isLowSurrogate(var5)) { 93 | character = Character.toCodePoint(c, var5); 94 | return character; 95 | } else { 96 | return -1; 97 | } 98 | } 99 | } else { 100 | return -1; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/benchmark/Runner.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.benchmark; 2 | 3 | import com.github.smartbuf.benchmark.large.LargeDeserBenchmark; 4 | import com.github.smartbuf.benchmark.large.LargeSerialBenchmark; 5 | import com.github.smartbuf.benchmark.medium.MediumDeserBenchmark; 6 | import com.github.smartbuf.benchmark.medium.MediumSerialBenchmark; 7 | import com.github.smartbuf.benchmark.small.SmallDeserBenchmark; 8 | import com.github.smartbuf.benchmark.small.SmallSerialBenchmark; 9 | import org.openjdk.jmh.runner.RunnerException; 10 | import org.openjdk.jmh.runner.options.OptionsBuilder; 11 | 12 | /** 13 | * @author sulin 14 | * @since 2019-11-12 12:13:41 15 | */ 16 | public class Runner { 17 | 18 | public static void main(String[] args) { 19 | OptionsBuilder builder = new OptionsBuilder(); 20 | 21 | builder.include(SmallSerialBenchmark.class.getName()); 22 | builder.include(SmallDeserBenchmark.class.getName()); 23 | 24 | builder.include(MediumSerialBenchmark.class.getName()); 25 | builder.include(MediumDeserBenchmark.class.getName()); 26 | 27 | builder.include(LargeSerialBenchmark.class.getName()); 28 | builder.include(LargeDeserBenchmark.class.getName()); 29 | 30 | try { 31 | new org.openjdk.jmh.runner.Runner(builder.build()).run(); 32 | } catch (RunnerException e) { 33 | throw new RuntimeException(e); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/benchmark/TestBenchmark.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.benchmark; 2 | 3 | import org.apache.commons.lang3.RandomUtils; 4 | import org.openjdk.jmh.annotations.*; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.concurrent.TimeUnit; 9 | 10 | /** 11 | * @author sulin 12 | * @since 2019-10-30 20:21:38 13 | */ 14 | @Warmup(iterations = 2, time = 2) 15 | @Fork(2) 16 | @Measurement(iterations = 3, time = 3) 17 | @BenchmarkMode(Mode.AverageTime) 18 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 19 | public class TestBenchmark { 20 | 21 | static Object[] arr = new Object[1024]; 22 | static List list = new ArrayList<>(); 23 | 24 | static { 25 | for (int i = 0; i < arr.length; i++) { 26 | arr[i] = RandomUtils.nextDouble(); 27 | list.add(arr[i]); 28 | } 29 | } 30 | 31 | @Benchmark 32 | public void test() { 33 | Class prevCls = null; 34 | Class currCls = null; 35 | int i = 0; 36 | // 674ns 37 | for (Object o : list) { 38 | currCls = o == null ? null : o.getClass(); 39 | if (prevCls == currCls) { 40 | i++; 41 | } 42 | prevCls = currCls; 43 | } 44 | } 45 | 46 | @Benchmark 47 | public void test2() { 48 | Class cls = Object.class; 49 | cls.isEnum(); 50 | cls.isArray(); 51 | cls.getName(); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/benchmark/large/LargeDeserBenchmark.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.benchmark.large; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.io.ByteBufferInput; 5 | import com.esotericsoftware.kryo.io.ByteBufferOutput; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.github.smartbuf.SmartPacket; 8 | import com.github.smartbuf.SmartStream; 9 | import org.msgpack.MessagePack; 10 | import org.openjdk.jmh.annotations.*; 11 | 12 | import java.io.IOException; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | /** 16 | * Benchmark Mode Cnt Score Error Units 17 | * LargeDeserBenchmark.json avgt 9 215988.530 ± 14369.676 ns/op 18 | * LargeDeserBenchmark.kryo avgt 9 144229.596 ± 8665.693 ns/op 19 | * LargeDeserBenchmark.msgpack avgt 9 91418.850 ± 2470.538 ns/op 20 | * LargeDeserBenchmark.protobuf avgt 9 49573.240 ± 483.989 ns/op 21 | * LargeDeserBenchmark.sb_packet avgt 9 105982.178 ± 6484.683 ns/op 22 | * LargeDeserBenchmark.sb_stream avgt 9 98243.964 ± 2018.606 ns/op 23 | * 24 | * @author sulin 25 | * @since 2019-11-11 10:58:07 26 | */ 27 | @Warmup(iterations = 2, time = 2) 28 | @Fork(3) 29 | @Measurement(iterations = 3, time = 3) 30 | @BenchmarkMode(Mode.AverageTime) 31 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 32 | public class LargeDeserBenchmark { 33 | 34 | static final LargeTest.TrendsModel trends = LargeTest.trendsModel; 35 | 36 | static final ObjectMapper MAPPER = new ObjectMapper(); 37 | static final SmartStream STREAM = new SmartStream(); 38 | static final MessagePack MSGPACK = new MessagePack(); 39 | static final Kryo KRYO = new Kryo(); 40 | 41 | static byte[] jsonBytes; 42 | static byte[] kryoBytes; 43 | static byte[] msgpackBytes; 44 | static byte[] pbBytes; 45 | static byte[] packetBytes; 46 | static byte[] streamBytes; 47 | 48 | static { 49 | ByteBufferOutput kryoOutput = new ByteBufferOutput(1 << 20); 50 | 51 | try { 52 | KRYO.writeObject(kryoOutput, trends); 53 | kryoBytes = kryoOutput.toBytes(); 54 | jsonBytes = MAPPER.writeValueAsBytes(trends); 55 | msgpackBytes = MSGPACK.write(trends); 56 | pbBytes = trends.toPB().toByteArray(); 57 | packetBytes = SmartPacket.serialize(trends); 58 | streamBytes = STREAM.serialize(trends); 59 | 60 | // smartbuf's stream-mode need warm up to avoid sequence error 61 | STREAM.deserialize(streamBytes, LargeTest.TrendsModel.class); 62 | 63 | jsonBytes = MAPPER.writeValueAsBytes(trends); 64 | pbBytes = trends.toPB().toByteArray(); 65 | packetBytes = SmartPacket.serialize(trends); 66 | streamBytes = STREAM.serialize(trends); 67 | } catch (IOException e) { 68 | throw new RuntimeException(e); 69 | } 70 | } 71 | 72 | @Benchmark 73 | public void json() throws Exception { 74 | MAPPER.readValue(jsonBytes, LargeTest.TrendsModel.class); 75 | } 76 | 77 | @Benchmark 78 | public void kryo() { 79 | KRYO.readObject(new ByteBufferInput(kryoBytes), LargeTest.TrendsModel.class); 80 | } 81 | 82 | @Benchmark 83 | public void msgpack() throws IOException { 84 | MSGPACK.read(msgpackBytes, LargeTest.TrendsModel.class); 85 | } 86 | 87 | @Benchmark 88 | public void protobuf() throws Exception { 89 | Large.Trends.parseFrom(pbBytes); 90 | } 91 | 92 | @Benchmark 93 | public void sb_packet() throws Exception { 94 | SmartPacket.deserialize(packetBytes, LargeTest.TrendsModel.class); 95 | } 96 | 97 | @Benchmark 98 | public void sb_stream() throws Exception { 99 | STREAM.deserialize(streamBytes, LargeTest.TrendsModel.class); 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/benchmark/large/LargeSerialBenchmark.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.benchmark.large; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.io.ByteBufferOutput; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.github.smartbuf.SmartPacket; 7 | import com.github.smartbuf.SmartStream; 8 | import org.msgpack.MessagePack; 9 | import org.openjdk.jmh.annotations.*; 10 | 11 | import java.io.IOException; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | /** 15 | * Benchmark Mode Cnt Score Error Units 16 | * LargeSerialBenchmark.json avgt 9 126749.482 ± 3173.811 ns/op 17 | * LargeSerialBenchmark.kryo avgt 9 134176.479 ± 1208.534 ns/op 18 | * LargeSerialBenchmark.msgpack avgt 9 70548.730 ± 3072.337 ns/op 19 | * LargeSerialBenchmark.protobuf avgt 9 97395.157 ± 1056.336 ns/op 20 | * LargeSerialBenchmark.sb_packet avgt 9 81460.734 ± 1396.504 ns/op 21 | * LargeSerialBenchmark.sb_stream avgt 9 77611.622 ± 430.881 ns/op 22 | * 23 | * @author sulin 24 | * @since 2019-11-10 16:12:28 25 | */ 26 | @Warmup(iterations = 2, time = 2) 27 | @Fork(3) 28 | @Measurement(iterations = 3, time = 3) 29 | @BenchmarkMode(Mode.AverageTime) 30 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 31 | public class LargeSerialBenchmark { 32 | 33 | static final LargeTest.TrendsModel trends = LargeTest.trendsModel; 34 | 35 | static final ObjectMapper MAPPER = new ObjectMapper(); 36 | static final SmartStream STREAM = new SmartStream(); 37 | static final MessagePack MSGPACK = new MessagePack(); 38 | static final Kryo KRYO = new Kryo(); 39 | 40 | static ByteBufferOutput kryoOutput = new ByteBufferOutput(1 << 20); 41 | 42 | @Benchmark 43 | public void json() throws Exception { 44 | MAPPER.writeValueAsBytes(trends); 45 | } 46 | 47 | @Benchmark 48 | public void kryo() { 49 | KRYO.writeObject(kryoOutput, trends); 50 | kryoOutput.toBytes(); 51 | kryoOutput.clear(); 52 | } 53 | 54 | @Benchmark 55 | public void msgpack() throws IOException { 56 | MSGPACK.write(trends); 57 | } 58 | 59 | @Benchmark 60 | public void protobuf() { 61 | trends.toPB().toByteArray(); 62 | } 63 | 64 | @Benchmark 65 | public void sb_packet() throws Exception { 66 | SmartPacket.serialize(trends); 67 | } 68 | 69 | @Benchmark 70 | public void sb_stream() throws Exception { 71 | STREAM.serialize(trends); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/benchmark/medium/MediumDeserBenchmark.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.benchmark.medium; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.io.ByteBufferInput; 5 | import com.esotericsoftware.kryo.io.ByteBufferOutput; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.github.smartbuf.SmartPacket; 8 | import com.github.smartbuf.SmartStream; 9 | import org.msgpack.MessagePack; 10 | import org.openjdk.jmh.annotations.*; 11 | 12 | import java.io.IOException; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | /** 16 | * Benchmark Mode Cnt Score Error Units 17 | * MediumDeserBenchmark.json avgt 6 7040.950 ± 459.725 ns/op 18 | * MediumDeserBenchmark.kryo avgt 6 6432.450 ± 731.190 ns/op 19 | * MediumDeserBenchmark.msgpack avgt 6 15989.744 ± 208.045 ns/op 20 | * MediumDeserBenchmark.protobuf avgt 6 2598.041 ± 135.756 ns/op 21 | * MediumDeserBenchmark.sb_packet avgt 6 6819.044 ± 546.147 ns/op 22 | * MediumDeserBenchmark.sb_stream avgt 6 5466.728 ± 141.585 ns/op 23 | * 24 | * @author sulin 25 | * @since 2019-11-11 10:53:43 26 | */ 27 | @Warmup(iterations = 2, time = 2) 28 | @Fork(2) 29 | @Measurement(iterations = 3, time = 3) 30 | @BenchmarkMode(Mode.AverageTime) 31 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 32 | public class MediumDeserBenchmark { 33 | 34 | private static final UserModel user = UserModel.random(); 35 | 36 | static final ObjectMapper MAPPER = new ObjectMapper(); 37 | static final SmartStream STREAM = new SmartStream(); 38 | static final MessagePack MSGPACK = new MessagePack(); 39 | static final Kryo KRYO = new Kryo(); 40 | 41 | static byte[] jsonBytes; 42 | static byte[] kryoBytes; 43 | static byte[] msgpackBytes; 44 | static byte[] pbBytes; 45 | static byte[] packetBytes; 46 | static byte[] streamBytes; 47 | 48 | static { 49 | KRYO.register(UserModel.class); 50 | KRYO.register(UserModel.Message.class); 51 | KRYO.register(UserModel.Tag.class); 52 | 53 | ByteBufferOutput kryoOutput = new ByteBufferOutput(1024); 54 | try { 55 | KRYO.writeObject(kryoOutput, user); 56 | 57 | jsonBytes = MAPPER.writeValueAsBytes(user); 58 | msgpackBytes = MSGPACK.write(user); 59 | kryoBytes = kryoOutput.toBytes(); 60 | pbBytes = user.toUser().toByteArray(); 61 | packetBytes = SmartPacket.serialize(user); 62 | streamBytes = STREAM.serialize(user); 63 | // smartbuf's stream-mode need warm up to avoid sequence error 64 | STREAM.deserialize(streamBytes, UserModel.class); 65 | 66 | jsonBytes = MAPPER.writeValueAsBytes(user); 67 | pbBytes = user.toUser().toByteArray(); 68 | packetBytes = SmartPacket.serialize(user); 69 | streamBytes = STREAM.serialize(user); 70 | } catch (IOException e) { 71 | throw new RuntimeException(e); 72 | } 73 | } 74 | 75 | @Benchmark 76 | public void json() throws Exception { 77 | MAPPER.readValue(jsonBytes, UserModel.class); 78 | } 79 | 80 | @Benchmark 81 | public void msgpack() throws IOException { 82 | MSGPACK.read(msgpackBytes, UserModel.class); 83 | } 84 | 85 | @Benchmark 86 | public void kryo() { 87 | KRYO.readObject(new ByteBufferInput(kryoBytes), UserModel.class); 88 | } 89 | 90 | @Benchmark 91 | public void protobuf() throws Exception { 92 | Medium.User.parseFrom(pbBytes); 93 | } 94 | 95 | @Benchmark 96 | public void sb_packet() throws Exception { 97 | SmartPacket.deserialize(packetBytes, UserModel.class); 98 | } 99 | 100 | @Benchmark 101 | public void sb_stream() throws Exception { 102 | STREAM.deserialize(streamBytes, UserModel.class); 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/benchmark/medium/MediumSerialBenchmark.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.benchmark.medium; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.io.ByteBufferOutput; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.github.smartbuf.SmartPacket; 7 | import com.github.smartbuf.SmartStream; 8 | import org.msgpack.MessagePack; 9 | import org.openjdk.jmh.annotations.*; 10 | 11 | import java.util.concurrent.TimeUnit; 12 | 13 | /** 14 | * Benchmark Mode Cnt Score Error Units 15 | * MediumSerialBenchmark.json avgt 9 4329.829 ± 69.129 ns/op 16 | * MediumSerialBenchmark.kryo avgt 9 5325.744 ± 142.879 ns/op 17 | * MediumSerialBenchmark.msgpack avgt 9 21493.727 ± 207.717 ns/op 18 | * MediumSerialBenchmark.protobuf avgt 9 796.052 ± 11.317 ns/op 19 | * MediumSerialBenchmark.sb_packet avgt 9 4486.963 ± 43.700 ns/op 20 | * MediumSerialBenchmark.sb_stream avgt 9 3927.292 ± 57.563 ns/op 21 | * 22 | * @author sulin 23 | * @since 2019-10-31 20:40:55 24 | */ 25 | @Warmup(iterations = 2, time = 2) 26 | @Fork(2) 27 | @Measurement(iterations = 3, time = 3) 28 | @BenchmarkMode(Mode.AverageTime) 29 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 30 | public class MediumSerialBenchmark { 31 | 32 | static final ObjectMapper MAPPER = new ObjectMapper(); 33 | static final SmartStream STREAM = new SmartStream(); 34 | static final MessagePack MSGPACK = new MessagePack(); 35 | static final Kryo KRYO = new Kryo(); 36 | 37 | static final UserModel model = UserModel.random(); 38 | 39 | static final ByteBufferOutput kryoOutput = new ByteBufferOutput(1024); 40 | 41 | static { 42 | KRYO.register(UserModel.class); 43 | KRYO.register(UserModel.Message.class); 44 | KRYO.register(UserModel.Tag.class); 45 | } 46 | 47 | @Benchmark 48 | public void json() throws Exception { 49 | MAPPER.writeValueAsBytes(model); 50 | } 51 | 52 | @Benchmark 53 | public void msgpack() throws Exception { 54 | MSGPACK.write(model); 55 | } 56 | 57 | @Benchmark 58 | public void kryo() { 59 | KRYO.writeObject(kryoOutput, model); 60 | kryoOutput.toBytes(); 61 | kryoOutput.clear(); 62 | } 63 | 64 | @Benchmark 65 | public void protobuf() { 66 | model.toUser().toBuilder(); 67 | } 68 | 69 | @Benchmark 70 | public void sb_packet() throws Exception { 71 | SmartPacket.serialize(model); 72 | } 73 | 74 | @Benchmark 75 | public void sb_stream() throws Exception { 76 | STREAM.serialize(model); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/benchmark/medium/UserModel.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.benchmark.medium; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import org.apache.commons.lang3.RandomStringUtils; 7 | import org.apache.commons.lang3.RandomUtils; 8 | import org.msgpack.annotation.Message; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.UUID; 13 | 14 | /** 15 | * @author sulin 16 | * @since 2019-10-31 19:58:41 17 | */ 18 | @Data 19 | @Message 20 | public class UserModel { 21 | 22 | private long id; 23 | private String nickname; 24 | private String portrait; 25 | private float score; 26 | private String mail; 27 | private String mobile; 28 | private String token; 29 | private Integer type; 30 | private Integer source; 31 | private Boolean blocked; 32 | private int loginTimes; 33 | private long updateTime; 34 | private long createTime; 35 | 36 | private List msgs; 37 | private List tags; 38 | 39 | public static UserModel random() { 40 | UserModel user = new UserModel(); 41 | user.id = RandomUtils.nextLong(); 42 | user.nickname = RandomStringUtils.randomAlphanumeric(12); 43 | user.portrait = RandomStringUtils.randomAlphabetic(24); 44 | user.score = RandomUtils.nextFloat(); 45 | user.mail = RandomStringUtils.randomAlphanumeric(16) + "@gmail.com"; 46 | user.mobile = RandomStringUtils.randomNumeric(12); 47 | user.token = UUID.randomUUID().toString(); 48 | user.type = RandomUtils.nextInt(1, 10); 49 | user.source = RandomUtils.nextInt(1, 10); 50 | user.blocked = RandomUtils.nextBoolean(); 51 | user.loginTimes = RandomUtils.nextInt(10, 10000); 52 | user.updateTime = System.currentTimeMillis(); 53 | user.createTime = System.currentTimeMillis(); 54 | user.msgs = new ArrayList<>(); 55 | user.tags = new ArrayList<>(); 56 | 57 | long toUUID = RandomUtils.nextInt(1000000, 9999999); 58 | for (int i = 0; i < 10; i++) { 59 | Message m = new Message(); 60 | m.id = (long) i; 61 | m.from = RandomUtils.nextLong(1000000, 9999999); 62 | m.to = toUUID; 63 | m.msg = RandomStringUtils.randomAlphabetic(40); 64 | m.timestamp = System.currentTimeMillis(); 65 | user.msgs.add(m); 66 | } 67 | for (int i = 0; i < 16; i++) { 68 | user.tags.add(new Tag(i, "Tag" + i)); 69 | } 70 | return user; 71 | } 72 | 73 | public Medium.User toUser() { 74 | Medium.User.Builder builder = Medium.User.newBuilder() 75 | .setId(id) 76 | .setNickname(nickname) 77 | .setPortrait(portrait) 78 | .setScore(score) 79 | .setMail(mail) 80 | .setMobile(mobile) 81 | .setToken(token) 82 | .setType(type) 83 | .setSource(source) 84 | .setBlocked(blocked) 85 | .setLoginTimes(loginTimes) 86 | .setUpdateTime(updateTime) 87 | .setCreateTime(createTime); 88 | 89 | for (Message msg : msgs) { 90 | builder.addMsgs(Medium.Message.newBuilder() 91 | .setId(msg.id) 92 | .setFrom(msg.from) 93 | .setTo(msg.to) 94 | .setMsg(msg.msg) 95 | .setTimestamp(msg.timestamp) 96 | .build()); 97 | } 98 | 99 | for (Tag tag : tags) { 100 | builder.addTags(Medium.Tag.newBuilder() 101 | .setCode(tag.code) 102 | .setName(tag.name) 103 | .build()); 104 | } 105 | 106 | return builder.build(); 107 | } 108 | 109 | @Data 110 | @org.msgpack.annotation.Message 111 | public static class Message { 112 | private Long id; 113 | private Long from; 114 | private Long to; 115 | private String msg; 116 | private Long timestamp; 117 | } 118 | 119 | @Data 120 | @NoArgsConstructor 121 | @AllArgsConstructor 122 | @org.msgpack.annotation.Message 123 | public static class Tag { 124 | private int code; 125 | private String name; 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/benchmark/small/SmallDeserBenchmark.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.benchmark.small; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.io.ByteBufferInput; 5 | import com.esotericsoftware.kryo.io.ByteBufferOutput; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.github.smartbuf.SmartPacket; 8 | import com.github.smartbuf.SmartStream; 9 | import org.msgpack.MessagePack; 10 | import org.openjdk.jmh.annotations.*; 11 | 12 | import java.io.IOException; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | /** 16 | * Benchmark Mode Cnt Score Error Units 17 | * SmallDeserBenchmark.json avgt 6 831.411 ± 133.241 ns/op 18 | * SmallDeserBenchmark.kryo avgt 6 958.711 ± 901.156 ns/op 19 | * SmallDeserBenchmark.msgpack avgt 6 1304.432 ± 21.346 ns/op 20 | * SmallDeserBenchmark.protobuf avgt 6 142.961 ± 1.740 ns/op 21 | * SmallDeserBenchmark.sb_packet avgt 6 624.565 ± 4.355 ns/op 22 | * SmallDeserBenchmark.sb_stream avgt 6 363.003 ± 8.824 ns/op 23 | * 24 | * @author sulin 25 | * @since 2019-11-11 10:38:04 26 | */ 27 | @Warmup(iterations = 2, time = 2) 28 | @Fork(2) 29 | @Measurement(iterations = 3, time = 3) 30 | @BenchmarkMode(Mode.AverageTime) 31 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 32 | public class SmallDeserBenchmark { 33 | 34 | private static final ObjectMapper mapper = new ObjectMapper(); 35 | private static final SmartStream stream = new SmartStream(); 36 | static final MessagePack MSGPACK = new MessagePack(); 37 | static final Kryo KRYO = new Kryo(); 38 | 39 | private static final UserModel user = UserModel.random(); 40 | 41 | static byte[] jsonBytes; 42 | static byte[] msgpackBytes; 43 | static byte[] kryoBytes; 44 | static byte[] pbBytes; 45 | static byte[] packetBytes; 46 | static byte[] streamBytes; 47 | 48 | static { 49 | try { 50 | ByteBufferOutput kryoOutput = new ByteBufferOutput(1024); 51 | 52 | KRYO.writeObject(kryoOutput, user); 53 | 54 | jsonBytes = mapper.writeValueAsBytes(user); 55 | msgpackBytes = MSGPACK.write(user); 56 | pbBytes = user.toPB().toByteArray(); 57 | kryoBytes = kryoOutput.toBytes(); 58 | packetBytes = SmartPacket.serialize(user); 59 | streamBytes = stream.serialize(user); 60 | 61 | // smartbuf's stream-mode need warm up to avoid sequence error 62 | stream.deserialize(streamBytes, UserModel.class); 63 | 64 | jsonBytes = mapper.writeValueAsBytes(user); 65 | pbBytes = user.toPB().toByteArray(); 66 | packetBytes = SmartPacket.serialize(user); 67 | streamBytes = stream.serialize(user); 68 | } catch (IOException e) { 69 | throw new RuntimeException(e); 70 | } 71 | } 72 | 73 | @Benchmark 74 | public void json() throws Exception { 75 | mapper.readValue(jsonBytes, UserModel.class); 76 | } 77 | 78 | @Benchmark 79 | public void kryo() { 80 | KRYO.readObject(new ByteBufferInput(kryoBytes), UserModel.class); 81 | } 82 | 83 | @Benchmark 84 | public void msgpack() throws Exception { 85 | MSGPACK.read(msgpackBytes, UserModel.class); 86 | } 87 | 88 | @Benchmark 89 | public void protobuf() throws Exception { 90 | Small.User.parseFrom(pbBytes); 91 | } 92 | 93 | @Benchmark 94 | public void sb_packet() throws Exception { 95 | SmartPacket.deserialize(packetBytes, UserModel.class); 96 | } 97 | 98 | @Benchmark 99 | public void sb_stream() throws Exception { 100 | stream.deserialize(streamBytes, UserModel.class); 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/benchmark/small/SmallSerialBenchmark.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.benchmark.small; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.io.ByteBufferOutput; 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.github.smartbuf.SmartPacket; 8 | import com.github.smartbuf.SmartStream; 9 | import org.msgpack.MessagePack; 10 | import org.openjdk.jmh.annotations.*; 11 | 12 | import java.io.IOException; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | /** 16 | * Benchmark Mode Cnt Score Error Units 17 | * SmallSerialBenchmark.json avgt 6 767.941 ± 20.675 ns/op 18 | * SmallSerialBenchmark.kryo avgt 6 303.953 ± 5.110 ns/op 19 | * SmallSerialBenchmark.msgpack avgt 6 1458.512 ± 47.205 ns/op 20 | * SmallSerialBenchmark.protobuf avgt 6 210.945 ± 20.209 ns/op 21 | * SmallSerialBenchmark.sb_packet avgt 6 635.780 ± 8.427 ns/op 22 | * SmallSerialBenchmark.sb_stream avgt 6 397.773 ± 12.083 ns/op 23 | * 24 | * @author sulin 25 | * @since 2019-10-28 17:32:33 26 | */ 27 | @Warmup(iterations = 2, time = 2) 28 | @Fork(2) 29 | @Measurement(iterations = 3, time = 3) 30 | @BenchmarkMode(Mode.AverageTime) 31 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 32 | public class SmallSerialBenchmark { 33 | 34 | static final UserModel user = UserModel.random(); 35 | 36 | static final ObjectMapper MAPPER = new ObjectMapper(); 37 | static final SmartStream STREAM = new SmartStream(); 38 | static final MessagePack MSGPACK = new MessagePack(); 39 | static final Kryo KRYO = new Kryo(); 40 | 41 | static final ByteBufferOutput kryoOutput = new ByteBufferOutput(1024); 42 | 43 | static { 44 | KRYO.register(UserModel.class); 45 | } 46 | 47 | @Benchmark 48 | public void json() throws JsonProcessingException { 49 | MAPPER.writeValueAsString(user); 50 | } 51 | 52 | @Benchmark 53 | public void msgpack() throws Exception { 54 | MSGPACK.write(user); 55 | } 56 | 57 | @Benchmark 58 | public void protobuf() { 59 | user.toPB().toByteArray(); 60 | } 61 | 62 | @Benchmark 63 | public void kryo() { 64 | KRYO.writeObject(kryoOutput, user); 65 | kryoOutput.toBytes(); 66 | kryoOutput.clear(); 67 | } 68 | 69 | @Benchmark 70 | public void sb_packet() throws IOException { 71 | SmartPacket.serialize(user); 72 | } 73 | 74 | @Benchmark 75 | public void sb_stream() throws IOException { 76 | STREAM.serialize(user); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/benchmark/small/UserModel.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.benchmark.small; 2 | 3 | import lombok.Data; 4 | import org.apache.commons.lang3.RandomStringUtils; 5 | import org.apache.commons.lang3.RandomUtils; 6 | import org.msgpack.annotation.Message; 7 | 8 | /** 9 | * Simple bean for test 10 | * 11 | * @author sulin 12 | * @since 2019-10-28 17:27:09 13 | */ 14 | @Data 15 | @Message 16 | public class UserModel { 17 | 18 | private long id; 19 | private Boolean blocked; 20 | private String nickname; 21 | private String portrait; 22 | private float score; 23 | private int loginTimes; 24 | private long createTime; 25 | 26 | public static UserModel random() { 27 | UserModel user = new UserModel(); 28 | user.id = RandomUtils.nextLong(); 29 | user.blocked = RandomUtils.nextBoolean(); 30 | user.nickname = RandomStringUtils.randomAlphanumeric(12); 31 | user.portrait = RandomStringUtils.randomAlphabetic(24); 32 | user.score = RandomUtils.nextFloat(); 33 | user.loginTimes = RandomUtils.nextInt(10, 10000); 34 | user.createTime = System.currentTimeMillis(); 35 | return user; 36 | } 37 | 38 | public Small.User toPB() { 39 | Small.User.Builder builder = Small.User.newBuilder() 40 | .setId(id) 41 | .setBlocked(blocked) 42 | .setNickname(nickname) 43 | .setPortrait(portrait) 44 | .setScore(score) 45 | .setLoginTimes(loginTimes) 46 | .setCreateTime(createTime); 47 | return builder.build(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/benchmark/tiny/TinyTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.benchmark.tiny; 2 | 3 | import com.github.smartbuf.SmartPacket; 4 | import com.github.smartbuf.SmartStream; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import java.io.IOException; 11 | 12 | /** 13 | * ProtoBuf: [8, -23, 7, 26, 5, 104, 101, 108, 108, 111, 56, -112, 78] 14 | * 15 | * @author sulin 16 | * @since 2019-11-12 20:16:49 17 | */ 18 | public class TinyTest { 19 | 20 | @Test 21 | public void testPB() { 22 | Tiny.User user = Tiny.User.newBuilder() 23 | .setId(1001) 24 | .setName("hello") 25 | .setTime(10000L) 26 | .build(); 27 | 28 | System.out.println(Integer.toHexString(0b1101001)); 29 | System.out.println(Integer.toHexString(0b0010000)); 30 | System.out.println(Integer.toBinaryString(1001)); 31 | System.out.println(Integer.toBinaryString(10000)); 32 | System.out.println(bytesToHex(user.getName().getBytes())); 33 | 34 | System.out.println("ProtoBuf: " + bytesToHex(user.toByteArray())); 35 | } 36 | 37 | @Test 38 | public void testSB() throws IOException { 39 | UserModel user = new UserModel(1001, "hello", 10000L); 40 | SmartStream stream = new SmartStream(); 41 | 42 | byte[] streamData = stream.serialize(user); 43 | 44 | UserModel newUser = stream.deserialize(streamData, UserModel.class); 45 | assert user.equals(newUser); 46 | 47 | System.out.println(bytesToHex(streamData)); 48 | 49 | streamData = stream.serialize(user); 50 | System.out.println(bytesToHex(streamData)); 51 | 52 | // byte[] bytes = SmartPacket.serialize(user); 53 | // UserModel newUser = SmartPacket.deserialize(bytes, UserModel.class); 54 | // assert user.equals(newUser); 55 | 56 | System.out.println(bytesToHex("hello".getBytes())); 57 | System.out.println(bytesToHex("id".getBytes())); 58 | System.out.println(bytesToHex("name".getBytes())); 59 | System.out.println(bytesToHex("time".getBytes())); 60 | 61 | } 62 | 63 | @Data 64 | @NoArgsConstructor 65 | @AllArgsConstructor 66 | public static class UserModel { 67 | private int id; 68 | private String name; 69 | private long time; 70 | } 71 | 72 | private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); 73 | 74 | public static String bytesToHex(byte[] bytes) { 75 | StringBuilder sb = new StringBuilder(); 76 | for (byte aByte : bytes) { 77 | int v = aByte & 0xFF; 78 | if (sb.length() > 0) { 79 | sb.append(", "); 80 | } 81 | sb.append("0x"); 82 | sb.append(HEX_ARRAY[v >>> 4]); 83 | sb.append(HEX_ARRAY[v & 0x0F]); 84 | } 85 | return "[" + sb + "]"; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/CodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | /** 6 | * @author sulin 7 | * @since 2019-05-19 14:11:03 8 | */ 9 | public class CodecTest { 10 | 11 | @Test 12 | public void testArray() { 13 | Object intArr = new Integer[0]; 14 | System.out.println(intArr.getClass()); 15 | System.out.println(intArr instanceof Object[]); 16 | System.out.println(intArr.getClass().getComponentType()); 17 | 18 | Object[] objArr = new Object[]{1, 2}; 19 | System.out.println(objArr instanceof Integer[]); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/ConverterMapTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter; 2 | 3 | import com.github.smartbuf.reflect.XType; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.util.Date; 7 | 8 | /** 9 | * @author sulin 10 | * @since 2019-08-02 16:31:07 11 | */ 12 | public class ConverterMapTest { 13 | 14 | @Test 15 | public void printChart() { 16 | ConverterMap map = CodecFactory.Instance.getConverterMap(); 17 | map.printDot(); 18 | } 19 | 20 | @Test 21 | public void test() throws NoSuchMethodException { 22 | ConverterMap map = new ConverterMap(); 23 | assert map.get(Date.class).isEmpty(); 24 | assert map.get(Date.class, Long.class) == null; 25 | 26 | map.put(new TranConverterMethod(Long.class, Number.class)); 27 | map.put(new TranConverterMethod(Long.class, Number.class)); // should do nothing 28 | try { 29 | map.put(new InvalidConverterMethod(Long.class, Number.class)); 30 | assert false; 31 | } catch (Exception e) { 32 | assert e instanceof IllegalArgumentException; 33 | } 34 | 35 | map.put(RealConverterMethod.valueOf(new TmpCodec(), TmpCodec.class.getDeclaredMethod("toNumber", Long.class))); 36 | map.put(new TranConverterMethod(Long.class, Number.class)); // should do nothing 37 | try { 38 | map.put(new InvalidConverterMethod(Long.class, Number.class)); 39 | assert false; 40 | } catch (Exception e) { 41 | assert e instanceof IllegalArgumentException; 42 | } 43 | 44 | map.put(new InvalidConverterMethod(Date.class, Long.class)); 45 | try { 46 | map.put(new InvalidConverterMethod(Date.class, Long.class)); 47 | assert false; 48 | } catch (Exception e) { 49 | assert e instanceof IllegalArgumentException; 50 | } 51 | } 52 | 53 | static class TmpCodec extends Codec { 54 | @Converter 55 | public Number toNumber(Long l) { 56 | return 0; 57 | } 58 | } 59 | 60 | static class InvalidConverterMethod extends ConverterMethod { 61 | 62 | public InvalidConverterMethod(Class srcClass, Class tgtClass) { 63 | super(srcClass, tgtClass); 64 | } 65 | 66 | @Override 67 | public Object convert(Object data, XType tgtType) { 68 | return null; 69 | } 70 | 71 | @Override 72 | public int getDistance() { 73 | return 0; 74 | } 75 | 76 | @Override 77 | public boolean isExtensible() { 78 | return false; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/ConverterMethodTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter; 2 | 3 | import com.github.smartbuf.reflect.XType; 4 | import com.github.smartbuf.reflect.XTypeUtils; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Type; 9 | import java.sql.Timestamp; 10 | import java.util.*; 11 | 12 | /** 13 | * @author sulin 14 | * @since 2019-08-03 12:07:12 15 | */ 16 | public class ConverterMethodTest { 17 | 18 | @Test 19 | public void testTranConverterMethod() { 20 | ConverterMethod method = new TranConverterMethod(ArrayList.class, Collection.class); 21 | Object tgt = method.convert(new ArrayList(), null); 22 | assert tgt != null; 23 | assert tgt instanceof Collection; 24 | 25 | System.out.println(method); 26 | } 27 | 28 | @Test 29 | public void testRealConverterMethod() { 30 | TestCodec codec = new TestCodec(); 31 | Map methodMap = new HashMap<>(); 32 | for (Method method : codec.getClass().getDeclaredMethods()) { 33 | methodMap.put(method.getName(), RealConverterMethod.valueOf(codec, method)); 34 | } 35 | 36 | assert methodMap.get("invalid1") == null; 37 | assert methodMap.get("invalid2") == null; 38 | assert methodMap.get("invalid3") == null; 39 | assert methodMap.get("invalid4") == null; 40 | assert methodMap.get("invalid5") == null; 41 | assert methodMap.get("invalid6") == null; 42 | 43 | assert methodMap.get("valid1") != null; 44 | assert methodMap.get("valid2") != null; 45 | 46 | assert methodMap.get("valid1").getTgtClass() == BitSet.class; 47 | assert methodMap.get("valid1").getSrcClass() == String.class; 48 | assert !methodMap.get("valid1").isHasTypeArg(); 49 | 50 | assert methodMap.get("valid2").getTgtClass() == Timestamp.class; 51 | assert methodMap.get("valid2").getSrcClass() == String.class; 52 | assert methodMap.get("valid2").isHasTypeArg(); 53 | 54 | RealConverterMethod method = methodMap.get("valid1"); 55 | try { 56 | method.convert(new Date(), null); 57 | assert false; 58 | } catch (Exception e) { 59 | assert e instanceof IllegalArgumentException; 60 | } 61 | try { 62 | method.convert(null, XTypeUtils.toXType(BitSet.class)); 63 | assert false; 64 | } catch (Exception e) { 65 | assert e instanceof IllegalStateException; 66 | } 67 | } 68 | 69 | private static class TestCodec extends Codec implements IC { 70 | 71 | @Converter(nullable = true) 72 | public BitSet valid1(String s) { 73 | throw new UnsupportedOperationException(); 74 | } 75 | 76 | @Converter 77 | public Timestamp valid2(String s, XType type) { 78 | return null; 79 | } 80 | 81 | public Object invalid1(String s) { 82 | return null; 83 | } 84 | 85 | public Object invalid2(String s, XType type) { 86 | return null; 87 | } 88 | 89 | @Converter 90 | public Object invalid3() { 91 | return null; 92 | } 93 | 94 | @Converter 95 | public Object invalid4(String s, Type type) { 96 | return null; 97 | } 98 | 99 | @Converter 100 | public void invalid5(String s) { 101 | } 102 | 103 | @Converter 104 | public Object invalid6(String... s) { 105 | return null; 106 | } 107 | 108 | @Converter 109 | public Void invalid7(String s) { 110 | return null; 111 | } 112 | 113 | @Override 114 | public void setFactory(CodecFactory factory) { 115 | super.setFactory(factory); 116 | } 117 | } 118 | 119 | interface IC { 120 | default void test() { 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/ConverterPipelineTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter; 2 | 3 | import com.github.smartbuf.reflect.TypeRef; 4 | import com.github.smartbuf.reflect.XTypeUtils; 5 | import org.junit.jupiter.api.BeforeEach; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.util.*; 9 | 10 | /** 11 | * @author sulin 12 | * @since 2019-08-03 11:09:37 13 | */ 14 | public class ConverterPipelineTest { 15 | 16 | private CodecFactory factory = new CodecFactory(); 17 | 18 | @BeforeEach 19 | void setUp() { 20 | factory = CodecFactory.Instance; 21 | } 22 | 23 | @Test 24 | public void convert() { 25 | ConverterPipeline pipeline = factory.getPipeline(BitSet.class, Byte[].class); 26 | 27 | Object tgt = pipeline.convert(BitSet.valueOf(new byte[]{1, 2, 3, 4}), XTypeUtils.toXType(Byte[].class)); 28 | assert tgt != null; 29 | assert tgt instanceof Byte[]; 30 | 31 | Byte[] bs = (Byte[]) tgt; 32 | assert bs.length == 4; 33 | assert bs[0] == 1; 34 | assert bs[1] == 2; 35 | assert bs[2] == 3; 36 | assert bs[3] == 4; 37 | } 38 | 39 | @Test 40 | public void test() throws Exception { 41 | ConverterPipeline pipeline = factory.getPipeline(Long.class, Optional.class); 42 | 43 | List methods = new ArrayList<>(); 44 | for (ConverterMethod method : pipeline.getMethods()) { 45 | if (method instanceof RealConverterMethod) { 46 | methods.add((RealConverterMethod) method); 47 | } 48 | } 49 | 50 | ConverterPipeline.Pipeline pip = ConverterPipeline.build(methods); 51 | Object result = pip.convert(1L, XTypeUtils.toXType(new TypeRef>() { 52 | }.getType())); 53 | System.out.println(result); 54 | } 55 | 56 | @Test 57 | public void testError() { 58 | new ConverterPipeline(Collections.singletonList(new RealConverterMethod(Long.class, BitSet.class))); 59 | } 60 | 61 | @Test 62 | public void disableAsm() { 63 | ConverterPipeline.ENABLE_ASM = false; 64 | 65 | Collection collection = factory.convert(new int[]{1, 2, 3}, Collection.class); 66 | assert collection.size() == 3; 67 | 68 | assert factory.convert(OptionalInt.empty(), BitSet.class) == null; 69 | 70 | ConverterPipeline.ENABLE_ASM = true; 71 | } 72 | 73 | @Test 74 | public void testPrimaryArg() { 75 | CodecFactory factory = new CodecFactory(); 76 | factory.installCodec(PrimaryArgCodec.class); 77 | 78 | OptionalInt opt = factory.convert(100, OptionalInt.class); 79 | assert opt.getAsInt() == 101; 80 | } 81 | 82 | public static class PrimaryArgCodec extends Codec { 83 | @Converter(distance = -100) 84 | public OptionalInt toBitSet(int i) { 85 | return OptionalInt.of(i + 1); 86 | } 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/codec/AtomicCodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | import com.github.smartbuf.reflect.TypeRef; 5 | import com.github.smartbuf.reflect.XTypeUtils; 6 | import org.junit.jupiter.api.BeforeEach; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.util.Arrays; 10 | import java.util.BitSet; 11 | import java.util.Objects; 12 | import java.util.Optional; 13 | import java.util.concurrent.atomic.*; 14 | 15 | /** 16 | * @author sulin 17 | * @since 2019-08-03 16:26:30 18 | */ 19 | @SuppressWarnings("ALL") 20 | public class AtomicCodecTest { 21 | 22 | private AtomicCodec codec = new AtomicCodec(); 23 | 24 | @BeforeEach 25 | void setUp() { 26 | codec.setFactory(CodecFactory.Instance); 27 | } 28 | 29 | @Test 30 | public void testAtomic() { 31 | assert codec.toBoolean(new AtomicBoolean(true)); 32 | assert codec.toAtomicBoolean(true).get(); 33 | 34 | assert codec.toInteger(new AtomicInteger(100)) == 100; 35 | assert codec.toAtomicInteger(100).get() == 100; 36 | 37 | assert codec.toLong(new AtomicLong(2000)) == 2000; 38 | assert codec.toAtomicLong(2000L).get() == 2000; 39 | 40 | DoubleAdder doubleAdder = new DoubleAdder(); 41 | doubleAdder.add(0.02); 42 | assert codec.toDoubleAdder(0.02).doubleValue() == 0.02; 43 | assert codec.toDouble(doubleAdder) == 0.02; 44 | 45 | LongAdder longAdder = new LongAdder(); 46 | longAdder.add(999); 47 | assert codec.toLongAdder(999L).longValue() == 999; 48 | assert codec.toLong(longAdder) == 999; 49 | 50 | int[] ints = new int[]{1, 4, 9}; 51 | assert Arrays.equals(codec.toIntegerArray(codec.toAtomicIntegerArray(ints)), ints); 52 | 53 | long[] longs = new long[]{100, 700, 999}; 54 | assert Arrays.equals(codec.toLongArray(codec.toAtomicLongArray(longs)), longs); 55 | 56 | Byte[] bytes = new Byte[]{1, 9, 100}; 57 | assert bytes == codec.toAtomicReference(bytes, XTypeUtils.toXType(AtomicReference.class)).get(); 58 | assert bytes == codec.toAtomicReference(bytes, XTypeUtils.toXType(new TypeRef>() { 59 | }.getType())).get(); 60 | AtomicReference ref = (AtomicReference) codec.toAtomicReference(bytes, XTypeUtils.toXType(new TypeRef>() { 61 | }.getType())); 62 | assert ref.get().toByteArray().length == bytes.length; 63 | assert ref.get().toByteArray()[2] == bytes[2]; 64 | 65 | Object obj = codec.toObject(ref, XTypeUtils.toXType(Object.class)); 66 | assert obj instanceof BitSet; 67 | 68 | AtomicReference ref2 = codec.toAtomicReference(0L, XTypeUtils.toXType(new TypeRef>>() { 69 | }.getType())); 70 | assert ref2.get() instanceof Optional; 71 | assert Objects.equals(0, ((Optional) ref2.get()).get()); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/codec/AwtCodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | import org.junit.jupiter.api.BeforeEach; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.awt.*; 8 | import java.util.Map; 9 | 10 | /** 11 | * @author sulin 12 | * @since 2019-08-03 16:43:57 13 | */ 14 | @SuppressWarnings("unchecked") 15 | public class AwtCodecTest { 16 | 17 | private AwtCodec codec = new AwtCodec(); 18 | 19 | @BeforeEach 20 | void setUp() { 21 | codec.setFactory(CodecFactory.Instance); 22 | } 23 | 24 | @Test 25 | public void testAwt() { 26 | Rectangle rectangle = new Rectangle(1, 1, 100, 200); 27 | Map rectMap = codec.toMap(rectangle); 28 | assert rectangle.equals(codec.toRectangle(rectMap)); 29 | 30 | Dimension dimension = new Dimension(100, 400); 31 | Map dimensionMap = codec.toMap(dimension); 32 | assert dimension.equals(codec.toDimension(dimensionMap)); 33 | 34 | Point point = new Point(1, 999); 35 | Map pointMap = codec.toMap(point); 36 | assert point.equals(codec.toPoint(pointMap)); 37 | 38 | Font font = new Font(Font.SANS_SERIF, Font.BOLD, 20); 39 | Map fontMap = codec.toMap(font); 40 | assert font.equals(codec.toFont(fontMap)); 41 | 42 | fontMap.remove("style"); 43 | fontMap.remove("size"); 44 | Font newFont = codec.toFont(fontMap); 45 | assert newFont.getSize() != font.getSize(); 46 | assert newFont.getStyle() != font.getStyle(); 47 | assert newFont.getName().equals(font.getName()); 48 | 49 | String rgb = "#00FF88"; 50 | Color rgbColor = codec.toColor(rgb); 51 | assert (rgb + "FF").equalsIgnoreCase(codec.toString(rgbColor)); 52 | 53 | String rgba = "#00112233"; 54 | Color rgbaColor = codec.toColor(rgba); 55 | assert rgba.equalsIgnoreCase(codec.toString(rgbaColor)); 56 | 57 | codec.toColor("001122330"); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/codec/BufferCodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | import org.junit.jupiter.api.BeforeEach; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.nio.ByteBuffer; 8 | import java.util.Arrays; 9 | 10 | /** 11 | * @author sulin 12 | * @since 2019-08-04 15:36:57 13 | */ 14 | public class BufferCodecTest { 15 | 16 | private BufferCodec codec = new BufferCodec(); 17 | 18 | @BeforeEach 19 | void setUp() { 20 | codec.setFactory(CodecFactory.Instance); 21 | } 22 | 23 | @Test 24 | public void testByteBuffer() { 25 | String str = "hello world"; 26 | byte[] bytes = str.getBytes(); 27 | 28 | ByteBuffer byteBuffer = codec.toByteBuffer(bytes); 29 | assert Arrays.equals(codec.toByteArray(byteBuffer), bytes); 30 | 31 | assert codec.toCharBuffer(byteBuffer) != null; 32 | assert codec.toShortBuffer(byteBuffer) != null; 33 | assert codec.toIntBuffer(byteBuffer) != null; 34 | assert codec.toLongBuffer(byteBuffer) != null; 35 | assert codec.toFloatBuffer(byteBuffer) != null; 36 | assert codec.toDoubleBuffer(byteBuffer) != null; 37 | } 38 | 39 | @Test 40 | public void testBuffer() { 41 | char[] chars = "hello".toCharArray(); 42 | assert Arrays.equals(codec.toCharArray(codec.toCharBuffer(chars)), chars); 43 | 44 | short[] shorts = new short[]{1, 100, 10000}; 45 | assert Arrays.equals(shorts, codec.toShortArray(codec.toShortBuffer(shorts))); 46 | 47 | int[] ints = new int[]{1, 200, 50000}; 48 | assert Arrays.equals(ints, codec.toIntArray(codec.toIntBuffer(ints))); 49 | 50 | long[] longs = new long[]{100L, 100000L, 100000000L}; 51 | assert Arrays.equals(longs, codec.toLongArray(codec.toLongBuffer(longs))); 52 | 53 | float[] floats = new float[]{1.0f, 0.001f, 0.00001f}; 54 | assert Arrays.equals(floats, codec.toFloatArray(codec.toFloatBuffer(floats))); 55 | 56 | double[] doubles = new double[]{1.0, 0.000001, 0.00000000000001}; 57 | assert Arrays.equals(doubles, codec.toDoubleArray(codec.toDoubleBuffer(doubles))); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/codec/IOCodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | import com.github.smartbuf.reflect.XTypeUtils; 5 | import com.github.smartbuf.utils.CodecUtils; 6 | import org.junit.jupiter.api.BeforeEach; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.io.*; 10 | import java.nio.charset.Charset; 11 | import java.nio.charset.StandardCharsets; 12 | import java.util.Arrays; 13 | import java.util.Objects; 14 | 15 | /** 16 | * @author sulin 17 | * @since 2019-08-04 17:02:04 18 | */ 19 | public class IOCodecTest { 20 | 21 | private IOCodec codec = new IOCodec(); 22 | 23 | @BeforeEach 24 | void setUp() { 25 | codec.setFactory(CodecFactory.Instance); 26 | } 27 | 28 | @Test 29 | public void test() throws IOException { 30 | Charset charset = StandardCharsets.UTF_8; 31 | assert Objects.equals(charset, codec.toCharset(codec.toString(charset))); 32 | 33 | File file = File.createTempFile("100", "test"); 34 | String fileName = codec.toString(file); 35 | assert fileName != null; 36 | } 37 | 38 | @Test 39 | public void testInputStream() throws IOException { 40 | byte[] bytes = new byte[]{1, 2, 3, 4, 5}; 41 | assert Arrays.equals(bytes, codec.toByteArray(codec.toInputStream(bytes, XTypeUtils.toXType(ByteArrayInputStream.class)))); 42 | 43 | assert codec.toInputStream(bytes, XTypeUtils.toXType(ByteArrayInputStream.class)).getClass() == ByteArrayInputStream.class; 44 | assert codec.toInputStream(bytes, XTypeUtils.toXType(BufferedInputStream.class)).getClass() == BufferedInputStream.class; 45 | assert codec.toInputStream(bytes, XTypeUtils.toXType(DataInputStream.class)).getClass() == DataInputStream.class; 46 | 47 | try { 48 | codec.toInputStream(bytes, CodecUtils.toXType(FileInputStream.class)); 49 | assert false; 50 | } catch (Exception e) { 51 | assert e instanceof UnsupportedOperationException; 52 | } 53 | } 54 | 55 | @Test 56 | public void testReadable() throws IOException { 57 | String str = "hello world"; 58 | Readable readable = codec.toReadable(str, XTypeUtils.toXType(CharArrayReader.class)); 59 | assert readable instanceof CharArrayReader; 60 | assert str.equals(codec.toString(readable)); 61 | 62 | assert codec.toReadable(str, XTypeUtils.toXType(StringReader.class)) instanceof StringReader; 63 | assert codec.toReadable(str, XTypeUtils.toXType(BufferedReader.class)) instanceof BufferedReader; 64 | 65 | try { 66 | codec.toReadable(str, XTypeUtils.toXType(FileReader.class)); 67 | } catch (Exception e) { 68 | assert e instanceof UnsupportedOperationException; 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/codec/JodaCodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | import com.github.smartbuf.utils.CodecUtils; 5 | import org.joda.time.DateTime; 6 | import org.joda.time.Interval; 7 | import org.joda.time.Period; 8 | import org.joda.time.format.DateTimeFormat; 9 | import org.junit.jupiter.api.BeforeEach; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import java.time.*; 13 | import java.util.TimeZone; 14 | 15 | /** 16 | * @author sulin 17 | * @since 2019-08-04 17:20:28 18 | */ 19 | public class JodaCodecTest { 20 | 21 | private JodaCodec codec = new JodaCodec(); 22 | 23 | @BeforeEach 24 | void setUp() { 25 | codec.setFactory(CodecFactory.Instance); 26 | 27 | CodecUtils.installCodec(codec); 28 | } 29 | 30 | @Test 31 | public void testDateTime() { 32 | // Instant 33 | Instant instant = Instant.now(); 34 | System.out.println(instant); 35 | System.out.println(codec.toInstant(instant)); 36 | Instant newInstant = codec.toInstant(codec.toInstant(instant)); 37 | System.out.println(newInstant); 38 | assert instant.toEpochMilli() == newInstant.toEpochMilli(); 39 | 40 | // Duration 41 | Duration duration = Duration.ofMillis(System.currentTimeMillis()); 42 | System.out.println(duration); 43 | System.out.println(codec.toDuration(duration)); 44 | assert duration.equals(codec.toDuration(codec.toDuration(duration))); 45 | 46 | // LocalTime 47 | LocalTime localTime = LocalTime.now(); 48 | System.out.println(localTime); 49 | System.out.println(codec.toLocalTime(localTime)); 50 | LocalTime localTime2 = codec.toLocalTime(codec.toLocalTime(localTime)); 51 | assert localTime.toSecondOfDay() == localTime2.toSecondOfDay(); 52 | 53 | // LocalDate 54 | LocalDate localDate = LocalDate.now(); 55 | System.out.println(localDate); 56 | System.out.println(codec.toLocalDate(localDate)); 57 | assert localDate.equals(codec.toLocalDate(codec.toLocalDate(localDate))); 58 | 59 | // DateTime 60 | DateTime dateTime = DateTime.now(); 61 | System.out.println(dateTime); 62 | System.out.println(codec.toLocalDateTime(dateTime)); 63 | assert dateTime.equals(codec.toDateTime(codec.toLocalDateTime(dateTime))); 64 | 65 | // LocalDateTime 66 | LocalDateTime localDateTime = LocalDateTime.now(); 67 | System.out.println(localDateTime); 68 | System.out.println(codec.toLocalDateTime(localDateTime)); 69 | LocalDateTime localDateTime2 = codec.toLocalDateTime(codec.toLocalDateTime(localDateTime)); 70 | assert localDateTime.toEpochSecond(ZoneOffset.UTC) == localDateTime2.toEpochSecond(ZoneOffset.UTC); 71 | } 72 | 73 | @Test 74 | public void testOthers() { 75 | // interval 76 | Interval interval = new Interval(0, 365 * 24 * 60 * 60 * 1000L); 77 | String str = codec.toString(interval); 78 | System.out.println(str); 79 | assert interval.equals(codec.toInterval(str)); 80 | 81 | // period 82 | Period period = new Period(2019, 8, 1, 4, 17, 30, 40, 300); 83 | String periodStr = codec.toString(period); 84 | System.out.println(periodStr); 85 | assert period.equals(codec.toPeriod(periodStr)); 86 | 87 | // DateTimeFormatter 88 | assert codec.toDateTimeFormatter("yyyy-MM-dd") != null; 89 | try { 90 | codec.toString(DateTimeFormat.fullDateTime()); 91 | } catch (Exception e) { 92 | assert e instanceof UnsupportedOperationException; 93 | } 94 | 95 | // DateTimeZone 96 | TimeZone zone = TimeZone.getDefault(); 97 | TimeZone newZone = codec.toTimeZone(codec.toDateTimeZone(zone)); 98 | System.out.println(zone); 99 | System.out.println(newZone); 100 | assert zone.getID().equals(newZone.getID()); 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/codec/MathCodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | import org.junit.jupiter.api.BeforeEach; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.math.BigDecimal; 8 | import java.math.BigInteger; 9 | 10 | /** 11 | * @author sulin 12 | * @since 2019-08-04 18:29:52 13 | */ 14 | public class MathCodecTest { 15 | 16 | private MathCodec codec = new MathCodec(); 17 | 18 | @BeforeEach 19 | void setUp() { 20 | codec.setFactory(CodecFactory.Instance); 21 | } 22 | 23 | @Test 24 | public void test() { 25 | BigDecimal decimal = new BigDecimal("199999.222232323134123412312312312312312312312"); 26 | BigInteger integer = new BigInteger("999999999999999999999999999999999999999999"); 27 | 28 | assert decimal.equals(codec.toBigDecimal(codec.toString(decimal))); 29 | assert integer.equals(codec.toBigInteger(codec.toString(integer))); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/codec/NetCodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | import org.junit.jupiter.api.BeforeEach; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.net.Inet4Address; 8 | import java.net.Inet6Address; 9 | import java.net.InetAddress; 10 | import java.net.InetSocketAddress; 11 | 12 | /** 13 | * @author sulin 14 | * @since 2019-08-04 18:58:14 15 | */ 16 | public class NetCodecTest { 17 | 18 | private NetCodec codec = new NetCodec(); 19 | 20 | @BeforeEach 21 | void setUp() { 22 | codec.setFactory(CodecFactory.Instance); 23 | } 24 | 25 | @Test 26 | public void test() throws Exception { 27 | InetSocketAddress address = new InetSocketAddress("www.bing.com", 80); 28 | assert address.equals(codec.toInetSocketAddress(codec.toString(address))); 29 | assert codec.toInetSocketAddress("www.bing.com").getPort() == 0; 30 | 31 | assert codec.toInetAddress("/127.0.0.1") != null; 32 | 33 | InetAddress inetAddress = InetAddress.getByName("www.bing.com"); 34 | assert inetAddress.equals(codec.toInetAddress(codec.toString(inetAddress))); 35 | 36 | Inet4Address inet4Address = (Inet4Address) Inet4Address.getByName("www.bing.com"); 37 | assert inet4Address.equals(codec.toInetAddress(codec.toString(inet4Address))); 38 | 39 | Inet6Address inet6Address = (Inet6Address) Inet6Address.getByName("2400:3200:1600::152"); 40 | assert inet6Address.equals(codec.toInetAddress(codec.toString(inet6Address))); 41 | 42 | // auto split hostname by / 43 | assert inetAddress.equals(codec.toInetAddress(inetAddress.toString())); 44 | 45 | String uri1 = "http://java.sun.com/j2se/1.3/"; 46 | String uri2 = "../../../demo/jfc/SwingSet2/src/SwingSet2.java"; 47 | String uri3 = "file:///~/calendar"; 48 | String uri4 = "docs/guide/collections/designfaq.html#28"; 49 | assert uri1.equals(codec.toString(codec.toURI(uri1))); 50 | assert uri2.equals(codec.toString(codec.toURI(uri2))); 51 | assert uri3.equals(codec.toString(codec.toURI(uri3))); 52 | assert uri4.equals(codec.toString(codec.toURI(uri4))); 53 | 54 | String url = "https://www.javatpoint.com/URL-class"; 55 | assert url.equals(codec.toString(codec.toURL(url))); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/codec/NumberCodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | import org.junit.jupiter.api.BeforeEach; 5 | import org.junit.jupiter.api.Test; 6 | 7 | /** 8 | * @author sulin 9 | * @since 2019-08-04 18:58:23 10 | */ 11 | public class NumberCodecTest { 12 | 13 | private NumberCodec codec = new NumberCodec(); 14 | 15 | @BeforeEach 16 | void setUp() { 17 | codec.setFactory(CodecFactory.Instance); 18 | } 19 | 20 | @Test 21 | public void test() { 22 | String str = "1234567890"; 23 | assert str.equals(codec.toString(codec.toLong(str))); 24 | 25 | assert Long.valueOf(100L).equals(codec.toLong(codec.toByte(100L))); 26 | assert Long.valueOf(10000L).equals(codec.toLong(codec.toShort(10000L))); 27 | assert Long.valueOf(100000000L).equals(codec.toLong(codec.toInteger(100000000L))); 28 | 29 | Double d = 1234567890.123456; 30 | Float f = 123.4567F; 31 | assert Math.abs(codec.toDouble(codec.toString(d)) - d) < 0.0001; 32 | assert codec.toDouble(codec.toLong(d)) == 1234567890; 33 | assert Math.abs(codec.toFloat(codec.toDouble(f)) - f) < 0.01; // precision lost 34 | assert Math.abs(codec.toFloat(codec.toString(f)) - f) < 0.01; 35 | 36 | assert codec.toBoolean(codec.toLong(true)); 37 | assert !codec.toBoolean(codec.toLong(false)); 38 | assert codec.toBoolean(codec.toString(true)); 39 | 40 | Character c = 'C'; 41 | assert c.equals(codec.toCharacter(codec.toInteger(c))); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/codec/PrimaryCodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | import org.junit.jupiter.api.BeforeEach; 5 | import org.junit.jupiter.api.Test; 6 | 7 | /** 8 | * @author sulin 9 | * @since 2019-08-05 19:49:55 10 | */ 11 | class PrimaryCodecTest { 12 | 13 | private PrimaryCodec codec = new PrimaryCodec(); 14 | 15 | @BeforeEach 16 | void setUp() { 17 | codec.setFactory(CodecFactory.Instance); 18 | } 19 | 20 | @Test 21 | public void test() { 22 | assert codec.toBoolean(codec.toBoolean(true)); 23 | assert codec.toByte(codec.toByte((byte) 1)) == 1; 24 | assert codec.toShort(codec.toShort((short) 1)) == 1; 25 | assert codec.toInt(codec.toInteger(1)) == 1; 26 | assert codec.toLong(codec.toLong(1L)) == 1L; 27 | assert codec.toFloat(codec.toFloat(1.0f)) == 1.0f; 28 | assert codec.toDouble(codec.toDouble(1.0)) == 1.0; 29 | assert codec.toChar(codec.toCharacter('a')) == 'a'; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/codec/ReferenceCodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | import com.github.smartbuf.reflect.TypeRef; 5 | import com.github.smartbuf.reflect.XTypeUtils; 6 | import org.junit.jupiter.api.BeforeEach; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.lang.ref.PhantomReference; 10 | import java.lang.ref.Reference; 11 | import java.lang.ref.SoftReference; 12 | import java.lang.ref.WeakReference; 13 | import java.util.Objects; 14 | import java.util.Optional; 15 | 16 | /** 17 | * @author sulin 18 | * @since 2019-08-04 18:58:30 19 | */ 20 | @SuppressWarnings("ALL") 21 | public class ReferenceCodecTest { 22 | 23 | private ReferenceCodec codec = new ReferenceCodec(); 24 | 25 | @BeforeEach 26 | void setUp() { 27 | codec.setFactory(CodecFactory.Instance); 28 | } 29 | 30 | @Test 31 | public void testToReference() { 32 | int i = 1000; 33 | WeakReference ref = (WeakReference) codec.toReference(i, XTypeUtils.toXType(new TypeRef>() { 34 | }.getType())); 35 | 36 | // shouldn't gc 37 | assert ref != null; 38 | assert i == ref.get().intValue(); 39 | 40 | SoftReference softRef = (SoftReference) codec.toReference(i, XTypeUtils.toXType(new TypeRef>() { 41 | }.getType())); 42 | 43 | // shouldn't gc 44 | assert softRef != null; 45 | assert i == softRef.get().intValue(); 46 | 47 | try { 48 | codec.toReference(i, XTypeUtils.toXType(PhantomReference.class)); 49 | } catch (Exception e) { 50 | assert e instanceof IllegalArgumentException; 51 | } 52 | 53 | Reference result = codec.toReference("", XTypeUtils.toXType(new TypeRef>>() { 54 | }.getType())); 55 | assert result.get() instanceof Optional; 56 | assert Objects.equals("", ((Optional) result.get()).get()); 57 | 58 | Reference ref2 = codec.toReference(0L, XTypeUtils.toXType(new TypeRef>() { 59 | }.getType())); 60 | assert Objects.equals(0L, ref2.get()); 61 | } 62 | 63 | @Test 64 | public void testToObject() { 65 | SoftReference ref = new SoftReference<>(10000L); 66 | assert codec.toObject(ref, XTypeUtils.toXType(Integer.class)) instanceof Integer; 67 | assert codec.toObject(ref, XTypeUtils.toXType(Long.class)) == ref.get(); 68 | 69 | SoftReference ref2 = new SoftReference<>(""); 70 | Object result = codec.toObject(ref2, XTypeUtils.toXType(new TypeRef>() { 71 | }.getType())); 72 | assert result instanceof Optional; 73 | assert Objects.equals(((Optional) result).get(), ""); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/codec/SqlCodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | import org.junit.jupiter.api.BeforeEach; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.io.InputStream; 8 | import java.io.Reader; 9 | import java.sql.*; 10 | import java.util.Arrays; 11 | 12 | /** 13 | * @author sulin 14 | * @since 2019-08-04 18:58:39 15 | */ 16 | @SuppressWarnings("ALL") 17 | public class SqlCodecTest { 18 | 19 | private SqlCodec codec = new SqlCodec(); 20 | 21 | @BeforeEach 22 | void setUp() { 23 | codec.setFactory(CodecFactory.Instance); 24 | } 25 | 26 | @Test 27 | public void test() throws SQLException { 28 | byte[] bytes = new byte[]{1, 2, 3, 4, 5, 6, 7, 8}; 29 | Blob blob = codec.toBlob(bytes); 30 | InputStream is = codec.toInputStream(blob); 31 | assert Arrays.equals(CodecFactory.Instance.convert(is, byte[].class), bytes); 32 | 33 | String str = "hello world"; 34 | Clob clob = codec.toClob(str); 35 | Reader reader = codec.toReader(clob); 36 | assert str.equals(CodecFactory.Instance.convert(reader, String.class)); 37 | 38 | Date date = new Date(System.currentTimeMillis()); 39 | Date date2 = codec.toDate(codec.toLong(date)); 40 | assert date2.getYear() == date.getYear(); 41 | assert date2.getMonth() == date.getMonth(); 42 | assert date2.getDay() == date.getDay(); 43 | 44 | Time time = new Time(System.currentTimeMillis()); 45 | Time time2 = codec.toTime(codec.toLong(time)); 46 | assert time.getHours() == time2.getHours(); 47 | assert time.getMinutes() == time2.getMinutes(); 48 | assert time.getSeconds() == time2.getSeconds(); 49 | 50 | Timestamp timestamp = new Timestamp(System.currentTimeMillis()); 51 | assert timestamp.equals(codec.toTimestamp(codec.toLong(timestamp))); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/codec/StringCodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | import org.junit.jupiter.api.BeforeEach; 5 | import org.junit.jupiter.api.Test; 6 | 7 | /** 8 | * @author sulin 9 | * @since 2019-08-04 18:58:48 10 | */ 11 | public class StringCodecTest { 12 | 13 | private StringCodec codec = new StringCodec(); 14 | 15 | @BeforeEach 16 | void setUp() { 17 | codec.setFactory(CodecFactory.Instance); 18 | } 19 | 20 | @Test 21 | public void test() { 22 | String str = "hello world"; 23 | assert str.equals(codec.toString(codec.toStringBuffer(str))); 24 | assert str.equals(codec.toString(codec.toStringBuilder(str))); 25 | assert str.equals(codec.toString(codec.toCharArray(str))); 26 | assert str.equals(codec.toString(codec.toByteArray(str))); 27 | assert str.equals(codec.toString(codec.toStringCharacterIterator(str))); 28 | try { 29 | codec.toCharacter(str); 30 | } catch (Exception e) { 31 | assert e instanceof UnsupportedOperationException; 32 | } 33 | 34 | String s = "s"; 35 | assert s.equals(codec.toString(codec.toCharacter(s))); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/converter/codec/UtilCodecTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.converter.codec; 2 | 3 | import com.github.smartbuf.converter.CodecFactory; 4 | import com.github.smartbuf.reflect.TypeRef; 5 | import com.github.smartbuf.reflect.XType; 6 | import com.github.smartbuf.reflect.XTypeUtils; 7 | import org.junit.jupiter.api.BeforeEach; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import java.util.*; 11 | import java.util.concurrent.atomic.AtomicReference; 12 | import java.util.regex.Pattern; 13 | 14 | /** 15 | * @author sulin 16 | * @since 2019-08-04 18:59:09 17 | */ 18 | public class UtilCodecTest { 19 | 20 | private UtilCodec codec = new UtilCodec(); 21 | 22 | @BeforeEach 23 | void setUp() { 24 | codec.setFactory(CodecFactory.Instance); 25 | } 26 | 27 | @Test 28 | public void test() { 29 | byte[] bytes = new byte[]{1, 4, 8, 100}; 30 | assert Arrays.equals(bytes, codec.toByteArray(codec.toBitSet(bytes))); 31 | 32 | Currency currency = Currency.getInstance(Locale.CHINA); 33 | assert currency.equals(codec.toCurrency(codec.toString(currency))); 34 | 35 | Locale locale = Locale.KOREAN; 36 | assert locale.equals(codec.toLocale(codec.toString(locale))); 37 | 38 | TimeZone timeZone = TimeZone.getDefault(); 39 | assert timeZone.equals(codec.toTimeZone(codec.toString(timeZone))); 40 | 41 | Pattern pattern = Pattern.compile(".*"); 42 | Pattern pattern1 = codec.toPattern(codec.toString(pattern)); 43 | assert pattern.pattern().equals(pattern1.pattern()); 44 | } 45 | 46 | @Test 47 | public void testOptional() { 48 | Integer i = 100; 49 | assert i.equals(codec.toInteger(codec.toOptionalInt(i))); 50 | assert codec.toInteger(codec.toOptionalInt(null)) == null; 51 | 52 | Long l = 100000L; 53 | assert l.equals(codec.toLong(codec.toOptionalLong(l))); 54 | assert codec.toLong(codec.toOptionalLong(null)) == null; 55 | 56 | Double d = 1.0; 57 | assert d.equals(codec.toDouble(codec.toOptionalDouble(d))); 58 | assert codec.toDouble(codec.toOptionalDouble(null)) == null; 59 | 60 | XType oType = XTypeUtils.toXType(l.getClass()); 61 | XType optionalType = XTypeUtils.toXType(new TypeRef>() { 62 | }.getType()); 63 | assert l == codec.toObject(codec.toOptional(l, optionalType), oType); 64 | assert codec.toObject(codec.toOptional(null, optionalType), oType) == null; 65 | 66 | Optional optional = codec.toOptional(l, XTypeUtils.toXType(new TypeRef>() { 67 | }.getType())); 68 | assert optional.isPresent() && optional.get().equals(l.intValue()); 69 | 70 | assert Objects.equals(codec.toObject(optional, oType), l); 71 | 72 | Object obj = codec.toObject(Optional.of(1), XTypeUtils.toXType(new TypeRef>() { 73 | }.getType())); 74 | assert obj instanceof AtomicReference; 75 | assert Objects.equals(((AtomicReference) obj).get(), 1L); 76 | 77 | Optional opt2 = codec.toOptional(1, XTypeUtils.toXType(new TypeRef>>() { 78 | }.getType())); 79 | assert opt2.isPresent(); 80 | assert opt2.get() instanceof AtomicReference; 81 | assert Objects.equals(1L, ((AtomicReference) opt2.get()).get()); 82 | } 83 | 84 | @Test 85 | public void testUUID() { 86 | UUID uuid = UUID.randomUUID(); 87 | assert uuid.equals(codec.toUUID(codec.toString(uuid))); 88 | 89 | String uuidStr = codec.toString(UUID.randomUUID()).replaceAll("-", ""); 90 | assert uuidStr.equals(codec.toString(codec.toUUID(uuidStr)).replaceAll("-", "")); 91 | 92 | try { 93 | codec.toUUID("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); 94 | } catch (Exception e) { 95 | assert e instanceof IllegalArgumentException && e.getCause() instanceof NumberFormatException; 96 | } 97 | 98 | try { 99 | codec.toUUID(""); 100 | assert false; 101 | } catch (Exception e) { 102 | assert e instanceof IllegalArgumentException; 103 | } 104 | 105 | try { 106 | codec.toUUID("b8f7f030-e07d-44d3-bded-b6dce4cff-a3"); 107 | assert false; 108 | } catch (Exception e) { 109 | assert e instanceof IllegalArgumentException; 110 | } 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/node/NodeTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.node; 2 | 3 | import com.github.smartbuf.node.array.*; 4 | import com.github.smartbuf.node.basic.*; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | /** 11 | * @author sulin 12 | * @since 2019-09-21 14:10:57 13 | */ 14 | public class NodeTest { 15 | 16 | @Test 17 | public void testBasic() { 18 | Node node = StringNode.valueOf(""); 19 | assert node.type() == NodeType.STRING; 20 | 21 | node = BooleanNode.valueOf(true); 22 | assert node.type() == NodeType.BOOLEAN; 23 | 24 | node = DoubleNode.valueOf(111.0); 25 | assert node.type() == NodeType.DOUBLE; 26 | 27 | node = FloatNode.valueOf(11.0f); 28 | assert node.type() == NodeType.FLOAT; 29 | 30 | node = VarintNode.valueOf(1); 31 | assert node.type() == NodeType.VARINT; 32 | 33 | node = VarintNode.valueOf(1000); 34 | assert node.type() == NodeType.VARINT; 35 | 36 | node = SymbolNode.valueOf(Thread.State.BLOCKED); 37 | assert node.type() == NodeType.SYMBOL; 38 | } 39 | 40 | @Test 41 | public void testArray() { 42 | Node node = new BooleanArrayNode(new boolean[]{true}); 43 | assert node.type() == NodeType.ARRAY_BOOLEAN; 44 | assert node.value() instanceof boolean[]; 45 | 46 | node = new ByteArrayNode(new byte[]{1}); 47 | assert node.type() == NodeType.ARRAY_BYTE; 48 | assert node.value() instanceof byte[]; 49 | 50 | node = new ShortArrayNode(new short[]{1}); 51 | assert node.type() == NodeType.ARRAY_SHORT; 52 | assert node.value() instanceof short[]; 53 | 54 | node = new IntArrayNode(new int[]{1, 2}); 55 | assert node.type() == NodeType.ARRAY_INT; 56 | assert node.value() instanceof int[]; 57 | 58 | node = new LongArrayNode(new long[]{1, 2}); 59 | assert node.type() == NodeType.ARRAY_LONG; 60 | assert node.value() instanceof long[]; 61 | 62 | node = new FloatArrayNode(new float[]{1, 2}); 63 | assert node.type() == NodeType.ARRAY_FLOAT; 64 | assert node.value() instanceof float[]; 65 | 66 | node = new DoubleArrayNode(new double[]{1, 2}); 67 | assert node.type() == NodeType.ARRAY_DOUBLE; 68 | assert node.value() instanceof double[]; 69 | 70 | node = new ArrayNode(Arrays.asList(1, 2)); 71 | assert node.type() == NodeType.ARRAY; 72 | assert node.value() instanceof List; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/reflect/BeanReaderBenchmark.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.reflect; 2 | 3 | import lombok.Data; 4 | import net.sf.cglib.beans.BeanMap; 5 | import org.openjdk.jmh.annotations.*; 6 | 7 | import java.lang.reflect.Method; 8 | import java.util.Date; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | /** 12 | * Get BeanHelper by valueOf: 13 | * Benchmark Mode Cnt Score Error Units 14 | * BeanHelperBenchmark.accessor avgt 6 8.076 ± 0.130 ns/op 15 | * BeanHelperBenchmark.beanHelper avgt 6 27.146 ± 0.349 ns/op 16 | * BeanHelperBenchmark.beanmap avgt 6 137.735 ± 13.050 ns/op 17 | * BeanHelperBenchmark.direct avgt 6 8.362 ± 0.052 ns/op 18 | * BeanHelperBenchmark.methods avgt 6 45.565 ± 0.708 ns/op 19 | *

20 | * Cache BeanHelper(about 4~6ns for valueOf): 21 | * Benchmark Mode Cnt Score Error Units 22 | * BeanHelperBenchmark.accessor avgt 6 8.010 ± 0.055 ns/op 23 | * BeanHelperBenchmark.beanHelper avgt 6 21.527 ± 0.281 ns/op 24 | * BeanHelperBenchmark.beanmap avgt 6 137.474 ± 0.644 ns/op 25 | * BeanHelperBenchmark.direct avgt 6 8.261 ± 0.128 ns/op 26 | * BeanHelperBenchmark.methods avgt 6 43.558 ± 0.405 ns/op 27 | *

28 | * Where is the 20ns? 29 | * 30 | * @author sulin 31 | * @since 2019-10-28 17:57:59 32 | */ 33 | @Warmup(iterations = 2, time = 2) 34 | @Fork(2) 35 | @Measurement(iterations = 3, time = 3) 36 | @BenchmarkMode(Mode.AverageTime) 37 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 38 | public class BeanReaderBenchmark { 39 | 40 | private static final User USER = new User(); 41 | private static final Method[] GETTERS = new Method[7]; 42 | private static final BeanReader reader = BeanReaderBuilder.build(User.class); 43 | 44 | static { 45 | try { 46 | GETTERS[0] = User.class.getDeclaredMethod("getId"); 47 | GETTERS[1] = User.class.getDeclaredMethod("getBlocked"); 48 | GETTERS[2] = User.class.getDeclaredMethod("getCreateTime"); 49 | GETTERS[3] = User.class.getDeclaredMethod("getLoginTimes"); 50 | GETTERS[4] = User.class.getDeclaredMethod("getNickname"); 51 | GETTERS[5] = User.class.getDeclaredMethod("getPortrait"); 52 | GETTERS[6] = User.class.getDeclaredMethod("getScore"); 53 | } catch (NoSuchMethodException e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | 58 | @Benchmark 59 | public void beanmap() { 60 | BeanMap beanMap = BeanMap.create(USER); 61 | Object[] arr = new Object[beanMap.size()]; 62 | int off = 0; 63 | for (Object key : beanMap.keySet()) { 64 | arr[off++] = beanMap.get(key); 65 | } 66 | } 67 | 68 | @Benchmark 69 | public void methods() throws Exception { 70 | Object[] arr = new Object[GETTERS.length]; 71 | for (int i = 0; i < GETTERS.length; i++) { 72 | arr[i] = GETTERS[i].invoke(USER); 73 | } 74 | } 75 | 76 | @Benchmark 77 | public void beanHelper() { 78 | Object[] arr = BeanReaderBuilder.build(User.class).getValues(USER); 79 | } 80 | 81 | @Benchmark 82 | public void accessor() { 83 | Object[] arr = new Object[GETTERS.length]; 84 | reader.api.getAll(USER, arr); 85 | } 86 | 87 | @Benchmark 88 | public void direct() { 89 | Object[] arr = new Object[GETTERS.length]; 90 | arr[0] = USER.getId(); 91 | arr[1] = USER.getBlocked(); 92 | arr[2] = USER.getCreateTime(); 93 | arr[3] = USER.getNickname(); 94 | arr[4] = USER.getPortrait(); 95 | arr[5] = USER.getLoginTimes(); 96 | arr[6] = USER.getScore(); 97 | } 98 | 99 | @Data 100 | public static class User { 101 | private long id = 1385434576456830976L; 102 | private Boolean blocked = false; 103 | private String nickname = "1uOlvFfhZuda"; 104 | private String portrait = "OCCCAcnrKtKmbOkzRNYbWLnR"; 105 | private float score = 2.7177553E38f; 106 | private int loginTimes = 1543; 107 | private Date createTime = new Date(); 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/reflect/BeanReaderBuilderTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.reflect; 2 | 3 | import lombok.Data; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.util.Arrays; 7 | import java.util.Objects; 8 | 9 | /** 10 | * @author sulin 11 | * @since 2019-11-08 19:42:15 12 | */ 13 | public class BeanReaderBuilderTest { 14 | 15 | @Test 16 | public void test() { 17 | BeanReader reader = BeanReaderBuilder.build(Child.class); 18 | 19 | Child child = new Child(); 20 | child._name = "_name"; 21 | child.enable = true; 22 | child.name = "name"; 23 | child.time = System.currentTimeMillis(); 24 | 25 | String[] fieldNames = reader.getFieldNames(); 26 | assert fieldNames.length == 4; 27 | assert Arrays.equals(fieldNames, new String[]{"_name", "enable", "name", "time"}); 28 | 29 | Object[] arr = reader.getValues(child); 30 | assert Objects.equals(child._name, arr[0]); 31 | assert Objects.equals(child.enable, arr[1]); 32 | assert Objects.equals(child.getName(), arr[2]); 33 | assert Objects.equals(child.getTime(), arr[3]); 34 | } 35 | 36 | @Test 37 | public void testFull() { 38 | Full full = new Full(); 39 | full.setV(null); 40 | 41 | BeanReader reader = BeanReaderBuilder.build(Full.class); 42 | assert reader.getFieldNames().length == 24; 43 | } 44 | 45 | @Test 46 | public void testError() { 47 | String oldName = BeanReader.API_NAME; 48 | 49 | BeanReader.API_NAME = "..."; 50 | try { 51 | BeanReaderBuilder.build(Full.class); 52 | assert false; 53 | } catch (Exception e) { 54 | assert e instanceof IllegalArgumentException; 55 | } 56 | 57 | BeanReader.API_NAME = oldName; 58 | } 59 | 60 | public static abstract class Parent { 61 | 62 | public String _name; 63 | @Deprecated 64 | public String $name; 65 | 66 | private long timestamp; 67 | 68 | public abstract long getTime(); 69 | 70 | public static int getId() { 71 | return 0; 72 | } 73 | 74 | public int getIder() { 75 | return 1; 76 | } 77 | 78 | @Deprecated 79 | public String getDesc() { 80 | return null; 81 | } 82 | 83 | public String getTimestamp() { 84 | return ""; 85 | } 86 | 87 | } 88 | 89 | @Data 90 | public static class Child extends Parent { 91 | private boolean enable; 92 | private String name; 93 | private long time; 94 | } 95 | 96 | @Data 97 | public static class Full { 98 | private boolean bool1; 99 | private Boolean bool2; 100 | private float float1; 101 | private Float float2; 102 | private double double1; 103 | private Double double2; 104 | private byte byte1; 105 | private Byte byte2; 106 | private short short1; 107 | private Short short2; 108 | private int int1; 109 | private Integer int2; 110 | private long long1; 111 | private Long long2; 112 | private char char1; 113 | private Character char2; 114 | private boolean[] booleans; 115 | private byte[] bytes; 116 | private short[] shorts; 117 | private int[] ints; 118 | private long[] longs; 119 | private float[] floats; 120 | private double[] doubles; 121 | private char[] chars; 122 | private Void v; 123 | 124 | public String isValid() { 125 | return "true"; 126 | } 127 | 128 | public String get_name() { 129 | return null; 130 | } 131 | 132 | public String get$name() { 133 | return null; 134 | } 135 | 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/reflect/GenericModel.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.reflect; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.*; 6 | import java.util.concurrent.atomic.AtomicReference; 7 | 8 | /** 9 | * @author sulin 10 | * @since 2019-07-16 12:04:04 11 | */ 12 | @Data 13 | public class GenericModel { 14 | 15 | private T t; 16 | private X x; 17 | private R r; 18 | 19 | private Map rMap; 20 | private List dates; 21 | private AtomicReference> ref; 22 | 23 | private GenBean> gen1; 24 | private GenBean gen2; 25 | private GenBean gen3; 26 | 27 | private GenPojo> pojo; 28 | 29 | public static class GenBean> { 30 | private C c; 31 | } 32 | 33 | public static class GenPojo { 34 | private Z z; 35 | } 36 | 37 | public void test() { 38 | gen1.c.add(null); 39 | gen2.c.add(""); 40 | gen3.c.add(null); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/reflect/TypeRefTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.reflect; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @author sulin 9 | * @since 2019-09-20 14:24:25 10 | */ 11 | public class TypeRefTest { 12 | 13 | @Test 14 | public void testRef() { 15 | TypeRef ref = new TypeRef() { 16 | }; 17 | 18 | assert ref.getType() != null; 19 | 20 | try { 21 | new TypeRef() { 22 | }; 23 | assert false; 24 | } catch (Exception e) { 25 | assert e instanceof IllegalArgumentException; 26 | } 27 | } 28 | 29 | @Test 30 | public void testCompare() { 31 | TypeRef ref = new TypeRef() { 32 | }; 33 | } 34 | 35 | @Test 36 | public void test2() { 37 | TypeRef ref1 = new TypeRef>() { 38 | }; 39 | TypeRef ref2 = new TypeRef>() { 40 | }; 41 | TypeRef ref3 = new TypeRef>() { 42 | }; 43 | 44 | assert ref1.getType() != ref2.getType(); 45 | assert ref1.getType() != ref3.getType(); 46 | assert ref3.getType() != ref2.getType(); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/reflect/TypeTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.reflect; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import lombok.Data; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.lang.ref.Reference; 8 | import java.lang.reflect.*; 9 | import java.util.*; 10 | 11 | /** 12 | * Test type 13 | * 14 | * @author sulin 15 | * @since 2019-07-13 17:20:50 16 | */ 17 | public class TypeTest { 18 | 19 | @Test 20 | public void testRawType() { 21 | TypeReference ref = new TypeReference>>() { 22 | }; 23 | Type type = ref.getType(); 24 | System.out.println(type); 25 | 26 | ParameterizedType pt = (ParameterizedType) type; 27 | System.out.println(pt.getRawType() instanceof Class); 28 | } 29 | 30 | @Test 31 | public void testNormalType() throws NoSuchFieldException { 32 | for (Field field : Model.class.getDeclaredFields()) { 33 | System.out.println(field.getGenericType()); 34 | } 35 | GenericArrayType tsType = (GenericArrayType) Model.class.getDeclaredField("ts").getGenericType(); 36 | System.out.println(tsType); 37 | } 38 | 39 | @Test 40 | public void testGenericType() throws NoSuchFieldException { 41 | TypeReference typeReference = new TypeReference>>() { 42 | }; 43 | Type type = typeReference.getType(); 44 | System.out.println(type); 45 | 46 | ParameterizedType pt = (ParameterizedType) type; 47 | Class clz = (Class) pt.getRawType(); 48 | for (Field field : clz.getDeclaredFields()) { 49 | Type fType = field.getGenericType(); 50 | System.out.println(fType); 51 | } 52 | 53 | Type tsType = clz.getDeclaredField("ts").getGenericType(); 54 | GenericArrayType arrayType = (GenericArrayType) tsType; 55 | TypeVariable genArrType = (TypeVariable) arrayType.getGenericComponentType(); 56 | System.out.println(genArrType.getGenericDeclaration()); 57 | System.out.println(tsType); 58 | 59 | Class decClass = (Class) genArrType.getGenericDeclaration(); 60 | for (TypeVariable parameter : decClass.getTypeParameters()) { 61 | System.out.println(parameter.getName()); 62 | } 63 | } 64 | 65 | @Test 66 | public void testSuper() { 67 | XType xType = XTypeUtils.toXType(Child.class); 68 | assert xType.getField("k") != null; 69 | assert xType.getField("v") != null; 70 | assert xType.getField("xxx") == null; 71 | } 72 | 73 | @Data 74 | public static class Model { 75 | private long time; 76 | private Map objectMap; 77 | private Map strDateMap; 78 | private Map wildMap; 79 | private List longs; 80 | private T[] ts; 81 | private Reference ref; 82 | } 83 | 84 | @Data 85 | public static class Bean { 86 | private T[] name; 87 | } 88 | 89 | public static class P { 90 | @Data 91 | public class Item { 92 | private T t; 93 | } 94 | } 95 | 96 | public static class Parent { 97 | private K k; 98 | private V v; 99 | } 100 | 101 | public static class Child extends Parent { 102 | private V v; 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/reflect/XTypeUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.reflect; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import java.awt.*; 6 | import java.lang.ref.Reference; 7 | import java.lang.reflect.Field; 8 | import java.lang.reflect.Method; 9 | import java.lang.reflect.Type; 10 | import java.lang.reflect.TypeVariable; 11 | import java.util.Date; 12 | import java.util.List; 13 | 14 | /** 15 | * @author sulin 16 | * @since 2019-07-22 14:59:45 17 | */ 18 | public class XTypeUtilsTest { 19 | 20 | @Test 21 | public void testTypeVariable() throws Exception { 22 | Field field = TypeVariableBean.class.getDeclaredField("t"); 23 | TypeVariable typeVariable = (TypeVariable) field.getGenericType(); 24 | Type[] bounds = typeVariable.getBounds(); 25 | System.out.println(bounds); 26 | 27 | Method method = TypeVariableBean.class.getDeclaredMethod("hh"); 28 | TypeVariable returnType = (TypeVariable) method.getGenericReturnType(); 29 | Type[] returnBounds = returnType.getBounds(); 30 | System.out.println(returnBounds); 31 | } 32 | 33 | @Test 34 | public void testReference() { 35 | XType type = XTypeUtils.toXType(new TypeRef>() { 36 | }.getType()); 37 | System.out.println(type); 38 | } 39 | 40 | @Test 41 | public void testGenModel() { 42 | Type type = new TypeRef>() { 43 | }.getType(); 44 | 45 | XType xType = XTypeUtils.toXType(type); 46 | System.out.println(xType); 47 | } 48 | 49 | @Test 50 | public void testCache() { 51 | XType prevXT = null; 52 | for (int i = 0; i < 10; i++) { 53 | Type type = new TypeRef>() { 54 | }.getType(); 55 | XType xt = XTypeUtils.toXType(type); 56 | assert prevXT == null || prevXT == xt; 57 | prevXT = xt; 58 | System.out.println(xt); 59 | } 60 | } 61 | 62 | @Test 63 | public void testVariable() { 64 | Type type = new TypeRef>() { 65 | }.getType(); 66 | 67 | XType xt = XTypeUtils.toXType(type); 68 | 69 | assert xt.getRawType() == TypeVariableBean.class; 70 | 71 | XField tField = xt.getField("t"); 72 | XField listField = xt.getField("list"); 73 | assert tField != null && listField != null; 74 | 75 | assert tField.getType().getRawType() == Date.class; 76 | 77 | assert listField.getType().getParameterizedType("E").getRawType() == Date.class; 78 | } 79 | 80 | public static class TypeVariableBean { 81 | 82 | private T t; 83 | private List list; 84 | 85 | public X hh() { 86 | return null; 87 | } 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/transport/ArrayTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.transport; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | /** 6 | * @author sulin 7 | * @since 2019-09-29 16:36:47 8 | */ 9 | public class ArrayTest { 10 | 11 | @Test 12 | public void test() { 13 | Array array = new Array<>(); 14 | assert array.cap() == 0; 15 | assert array.size() == 0; 16 | 17 | array.add(1L); 18 | array.add(2L); 19 | array.add(3L); 20 | array.add(4L); 21 | array.add(5L); 22 | 23 | assert array.size() == 5; 24 | 25 | array.clear(); 26 | assert array.size() == 0; 27 | assert array.cap() > 0; 28 | } 29 | 30 | @Test 31 | public void testEquals() { 32 | Array array1 = new Array<>(); 33 | Array array2 = new Array<>(); 34 | 35 | assert !array1.equals(new Object()); 36 | assert array1.equals(array2); 37 | 38 | array1.add(1L); 39 | array1.add(2L); 40 | assert !array1.equals(array2); 41 | 42 | array2.add(1L); 43 | assert !array1.equals(array2); 44 | 45 | array2.add(2L); 46 | assert array1.equals(array2); 47 | 48 | array1.add(3L); 49 | array2.add(4L); 50 | assert !array1.equals(array2); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/transport/IDAllocatorTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.transport; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | 6 | /** 7 | * @author sulin 8 | * @since 2019-09-30 18:01:40 9 | */ 10 | public class IDAllocatorTest { 11 | 12 | @Test 13 | public void test() { 14 | IDAllocator allocator = new IDAllocator(); 15 | Assertions.assertEquals(0, allocator.acquire()); 16 | Assertions.assertEquals(1, allocator.acquire()); 17 | Assertions.assertEquals(2, allocator.acquire()); 18 | Assertions.assertEquals(3, allocator.acquire()); 19 | Assertions.assertNotEquals(5, allocator.acquire()); 20 | 21 | allocator.release(2); 22 | allocator.release(1); 23 | Assertions.assertEquals(1, allocator.acquire()); 24 | Assertions.assertEquals(2, allocator.acquire()); 25 | 26 | allocator.release(0); 27 | allocator.release(3); 28 | Assertions.assertEquals(0, allocator.acquire()); 29 | Assertions.assertEquals(3, allocator.acquire()); 30 | 31 | try { 32 | allocator.release(10); 33 | assert false; 34 | } catch (Exception e) { 35 | assert e instanceof IllegalArgumentException; 36 | } 37 | 38 | assert allocator.acquire() == 5; 39 | assert allocator.acquire() == 6; 40 | assert allocator.acquire() == 7; 41 | assert allocator.acquire() == 8; 42 | assert allocator.acquire() == 9; 43 | assert allocator.acquire() == 10; 44 | 45 | allocator.release(6); 46 | allocator.release(7); 47 | allocator.release(8); 48 | allocator.release(9); 49 | allocator.release(3); 50 | allocator.release(1); 51 | 52 | assert allocator.acquire() == 1; 53 | assert allocator.acquire() == 3; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/transport/IOExpireTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.transport; 2 | 3 | import com.github.smartbuf.utils.CodecUtils; 4 | import com.github.smartbuf.node.basic.ObjectNode; 5 | import com.github.smartbuf.node.basic.SymbolNode; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.io.IOException; 9 | import java.util.Objects; 10 | 11 | /** 12 | * @author sulin 13 | * @since 2019-11-07 21:39:28 14 | */ 15 | public class IOExpireTest { 16 | 17 | @Test 18 | public void testSymbolExpire() throws IOException { 19 | Output.SYMBOL_LIMIT = 4; 20 | 21 | Output output = new Output(true); 22 | Input input = new Input(true); 23 | 24 | for (int i = 0; i <= Output.SYMBOL_LIMIT + 1; i++) { 25 | SymbolNode node = SymbolNode.valueOf("SYM" + i); 26 | 27 | byte[] data = output.write(node); 28 | Object obj = input.read(data); 29 | assert obj instanceof String; 30 | assert Objects.equals(obj, node.value()); 31 | } 32 | 33 | // test only DATA_SYMBOL_EXPIRED 34 | byte[] data = output.write("hello world"); 35 | Object object = input.read(data); 36 | assert Objects.equals(object, "hello world"); 37 | } 38 | 39 | @Test 40 | public void testStructExpire() throws IOException { 41 | Output.STRUCT_LIMIT = 4; 42 | 43 | Output output = new Output(true); 44 | Input input = new Input(true); 45 | 46 | for (int i = 0; i <= Output.STRUCT_LIMIT + 1; i++) { 47 | ObjectNode node = new ObjectNode(true, new String[]{"id", "name" + i}, new Object[]{i, "name" + i}); 48 | 49 | byte[] data = output.write(node); 50 | Object obj = input.read(data); 51 | 52 | ObjectNode newNode = CodecUtils.convert(obj, ObjectNode.class); 53 | assert newNode.keys().length == 2; 54 | assert newNode.values().length == 2; 55 | } 56 | 57 | // test only *_EXPIRED 58 | byte[] data = output.write("hello world"); 59 | Object object = input.read(data); 60 | assert Objects.equals(object, "hello world"); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/transport/IOFullTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.transport; 2 | 3 | import com.github.smartbuf.utils.CodecUtils; 4 | import com.github.smartbuf.node.basic.SymbolNode; 5 | import lombok.Data; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.io.IOException; 9 | import java.util.Arrays; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.Objects; 13 | 14 | /** 15 | * @author sulin 16 | * @since 2019-10-21 20:40:21 17 | */ 18 | public class IOFullTest { 19 | 20 | @Test 21 | public void testOthers() throws IOException { 22 | IOTest.enableCxt = false; 23 | 24 | Bean bean = new Bean(); 25 | bean.c = 'a'; 26 | bean.chars = "hello".toCharArray(); 27 | bean.node = SymbolNode.valueOf("HELLO"); 28 | Object result = IOTest.transIO(bean); 29 | Bean newBean = CodecUtils.convert(result, Bean.class); 30 | assert bean.c == newBean.c; 31 | assert Arrays.equals(bean.chars, newBean.chars); 32 | assert Objects.equals(bean.node.value(), newBean.node.value()); 33 | } 34 | 35 | @Test 36 | public void testMap() throws IOException { 37 | Map map = new HashMap<>(); 38 | map.put("id", 1); 39 | map.put("name", "hello"); 40 | IOTest.transIO(map); 41 | } 42 | 43 | @Data 44 | public static class Bean { 45 | private Character c; 46 | private char[] chars; 47 | private SymbolNode node; 48 | private double double1; 49 | private Double double2; 50 | private Thread.State state = Thread.State.BLOCKED; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/transport/OutputTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.transport; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import org.apache.commons.lang3.RandomUtils; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.io.IOException; 10 | import java.math.BigInteger; 11 | import java.util.Arrays; 12 | import java.util.BitSet; 13 | import java.util.Collection; 14 | import java.util.Date; 15 | 16 | /** 17 | * @author sulin 18 | * @since 2019-11-04 16:33:52 19 | */ 20 | public class OutputTest { 21 | 22 | @Test 23 | public void test() throws IOException { 24 | Output output = new Output(true); 25 | 26 | assert output.write(null).length == 2; 27 | assert output.write(BigInteger.valueOf(1000L)).length > 2; 28 | assert output.write(new Bean()).length > 2; 29 | 30 | try { 31 | output.writeData(Byte.MAX_VALUE, 1); 32 | assert false; 33 | } catch (Exception e) { 34 | assert e instanceof IllegalArgumentException; 35 | } 36 | } 37 | 38 | @Test 39 | public void testBuffer() throws IOException { 40 | OutputBuffer buffer = new OutputBuffer(1 << 20); 41 | for (int i = 0; i < 1000; i++) { 42 | buffer.writeShort((short) i); 43 | } 44 | buffer.writeBooleanArray(new boolean[100000]); 45 | } 46 | 47 | @Data 48 | public static class Bean { 49 | private int id = RandomUtils.nextInt(); 50 | private String name = "hello"; 51 | private Date time = new Date(); 52 | private BitSet flags = BitSet.valueOf(RandomUtils.nextBytes(8)); 53 | private Collection tags = Arrays.asList(new Tag(1, "tag1"), null, new Tag(3, "tag3")); 54 | } 55 | 56 | @Data 57 | @NoArgsConstructor 58 | @AllArgsConstructor 59 | public static class Tag { 60 | private int code; 61 | private String name; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/utils/ASMUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.utils; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.objectweb.asm.ClassWriter; 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | 8 | /** 9 | * @author sulin 10 | * @since 2019-11-06 20:16:10 11 | */ 12 | public class ASMUtilsTest { 13 | 14 | @Test 15 | public void test() { 16 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); 17 | cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "Test", null, "java/lang/Object", null); 18 | 19 | MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); 20 | mv.visitCode(); 21 | mv.visitVarInsn(Opcodes.ALOAD, 0); 22 | mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); 23 | 24 | ASMUtils.addIntInstruction(mv, 1 << 20); 25 | 26 | mv.visitInsn(Opcodes.RETURN); 27 | mv.visitMaxs(0, 0); 28 | mv.visitEnd(); 29 | 30 | try { 31 | ASMUtils.addBoxInstruction(null, Void.class); 32 | assert false; 33 | } catch (Exception e) { 34 | assert e instanceof IllegalArgumentException; 35 | } 36 | 37 | try { 38 | ASMUtils.addUnboxInstruction(null, Void.class); 39 | assert false; 40 | } catch (Exception e) { 41 | assert e instanceof IllegalArgumentException; 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/utils/ArrayUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.utils; 2 | 3 | import org.apache.commons.lang3.RandomUtils; 4 | import org.junit.jupiter.api.Test; 5 | 6 | /** 7 | * @author sulin 8 | * @since 2019-10-02 15:18:19 9 | */ 10 | public class ArrayUtilsTest { 11 | 12 | @Test 13 | public void testDescFastSort() { 14 | ArrayUtils.descFastSort(new int[0], 0, 0); 15 | 16 | int[] arr = {1}; 17 | ArrayUtils.descFastSort(arr, 0, 0); 18 | assert arr[0] == 1; 19 | 20 | arr = new int[]{1, 2}; 21 | ArrayUtils.descFastSort(arr, 0, 1); 22 | assert arr[0] == 2; 23 | assert arr[1] == 1; 24 | 25 | arr = new int[]{3, 2, 4, 1, 7}; 26 | ArrayUtils.descFastSort(arr, 0, arr.length - 1); 27 | assert arr[0] == 7; 28 | assert arr[1] == 4; 29 | assert arr[2] == 3; 30 | assert arr[3] == 2; 31 | assert arr[4] == 1; 32 | 33 | arr = new int[100]; 34 | for (int i = 0; i < 100; i++) { 35 | arr[i] = RandomUtils.nextInt(1, 10000000); 36 | } 37 | ArrayUtils.descFastSort(arr, 0, arr.length - 1); 38 | for (int i = 0; i < 99; i++) { 39 | assert arr[i] >= arr[i + 1]; 40 | } 41 | } 42 | 43 | @Test 44 | public void testLongArray() { 45 | ArrayUtils.descFastSort(new long[0], 0, 0); 46 | 47 | long[] arr = {1}; 48 | ArrayUtils.descFastSort(arr, 0, 0); 49 | assert arr[0] == 1; 50 | 51 | arr = new long[]{1, 2}; 52 | ArrayUtils.descFastSort(arr, 0, 1); 53 | assert arr[0] == 2; 54 | assert arr[1] == 1; 55 | 56 | arr = new long[]{3, 2, 4, 1, 7}; 57 | ArrayUtils.descFastSort(arr, 0, arr.length - 1); 58 | assert arr[0] == 7; 59 | assert arr[1] == 4; 60 | assert arr[2] == 3; 61 | assert arr[3] == 2; 62 | assert arr[4] == 1; 63 | 64 | arr = new long[100]; 65 | for (int i = 0; i < 100; i++) { 66 | arr[i] = RandomUtils.nextInt(1, 10000000); 67 | } 68 | ArrayUtils.descFastSort(arr, 0, arr.length - 1); 69 | for (int i = 0; i < 99; i++) { 70 | assert arr[i] >= arr[i + 1]; 71 | } 72 | } 73 | 74 | @Test 75 | public void testAr() { 76 | Object[] arr = new Object[4]; 77 | arr[0] = "1"; 78 | assert arr[0] == "1"; 79 | 80 | arr = ArrayUtils.put(null, 0, "0"); 81 | arr = ArrayUtils.put(arr, 1, "1"); 82 | arr = ArrayUtils.put(arr, 2, "2"); 83 | arr = ArrayUtils.put(arr, 3, "3"); 84 | arr = ArrayUtils.put(arr, 4, "4"); 85 | 86 | assert arr[0] == "0"; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/utils/NumberUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.utils; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.apache.commons.lang3.RandomUtils; 5 | import org.junit.jupiter.api.RepeatedTest; 6 | import org.junit.jupiter.api.Test; 7 | 8 | /** 9 | * @author sulin 10 | * @since 2019-04-27 16:14:07 11 | */ 12 | @Slf4j 13 | public class NumberUtilsTest { 14 | 15 | @Test 16 | public void testFloat() { 17 | float f = 1.1f; 18 | log.info("{}: \t{}", f, NumberUtils.floatToBits(f)); 19 | 20 | for (int i = 0; i < 1000000; i++) { 21 | float f1 = RandomUtils.nextFloat(); 22 | int bits = NumberUtils.floatToBits(f1); 23 | float f2 = NumberUtils.bitsToFloat(bits); 24 | if (f1 != f2) { 25 | log.error("err: {}, {}", f1, f2); 26 | } 27 | } 28 | } 29 | 30 | @Test 31 | public void testDouble() { 32 | double d = 1.1; 33 | log.info("{}: \t{}", d, NumberUtils.doubleToBits(d)); 34 | 35 | for (int i = 0; i < 1000000; i++) { 36 | double d1 = RandomUtils.nextDouble(); 37 | long bits = NumberUtils.doubleToBits(d1); 38 | double d2 = NumberUtils.bitsToDouble(bits); 39 | if (d1 != d2) { 40 | log.error("err: {}, {}", d1, d2); 41 | } 42 | } 43 | } 44 | 45 | @RepeatedTest(1000) 46 | public void testUint() { 47 | this.testUintOnce(RandomUtils.nextLong()); 48 | } 49 | 50 | @Test 51 | public void testUint2() { 52 | this.testUintOnce(8976814520369533952L); 53 | } 54 | 55 | private void testUintOnce(long l) { 56 | long ul = NumberUtils.intToUint(l); 57 | long l2 = NumberUtils.uintToInt(ul); 58 | assert l == l2; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/utils/ReflectUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.utils; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | /** 8 | * @author sulin 9 | * @since 2019-11-09 19:55:16 10 | */ 11 | public class ReflectUtilsTest { 12 | 13 | @Test 14 | public void test() throws NoSuchFieldException { 15 | assert ReflectUtils.findAllValidFields(null).isEmpty(); 16 | assert ReflectUtils.findAllValidFields(boolean.class).isEmpty(); 17 | assert !ReflectUtils.findAllValidFields(Boolean.class).isEmpty(); 18 | 19 | Field field = Bean.class.getDeclaredField("blocked"); 20 | assert ReflectUtils.findGetter(Bean.class, field) != null; 21 | assert ReflectUtils.findSetter(Bean.class, field) != null; 22 | 23 | field = Bean.class.getDeclaredField("is_valid"); 24 | assert ReflectUtils.findGetter(Bean.class, field) != null; 25 | assert ReflectUtils.findSetter(Bean.class, field) != null; 26 | 27 | field = Bean.class.getDeclaredField("is_visible"); 28 | assert ReflectUtils.findGetter(Bean.class, field) != null; 29 | assert ReflectUtils.findSetter(Bean.class, field) != null; 30 | 31 | field = Bean.class.getDeclaredField("is_ok"); 32 | assert ReflectUtils.findGetter(Bean.class, field) == null; 33 | assert ReflectUtils.findSetter(Bean.class, field) == null; 34 | } 35 | 36 | public static class Bean { 37 | private boolean blocked; 38 | private boolean is_valid; 39 | private boolean is_visible; 40 | private boolean is_ok; 41 | 42 | public boolean isBlocked() { 43 | return blocked; 44 | } 45 | 46 | public void setBlocked(boolean blocked) { 47 | this.blocked = blocked; 48 | } 49 | 50 | public boolean isIs_valid() { 51 | return is_valid; 52 | } 53 | 54 | public void setIs_valid(boolean is_valid) { 55 | this.is_valid = is_valid; 56 | } 57 | 58 | public boolean isIs_visible() { 59 | return is_visible; 60 | } 61 | 62 | public void setIs_visible(boolean is_visible) { 63 | this.is_visible = is_visible; 64 | } 65 | 66 | @Deprecated 67 | public boolean isIs_ok() { 68 | return is_ok; 69 | } 70 | 71 | public static void setIs_ok(boolean is_ok) { 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/utils/TimeUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.utils; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | /** 6 | * @author sulin 7 | * @since 2019-10-08 21:20:43 8 | */ 9 | public class TimeUtilsTest { 10 | 11 | @Test 12 | public void test() throws InterruptedException { 13 | long now = TimeUtils.fastNow(); 14 | long uptime = TimeUtils.fastUpTime(); 15 | System.out.println(now); 16 | System.out.println(uptime); 17 | 18 | Thread.sleep(1000); 19 | 20 | assert TimeUtils.fastNow() > now; 21 | assert TimeUtils.fastUpTime() > uptime; 22 | } 23 | 24 | @Test 25 | public void testThread() throws InterruptedException { 26 | TimeUtils.TIMER_THREAD.interrupt(); 27 | 28 | Thread.sleep(100); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/com/github/smartbuf/utils/UTF8UtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.smartbuf.utils; 2 | 3 | import org.apache.commons.lang3.RandomStringUtils; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.nio.CharBuffer; 7 | import java.nio.charset.StandardCharsets; 8 | import java.util.Objects; 9 | 10 | /** 11 | * @author sulin 12 | * @since 2019-11-05 19:53:37 13 | */ 14 | public class UTF8UtilsTest { 15 | 16 | @Test 17 | public void encode() { 18 | String[] strs = new String[]{ 19 | "hello world", 20 | "你好,中国", 21 | "😝😝😝😝😝", 22 | RandomStringUtils.random(64), 23 | RandomStringUtils.randomGraph(64) 24 | }; 25 | 26 | for (String str : strs) { 27 | byte[] bytes = UTF8Utils.encode(str); 28 | String newStr = new String(bytes, StandardCharsets.UTF_8); 29 | assert Objects.equals(str, newStr); 30 | } 31 | } 32 | 33 | @Test 34 | public void testSurrogate() { 35 | byte[] bytes = UTF8Utils.encode(CharBuffer.wrap(new char[]{0xDDFF})); 36 | assert bytes[0] == UTF8Utils.REPL; 37 | 38 | bytes = UTF8Utils.encode(CharBuffer.wrap(new char[]{0xDBFF})); 39 | assert bytes[0] == UTF8Utils.REPL; 40 | 41 | bytes = UTF8Utils.encode(CharBuffer.wrap(new char[]{0xDBFF, 0x00ff})); 42 | assert bytes[0] == UTF8Utils.REPL; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | UTF-8 8 | %d{yyyy/MM/dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test/resources/proto/large.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package com.github.smartbuf.benchmark.large; 4 | 5 | message Trends { 6 | repeated Trend trends = 1; 7 | } 8 | 9 | message Trend { 10 | int64 id = 1; 11 | string id_str = 2; 12 | string name = 3; 13 | string screen_name = 4; 14 | string location = 5; 15 | string description = 6; 16 | string url = 7; 17 | Entities entities = 8; 18 | bool protect = 9; 19 | int64 followers_count = 10; 20 | int64 fast_followers_count = 11; 21 | int64 normal_followers_count = 12; 22 | int64 friends_count = 13; 23 | int64 listed_count = 14; 24 | string created_at = 15; 25 | int64 favourites_count = 16; 26 | string utc_offset = 17; 27 | string time_zone = 18; 28 | bool geo_enabled = 19; 29 | bool verified = 20; 30 | int64 statuses_count = 21; 31 | int64 media_count = 22; 32 | string lang = 23; 33 | bool contributors_enabled = 24; 34 | bool is_translator = 25; 35 | bool is_translation_enabled = 26; 36 | string profile_background_color = 27; 37 | string profile_background_image_url = 28; 38 | string profile_background_image_url_https = 29; 39 | bool profile_background_tile = 30; 40 | string profile_image_url = 31; 41 | string profile_image_url_https = 32; 42 | string profile_banner_url = 33; 43 | string profile_link_color = 34; 44 | string profile_sidebar_border_color = 35; 45 | string profile_sidebar_fill_color = 36; 46 | string profile_text_color = 37; 47 | bool profile_use_background_image = 38; 48 | bool has_extended_profile = 39; 49 | bool default_profile = 40; 50 | bool default_profile_image = 41; 51 | repeated int64 pinned_tweet_ids = 42; 52 | repeated string pinned_tweet_ids_str = 43; 53 | bool has_custom_timelines = 44; 54 | bool can_dm = 45; 55 | bool can_media_tag = 46; 56 | bool following = 47; 57 | bool follow_request_sent = 48; 58 | bool notifications = 49; 59 | bool muting = 50; 60 | bool blocking = 51; 61 | bool blocked_by = 52; 62 | bool want_retweets = 53; 63 | string advertiser_account_type = 54; 64 | repeated string advertiser_account_service_levels = 55; 65 | string profile_interstitial_type = 56; 66 | string business_profile_state = 57; 67 | string translator_type = 58; 68 | bool followed_by = 59; 69 | bool require_some_consent = 60; 70 | } 71 | 72 | message Entities { 73 | Urls url = 1; 74 | Description description = 2; 75 | } 76 | 77 | message Description { 78 | repeated Url urls = 1; 79 | } 80 | 81 | message Urls { 82 | repeated Url urls = 1; 83 | } 84 | 85 | message Url { 86 | string url = 1; 87 | string expanded_url = 2; 88 | string display_url = 3; 89 | repeated int64 indices = 4; 90 | } 91 | -------------------------------------------------------------------------------- /src/test/resources/proto/medium.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package com.github.smartbuf.benchmark.medium; 4 | 5 | message User { 6 | int64 id = 1; 7 | string nickname = 2; 8 | string portrait = 3; 9 | float score = 4; 10 | string mail = 5; 11 | string mobile = 6; 12 | string token = 7; 13 | int32 type = 8; 14 | int32 source = 9; 15 | bool blocked = 10; 16 | int32 loginTimes = 11; 17 | int64 updateTime = 12; 18 | int64 createTime = 13; 19 | 20 | repeated Message msgs = 20; 21 | repeated Tag tags = 21; 22 | } 23 | 24 | message Message { 25 | int64 id = 1; 26 | int64 from = 2; 27 | int64 to = 3; 28 | string msg = 4; 29 | int64 timestamp = 5; 30 | } 31 | 32 | message Tag { 33 | int32 code = 1; 34 | string name = 2; 35 | } 36 | -------------------------------------------------------------------------------- /src/test/resources/proto/message.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package com.github.smartbuf.model; 4 | 5 | message Message { 6 | int32 id = 1; 7 | bool enable = 2; 8 | float score1 = 3; 9 | double score2 = 4; 10 | string text = 5; 11 | int64 timestamp = 6; 12 | repeated Receiver receivers = 7; 13 | } 14 | 15 | message Receiver { 16 | int32 userId = 1; 17 | string iconUrl = 2; 18 | string remark = 3; 19 | int32 followNum = 4; 20 | int32 fanNum = 5; 21 | int64 createTime = 6; 22 | int64 updateTime = 7; 23 | } 24 | -------------------------------------------------------------------------------- /src/test/resources/proto/small.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package com.github.smartbuf.benchmark.small; 4 | 5 | message User { 6 | int64 id = 1; 7 | bool blocked = 2; 8 | string nickname = 3; 9 | string portrait = 4; 10 | float score = 5; 11 | int32 loginTimes = 6; 12 | int64 createTime = 7; 13 | } 14 | -------------------------------------------------------------------------------- /src/test/resources/proto/tiny.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package com.github.smartbuf.benchmark.tiny; 4 | 5 | message User { 6 | int32 id = 1; 7 | string name = 2; 8 | int64 time = 3; 9 | } 10 | --------------------------------------------------------------------------------