credibledoc / credible-doc

Libraries and utilities for creation and maintaining of documents based on generated content
Apache License 2.0
14 stars 6 forks source link

HexBodyPacker about =/D #16

Closed wangbo131535 closed 1 year ago

wangbo131535 commented 1 year ago

About how HexBodyPacker pack =/D ishandled]

EX:7612000890000123D25121011111199911111

D:D F:4 and Track 2 data is 37length ,There is the letter D,length is singular

Expected reply:wang131535@163.com

KyryloSemenko commented 1 year ago

When you need to pack or unpack track2 into bytes using this library, you can proceed as follows:

    private FieldBuilder defineMessageStructure() {
        return FieldBuilder.builder(MsgFieldType.VAL)
            .defineName("Track2")
            .defineLen(37)

            .createChild(MsgFieldType.VAL)
            .defineName("PAN")
            .defineLen(16)
            .defineBodyPacker(AsciiBodyPacker.getInstance())

            .cloneToSibling()
            .defineName("Separator")
            .defineLen(1)

            .cloneToSibling()
            .defineName("Expired")
            .defineLen(4)

            .cloneToSibling()
            .defineName("OtherData")
            .defineLen(16)

            .jumpToRoot()
            .validateStructure();
    }

    @Test
    public void unpackAndPackTest() {
        // unpack from bytes
        MsgField msgField = defineMessageStructure().getCurrentField();
        ValueHolder unpacker = ValueHolder.newInstance(msgField);
        byte[] track2 = "7612000890000123D25121011111199911111".getBytes();
        unpacker.unpack(track2);

        assertEquals("7612000890000123", unpacker.jumpToChild("PAN").getValue(String.class));
        assertEquals("D", unpacker.jumpToSibling("Separator").getValue(String.class));
        assertEquals("2512", unpacker.jumpToSibling("Expired").getValue(String.class));
        assertEquals("1011111199911111", unpacker.jumpToSibling("OtherData").getValue(String.class));

        // pack to HEX
        ValueHolder packer = ValueHolder.newInstance(defineMessageStructure().getCurrentField());
        packer.setValue("7612000890000123", "Track2", "PAN");
        packer.setValue("D", "Track2", "Separator");
        packer.setValue("2512", "Track2", "Expired");
        packer.setValue("1011111199911111", "Track2", "OtherData");
        byte[] bytes = packer.pack();
        assertEquals("7612000890000123D25121011111199911111", new String(bytes));
        assertEquals(HexService.bytesToHex(bytes), "37363132303030383930303030313233443235313231303131313131313939393131313131");
    }

Thank you for your question.

wangbo131535 commented 1 year ago

How can a defineName support two formats at the same time? A format is 2 nibblel ength, value formats including 16-19 PAN, as well as the Separator, Expired, OtherData.

The other format is 2 nibblel ength, including 8bytes Issuer ID,16Bytes PAN,240bin Remarks

If you want to support both formats, the distinction between the two formats is based on DE3= some value

Can I choose the format dynamically now? Thanks

KyryloSemenko commented 1 year ago

In the case where you need to use just one DefineName for both formats, I would store this field in the TAG_LEN_VAL format, where TAG is the field name, LEN is its length, and VAL is its value. Subsequently, this field will need to be manually parsed based on the value of DE3.

However, it is better to use a dedicated DefineName for each part of the message (IssuerID, Separator, Expired, OtherData, Remarks).

TAG_LEN_VAL or LEN_TAG_VAL should be used when the field may or may not be present in the message, and you do not know its length.

TAG_VAL should be used when you know its length, but you do not know whether the field will be present in the message or not.

LEN_VAL should be used when you do not know its length, but you know it will be present in the message.

VAL should be used when you know its length and you know it will be present in the message.

If you could provide examples of data, I can try to suggest field formats.

Thank you for your questions.