ABuf高压缩率,高健壮性,序列化二进制格式

原创
2019/08/17 09:34
阅读数 343

1.VInt数字压缩, 支持正负数

2.TAG标识可获取原始基本类型

2.支持序列化写入流和反序列化读取流

代码分享


package axj.seri.abuf;

import axj.kt.KtB;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;

/**
 * Created with IDEA
 *
 * [@author](https://my.oschina.net/arthor):absir
 * [@Date](https://my.oschina.net/u/2504391) 2019-08-14 13:45
 */
public class ABufOut {

    final OutputStream out;

    boolean writeStrEmpty;

    OutBuf buf;

    public static class OutBuf extends ByteArrayOutputStream {

        public byte[] getBuf() {
            return buf;
        }
    }

    public ABufOut(OutputStream out) {
        this.out = out;
    }

    public void writeInt(int i) throws IOException {
        writeI(out, 0, i);
    }

    public void writeLong(long l) throws IOException {
        writeL(out, 0, l);
    }

    public void writeString(CharSequence str) throws IOException {
        if (str == null) {
            writeNil();

        } else {
            int len = str.length();
            writeI(out, TAG_STRI, len);
            for (int i = 0; i < len; i++) {
                writeInt(str.charAt(i));
            }
        }
    }

    public void writeBytes(byte[] bytes, int off, int len) throws IOException {
        if (bytes == null) {
            writeNil();

        } else {
            writeI(out, TAG_SPEC, SPEC_BUF);
            if (len > off) {
                writeI(out, 0, len - off);
                out.write(bytes, off, len);

            } else {
                writeI(out, 0, 0);
            }
        }
    }

    public ByteArrayOutputStream buf() {
        if (buf == null) {
            buf = new OutBuf();

        } else {
            buf.reset();
        }

        return buf;
    }

    public void writeBuf() throws IOException {
        writeI(out, TAG_SPEC, SPEC_BUF);
        int len = buf == null ? 0 : buf.size();
        writeI(out, 0, len);
        out.write(buf.getBuf(), 0, len);
    }

    public void writeNil() throws IOException {
        writeI(out, TAG_SPEC, SPEC_NIL);
    }

    public void writeLst() throws IOException {
        writeI(out, TAG_SPEC, SPEC_LST);
    }

    public void writeMap() throws IOException {
        writeI(out, TAG_SPEC, SPEC_MAP);
    }

    public void writeEnd() throws IOException {
        writeI(out, TAG_SPEC, SPEC_END);
    }

    public void writeObject(Object val) throws Exception {
        ABuf.ME.writeObject(val, this);
    }

    static class InBuf extends InputStream {

        final InputStream in;

        int max;

        InBuf(InputStream in) {
            this.in = in;
        }

