{"id":20509277,"url":"https://github.com/raydac/java-binary-block-parser","last_synced_at":"2025-04-13T04:56:42.752Z","repository":{"id":28647062,"uuid":"32166298","full_name":"raydac/java-binary-block-parser","owner":"raydac","description":"most comfortable and dynamic way to process binary data in Java and Android","archived":false,"fork":false,"pushed_at":"2025-02-08T13:34:50.000Z","size":10727,"stargazers_count":246,"open_issues_count":1,"forks_count":33,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-04-13T04:56:32.643Z","etag":null,"topics":["data-parsing","dsl","java","parser"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/raydac.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.txt","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-03-13T16:14:06.000Z","updated_at":"2025-02-08T13:34:54.000Z","dependencies_parsed_at":"2022-08-07T14:00:29.396Z","dependency_job_id":"ae55ac45-1c0b-42fe-a7c0-6fd087cfb456","html_url":"https://github.com/raydac/java-binary-block-parser","commit_stats":{"total_commits":687,"total_committers":3,"mean_commits":229.0,"dds":"0.0029112081513827937","last_synced_commit":"4daea782074c05abbbb6444ea3dda20ee14c4304"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raydac%2Fjava-binary-block-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raydac%2Fjava-binary-block-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raydac%2Fjava-binary-block-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raydac%2Fjava-binary-block-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/raydac","download_url":"https://codeload.github.com/raydac/java-binary-block-parser/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248665762,"owners_count":21142123,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data-parsing","dsl","java","parser"],"created_at":"2024-11-15T20:23:43.683Z","updated_at":"2025-04-13T04:56:42.731Z","avatar_url":"https://github.com/raydac.png","language":"Java","readme":"![JBBP Logo](https://github.com/raydac/java-binary-block-parser/blob/master/logo.png)\n\n[![License Apache 2.0](https://img.shields.io/badge/license-Apache%20License%202.0-green.svg)](http://www.apache.org/licenses/LICENSE-2.0)\n[![Maven central](https://maven-badges.herokuapp.com/maven-central/com.igormaznitsa/jbbp/badge.svg)](http://search.maven.org/#artifactdetails|com.igormaznitsa|jbbp|3.0.1|jar)\n[![Java 11+](https://img.shields.io/badge/java-11%2b-green.svg)](http://www.oracle.com/technetwork/java/javase/downloads/index.html)\n[![Android 12+](https://img.shields.io/badge/android-12%2b-green.svg)](http://developer.android.com/sdk/index.html)\n[![PayPal donation](https://img.shields.io/badge/donation-PayPal-cyan.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=AHWJHJFBAWGL2)\n[![YooMoney donation](https://img.shields.io/badge/donation-Yoo.money-blue.svg)](https://yoomoney.ru/to/41001158080699)\n\n# Introduction\n\nJava has some embedded features to parse binary data (for instance ByteBuffer), but sometime it is needed to work on bit\nlevel and describe binary structures through some DSL(domain specific language). I was impressed by\nthe [the Python Struct package](https://docs.python.org/2/library/struct.html) package and wanted to get something like\nthat for Java. So I developed the JBBP library.\u003cbr\u003e\n![Use cases](https://github.com/raydac/java-binary-block-parser/blob/master/docs/jbbp_mm.png)\n\n# Change log\n\n- __3.0.1 (24-dec-2024)__\n  - added `MSB0_DIRECT` bit order mode, MSB0 without data\n    revers [#46](https://github.com/raydac/java-binary-block-parser/issues/46)\n  - added `JBBPBitInputStream#isDetectedPartlyReadBitField` to check that only part of bit field read during last\n    operation\n  - added flag into constructors for JBBPBitInputStream to force return -1 instead of partly accumulated bits data if\n    end of field\n\n- __3.0.0 (16-nov-2024)__\n  - __Minimum JDK Version: Updated to 11.0.__\n  - __Minimum Supported Android: Updated to 12 (API 32).__\n  - __API Changes:__ Modifications made to the CompiledBlockVisitor API.\n  - __New Feature:__ Added `JBBPUtils#findMaxStaticArraySize` for calculating the largest static array size defined in a\n    JBBP script.\n  - __Internal API:__ Certain internal APIs have been opened.\n  - __Codebase Improvements:__ General refactoring performed.\n\n- __2.1.0 (05-nov-2024)__\n  - minor changes in API for `JBBPVarFieldProcessor` and `JBBPCustomFieldTypeProcessor`\n  - provided way to control size of arrays read as stream\n    rest [#44](https://github.com/raydac/java-binary-block-parser/issues/44)\n  - provided way to control size of arrays which size calculated through\n    expressions [#45](https://github.com/raydac/java-binary-block-parser/issues/45)\n  - improved tests\n\n[Full changelog](https://github.com/raydac/java-binary-block-parser/blob/master/changelog.txt)\n\n# Maven dependency\n\nThe Framework has been published in the Maven Central and can be easily added as a dependency\n\n```\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.igormaznitsa\u003c/groupId\u003e\n  \u003cartifactId\u003ejbbp\u003c/artifactId\u003e\n  \u003cversion\u003e3.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nthe precompiled library jar, javadoc and sources also can be downloaded directly\nfrom [the Maven central.](https://search.maven.org/artifact/com.igormaznitsa/jbbp/3.0.1/jar)\n\n# Hello world\n\nThe library is very easy in use because in many cases only two its classes are needed -\ncom.igormaznitsa.jbbp.JBBPParser (for data parsing) and com.igormaznitsa.jbbp.io.JBBPOut (for binary block writing).\nBoth these classes work over low-level IO classes - com.igormaznitsa.jbbp.io.JBBPBitInputStream and\ncom.igormaznitsa.jbbp.io.JBBPBitOutputStream, those bit stream classes are the core of the library.\n\nThe easiet use case shows parsing of whole byte array to bits.\n\n```Java\n  byte[]parsedBits=JBBPParser.prepare(\"bit:1 [_];\").parse(new byte[]{1,2,3,4,5}).\n        findFieldForType(JBBPFieldArrayBit.class).getArray();\n```\n\nOn start it was the only functionality but then I found that it is no so comfort way to get result, so that added some\nmapping of parsed result to pre-instantiated object. It works slower, because uses a lot of Java reflection but much\neasy in some cases.\n\n```Java\nclass Parsed {\n  @Bin(type = BinType.BIT_ARRAY)\n  byte[] parsed;\n}\n  Parsed parsedBits = JBBPParser.prepare(\"bit:1 [_] parsed;\").parse(new byte[] {1, 2, 3, 4, 5}).mapTo(new Parsed());\n```\n\n# Relative speed of different approaches in parsing\n\nMainly I developed the library to help in my development of ZX-Spectrum emulator where I needed to work with data\nsnapshots containing data on bit level. It didn't need much productivity in work. But since 1.3.0 version I added way to\ngenerate Java classes from JBBP scripts, such classes work in about five times faster than dynamic parsing and mapping\napproaches.  \n![JMH results](https://github.com/raydac/java-binary-block-parser/blob/master/docs/jmh_results.png)   \nChart below compares speed of three provided ways to parse data with JBBP:\n\n* __Dynamic__ - the basic parsing through interpretation of prepared JBBP DSL script. It is no so fast, but provide way\n  to generate parsers on fly from text description.\n* __Dynamic + map to class__ - parsing through interpretation of parsed JBBP script and mapping of parsed data to\n  pre-instantiated class instance. It provides compfortable way to work with data and get result but uses a lot of Java\n  reflection features and so fast.\n* __Static class__ - the fastest way of JBBP use, some JBBP script is translated into Java class. There is no any\n  interpretation or reflection operators so that it is very\n  fast. [You can take a look at auxiliary class which I use in tests](https://github.com/raydac/java-binary-block-parser/blob/master/jbbp/src/test/java/com/igormaznitsa/jbbp/testaux/AbstractJBBPToJavaConverterTest.java)\n  .\n\n# Generate sources from JBBP scripts\n\nSince 1.3.0 version, the library provides Java source generator for JBBP scripts, __(keep in mind that generated sources\nanyway depends on JBBP library and it is needed for their work)__. For instance such snippet can be used to generate\nJava classes from a JBBP script. It also can generate multiple classes.\n\n```Java\n  JBBPParser parser=JBBPParser.prepare(\"byte a; byte b; byte c;\");\n  List\u003cResultSrcItem\u003e generated=parser.convertToSrc(TargetSources.JAVA,\"com.test.jbbp.gen.SomeClazz\");\n  for(ResultSrcItem i:generated){\n    for(Map.Entry\u003cString, String\u003e j:i.getResult().entrySet()) {\n      System.out.println(\"Class file name \"+j.getKey());\n      System.out.println(\"Class file content \"+j.getValue());\n    }\n  }\n```\n\nalso there are developed plug-ins for both Maven and Gradle to generate sources from JBBP scripts during source generate\nphase.   \nin Maven it can be used through snippet:\n\n```xml\n\n\u003cplugin\u003e\n  \u003cgroupId\u003ecom.igormaznitsa\u003c/groupId\u003e\n  \u003cartifactId\u003ejbbp-maven-plugin\u003c/artifactId\u003e\n  \u003cversion\u003e3.0.1\u003c/version\u003e\n  \u003cexecutions\u003e\n    \u003cexecution\u003e\n      \u003cid\u003egen-jbbp-src\u003c/id\u003e\n      \u003cgoals\u003e\n        \u003cgoal\u003egenerate\u003c/goal\u003e\n      \u003c/goals\u003e\n    \u003c/execution\u003e\n  \u003c/executions\u003e\n\u003c/plugin\u003e\n```\n\nBy default the maven plug-in looks for files with `jbbp` extension in `src/jbbp` folder of the project (it can be\nchanged through plug-in configuration) and produces resulting java classes into `target/generated-sources/jbbp`\nfolder. [For instance, I use such approach in my ZX-Poly emulator](https://github.com/raydac/zxpoly/tree/master/zxpoly-emul/src/jbbp)\n.\n\n# More complex example with features added as of 1.1.0\n\nExample below shows how to parse a byte stream written in non-standard MSB0 order (Java has LSB0 bit order) into bit\nfields, then print its values and pack fields back:\n\n```Java\nclass Flags {\n  @Bin(order = 1, name = \"f1\", type = BinType.BIT, bitNumber = JBBPBitNumber.BITS_1, comment = \"It's flag one\")\n  byte flag1;\n  @Bin(order = 2, name = \"f2\", type = BinType.BIT, bitNumber = JBBPBitNumber.BITS_2, comment = \"It's second flag\")\n  byte flag2;\n  @Bin(order = 3, name = \"f3\", type = BinType.BIT, bitNumber = JBBPBitNumber.BITS_1, comment = \"It's 3th flag\")\n  byte flag3;\n  @Bin(order = 4, name = \"f4\", type = BinType.BIT, bitNumber = JBBPBitNumber.BITS_4, comment = \"It's 4th flag\")\n  byte flag4;\n}\n\n  final int data = 0b10101010;\n    Flags parsed = JBBPParser.prepare(\"bit:1 f1; bit:2 f2; bit:1 f3; bit:4 f4;\", JBBPBitOrder.MSB0).parse(new byte[]{(byte)data}).mapTo(new Flags());\n    assertEquals(1, parsed.flag1);\n    assertEquals(2, parsed.flag2);\n    assertEquals(0, parsed.flag3);\n    assertEquals(5, parsed.flag4);\n\n    System.out.println(new JBBPTextWriter().Bin(parsed).Close().toString());\n\n    assertEquals(data, JBBPOut.BeginBin(JBBPBitOrder.MSB0).Bin(parsed).End().toByteArray()[0] \u0026 0xFF);\n```\n\nThe Example will print in console the text below\n\n```\n;--------------------------------------------------------------------------------\n; START : Flags\n;--------------------------------------------------------------------------------\n    01; f1, It's flag one\n    02; f2, It's second flag\n    00; f3, It's 3th flag\n    05; f4, It's 4th flag\n;--------------------------------------------------------------------------------\n; END : Flags\n;--------------------------------------------------------------------------------\n```\n\n# Fields\n\nEach field can have case insensitive name which must not contain '.' (because dot is reserved for links to structure\nfield values) and '#'(because it is also reserved for internal library use). A field name must not be started with\neither number or chars '$' and '_'. *Keep in mind that field names are case insensitive!*\n\n```\nint someNamedField;\nbyte field1;\nbyte field2;\nbyte field3;\n```\n\n![JBBP field format, types and examples](https://github.com/raydac/java-binary-block-parser/blob/master/docs/jbbp_fields.png)\n\n## Primitive types\n\nJBBP supports full set of Java numeric primitives with some extra types like ubyte and bit.\n![JBBP field format, types and examples](https://github.com/raydac/java-binary-block-parser/blob/master/docs/jbbp_primitives.png)\n\n## Complex types\n\nJBBP provides support both arrays and structures. __In expressions you can use links only to field values which already\nread!__\n![JBBP field format, types and examples](https://github.com/raydac/java-binary-block-parser/blob/master/docs/jbbp_complex_types.png)\n\n## Custom types\n\nIt is possible to define processors for custom data types. For instance you can take a look\nat [case processing three byte unsigned integer types](https://github.com/raydac/java-binary-block-parser/blob/master/jbbp/src/test/java/com/igormaznitsa/jbbp/it/CustomThreeByteIntegerTypeTest.java)\n.\n\n### Support of float, double and String types\n\nSince 1.4.0 in JBBP was added support of Java float, double and String values. Because they have specific format, they\nare named as `doublej`, `floatj` and `stringj`.\n\n## Variable fields\n\nIf you have some data which internal structure is undefined and variable then you can use the `var` type to mark such\nfield and provide custom processor to read data of such value. Processor should implement\ninterface [JBBPVarFieldProcessor](https://github.com/raydac/java-binary-block-parser/blob/master/src/main/java/com/igormaznitsa/jbbp/JBBPVarFieldProcessor.java)\ninstance.\n\n```\n    final JBBPParser parser = JBBPParser.prepare(\"short k; var; int;\");\n    final JBBPIntCounter counter = new JBBPIntCounter();\n    final JBBPFieldStruct struct = parser.parse(new byte[]{9, 8, 33, 1, 2, 3, 4}, new JBBPVarFieldProcessor() {\n\n      public JBBPAbstractArrayField\u003c? extends JBBPAbstractField\u003e readVarArray(JBBPBitInputStream inStream, int arraySize, JBBPNamedFieldInfo fieldName, int extraValue, JBBPByteOrder byteOrder, JBBPNamedNumericFieldMap numericFieldMap) throws IOException {\n        fail(\"Must not be called\");\n        return null;\n      }\n\n      public JBBPAbstractField readVarField(JBBPBitInputStream inStream, JBBPNamedFieldInfo fieldName, int extraValue, JBBPByteOrder byteOrder, JBBPNamedNumericFieldMap numericFieldMap) throws IOException {\n        final int value = inStream.readByte();\n        return new JBBPFieldByte(fieldName, (byte) value);\n      }\n    }, null);\n```\n\n*NB! Some programmers trying to use only parser for complex data, it is a mistake. In the case it is much better to have\nseveral easy parsers working with the\nsame [JBBPBitInputStream](https://github.com/raydac/java-binary-block-parser/blob/master/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitInputStream.java)\ninstance, it allows to keep decision points on Java level and make solution easier.*\n\n## Special types\n\nSpecial types makes some actions to skip data in input stream\n![JBBP field format, types and examples](https://github.com/raydac/java-binary-block-parser/blob/master/docs/jbbp_special_fields.png)\n\n## Byte order\n\nMulti-byte types can be read with different byte order.\n![JBBP field format, types and examples](https://github.com/raydac/java-binary-block-parser/blob/master/docs/jbbp_byteorder.png)\n\n# Expressions\n\nExpressions are used for calculation of length of arrays and allow brackets and integer operators which work similar to\nJava operators:\n\n- Arithmetic operators: +,-,%,*,/,%\n- Bit operators: \u0026,|,^,~\n- Shift operators: \u003c\u003c,\u003e\u003e,\u003e\u003e\u003e\n- Brackets: (, )\n\nInside expression you can use integer numbers and named field values through their names (if you use fields from the\nsame structure) or paths. Keep in your mind that you can't use array fields or fields placed inside structure arrays.\n\n```\nint field1;\n   struct1 {\n      int field2;\n   }\n   byte [field1+struct1.field2] data;\n```\n\n# Commentaries\n\nYou can use commentaries inside a parser script, the parser supports the only comment format and recognizes as\ncommentaries all text after '//' till the end of line.\n\n```\n int;\n    // hello commentaries\n    byte field;\n```\n\n# Expression macroses\n\nInside expression you can use field names and field paths, also you can use the special macros '$$' which represents the\ncurrent input stream byte counter, all fields started with '$' will be recognized by the parser as special user defined\nvariables and it will be requesting them from special user defined provider. If the array size contains the only '_'\nsymbol then the field or structure will not have defined size and whole stream will be read.\n\n# How to get result of parsing\n\nThe Result of parsing is an instance of com.igormaznitsa.jbbp.model.JBBPFieldStruct class which represents the root\ninvisible structure for the parsed data and you can use its inside methods to find desired fields for their names, paths\nor classes. All Fields are successors of com.igormaznitsa.jbbp.model.JBBPAbstractField class. To increase comfort, it is\neasier to use mapping to classes when the mapper automatically places values to fields of a Java class.\n\n# Example\n\nExample below shows how to parse a PNG file through JBBP parser:\n\n```Java\nfinal InputStream pngStream = getResourceAsInputStream(\"picture.png\");\n    try {\n\n      final JBBPParser pngParser = JBBPParser.prepare(\n              \"long header;\"\n              + \"// chunks\\n\"\n              + \"chunk [_]{\"\n              + \"   int length; \"\n              + \"   int type; \"\n              + \"   byte[length] data; \"\n              + \"   int crc;\"\n              + \"}\"\n      );\n\n      JBBPFieldStruct result = pngParser.parse(pngStream);\n\n      assertEquals(0x89504E470D0A1A0AL,result.findFieldForNameAndType(\"header\",JBBPFieldLong.class).getAsLong());\n\n      JBBPFieldArrayStruct chunks = result.findFieldForNameAndType(\"chunk\", JBBPFieldArrayStruct.class);\n\n      String [] chunkNames = new String[]{\"IHDR\",\"gAMA\",\"bKGD\",\"pHYs\",\"tIME\",\"tEXt\",\"IDAT\",\"IEND\"};\n      int [] chunkSizes = new int[]{0x0D, 0x04, 0x06, 0x09, 0x07, 0x19, 0x0E5F, 0x00};\n\n      assertEquals(chunkNames.length,chunks.size());\n\n      for(int i=0;i\u003cchunks.size();i++){\n        assertChunk(chunkNames[i], chunkSizes[i], (JBBPFieldStruct)chunks.getElementAt(i));\n      }\n    }\n    finally {\n      closeResource(pngStream);\n    }\n```\n\nAlso it is possible to map parsed packet to class fields\n\n```Java\nfinal JBBPParser pngParser = JBBPParser.prepare(\n              \"long header;\"\n              + \"chunk [_]{\"\n              + \"   int length; \"\n              + \"   int type; \"\n              + \"   byte[length] data; \"\n              + \"   int crc;\"\n              + \"}\"\n      );\n\n      class Chunk {\n        @Bin int length;\n        @Bin int type;\n        @Bin byte [] data;\n        @Bin int crc;\n      }\n\n      @Bin  \n      class Png {\n        long header;\n        Chunk [] chunk;\n\n        public Object newInstance(Class\u003c?\u003e klazz){\n          return klazz == Chunk.class ? new Chunk() : null;\n        }\n      }\n\n      final Png png = pngParser.parse(pngStream).mapTo(new Png());\n```\n\nExample shows how to parse TCP frame:\n\n```Java\nfinal JBBPParser tcpParser = JBBPParser.prepare(\n              \"skip:34; // skip bytes till the frame\\n\"\n              + \"ushort SourcePort;\"\n              + \"ushort DestinationPort;\"\n              + \"int SequenceNumber;\"\n              + \"int AcknowledgementNumber;\"\n\n              + \"bit:1 NONCE;\"\n              + \"bit:3 RESERVED;\"\n              + \"bit:4 HLEN;\"\n\n              + \"bit:1 FIN;\"\n              + \"bit:1 SYN;\"\n              + \"bit:1 RST;\"\n              + \"bit:1 PSH;\"\n              + \"bit:1 ACK;\"\n              + \"bit:1 URG;\"\n              + \"bit:1 ECNECHO;\"\n              + \"bit:1 CWR;\"\n\n              + \"ushort WindowSize;\"\n              + \"ushort TCPCheckSum;\"\n              + \"ushort UrgentPointer;\"\n              + \"byte [$$-34-HLEN*4] Option;\"\n              + \"byte [_] Data;\"\n      );\n\n      final JBBPFieldStruct result = pngParser.parse(tcpFrameStream);\n```\n\n# F.A.Q.\n\n## Is it possible to use `@Bin` annotations for parsing and not only mapping?\n\n`@Bin` annotations is used only for mapping and data writing, but there is special\nclass [JBBPDslBuilder](/jbbp/src/main/java/com/igormaznitsa/jbbp/utils/JBBPDslBuilder.java) which can convert `@Bin`\nmarked class into JBBP script, for instance:\n\n```java\nJBBPDslBuilder.Begin().AnnotatedClass(SomeBinAnnotatetClass.class).End(true);\n```\n\n## My Binary data format is too complex one to be decoded by a JBBP script\n\nNo problems! JBBP parser works\nover [com.igormaznitsa.jbbp.io.JBBPBitInputStream](/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitInputStream.java)\nclass which can be used directly and allows read bits, bytes, count bytes and align data. For writing there is similar\nclass [JBBPBitOutputStream](https://github.com/raydac/java-binary-block-parser/blob/master/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitOutputStream.java)\n.\n\n## I want to make a binary data block instead of parsing!\n\nLibrary provides special helper [JBBPOut](/jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPOut.java). The helper allows\nto generate binary blocks and provides some kind of DSL\n\n```Java\nimport static com.igormaznitsa.jbbp.io.JBBPOut.*;\n...\nfinal byte [] array =\n          BeginBin().\n            Bit(1, 2, 3, 0).\n            Bit(true, false, true).\n            Align().\n            Byte(5).\n            Short(1, 2, 3, 4, 5).\n            Bool(true, false, true, true).\n            Int(0xABCDEF23, 0xCAFEBABE).\n            Long(0x123456789ABCDEF1L, 0x212356239091AB32L).\n          End().toByteArray();\n```\n","funding_links":["https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=AHWJHJFBAWGL2"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraydac%2Fjava-binary-block-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraydac%2Fjava-binary-block-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraydac%2Fjava-binary-block-parser/lists"}