net.dongliu.prettypb.runtime.ProtoBufDecoder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of prettypb-runtime Show documentation
Show all versions of prettypb-runtime Show documentation
Prettypb serialization runtime
package net.dongliu.prettypb.runtime;
import net.dongliu.prettypb.runtime.code.ProtoFieldInfo;
import net.dongliu.prettypb.runtime.code.ProtoInfo;
import net.dongliu.prettypb.runtime.code.ProtoBufReader;
import net.dongliu.prettypb.runtime.exception.IllegalBeanException;
import net.dongliu.prettypb.runtime.exception.IllegalDataException;
import net.dongliu.prettypb.runtime.exception.ProtoDeSerializeException;
import net.dongliu.prettypb.runtime.include.Extendable;
import net.dongliu.prettypb.runtime.include.ExtensionField;
import net.dongliu.prettypb.runtime.include.ProtoBean;
import net.dongliu.prettypb.runtime.utils.BeanParser;
import net.dongliu.prettypb.runtime.utils.ExtensionFieldUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* protobuf decoder
*
* @author Dong Liu
*/
public class ProtoBufDecoder {
private ProtoBufReader protoBufReader;
private ProtoBufDecoder(InputStream in) {
protoBufReader = new ProtoBufReader(in);
}
/**
* deSerialize value from byte array
*/
public static T fromBytes(Class clazz, byte[] bytes) {
try (InputStream in = new ByteArrayInputStream(bytes)) {
return fromStream(clazz, in);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* deSerialize value from byte array
*/
public static T fromBytes(Class clazz, byte[] bytes, int offset, int len) {
try (InputStream in = new ByteArrayInputStream(bytes, offset, len)) {
return fromStream(clazz, in);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* deSerialize value from byte array
*/
public static T fromBytes(Class clazz, byte[] bytes,
ExtensionRegistry extensionRegistry) {
try (InputStream in = new ByteArrayInputStream(bytes)) {
return fromStream(clazz, in, extensionRegistry);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* deSerialize value from byte array
*/
public static T fromBytes(Class clazz, byte[] bytes, int offset, int len,
ExtensionRegistry extensionRegistry) {
try (InputStream in = new ByteArrayInputStream(bytes, offset, len)) {
return fromStream(clazz, in, extensionRegistry);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* deSerialize value from input stream
*
* @throws IOException
*/
public static T fromStream(Class clazz, InputStream in) throws IOException {
return fromStream(clazz, in, null);
}
/**
* deSerialize value from input stream
*
* @throws IOException
*/
public static T fromStream(Class clazz, InputStream in,
ExtensionRegistry extensionRegistry) throws IOException {
ProtoBufDecoder protoBufDecoder = new ProtoBufDecoder(in);
try {
return protoBufDecoder.readMessage(clazz, extensionRegistry);
} catch (IllegalBeanException | IllegalAccessException | InstantiationException
| IllegalDataException e) {
throw new ProtoDeSerializeException(e);
}
}
private T readMessage(Class clazz, ExtensionRegistry extensionRegistry)
throws IOException, IllegalBeanException, IllegalAccessException,
InstantiationException, IllegalDataException {
ProtoInfo protoInfo = BeanParser.getProtoInfo(clazz);
T bean = clazz.newInstance();
boolean extend = Extendable.class.isAssignableFrom(clazz);
while (true) {
int[] tag = protoBufReader.decodeTag();
if (tag == null) {
break;
}
int wireType = tag[0];
int idx = tag[1];
deSerializeField(clazz, extensionRegistry, protoInfo, bean, extend, wireType, idx);
}
// check required field
for (ProtoFieldInfo info : protoInfo.getProtoFieldInfos()) {
if (info.required() && !info.hasDefault() && !info.hasField(bean)) {
throw new IllegalDataException("Required field not exists, " + "bean:"
+ clazz.getName() + ", field:" + info.getName());
}
}
return bean;
}
private void deSerializeField(Class clazz, ExtensionRegistry extensionRegistry,
ProtoInfo protoInfo, T bean, boolean extend,
int wireType, int idx)
throws IOException, IllegalDataException {
ProtoFieldInfo protoFieldInfo = protoInfo.getProtoFieldInfo(idx);
if (protoFieldInfo != null) {
// bean field
try {
protoFieldInfo.deSerializeField(bean, protoBufReader, extensionRegistry);
} catch (ProtoDeSerializeException e) {
throw e;
} catch (IllegalAccessException | IllegalDataException | RuntimeException e) {
throw new ProtoDeSerializeException("DeSerialize field failed,bean:"
+ clazz.getName() + ", field:" + protoFieldInfo.getName(), e);
}
} else if (extend) {
Extendable extendable = (Extendable) bean;
if (!extendable.tagInExtensions(idx)) {
// just ignore this field
protoBufReader.skip(wireType);
}
if (extensionRegistry != null) {
ProtoBean protoBean = clazz.getAnnotation(ProtoBean.class);
ExtensionField