        [@Override](https://my.oschina.net/u/1162528)
        public int available() throws IOException {
            return Math.max(max, in.available());
        }

        [@Override](https://my.oschina.net/u/1162528)
        public int read() throws IOException {
            if (max <= 0) {
                return -1;
            }

            max--;
            return in.read();
        }
    }

    public enum ERead {
        /**
         * 数组
         */
        LST,
        /**
         * 字典
         */
        MAP,
        /**
         * 结束
         */
        END,
    }

    /**
     * Created with IDEA
     *
     * [@author](https://my.oschina.net/arthor):absir
     * @Date 2019-08-14 13:45
     */
    public static class ABufIn {

        final InputStream in;

        // 预加载bytes
        int pByte = -1;

        boolean merge;

        boolean skip;

        int tag;

        StringBuilder sb;

        InBuf inBuf;

        int rtI;

        long rtL;

        // 返回为空
        boolean rtNil;

        // 结构深度
        int inDepth;

        public int getTag() {
            return tag;
        }

        public boolean isRtNil() {
            return rtNil;
        }

        public int getInDepth() {
            return inDepth;
        }

        public ABufIn(InputStream in) {
            this.in = in;
        }

        protected int maxLen() {
            return 10485760;
        }

        protected StringBuilder getSb(int len) throws IOException {
            if (len > maxLen()) {
                throw new IOException("read len max " + len);
            }

            if (sb == null) {
                sb = new StringBuilder(len);
            }

            sb.setLength(len);
            return sb;
        }

        /**
         * @param l  long类型
         * @param bs 返回数组
         * @return
         * @throws IOException
         */
        public Object readNext(boolean l, boolean bs) throws IOException {
            skipBuf();
            rtNil = false;
            if (l) {
                rtL = readL(pByte, in, this);
                pByte = -1;
                if (tag <= TAG_NEGA) {
                    return null;
                }

                rtI = (int) rtL;

            } else {
                rtI = readI(pByte, in, this);
                pByte = -1;
                if (tag <= TAG_NEGA) {
                    return null;
                }
            }

            if (tag == TAG_STRI) {
                if (skip) {
                    skipLen(rtI);
                    return null;

                } else {
                    if (rtI == 0) {
                        return KtB.STR;
                    }

                    int len = rtI;
                    getSb(len);
                    for (int i = 0; i < len; i++) {
                        sb.setCharAt(i, (char) readInt());
                    }

                    tag = TAG_STRI;
                    rtI = len;
                    return sb.toString();
                }

            } else {
                switch (rtI) {
                    case SPEC_NIL:
                        if (!skip) {
                            rtNil = true;
                        }
                        return null;
                    case SPEC_BUF:
                        int len = readI(pByte, in, this);
                        tag = TAG_SPEC;
                        if (skip) {
                            skipLen(len);
                            return null;

                        } else {
                            if (bs) {
                                // 读取bytes
                                if (len == 0) {
                                    return KtB.BYTES;
                                }

                                if (len > maxLen()) {
                                    throw new IOException("read len max " + len);
                                }

                                byte[] buf = new byte[len];
                                for (int i = 0; i < len; i++) {
                                    buf[i] = (byte) in.read();
                                }

                                return buf;

                            } else {
                                // 读取流
                                if (inBuf == null) {
                                    inBuf = new InBuf(in);
                                }

                                inBuf.max = len;
                                return inBuf;
                            }
                        }
                    case SPEC_LST:
                        inDepth++;
                        return ERead.LST;
                    case SPEC_MAP:
                        inDepth++;
                        return ERead.MAP;
                    case SPEC_END:
                        inDepth--;
                        return ERead.END;
                    default:
                        return null;
                }
            }
        }

        protected void skipLen(int len) throws IOException {
            for (int i = 0; i < len; i++) {
                in.read();
            }
        }

        public void skipBuf() throws IOException {
            if (inBuf != null) {
                while (inBuf.read() >= 0) ;
            }
        }

        protected void skipDepth() throws IOException {
            boolean skipO = skip;
            int depthO = inDepth;
            skip = true;
            while (true) {
                if (readNext(false, false) == ERead.END && inDepth < depthO) {
                    break;
                }
            }

            // 恢复跳过状态
            skip = skipO;
        }

        protected void skipRetr(Object retr) throws IOException {
            if (retr == ERead.LST || retr == ERead.MAP) {
                skipDepth();

            } else {
                skipBuf();
            }
        }

        public int readInt() throws IOException {
            Object retr = readNext(false, false);
            if (tag <= TAG_NEGA) {
                return rtI;
            }

            if (tag == TAG_STRI) {
                return Integer.parseInt((String) retr);
            }

            skipRetr(retr);
            return 0;
        }


        public long readLong() throws IOException {
            Object retr = readNext(true, false);
            if (tag <= TAG_NEGA) {
                return rtL;
            }

            if (tag == TAG_STRI) {
                return Long.parseLong((String) retr);
            }

            skipRetr(retr);
            return 0;
        }

        public String readString() throws IOException {
            Object retr = readNext(false, false);
            switch (tag) {
                case TAG_STRI:
                    return (String) retr;
                case TAG_POSI:
                case TAG_NEGA:
                    return String.valueOf(rtI);
            }

            skipRetr(retr);
            return null;
        }

        public byte[] readBytes() throws IOException {
            Object retr = readNext(false, true);
            if (tag == TAG_SPEC && rtI == SPEC_BUF) {
                return (byte[]) retr;
            }

            skipRetr(retr);
            return null;
        }

        public InputStream readBuf() throws IOException {
            Object retr = readNext(false, false);
            if (tag == TAG_SPEC && rtI == SPEC_BUF) {
                return inBuf;
            }

            skipRetr(retr);
            return null;
        }

        public boolean readEnd() throws IOException {
            pByte = in.read();
            if (pByte == END_BYTE) {
                pByte = -1;
                return true;
            }

            return false;
        }

        public Object readObject(Type type) throws Exception {
            return ABuf.ME.readObject(this, type);
        }
    }

    static final int VINT_N = 0x80;

    static final int VINT = VINT_N - 1;

    static final int VINT0 = VINT >> 2;

    /**
     * 正数
     */
    static final int TAG_POSI = 0;

    /**
     * 负数
     */
    static final int TAG_NEGA = 1;

    /**
     * 字符串
     */
    static final int TAG_STRI = 2;

    /**
     * 特殊定义
     */
    static final int TAG_SPEC = 3;

    /**
     * 空值
     */
    static final int SPEC_NIL = 0;

    /**
     * 数组
     */
    static final int SPEC_BUF = 1;

    /**
     * 数组
     */
    static final int SPEC_LST = 2;

    /**
     * 字典
     */
    static final int SPEC_MAP = 3;

    /**
     * 结束
     */
    static final int SPEC_END = 4;

    /**
     * 结束BYTE
     */
    static final int END_BYTE = SPEC_END | (TAG_SPEC << 5);

    static void writeI(OutputStream out, int tag, int i) throws IOException {
        if (i < 0) {
            tag = TAG_NEGA;
            i = -i;
        }

        int b = i & VINT0;
        if (tag != 0) {
            b |= tag << 5;
        }

        i >>= 5;
        while (true) {
            if (i <= 0) {
                out.write(b);
                break;

            } else {
                b |= VINT_N;
                out.write(b);
            }

            b = i & VINT;
            i >>= 7;
        }
    }

    static void writeL(OutputStream out, int tag, long l) throws IOException {
        if (l < 0) {
            tag = TAG_NEGA;
            l = -l;
        }

        int b = (byte) (l & VINT0);
        if (tag != 0) {
            b |= tag << 5;
        }

        l >>= 5;
        while (true) {
            if (l <= 0) {
                out.write(b);
                break;

            } else {
                b |= VINT_N;
                out.write(b);
            }

            b = (byte) (l & VINT);
            l >>= 7;
        }
    }

    static int readI(int b, InputStream in, ABufIn bufIn) throws IOException {
        if (b < 0) {
            b = in.read();
        }

        if (b < 0) {
            throw new IOException("read stream ended");
        }

        int tag = (b & VINT) >> 5;
        int i = b & VINT0;
        if (bufIn != null) {
            bufIn.tag = tag;
        }

        int p = 5;
        while (true) {
            if ((b & VINT_N) == 0) {
                return tag == TAG_NEGA ? -i : i;
            }

            b = in.read();
            i += (b & VINT) << p;
            p += 7;
        }
    }

    static long readL(int b, InputStream in, ABufIn bufIn) throws IOException {
        if (b < 0) {
            b = in.read();
        }

        if (b < 0) {
            throw new IOException("read stream ended");
        }

        int tag = (b & VINT) >> 5;
        long l = b & VINT0;
        if (bufIn != null) {
            bufIn.tag = tag;
        }

        int p = 5;
        while (true) {
            if ((b & VINT_N) == 0) {
                return tag == TAG_NEGA ? -l : l;
            }

            b = in.read();
            l += ((long) (b & VINT)) << p;
            p += 7;
        }
    }
}



package axj.seri.abuf;

import axj.an.AInject;
import axj.ioc.APro;
import axj.kt.*;
import axj.seri.SBean;
import axj.seri.SJson;
import axj.seri.abuf.an.ABufJson;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import fastjson.ParseConfigB;
import fastjson.SerializeConfigB;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import static com.alibaba.fastjson.JSON.DEFAULT_GENERATE_FEATURE;

/**
 * Created with IDEA
 *
 * @author:absir
 * @Date 2019-08-14 10:55
 */
public class ABuf extends SBean.Holder<ABuf.Att> {

