From dc060c2fc28c75d1ae42d07c64288d6703ffa4cd Mon Sep 17 00:00:00 2001 From: free will <2647778488@qq.com> Date: Mon, 29 Mar 2021 20:28:04 +0800 Subject: [PATCH] add test: IdentifierFieldTest --- src/main/java/component/Identifier.java | 57 ++-- .../java/component/IdentifierComponent.java | 13 +- src/main/java/component/IdentifierField.java | 68 ++--- .../java/component/IdentifierWrapper.java | 75 +++-- src/main/java/encoding/Block.java | 280 +++++++++--------- src/main/java/encoding/ElementContainer.java | 3 +- src/main/java/encoding/Encoder.java | 212 ++++++------- .../java/component/IdentifierFieldTest.java | 40 +++ .../java/component/IdentifierWrapperTest.java | 4 +- 9 files changed, 392 insertions(+), 360 deletions(-) create mode 100644 src/test/java/component/IdentifierFieldTest.java diff --git a/src/main/java/component/Identifier.java b/src/main/java/component/Identifier.java index 944961d..0f4b573 100644 --- a/src/main/java/component/Identifier.java +++ b/src/main/java/component/Identifier.java @@ -18,10 +18,9 @@ import java.util.List; * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ class IdentifierComponentContainer { - private List identifierComponents; + private List identifierComponents=new LinkedList<>(); public IdentifierComponentContainer() { - identifierComponents = new LinkedList<>(); } /** @@ -102,10 +101,9 @@ class IdentifierComponentContainer { } public class Identifier implements TlvComponentBase, IEncodingAble { - private IdentifierComponentContainer components; + private IdentifierComponentContainer components=new IdentifierComponentContainer(); public Identifier() { - components = new IdentifierComponentContainer(); } /** @@ -125,7 +123,7 @@ public class Identifier implements TlvComponentBase, IEncodingAble { */ public Identifier(String identifierString) throws ComponentException { components = new IdentifierComponentContainer(); - if(!this.buildIdentifierByString(identifierString)){ + if (!this.buildIdentifierByString(identifierString)) { throw new ComponentException ("Identifier(String): identifierString does not starts with \"/\". "); } @@ -211,41 +209,37 @@ public class Identifier implements TlvComponentBase, IEncodingAble { */ @Override public int wireEncode(Encoder encoder) throws ComponentException { - int totalLength = 0; - // 编码 TLV-VALUE - for (int i = 0; i < components.length(); i++) { - int tmpLen = 0; - tmpLen = components.getElement(i).wireEncode(encoder); + try { + int totalLength = 0; + // 编码 TLV-VALUE + for (int i = components.length()-1; i >=0 ; i--) { + int tmpLen = components.getElement(i).wireEncode(encoder); + if (tmpLen <= 0) { + return -1; + } + totalLength += tmpLen; + } + + // 编码 TLV-LENGTH + int tmpLen = encoder.prependVarNumber(new VlInt(totalLength)); if (tmpLen <= 0) { return -1; } totalLength += tmpLen; - } - // 编码 TLV-LENGTH - int tmpLen = 0; - try { - tmpLen = encoder.prependVarNumber(new VlInt(totalLength)); - } catch (EncoderException e) { - throw new ComponentException("Identifier.wireEncode: " + e.getMessage()); - } - if (tmpLen <= 0) { - return -1; - } - totalLength += tmpLen; + // 编码 TLV-TYPE - // 编码 TLV-TYPE - try { tmpLen = encoder.prependVarNumber(new VlInt(TLV.TlvIdentifier)); + + if (tmpLen <= 0) { + return -1; + } + totalLength += tmpLen; + + return totalLength; } catch (EncoderException e) { throw new ComponentException("Identifier.wireEncode: " + e.getMessage()); } - if (tmpLen <= 0) { - return -1; - } - totalLength += tmpLen; - - return totalLength; } /** @@ -361,9 +355,10 @@ public class Identifier implements TlvComponentBase, IEncodingAble { /** * 标识后面新增一个名称组件 + * * @param component */ - public void append(IdentifierComponent component){ + public void append(IdentifierComponent component) { this.components.addElement(component); } } diff --git a/src/main/java/component/IdentifierComponent.java b/src/main/java/component/IdentifierComponent.java index 407f822..5f969dc 100644 --- a/src/main/java/component/IdentifierComponent.java +++ b/src/main/java/component/IdentifierComponent.java @@ -30,7 +30,7 @@ import java.util.Arrays; // 0x01 非负整数(可以用1、2、4、8个字节表示) // 0x02 任意字节数组 public class IdentifierComponent implements TlvComponentBase, IEncodingAble { - private Block identifierBlock; // IdentifierComponent数据以TLV形式存储下来 + private Block identifierBlock=new Block(); // IdentifierComponent数据以TLV形式存储下来 private byte marker; // 标记 => 用来区分不同类型的 IdentifierComponent private String stringValue; // 如果 Marker == 0x00,则本组件存储一个字符串 private long intValue; // 如果 Marker == 0x01,则本组件存储一个非负整型 @@ -59,7 +59,6 @@ public class IdentifierComponent implements TlvComponentBase, IEncodingAble { } public IdentifierComponent(){ - this.identifierBlock = new Block(); } /** @@ -68,7 +67,6 @@ public class IdentifierComponent implements TlvComponentBase, IEncodingAble { * @param nameComponent */ public IdentifierComponent(String nameComponent) { - this.identifierBlock = new Block(); this.identifierBlock.setType(new VlInt(TLV.TlvIdentifierComponent)); int len=nameComponent.getBytes(StandardCharsets.UTF_8).length; this.identifierBlock.setLength(new VlInt(len + 1)); @@ -86,7 +84,6 @@ public class IdentifierComponent implements TlvComponentBase, IEncodingAble { * @param intValue */ public IdentifierComponent(long intValue) { - this.identifierBlock = new Block(); this.identifierBlock.setType(new VlInt(TLV.TlvIdentifierComponent)); byte[] uint64Array=Encoder.buildNonNegativeIntegerArr(intValue); this.identifierBlock.setLength(new VlInt( uint64Array.length+ 1)); @@ -104,7 +101,6 @@ public class IdentifierComponent implements TlvComponentBase, IEncodingAble { * @param arr */ public IdentifierComponent(byte[] arr) { - this.identifierBlock = new Block(); this.identifierBlock.setType(new VlInt(TLV.TlvIdentifierComponent)); this.identifierBlock.setLength(new VlInt(arr.length + 1)); byte[] value = new byte[arr.length+1]; @@ -135,7 +131,6 @@ public class IdentifierComponent implements TlvComponentBase, IEncodingAble { * @param fragmentNumber */ public void buildFragmentNumberIdentifierComponent(long fragmentNumber){ - this.identifierBlock = new Block(); this.identifierBlock.setType(new VlInt(TLV.TlvIdentifierComponent)); int len=TLV.SizeOfNonNegativeInteger(fragmentNumber) + 1; this.identifierBlock.setLength(new VlInt(len)); @@ -286,7 +281,11 @@ public class IdentifierComponent implements TlvComponentBase, IEncodingAble { */ @Override public int wireEncode(Encoder encoder) throws ComponentException { - return this.identifierBlock.encode(encoder); + try { + return this.identifierBlock.encode(encoder); + } catch (BlockException e) { + throw new ComponentException("IdentifierComponent.wireEncode: "+e.getMessage()); + } } /** diff --git a/src/main/java/component/IdentifierField.java b/src/main/java/component/IdentifierField.java index c90df74..167d577 100644 --- a/src/main/java/component/IdentifierField.java +++ b/src/main/java/component/IdentifierField.java @@ -14,10 +14,9 @@ import java.util.List; * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ class IdentifierContainer { - private List identifierWrappers; + private List identifierWrappers=new LinkedList<>(); public IdentifierContainer() { - identifierWrappers = new LinkedList<>(); } /** @@ -82,10 +81,9 @@ class IdentifierContainer { } public class IdentifierField implements TlvComponentBase, IEncodingAble { - private IdentifierContainer identifiers; + private IdentifierContainer identifiers=new IdentifierContainer(); public IdentifierField() { - identifiers = new IdentifierContainer(); } /** @@ -151,46 +149,44 @@ public class IdentifierField implements TlvComponentBase, IEncodingAble { */ @Override public int wireEncode(Encoder encoder) throws ComponentException { - // 如果标识区不存在标识,则是一个无效的MIN包,直接抛出错误 - if (this.identifiers.length() == 0) { - return 0; - } - int totalLength = 0; - // 编码 TLV-VALUE - // 反向遍历,可以保证解码的时候正向输出 - for (int i = this.identifiers.length() - 1; i >= 0; i--) { - int tmplen = 0; - tmplen = this.identifiers.getElement(i).wireEncode(encoder); + try { + // 如果标识区不存在标识,则是一个无效的MIN包,直接抛出错误 + if (this.identifiers.length() <= 0) { + return -1; + } + int totalLength = 0; + // 编码 TLV-VALUE + // 反向遍历,可以保证解码的时候正向输出 + for (int i = this.identifiers.length() - 1; i >= 0; i--) { + int tmplen = this.identifiers.getElement(i).wireEncode(encoder); + if (tmplen <= 0) { + return -1; + } + totalLength += tmplen; + } + + // 编码 TLV-LENGTH + int tmplen = encoder.prependVarNumber(new VlInt(totalLength)); if (tmplen <= 0) { return -1; } totalLength += tmplen; - } - // 编码 TLV-LENGTH - int tmplen = 0; - try { - tmplen = encoder.prependVarNumber(new VlInt(totalLength)); + // 编码 TLV-LENGTH + try { + tmplen = encoder.prependVarNumber(new VlInt(TLV.TlvIdentifierField)); + } catch (EncoderException e) { + throw new ComponentException("IdentifierField.wireEncode: " + e.getMessage()); + } + if (tmplen <= 0) { + return -1; + } + totalLength += tmplen; + + return totalLength; } catch (EncoderException e) { throw new ComponentException("IdentifierField.wireEncode: " + e.getMessage()); } - if (tmplen <= 0) { - return -1; - } - totalLength += tmplen; - - // 编码 TLV-LENGTH - try { - tmplen = encoder.prependVarNumber(new VlInt(TLV.TlvIdentifierField)); - } catch (EncoderException e) { - throw new ComponentException("IdentifierField.wireEncode: " + e.getMessage()); - } - if (tmplen <= 0) { - return -1; - } - totalLength += tmplen; - - return totalLength; } /** diff --git a/src/main/java/component/IdentifierWrapper.java b/src/main/java/component/IdentifierWrapper.java index 7d1270d..b78d567 100644 --- a/src/main/java/component/IdentifierWrapper.java +++ b/src/main/java/component/IdentifierWrapper.java @@ -10,8 +10,8 @@ import encoding.*; * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ public class IdentifierWrapper implements TlvComponentBase, IEncodingAble { - private Identifier identifier=new Identifier(); - private VlInt tlvType=new VlInt(TLV.TlvInvalid); + private Identifier identifier = new Identifier(); + private VlInt tlvType = new VlInt(TLV.TlvInvalid); public IdentifierWrapper() { } @@ -40,9 +40,13 @@ public class IdentifierWrapper implements TlvComponentBase, IEncodingAble { } } - public IdentifierWrapper(VlInt tlvType,Identifier identifier){ - this.tlvType=tlvType; - this.identifier=identifier; + public IdentifierWrapper(VlInt tlvType, Identifier identifier) throws ComponentException { + if (!TLV.isValidIdentifierType(tlvType)) { + throw new ComponentException("IdentifierWrapper(VlInt tlvType,String identifierString): " + + "tlvType invalid"); + } + this.tlvType = tlvType; + this.identifier = identifier; } /** @@ -96,7 +100,7 @@ public class IdentifierWrapper implements TlvComponentBase, IEncodingAble { + "tlvType invalid"); } this.tlvType = tlvType; - if(!this.identifier.buildIdentifierByBlock(block)){ + if (!this.identifier.buildIdentifierByBlock(block)) { throw new ComponentException ("IdentifierWrapper(VlInt tlvType, Block block): Identifier block is valid"); } @@ -294,43 +298,38 @@ public class IdentifierWrapper implements TlvComponentBase, IEncodingAble { */ @Override public int wireEncode(Encoder encoder) throws ComponentException { - int totalLength = 0; - - // 编码 TLV-VALUE - int tmplen = 0; try { - tmplen = this.identifier.wireEncode(encoder); - } catch (ComponentException e) { - throw new ComponentException("IdentifierWrapper.wireEncode: " + e.getMessage()); - } - if (tmplen <= 0) { - return -1; - } - totalLength += tmplen; + int totalLength = 0; - // 编码 TLV-LENGTH - try { + // 编码 TLV-VALUE + int tmplen = this.identifier.wireEncode(encoder); + if (tmplen <= 0) { + return -1; + } + totalLength += tmplen; + + // 编码 TLV-LENGTH tmplen = encoder.prependVarNumber(new VlInt(totalLength)); - } catch (EncoderException e) { + if (tmplen <= 0) { + return -1; + } + totalLength += tmplen; + + // 编码 TLV-TYPE + try { + tmplen = encoder.prependVarNumber(this.tlvType); + } catch (EncoderException e) { + throw new ComponentException("IdentifierWrapper.wireEncode: " + e.getMessage()); + } + if (tmplen <= 0) { + return -1; + } + totalLength += tmplen; + + return totalLength; + } catch (ComponentException | EncoderException e) { throw new ComponentException("IdentifierWrapper.wireEncode: " + e.getMessage()); } - if (tmplen <= 0) { - return -1; - } - totalLength += tmplen; - - // 编码 TLV-TYPE - try { - tmplen = encoder.prependVarNumber(this.tlvType); - } catch (EncoderException e) { - throw new ComponentException("IdentifierWrapper.wireEncode: " + e.getMessage()); - } - if (tmplen <= 0) { - return -1; - } - totalLength += tmplen; - - return totalLength; } /** diff --git a/src/main/java/encoding/Block.java b/src/main/java/encoding/Block.java index 8be93e9..856c12d 100644 --- a/src/main/java/encoding/Block.java +++ b/src/main/java/encoding/Block.java @@ -12,146 +12,146 @@ import util.ByteHelper; */ public class Block { - private VlInt tlvType; // TLV-TYPE - private VlInt length; // TLV-LENGTH + private VlInt tlvType = new VlInt(TLV.TlvInvalid); // TLV-TYPE + private VlInt length = new VlInt(0); // TLV-LENGTH private byte[] value; // TLV-VALUE - private ElementContainer elements; // TLV-sub-elements + private ElementContainer elements = new ElementContainer(); // TLV-sub-elements private byte[] raw; // TLV编码后的字节数组 - public Block(){ - this.tlvType=new VlInt(TLV.TlvInvalid); - this.length=new VlInt(0); - this.elements=new ElementContainer(); + public Block() { } - public Block(byte[] buffer,boolean verifyLength) throws BlockException { - if(buffer.length==0){ + public Block(byte[] buffer, boolean verifyLength) throws BlockException { + if (buffer.length == 0) { throw new BlockException("createBlockByBuffer: buffer.length==0"); } // 读取type - VlInt tlvType= null; + VlInt tlvType = null; try { - tlvType = TLV.readType(buffer,new VlInt(0)); + tlvType = TLV.readType(buffer, new VlInt(0)); } catch (TLVException e) { - throw new BlockException("createBlockByBuffer: tlvType read error & "+e.getMessage()); + throw new BlockException("createBlockByBuffer: tlvType read error & " + e.getMessage()); } - if(tlvType==null){ + if (tlvType == null) { throw new BlockException("createBlockByBuffer: tlvType read error"); } // 读取length - VlInt tlvLength= null; + VlInt tlvLength = null; try { - tlvLength = TLV.readVarNumber(buffer,new VlInt(tlvType.size())); + tlvLength = TLV.readVarNumber(buffer, new VlInt(tlvType.size())); } catch (TLVException e) { - throw new BlockException("createBlockByBuffer: tlvLength read error"+e.getMessage()); + throw new BlockException("createBlockByBuffer: tlvLength read error" + e.getMessage()); } - if(tlvLength==null){ + if (tlvLength == null) { throw new BlockException("createBlockByBuffer: tlvLength read error"); } - this.buildBlockByTypeLengthBuffer(tlvType,tlvLength, - ByteHelper.getLenBytes(buffer,new VlInt(tlvType.size()+tlvLength.size()), - buffer.length-(tlvType.size()+tlvLength.size())),verifyLength); + this.buildBlockByTypeLengthBuffer(tlvType, tlvLength, + ByteHelper.getLenBytes(buffer, new VlInt(tlvType.size() + tlvLength.size()), + buffer.length - (tlvType.size() + tlvLength.size())), verifyLength); } /** * 从一个包含TLV的字节数组中构造一个 Block 对象 + * * @param buffer * @param verifyLength 是否要验证TLV的长度是否匹配,如果true, * 则会对比解析到的 TLV-LENGTH 与 TLV-VALUE的实际长度是否匹配 * @return */ - public static Block createBlockByBuffer(byte[] buffer,boolean verifyLength) throws BlockException { - return new Block(buffer,verifyLength); + public static Block createBlockByBuffer(byte[] buffer, boolean verifyLength) throws BlockException { + return new Block(buffer, verifyLength); } /** * 传入 T、L、V 构造一个 TLV Block + * * @param tlvType * @param tlvLength * @param buffer * @param verifyLength * @return */ - public static Block createBlockByTypeLengthBuffer(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength) throws BlockException { - return new Block(tlvType,tlvLength,buffer,verifyLength); + public static Block createBlockByTypeLengthBuffer(VlInt tlvType, VlInt tlvLength, byte[] buffer, boolean verifyLength) throws BlockException { + return new Block(tlvType, tlvLength, buffer, verifyLength); } /** * 构造函数 + * * @param tlvType * @param tlvLength * @param buffer * @param verifyLength */ - public Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength) throws BlockException{ - this.buildBlockByTypeLengthBuffer(tlvType,tlvLength,buffer,verifyLength); + public Block(VlInt tlvType, VlInt tlvLength, byte[] buffer, boolean verifyLength) throws BlockException { + this.buildBlockByTypeLengthBuffer(tlvType, tlvLength, buffer, verifyLength); } - public Block(Block block){ - this.tlvType=block.tlvType; - this.length=block.length; - this.value=block.value; - this.elements=block.elements; - this.raw=block.raw; + public Block(Block block) { + this.tlvType = block.tlvType; + this.length = block.length; + this.value = block.value; + this.elements = block.elements; + this.raw = block.raw; } - public void buildBlockByTypeLengthBuffer(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength) throws BlockException { - this.tlvType=tlvType; - this.length=tlvLength; - this.elements=new ElementContainer(); + public void buildBlockByTypeLengthBuffer(VlInt tlvType, VlInt tlvLength, byte[] buffer, boolean verifyLength) throws BlockException { + this.tlvType = tlvType; + this.length = tlvLength; + this.elements = new ElementContainer(); // 检查长度是否正确 - if(verifyLength && (!this.length.isEqual(buffer.length))){ + if (verifyLength && (!this.length.isEqual(buffer.length))) { throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): invalid length."); } // 设置 Raw - Encoder encoder=new Encoder(); - boolean resetBool= false; + Encoder encoder = new Encoder(); + boolean resetBool = false; try { - resetBool = encoder.encoderReset(new SizeT(tlvType.size()+tlvLength.size()+buffer.length),new SizeT(0)); + resetBool = encoder.encoderReset(new SizeT(tlvType.size() + tlvLength.size() + buffer.length), new SizeT(0)); } catch (EncoderException e) { throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): encoderReset error" - +e.getMessage()); + + e.getMessage()); } - if(!resetBool){ + if (!resetBool) { throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): encoderReset error"); } try { - if(encoder.prependByteArray(buffer,new SizeT(buffer.length))<0){ + if (encoder.prependByteArray(buffer, new SizeT(buffer.length)) < 0) { throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): prepenndByteArray buffer error"); } } catch (EncoderException e) { throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): prepenndByteArray buffer error" - +e.getMessage()); + + e.getMessage()); } try { - if(encoder.prependVarNumber(tlvLength)<=0){ + if (encoder.prependVarNumber(tlvLength) <= 0) { throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): prependVarNumber tlvLength error"); } } catch (EncoderException e) { throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): prependVarNumber tlvLength error" - +e.getMessage()); + + e.getMessage()); } try { - if(encoder.prependVarNumber(tlvType)<=0){ + if (encoder.prependVarNumber(tlvType) <= 0) { throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): prependVarNumber tlvType error"); } } catch (EncoderException e) { throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): prependVarNumber tlvType error" - +e.getMessage()); + + e.getMessage()); } - byte[] encodedBuffer=encoder.getBuffer(); - if(encodedBuffer==null){ + byte[] encodedBuffer = encoder.getBuffer(); + if (encodedBuffer == null) { throw new BlockException("Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength): encoder.getBuffer error"); } - this.raw=encodedBuffer; + this.raw = encodedBuffer; // 设置value - this.value=buffer; + this.value = buffer; } public VlInt getType() { @@ -184,29 +184,32 @@ public class Block { /** * 整个TLV编码后的大小,包含T和L + * * @return */ - public SizeT Size(){ - if(!this.isValid()){ + public SizeT Size() { + if (!this.isValid()) { return null; } - return new SizeT(this.tlvType.size()+this.length.size()+this.value.length); + return new SizeT(this.tlvType.size() + this.length.size() + this.value.length); } /** * 判断当前的 Block 对象是否含有 value + * * @return */ - public boolean hasValue(){ - return this.value.length!=0; + public boolean hasValue() { + return this.value.length != 0; } /** * 判断当前的 Block 对象是否含有 raw数组 + * * @return */ - public boolean hasRaw(){ - return this.raw.length!=0; + public boolean hasRaw() { + return (this.raw != null) && (this.raw.length != 0); } // ************** Sub-Elements ************** @@ -214,86 +217,89 @@ public class Block { /** * 判断当前 TLV Block 是否包含子 TLV * 1. 每次通过 CreateBlockBy* 系列工厂方法构造出Block之后,需要手动调用 ParseSubElements 方法, - * 才会去解析一级子TLV + * 才会去解析一级子TLV + * * @return */ - public boolean hasSubElement(){ - return this.elements.length()!=0; + public boolean hasSubElement() { + return this.elements.length() != 0; } /** * 获取所有的一级子TLV Block - * * 1. 每次通过 CreateBlockBy* 系列工厂方法构造出Block之后,需要手动调用 ParseSubElements 方法, - * * 才会去解析一级子TLV + * * 1. 每次通过 CreateBlockBy* 系列工厂方法构造出Block之后,需要手动调用 ParseSubElements 方法, + * * 才会去解析一级子TLV + * * @return */ - public ElementContainer getSubElements(){ + public ElementContainer getSubElements() { return this.elements; } /** * 从 value 字节数组中解析出所有的一级子 TLV Block - * 1. 这要求这个TLV确实存在嵌套的子TLV,或者为空; - * 2. 如果TLV的value不为空,且不存在嵌套的子TLV,则会抛出错误 + * 1. 这要求这个TLV确实存在嵌套的子TLV,或者为空; + * 2. 如果TLV的value不为空,且不存在嵌套的子TLV,则会抛出错误 + * * @return */ public boolean parseSubElements() throws BlockException { - if((this.value.length==0)||this.elements.length()!=0){ + if ((this.value.length == 0) || this.elements.length() != 0) { return true; } // 循环解析所有的一级子TLV for (int start = 0; start < this.value.length; ) { // 读取 TLV-TYPE - VlInt tlvType= null; + VlInt tlvType = null; try { - tlvType = TLV.readType(this.value,new VlInt(start)); + tlvType = TLV.readType(this.value, new VlInt(start)); } catch (TLVException e) { - throw new BlockException("parseSubElements"+e.getMessage()); + throw new BlockException("parseSubElements" + e.getMessage()); } - if(tlvType==null){ + if (tlvType == null) { this.clearElements(); return false; } - start+=tlvType.size(); + start += tlvType.size(); // 读取 TLV-LENGTH - VlInt tlvLength= null; + VlInt tlvLength = null; try { - tlvLength = TLV.readVarNumber(this.value,new VlInt(start)); + tlvLength = TLV.readVarNumber(this.value, new VlInt(start)); } catch (TLVException e) { - throw new BlockException("parseSubElements"+e.getMessage()); + throw new BlockException("parseSubElements" + e.getMessage()); } - if(tlvType==null){ + if (tlvType == null) { this.clearElements(); return false; } - start+=tlvLength.size(); + start += tlvLength.size(); // 检查 buffer 中是否有足够的字节 - if(tlvLength.add(start)>this.value.length){ + if (tlvLength.add(start) > this.value.length) { this.clearElements(); return false; } // 创建一个子 TLV Block 并添加到elements当中 - byte[] subBlockValue= new byte[0]; + byte[] subBlockValue = new byte[0]; try { subBlockValue = new byte[tlvLength.getVlIntValue2Int()]; - System.arraycopy(this.value,start,subBlockValue,0,tlvLength.getVlIntValue2Int()); - Block block= null; + System.arraycopy(this.value, start, subBlockValue, 0, tlvLength.getVlIntValue2Int()); + Block block = null; try { - block = createBlockByTypeLengthBuffer(tlvType,tlvLength,subBlockValue,true); + block = createBlockByTypeLengthBuffer(tlvType, tlvLength, subBlockValue, true); } catch (BlockException e) { return false; } - if(block==null){ + if (block == null) { return false; } this.addElement(block); - start+=tlvLength.getVlIntValue2Int(); + start += tlvLength.getVlIntValue2Int(); } catch (VlIntException e) { - return false; + return false; } } return true; @@ -302,6 +308,7 @@ public class Block { /** * 从 elements 中找到第一个指定type的子TLV + * * @param tlvType * @return */ @@ -311,101 +318,92 @@ public class Block { /** * 移除所有指定type的子tlv + * * @param tlvType */ - public void removeElements(VlInt tlvType){ + public void removeElements(VlInt tlvType) { this.elements.removeElements(tlvType); } /** * 往 elements 中添加一个子tlv + * * @param block */ - public void addElement(Block block){ + public void addElement(Block block) { this.elements.addElement(block); } /** * 清除 elements 中所有的子TLV */ - public void clearElements(){ + public void clearElements() { this.elements.clear(); } /** * 判断是否有效 + * * @return */ - public boolean isValid(){ + public boolean isValid() { // return this.tlvType.isEqual(TLV.TlvInvalid); return !this.tlvType.isEqual(TLV.TlvInvalid); } /** * 将当前的 TLV Block 编码成字节数组,存放在 raw 当中 + * * @param encoder * @return */ - public int encode(Encoder encoder) throws ComponentException { - // 如果已经有raw,则说明编码过,或者是解码而来的,不用在此Encode - if(this.hasRaw()){ - try { - return encoder.prependByteArray(this.raw,new SizeT(this.raw.length)); - } catch (EncoderException e) { - throw new ComponentException("encode: "+e.getMessage()); + public int encode(Encoder encoder) throws BlockException { + try { + // 如果已经有raw,则说明编码过,或者是解码而来的,不用在此Encode + if (this.hasRaw()) { + return encoder.prependByteArray(this.raw, new SizeT(this.raw.length)); } - } - int len=0; + int len = 0; - // 编码 TLV-VALUE - if(this.hasValue()){ - // 如果设置了 value ,则直接使用 - int tmplen= 0; - try { - tmplen = encoder.appendByteArray(this.value,new SizeT(this.value.length)); - } catch (EncoderException e) { - throw new ComponentException("encode: "+e.getMessage()); - } - if(tmplen<=0){ - return -1; - } - len+=tmplen; - }else{ - // 如果 value 为空,则看 elements 中有没有子TLV Block,有则编码后插入 - for(Block subBlock:this.elements.getElements()){ - int tmplen=subBlock.encode(encoder); - if(tmplen<=0){ + // 编码 TLV-VALUE + if (this.hasValue()) { + // 如果设置了 value ,则直接使用 + int tmplen = encoder.prependByteArray(this.value, new SizeT(this.value.length)); + if (tmplen <= 0) { return -1; } - len+=tmplen; + len += tmplen; + } else { + // 如果 value 为空,则看 elements 中有没有子TLV Block,有则编码后插入 + for (Block subBlock : this.elements.getElements()) { + int tmplen = subBlock.encode(encoder); + if (tmplen <= 0) { + return -1; + } + len += tmplen; + } } - } - // 编码 TLV-LENGTH - int tmplen= 0; - try { - tmplen = encoder.prependVarNumber(new VlInt(len)); + // 编码 TLV-LENGTH + int tmplen = encoder.prependVarNumber(new VlInt(len)); + + if (tmplen <= 0) { + return -1; + } + len += tmplen; + + // 编码 TLV-TYPE + tmplen = encoder.prependVarNumber(this.tlvType); + if (tmplen <= 0) { + return -1; + } + len += tmplen; + + return len; } catch (EncoderException e) { - throw new ComponentException("encode: "+e.getMessage()); + throw new BlockException("encode: " + e.getMessage()); } - if(tmplen<=0){ - return -1; - } - len+=tmplen; - - // 编码 TLV-TYPE - try { - tmplen=encoder.prependVarNumber(this.tlvType); - } catch (EncoderException e) { - throw new ComponentException("encode: "+e.getMessage()); - } - if(tmplen<=0){ - return -1; - } - len+=tmplen; - - return len; } } diff --git a/src/main/java/encoding/ElementContainer.java b/src/main/java/encoding/ElementContainer.java index 63a29df..f2f4f2c 100644 --- a/src/main/java/encoding/ElementContainer.java +++ b/src/main/java/encoding/ElementContainer.java @@ -14,9 +14,8 @@ import java.util.List; */ // TLV 组件容器 public class ElementContainer{ - private List elementContainer; + private List elementContainer = new LinkedList<>(); public ElementContainer(){ - elementContainer = new LinkedList<>(); } /** diff --git a/src/main/java/encoding/Encoder.java b/src/main/java/encoding/Encoder.java index eb5dc50..77d8119 100644 --- a/src/main/java/encoding/Encoder.java +++ b/src/main/java/encoding/Encoder.java @@ -16,78 +16,81 @@ public class Encoder { public boolean isEstimator;// 是否仅测量编码后的长度,而不实际进行编码 public SizeT totalReserve; // 编码缓存数组的大小 - public static final int MaxPacketSize=8800; + public static final int MaxPacketSize = 8800; /** * 编码测量初始化 - * @Description: - * 1. 一旦调用这个函数进行初始化,则调用所有的编码函数只会测量编码后的长度,不会执行实际的编码 + * + * @Description: 1. 一旦调用这个函数进行初始化,则调用所有的编码函数只会测量编码后的长度,不会执行实际的编码 */ - public void estimatorReset(){ - this.left=0; - this.right=1; - this.isInitial=true; - this.isEstimator=true; - this.totalReserve=new SizeT(Long.MAX_VALUE); + public void estimatorReset() { + this.left = 0; + this.right = 1; + this.isInitial = true; + this.isEstimator = true; + this.totalReserve = new SizeT(Long.MAX_VALUE); } /** * 编码初始化 - * @Description: - * @param totalReserve 总的存储编码结果的数组长度 - * @param reserveFromBack 默认情况下,左右指针都指向数组的最右侧,表示totalReserve指定的所有空间都是预留给 Prepend* 操作的 - * reserveFromBack 可以指定需要预留多少空间给 Append*操作 + * + * @param totalReserve 总的存储编码结果的数组长度 + * @param reserveFromBack 默认情况下,左右指针都指向数组的最右侧,表示totalReserve指定的所有空间都是预留给 Prepend* 操作的 + * reserveFromBack 可以指定需要预留多少空间给 Append*操作 + * @Description: */ - public boolean encoderReset(SizeT totalReserve,SizeT reserveFromBack) throws EncoderException{ - if(reserveFromBack.compareTo(totalReserve)>0){ + public boolean encoderReset(SizeT totalReserve, SizeT reserveFromBack) throws EncoderException { + if (reserveFromBack.compareTo(totalReserve) > 0) { throw new EncoderException("encoderReset: reserveFromBack > totalReserve"); } - this.isInitial=true; - this.isEstimator=false; - this.totalReserve=totalReserve; - int len=0; + this.isInitial = true; + this.isEstimator = false; + this.totalReserve = totalReserve; + int len = 0; try { - len=totalReserve.getVlIntValue2Int(); + len = totalReserve.getVlIntValue2Int(); } catch (VlIntException e) { - throw new EncoderException("encoderReset: "+e.getMessage()); + throw new EncoderException("encoderReset: " + e.getMessage()); } - this.buffer=new byte[len]; //todo: 特殊情况下,可能越界。 - this.left= (int) (totalReserve.subtract(reserveFromBack)-1);//todo: 特殊情况下,可能越界。 - this.right= (int) totalReserve.subtract(reserveFromBack);//todo: 特殊情况下,可能越界。 + this.buffer = new byte[len]; //todo: 特殊情况下,可能越界。 + this.left = (int) (totalReserve.subtract(reserveFromBack) - 1);//todo: 特殊情况下,可能越界。 + this.right = (int) totalReserve.subtract(reserveFromBack);//todo: 特殊情况下,可能越界。 return true; } /** * 判断是否为空 + * * @return */ - public boolean empty(){ - return (this.left+1)>=this.right; + public boolean empty() { + return (this.left + 1) >= this.right; } /** * 编码后的大小 + * * @return */ - public SizeT size(){ - return new SizeT(this.right-this.left-1); + public SizeT size() { + return new SizeT(this.right - this.left - 1); } /** * 在每个操作之前进行有效性检查 - * @Description: - * 1. 首先检查 Encoder 实例有没有初始化,没有初始化则返回错误; - * 2. 然后检查预计新增 size 个字节,会不会超出最大包限制,超出则返回错误; - * 3. 否则返回 nil + * * @param size * @return + * @Description: 1. 首先检查 Encoder 实例有没有初始化,没有初始化则返回错误; + * 2. 然后检查预计新增 size 个字节,会不会超出最大包限制,超出则返回错误; + * 3. 否则返回 nil */ - public boolean check(SizeT size){ - if(!this.isInitial){ + public boolean check(SizeT size) { + if (!this.isInitial) { return false; } - if(this.totalReserve.compareTo(this.size().add(size))<0){ + if (this.totalReserve.compareTo(this.size().add(size)) < 0) { return false; } return true; @@ -95,19 +98,20 @@ public class Encoder { /** * Prepend a byte + * * @param value * @return 返回成功插入的字节数 */ - public int prependByte(byte value){ - if(this.isEstimator){ + public int prependByte(byte value) { + if (this.isEstimator) { this.left--; return 1; } - if(check(new SizeT(1))){ - this.buffer[this.left]=value; + if (check(new SizeT(1))) { + this.buffer[this.left] = value; this.left--; return 1; - }else{ + } else { return -1; } } @@ -116,16 +120,16 @@ public class Encoder { * @param value * @return 返回插入成功的字节数 */ - public int appendByte(byte value){ - if(this.isEstimator){ + public int appendByte(byte value) { + if (this.isEstimator) { this.right++; return 1; } - if(check(new SizeT(1))){ - this.buffer[this.right]=value; + if (check(new SizeT(1))) { + this.buffer[this.right] = value; this.right++; return 1; - }else{ + } else { return -1; } } @@ -134,17 +138,18 @@ public class Encoder { /** * 编码一个非负整数到一个数组当中 * todo: 越界问题 + * * @param uint64 * @return */ - public static byte[] buildNonNegativeIntegerArr(long uint64){ - VlInt vlInt=new VlInt(uint64); - int len=vlInt.getVlIntBytes().length; - if(uint64<=255){ + public static byte[] buildNonNegativeIntegerArr(long uint64) { + VlInt vlInt = new VlInt(uint64); + int len = vlInt.getVlIntBytes().length; + if (uint64 <= 255) { return new byte[]{(byte) uint64}; - }else { + } else { byte[] res = new byte[len - 1]; - System.arraycopy(vlInt.getVlIntBytes(),1,res,0,len-1); + System.arraycopy(vlInt.getVlIntBytes(), 1, res, 0, len - 1); return res; } } @@ -152,23 +157,25 @@ public class Encoder { /** * 在前向插入一个非负整数,最大为 uint64::Max * todo: 越界问题 + * * @param uint64_value * @return */ public int prependNonNegativeInteger(long uint64_value) throws EncoderException { - byte[] bytes=buildNonNegativeIntegerArr(uint64_value); - return this.prependByteArray(bytes,new SizeT(bytes.length)); + byte[] bytes = buildNonNegativeIntegerArr(uint64_value); + return this.prependByteArray(bytes, new SizeT(bytes.length)); } /** * 在后向插入一个非负整数,最大为 uint64::Max * todo: 越界问题 + * * @param uint64_value * @return */ public int appendNonNegativeInteger(long uint64_value) throws EncoderException { - byte[] bytes=buildNonNegativeIntegerArr(uint64_value); - return this.appendByteArray(bytes,new SizeT(bytes.length)); + byte[] bytes = buildNonNegativeIntegerArr(uint64_value); + return this.appendByteArray(bytes, new SizeT(bytes.length)); } /** @@ -176,27 +183,27 @@ public class Encoder { * @param size * @return 返回插入成功的字节数 */ - public int prependByteArray(byte[] array,SizeT size) throws EncoderException { - if(check(size)&&(size.compareTo(array.length)<=0)){ - if(this.isEstimator){ - this.left-=array.length; + public int prependByteArray(byte[] array, SizeT size) throws EncoderException { + if (check(size) && (size.compareTo(array.length) <= 0)) { + if (this.isEstimator) { + this.left -= array.length; try { return size.getVlIntValue2Int(); } catch (VlIntException e) { - throw new EncoderException("prependByteArray: "+e.getMessage()); + throw new EncoderException("prependByteArray: " + e.getMessage()); } - }else{ + } else { try { - System.arraycopy(array,0,this.buffer, - this.left-size.getVlIntValue2Int()+1,size.getVlIntValue2Int()); + System.arraycopy(array, 0, this.buffer, + this.left - size.getVlIntValue2Int() + 1, size.getVlIntValue2Int()); } catch (VlIntException e) { - throw new EncoderException("prependByteArray: "+e.getMessage()); + throw new EncoderException("prependByteArray: " + e.getMessage()); } - this.left-=array.length; + this.left -= array.length; try { return size.getVlIntValue2Int(); } catch (VlIntException e) { - throw new EncoderException("prependByteArray: "+e.getMessage()); + throw new EncoderException("prependByteArray: " + e.getMessage()); } } } @@ -208,115 +215,114 @@ public class Encoder { * @param size * @return 返回插入成功的字节数 */ - public int appendByteArray(byte[] array,SizeT size) throws EncoderException { - if(check(size)&&(size.compareTo(array.length)<=0)){ - if(this.isEstimator){ - this.right+=array.length; - try { + public int appendByteArray(byte[] array, SizeT size) throws EncoderException { + try { + if (check(size) && (size.compareTo(array.length) <= 0)) { + if (this.isEstimator) { + this.right += array.length; return size.getVlIntValue2Int(); - } catch (VlIntException e) { - throw new EncoderException("appendByteArray: "+e.getMessage()); - } - }else{ - try { - System.arraycopy(array,0,this.buffer, - this.right,size.getVlIntValue2Int()); - } catch (VlIntException e) { - throw new EncoderException("appendByteArray: "+e.getMessage()); - } - this.right+=array.length; - try { + } else { + System.arraycopy(array, 0, this.buffer, + this.right, size.getVlIntValue2Int()); + this.right += array.length; return size.getVlIntValue2Int(); - } catch (VlIntException e) { - throw new EncoderException("appendByteArray: "+e.getMessage()); } } + return -1; + } catch (VlIntException e) { + throw new EncoderException("appendByteArray: " + e.getMessage()); } - return -1; } /** * 在前向插入一个可变长度的数字 + * * @param varNumber * @return */ public int prependVarNumber(VlInt varNumber) throws EncoderException { - return this.prependByteArray(varNumber.getVlIntBytes(),new SizeT(varNumber.size())); + return this.prependByteArray(varNumber.getVlIntBytes(), new SizeT(varNumber.size())); } /** * 在后向插入一个可变长度的数字 + * * @param varNumber * @return */ public int appendVarNumber(VlInt varNumber) throws EncoderException { - return this.appendByteArray(varNumber.getVlIntBytes(),new SizeT(varNumber.size())); + return this.appendByteArray(varNumber.getVlIntBytes(), new SizeT(varNumber.size())); } //todo: 在前向&后向插入一个非负整数 /** * 根据TLV-TYPE和一个字节数组,在前向插入一个 TLV Block + * * @param tlvType * @param array * @param size * @return */ - public int prependByteArrayBlock(VlInt tlvType,byte[] array,SizeT size) throws EncoderException { - int totalLength=this.prependByteArray(array,size); - totalLength+=this.prependVarNumber(new VlInt(size)); - totalLength+=this.prependVarNumber(tlvType); + public int prependByteArrayBlock(VlInt tlvType, byte[] array, SizeT size) throws EncoderException { + int totalLength = this.prependByteArray(array, size); + totalLength += this.prependVarNumber(new VlInt(size)); + totalLength += this.prependVarNumber(tlvType); return totalLength; } /** * 根据TLV-TYPE和一个字节数组,在后向插入一个 TLV Block + * * @param tlvType * @param array * @param size * @return */ - public int appendByteArrayBlock(VlInt tlvType,byte[] array,SizeT size) throws EncoderException { - int totalLength=0; + public int appendByteArrayBlock(VlInt tlvType, byte[] array, SizeT size) throws EncoderException { + int totalLength = 0; // Append TLV-TYPE - totalLength+=this.appendVarNumber(tlvType); + totalLength += this.appendVarNumber(tlvType); // Append TLV-LENGTH - totalLength+=this.appendVarNumber(new VlInt(size)); + totalLength += this.appendVarNumber(new VlInt(size)); // Append TLV-VALUE - totalLength+=this.appendByteArray(array,size); + totalLength += this.appendByteArray(array, size); return totalLength; } /** * 在前向插入一个 TLV Block + * * @param block * @return */ public int prependBlock(Block block) throws EncoderException { - return this.prependByteArrayBlock(block.getType(),block.getValue(),new SizeT(block.getLength())); + return this.prependByteArrayBlock(block.getType(), block.getValue(), new SizeT(block.getLength())); } /** * 在后向插入一个 TLV Block + * * @param block * @return */ public int appendBlock(Block block) throws EncoderException { - return this.appendByteArrayBlock(block.getType(),block.getValue(),new SizeT(block.getLength())); + return this.appendByteArrayBlock(block.getType(), block.getValue(), new SizeT(block.getLength())); } /** * 获取编码后的字节数组 + * * @return */ public byte[] getBuffer() { - if((!this.isInitial)||this.isEstimator){ + if ((!this.isInitial) || this.isEstimator) { return null; } - int len=this.right-this.left-1; - byte[] res=new byte[len]; - System.arraycopy(this.buffer,this.left+1,res,0,len); + int len = this.right - this.left - 1; + byte[] res = new byte[len]; + System.arraycopy(this.buffer, this.left + 1, res, 0, len); return res; } } diff --git a/src/test/java/component/IdentifierFieldTest.java b/src/test/java/component/IdentifierFieldTest.java new file mode 100644 index 0000000..a0031e9 --- /dev/null +++ b/src/test/java/component/IdentifierFieldTest.java @@ -0,0 +1,40 @@ +package component; + +import encoding.*; +import org.junit.Test; + +/* + * @Author: Wang Feng + * @Description: + * @Version: 1.0.0 + * @Date: 17:23 2021/3/29 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class IdentifierFieldTest { + @Test + public void TestIdentifierField_WireEncode() throws ComponentException, EncoderException, BlockException { + IdentifierWrapper wrapper=new IdentifierWrapper(). + createCommonIdentifierByString("/min/pku/sz"); + IdentifierWrapper wrapper1=new IdentifierWrapper(new VlInt(105),"/install/mnfd"); + IdentifierWrapper wrapper2=new IdentifierWrapper(new VlInt(106),"/1"); + IdentifierField field=new IdentifierField(); + field.addIdentifier(wrapper); + field.addIdentifier(wrapper1); + field.addIdentifier(wrapper2); + for (int i = 0; i < field.getIdentifiers().length(); i++) { + System.out.println(field.getIdentifiers().getElement(i).toUri()); + } + + Encoder encoder=new Encoder(); + encoder.encoderReset(new SizeT(Encoder.MaxPacketSize),new SizeT(0)); + field.wireEncode(encoder); + + byte[] buf=encoder.getBuffer(); + Block block=new Block(buf,false); + IdentifierField field1=new IdentifierField(); + System.out.println(field1.wireDecode(block)); + for (int i = 0; i < field1.getIdentifiers().length(); i++) { + System.out.println(field1.getIdentifiers().getElement(i).toUri()); + } + } +} diff --git a/src/test/java/component/IdentifierWrapperTest.java b/src/test/java/component/IdentifierWrapperTest.java index 7abfbb9..60341b8 100644 --- a/src/test/java/component/IdentifierWrapperTest.java +++ b/src/test/java/component/IdentifierWrapperTest.java @@ -162,9 +162,9 @@ public class IdentifierWrapperTest { @Test public void TestCreateIdentifierWrapperByTypeAndIdentifier() throws ComponentException { Identifier identifier=new Identifier("/min/pku/王"); - for (int i = 100; i < 200; i++) { + for (int i = 199; i >0; i--) { IdentifierWrapper got=new IdentifierWrapper(new VlInt(i),identifier); - System.out.println(got.toUri()); + System.out.println(i+":"+got.toUri()); } } }