    static {
        // 先动态添加注册ioc对象
        APro.regPack(ABuf.class.getPackage().getName() + ".ap", true, false);
    }

    public static final ABuf ME = APro.getBean(ABuf.class);

    @AInject(required = false)
    IPropSFact[] facts;

    static class Att {

        // 字段
        IPropS propS;

        // 附加
        Object at;

        // 默认值
        Object def;

        // 字段
        byte[] key;
    }

    @Override
    protected Att getHolderAtt(SBean bean, SBean.Prop prop) {
        if (prop.getKey() > 0) {
            Field field = prop.getField();
            if (field != null) {
                IPropS propS = prop(prop.getClazz(), prop);
                if (propS != null) {
                    Att att = new Att();
                    try {
                        att.propS = propS;
                        att.at = propS.at(prop.getClazz(), prop);
                        att.def = field.get(bean.getInstance());
                        ByteArrayOutputStream out = new ByteArrayOutputStream();
                        ABufOut.writeI(out, 0, prop.getKey());
                        att.key = out.toByteArray();

                    } catch (Throwable e) {
                        KtA.runTimeEx(e);
                    }

                    return att;
                }
            }
        }

        return null;
    }

    public interface IPropSFact {

        /**
         * 工厂模式
         *
         * @param prop
         * @return
         */
        IPropS propGet(SBean.IProp prop);
    }

    public interface IPropS<T> {

        /**
         * 附件属性
         *
         * @return
         */
        T at(Class cls, SBean.IProp prop);

        /**
         * 写入
         *
         * @param val
         * @param at
         * @param out
         */
        void write(Object val, T at, ABufOut out) throws Exception;

        /**
         * 获取绑定
         *
         * @param target
         * @param at
         * @return
         * @throws Exception
         */
        Object get(Object target, SBean.Prop prop, T at) throws Exception;

        /**
         * 读取
         *
         * @param merge
         * @param at
         * @param in
         * @return
         */
        Object read(Object merge, T at, ABufOut.ABufIn in) throws Exception;
    }

    protected IPropS prop(Class cls, SBean.Prop prop) {
        if (prop != null) {
            ABufJson bufJson = prop.getAtt(ABufJson.class, true);
            if (bufJson != null && bufJson.value()) {
                return bufJson.fastB() ? EPropS.PsJSonB : EPropS.PsJSon;
            }

            if (facts != null) {
                for (IPropSFact fact : facts) {
                    IPropS propS = fact.propGet(prop);
                    if (propS != null) {
                        return propS;
                    }
                }
            }
        }

        if (KtCvt.as(cls, Character.class)) {
            return EPropS.PsChar;

        } else if (KtCvt.as(cls, Byte.class)) {
            return EPropS.PsByte;

        } else if (KtCvt.as(cls, Short.class)) {
            return EPropS.PsShort;

        } else if (KtCvt.as(cls, Integer.class)) {
            return EPropS.PsInt;

        } else if (KtCvt.as(cls, Long.class)) {
            return EPropS.PsLong;

        } else if (KtCvt.as(cls, Float.class)) {
            return EPropS.PsFloat;

        } else if (KtCvt.as(cls, Double.class)) {
            return EPropS.PsDouble;

        } else if (KtCvt.as(cls, String.class)) {
            return EPropS.PsString;

        } else if (cls == byte[].class) {
            return EPropS.PsBytes;

        } else if (cls.isEnum()) {
            return EPropS.PsEnum;

        } else if (cls.isArray()) {
            return EPropS.PsAry;

        } else if (Collection.class.isAssignableFrom(cls)) {
            return EPropS.PsLst;

        } else if (Map.class.isAssignableFrom(cls)) {
            return EPropS.PsMap;
        }

        return EPropS.PsSBean;
    }

    static class KeyVal {

        SBean.IProp prop;

        IPropS val;

        Object valAt;

        IPropS key;

        Object keyAt;

        protected KeyVal(SBean.IProp prop) {
            this.prop = prop;
            Class cls = KtCls.raw(prop.getVType());
            val = ME.prop(cls, null);
            if (val == null) {
                val = EPropS.PsObject;
            }

            valAt = val.at(cls, null);

            if (prop.getOType() == SBean.EOType.Map) {
                cls = KtCls.raw(prop.getKType());
                key = ME.prop(cls, null);
                if (key == null) {
                    key = EPropS.PsObject;
                }

                keyAt = key.at(cls, null);

            }
        }
    }

    enum EPropS implements IPropS {

        PsInt {},

        PsLong {
            @Override
            public void write(Object val, Object at, ABufOut out) throws IOException {
                if (val == null) {
                    out.writeNil();

                } else {
                    out.writeLong((Long) val);
                }
            }

            @Override
            public Object read(Object merge, Object at, ABufOut.ABufIn in) throws IOException {
                long l = in.readLong();
                return at == Boolean.TRUE || in.isRtNil() ? null : l;
            }
        },

        PsChar {
            @Override
            protected int toInt(Object val, Object at) {
                return (int) (Character) (val);
            }

            @Override
            protected Object fromInt(int i, Object at) {
                return (char) i;
            }
        },

        PsByte {
            @Override
            protected int toInt(Object val, Object at) {
                return (int) (Byte) (val);
            }

            @Override
            protected Object fromInt(int i, Object at) {
                return (byte) i;
            }
        },

        PsShort {
            @Override
            protected int toInt(Object val, Object at) {
                return (int) (Short) (val);
            }

            @Override
            protected Object fromInt(int i, Object at) {
                return (short) i;
            }
        },

        PsFloat {
            @Override
            public void write(Object val, Object at, ABufOut out) throws IOException {
                out.writeString(val == null ? null : String.valueOf(val));
            }

            @Override
            public Object read(Object merge, Object at, ABufOut.ABufIn in) throws IOException {
                String str = in.readString();
                return str == null ? at == null ? 0 : null : Float.parseFloat(str);
            }
        },

        PsDouble {
            @Override
            public void write(Object val, Object at, ABufOut out) throws IOException {
                out.writeString(val == null ? null : String.valueOf(val));
            }

            @Override
            public Object read(Object merge, Object at, ABufOut.ABufIn in) throws IOException {
                String str = in.readString();
                return str == null ? at == null ? 0 : null : Double.parseDouble(str);
            }
        },

        PsString {
            @Override
            public void write(Object val, Object at, ABufOut out) throws IOException {
                out.writeString((CharSequence) val);
            }

            @Override
            public Object read(Object merge, Object at, ABufOut.ABufIn in) throws IOException {
                return in.readString();
            }
        },

        PsBytes {
            @Override
            public void write(Object val, Object at, ABufOut out) throws IOException {
                byte[] bytes = (byte[]) val;
                out.writeBytes(bytes, 0, bytes == null ? 0 : bytes.length);
            }

            @Override
            public Object read(Object merge, Object at, ABufOut.ABufIn in) throws IOException {
                return in.readBytes();
            }
        },

        PsEnum {
            @Override
            public Object at(Class cls, SBean.IProp prop) {
                return SBean.enumKeys(cls);
            }

            @Override
            public void write(Object val, Object at, ABufOut out) throws IOException {
                if (val != null) {
                    for (SBean.EnumKey key : (SBean.EnumKey[]) at) {
                        if (val == key.en) {
                            out.writeInt(key.k);
                            return;
                        }
                    }
                }

                out.writeNil();
            }

            @Override
            protected Object fromInt(int i, Object at) {
                for (SBean.EnumKey key : (SBean.EnumKey[]) at) {
                    if (i == key.k) {
                        return key.en;
                    }
                }

                return null;
            }
        },

        PsSBean {
            @Override
            public Object at(Class cls, SBean.IProp prop) {
                SBean sBean = SBean.getSBean(cls, true);
                if (sBean == null) {
                    throw new RuntimeException("PsSBean not match " + cls);
                }

                return sBean;
            }

            @Override
            public void write(Object val, Object at, ABufOut out) throws Exception {
                ME.write(val, (SBean) at, out);
            }

            @Override
            public Object get(Object target, SBean.Prop prop, Object at) throws Exception {
                return prop.getPubly(target, false, false);
            }

            @Override
            public Object read(Object target, Object at, ABufOut.ABufIn in) throws Exception {
                return ME.read(target, (SBean) at, in);
            }
        },

        PsObject {
            @Override
            public void write(Object val, Object at, ABufOut out) throws Exception {
                ME.writeObject(val, out);
            }

            @Override
            public Object read(Object merge, Object at, ABufOut.ABufIn in) throws Exception {
                return ME.readObject(in, null);
            }
        },

        PsAry {
            @Override
            public Object at(Class cls, SBean.IProp prop) {
                return new KeyVal(prop);
            }

            @Override
            public void write(Object val, Object at, ABufOut out) throws Exception {
                if (val == null) {
                    out.writeNil();

                } else {
                    KeyVal keyVal = (KeyVal) at;
                    out.writeLst();
                    int len = Array.getLength(val);
                    for (int i = 0; i < len; i++) {
                        keyVal.val.write(Array.get(val, i), keyVal.valAt, out);
                    }

                    out.writeEnd();
                }
            }

            @Override
            public Object read(Object merge, Object at, ABufOut.ABufIn in) throws Exception {
                KeyVal keyVal = (KeyVal) at;
                return SBinder.ME.to(ME.readLstA(merge, keyVal, true, in), keyVal.prop.getClazz());
            }
        },

        PsLst {
            @Override
            public Object at(Class cls, SBean.IProp prop) {
                return new KeyVal(prop);
            }

            @Override
            public void write(Object val, Object at, ABufOut out) throws Exception {
                if (val == null) {
                    out.writeNil();

                } else {
                    KeyVal keyVal = (KeyVal) at;
                    out.writeLst();
                    for (Object v : (Collection) val) {
                        keyVal.val.write(v, keyVal.valAt, out);
                    }

                    out.writeEnd();
                }
            }

            @Override
            public Object read(Object merge, Object at, ABufOut.ABufIn in) throws Exception {
                KeyVal keyVal = (KeyVal) at;
                return ME.readLstA(merge, keyVal, false, in);
            }
        },

        PsMap {
            @Override
            public Object at(Class cls, SBean.IProp prop) {
                return new KeyVal(prop);
            }

            @Override
            public void write(Object val, Object at, ABufOut out) throws Exception {
                if (val == null) {
                    out.writeNil();

                } else {
                    KeyVal keyVal = (KeyVal) at;
                    out.writeMap();
                    for (Map.Entry entry : ((Map<?, ?>) val).entrySet()) {
                        keyVal.key.write(entry.getKey(), keyVal.keyAt, out);
                        keyVal.val.write(entry.getValue(), keyVal.valAt, out);
                    }

                    out.writeEnd();
                }
            }

            @Override
            public Object read(Object merge, Object at, ABufOut.ABufIn in) throws Exception {
                KeyVal keyVal = (KeyVal) at;
                Object retr = in.readNext(false, false);
                if (retr == ABufOut.ERead.MAP) {
                    Map map = KtCvt.ToMap.newTo(keyVal.prop, keyVal.prop.getClazz(), 1);
                    while (!in.readEnd()) {
                        map.put(keyVal.key.read(merge, keyVal.keyAt, in), keyVal.val.read(merge, keyVal.valAt, in));
                    }

                    return map;
                }

                in.skipRetr(retr);
                return null;
            }
        },

        PsJSon {
            @Override
            public Object at(Class cls, SBean.IProp prop) {
                return prop.getType();
            }

            @Override
            public void write(Object val, Object at, ABufOut out) throws Exception {
                if (val == null) {
                    out.writeNil();

                } else {
                    SJson.ME().writeJSONString(out.buf(), val);
                    out.writeBuf();
                }
            }

            @Override
            public Object read(Object merge, Object at, ABufOut.ABufIn in) throws Exception {
                InputStream inp = in.readBuf();
                return inp == null ? null : SJson.ME().parseObject(inp, (Type) at);
            }
        },

        PsJSonB {
            @Override
            public Object at(Class cls, SBean.IProp prop) {
                return prop.getType();
            }

            @Override
            public void write(Object val, Object at, ABufOut out) throws Exception {
                if (val == null) {
                    out.writeNil();

                } else {
                    JSON.writeJSONString(out.buf(), KtIo.utf8(), val, SerializeConfigB.ME, null, null, DEFAULT_GENERATE_FEATURE, SerializerFeature.WriteNonStringKeyAsString);
                    out.writeBuf();
                }
            }

            @Override
            public Object read(Object merge, Object at, ABufOut.ABufIn in) throws Exception {
                InputStream inp = in.readBuf();
                return inp == null ? null : JSON.parseObject(inp, KtIo.utf8(), (Type) at, ParseConfigB.ME, Feature.AllowUnQuotedFieldNames);
            }
        },

        ;

        @Override
        public Object at(Class cls, SBean.IProp prop) {
            return Object.class.isAssignableFrom(cls) ? Boolean.TRUE : null;
        }

        @Override
        public void write(Object val, Object at, ABufOut out) throws Exception {
            if (val == null) {
                out.writeNil();

            } else {
                out.writeInt(toInt(val, at));
            }
        }

        protected int toInt(Object val, Object at) {
            return (int) val;
        }

        @Override
        public Object get(Object target, SBean.Prop prop, Object at) throws Exception {
            return null;
        }

        @Override
        public Object read(Object merge, Object at, ABufOut.ABufIn in) throws Exception {
            int i = in.readInt();
            return in.isRtNil() && at != null ? null : fromInt(i, at);
        }

        protected Object fromInt(int i, Object at) {
            return i;
        }
    }

    protected void write(Object target, SBean sBean, ABufOut out) throws Exception {
        if (target == null) {
            out.writeNil();

        } else {
            out.writeMap();
            Att att;
            for (SBean.Prop prop : sBean.props()) {
                att = prop.getHolderAtt(ME);
                if (att != null) {
                    Object v = prop.getPubly(target, false, false);
                    if (v != null && !v.equals(att.def)) {
                        if (att.propS == EPropS.PsString && !out.writeStrEmpty && ((String) v).length() == 0) {
                            continue;
                        }

                        // 写入字段
                        out.out.write(att.key);
                        att.propS.write(v, att.at, out);
                    }
                }
            }

            out.writeEnd();
        }
    }

    protected Object read(Object target, SBean sBean, ABufOut.ABufIn in) throws Exception {
        Object retr = in.readNext(false, false);
        if (retr == ABufOut.ERead.MAP) {
            return readB(target, sBean, in);
        }

        in.skipRetr(retr);
        return null;
    }

    protected Object readB(Object target, SBean sBean, ABufOut.ABufIn in) throws Exception {
        if (target == null) {
            target = sBean.newInstance();
        }

        while (!in.readEnd()) {
            in.readNext(false, false);
            if (in.tag != ABufOut.TAG_POSI) {
                throw new IOException("read key tag err " + in.tag);
            }

            SBean.Prop prop = sBean.getPropKey(in.rtI);
            Att att = prop == null ? null : prop.getHolderAtt(ME);
            if (att == null) {
                in.skipRetr(in.readNext(false, false));

            } else {
                Object merge = in.merge ? att.propS.get(target, prop, att.at) : null;
                Object to = att.propS.read(merge, att.at, in);
                if (!in.merge || to != merge) {
                    // 赋值
                    prop.setPubly(target, false, false, to, null);
                }
            }
        }

        return target;
    }

    protected void writeObject(Object val, ABufOut out) throws Exception {
        if (val == null) {
            out.writeNil();

        } else {
            Class cls = val.getClass();
            if (Number.class.isAssignableFrom(cls)) {
                if (cls == Long.class) {
                    out.writeLong((Long) val);

                } else if (cls == Float.class || cls == Double.class) {
                    out.writeString(val.toString());

                } else {
                    out.writeInt(((Number) val).intValue());
                }

            } else if (CharSequence.class.isAssignableFrom(cls)) {
                out.writeString((CharSequence) val);

            } else if (Map.class.isAssignableFrom(cls)) {
                out.writeMap();
                for (Map.Entry<?, ?> entry : ((Map<?, ?>) val).entrySet()) {
                    writeObject(entry.getKey(), out);
                    writeObject(entry.getValue(), out);
                }

                out.writeEnd();

            } else if (Collection.class.isAssignableFrom(cls)) {
                out.writeLst();
                for (Object v : (Collection) val) {
                    writeObject(v, out);
                }

                out.writeEnd();

            } else if (cls.isArray()) {
                out.writeLst();
                int len = Array.getLength(val);
                for (int i = 0; i < len; i++) {
                    writeObject(Array.get(val, i), out);
                }

                out.writeEnd();

            } else if (cls.isEnum()) {
                EPropS.PsEnum.write(val, SBean.enumKeys(cls), out);

            } else {
                SBean sBean = SBean.getSBean(cls, true);
                if (sBean == null) {
                    throw new IOException("write no support at " + cls);

                } else {
                    write(val, sBean, out);
                }
            }
        }
    }

    protected Object readObject(ABufOut.ABufIn in, Type type) throws Exception {
        Object retr = in.readNext(true, true);
        if (in.tag <= ABufOut.TAG_NEGA) {
            return SBinder.ME.to(in.rtL, type, null);
        }

        if (in.tag == ABufOut.TAG_SPEC) {
            if (in.rtI == ABufOut.SPEC_MAP) {
                Class cls = KtCls.raw(type);
                SBean sBean = SBean.getSBean(cls, true);
                if (sBean == null) {
                    Type vType = null;
                    Type kType = null;
                    if (cls != null && Map.class.isAssignableFrom(cls)) {
                        vType = KtCls.typeVar(type, KtCvt.MapV);
                        kType = KtCls.typeVar(type, KtCvt.MapK);
                    }

                    // 返回map
                    Map map = new HashMap();
                    while (!in.readEnd()) {
                        map.put(readObject(in, kType), readObject(in, vType));
                    }

                    return map;

                } else {
                    // 返回bean
                    return readB(null, sBean, in);
                }

            } else if (in.rtI == ABufOut.SPEC_LST) {
                Class cls = KtCls.raw(type);
                Type vType = type != null || Collection.class.isAssignableFrom(cls) ? KtCls.typeVar(type, KtCvt.ListT) : null;
                // 返回list
                Collection list = KtCvt.ToList.newTo(null, cls, 1);
                while (!in.readEnd()) {
                    list.add(readObject(in, vType));
                }

                return SBinder.ME.to(list, type, null);
            }
        }

        if (retr instanceof ABufOut.ERead) {
            retr = null;
        }

        return SBinder.ME.to(retr, type, null);
    }

    protected Collection readLstA(Object merge, KeyVal keyVal, boolean ary, ABufOut.ABufIn in) throws Exception {
        Object retr = in.readNext(false, false);
        if (retr == ABufOut.ERead.LST) {
            Collection list = ary ? new ArrayList(1) : KtCvt.ToList.newTo(keyVal.prop, keyVal.prop.getClazz(), 1);
            while (!in.readEnd()) {
                list.add(keyVal.val.read(merge, keyVal.valAt, in));
            }

            return list;
        }

        in.skipRetr(retr);
        return null;
    }

    public static byte[] toBytes(Object object) throws Exception {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ME.writeObject(object, new ABufOut(out));
        return out.toByteArray();
    }

    public static <T> T fromBytes(byte[] bytes, Class<T> cls) throws Exception {
        return SBinder.ME.to(ME.readObject(new ABufOut.ABufIn(new ByteArrayInputStream(bytes)), cls), cls);
    }
}


展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部