Skip to content

Commit

Permalink
Merge pull request #60 from filip26/feat/uvarint-15
Browse files Browse the repository at this point in the history
UVarInt improvements
  • Loading branch information
filip26 authored Jul 7, 2024
2 parents 58d2ebc + a0882b3 commit 894456a
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven

name: Java 8 CI
name: Java 11 CI

on:
pull_request:
Expand All @@ -13,10 +13,11 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
- uses: actions/checkout@v4
- name: Set up JDK 11
uses: actions/setup-java@v4
with:
java-version: 1.8
java-version: 11
distribution: 'temurin'
- name: Build with Maven
run: mvn -f pom.xml package
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Publish JRE8 to the Maven Central
name: Publish JRE11 to the Maven Central
on:
release:
types: [created]
Expand All @@ -11,10 +11,10 @@ jobs:
environment: maven-central
steps:
- uses: actions/checkout@v4
- name: Set up JDK 8
- name: Set up JDK 11
uses: actions/setup-java@v4
with:
java-version: '8'
java-version: 11
distribution: 'temurin'
server-id: ossrh
- name: Import GPG Key
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ if (KeyCodec.P521_PUBLIC_KEY.isEncoded(encoded)) {

### Gradle

Android 12+ (API Level >=32)

```gradle
implementation("com.apicatalog:copper-multicodec:0.1.1")
```
Expand Down
7 changes: 3 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.apicatalog</groupId>
<artifactId>copper-multicodec</artifactId>
<version>0.2.0</version>
<version>0.9.0-SNAPSHOT</version>
<packaging>jar</packaging>
<url>https://github.com/filip26/ccopper-multicodec</url>
<scm>
Expand All @@ -15,8 +15,8 @@
<url>https://github.com/filip26/ccopper-multicodec/tree/main</url>
</scm>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
Expand Down Expand Up @@ -180,5 +180,4 @@
</distributionManagement>
</profile>
</profiles>

</project>
67 changes: 49 additions & 18 deletions src/main/java/com/apicatalog/uvarint/UVarInt.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.apicatalog.uvarint;

import java.util.Arrays;

public class UVarInt {

/** Maximum encoded var length in bytes */
Expand All @@ -10,24 +8,26 @@ public class UVarInt {
public static final int SEGMENT_BITS = 0x7F;
public static final int CONTINUE_BIT = 0x80;
public static final int INT_OVERFLOW_BITS = 0x70;

public static final byte[] encode(final long value) {

byte[] buffer = new byte[UVarInt.MAX_VAR_LENGTH];
final int length = getLength(value);

if (length == 1) {
return new byte[] { (byte) value };
}

byte[] uintvar = new byte[length];
int offset = 0;
long bytes = value;

boolean next = false;
do {
if (offset >= UVarInt.MAX_VAR_LENGTH) {
throw new IllegalArgumentException("A var longer than " + UVarInt.MAX_VAR_LENGTH + " has been found. Only vars up to " + UVarInt.MAX_VAR_LENGTH + " are supported.");
}

if (next) {
buffer[offset - 1] |= UVarInt.CONTINUE_BIT;
uintvar[offset - 1] |= UVarInt.CONTINUE_BIT;
}

buffer[offset] = (byte) (bytes & UVarInt.SEGMENT_BITS);
uintvar[offset] = (byte) (bytes & UVarInt.SEGMENT_BITS);

bytes >>>= 7;

Expand All @@ -37,13 +37,11 @@ public static final byte[] encode(final long value) {

} while (next);

return offset == UVarInt.MAX_VAR_LENGTH
? buffer
: Arrays.copyOfRange(buffer, 0, offset);
return uintvar;
}

public static final long decode(final byte[] uvarint) {

int offset = 0;

boolean next = false;
Expand All @@ -59,14 +57,47 @@ public static final long decode(final byte[] uvarint) {

int b = uvarint[offset];

value |= (b & UVarInt.SEGMENT_BITS) << (offset * 7);

offset++;
value |= (long) (b & UVarInt.SEGMENT_BITS) << (offset * 7);

next = ((b & UVarInt.CONTINUE_BIT) != 0);

offset++;

} while (next);

return value;
}

protected static long[] MAX_VALUES = {
0x7FL,
0x3FFFL,
0x1FFFFFL,
0xFFFFFFFL,
0x7FFFFFFFFL,
0x3FFFFFFFFFFL,
0x1FFFFFFFFFFFFL,
0xFFFFFFFFFFFFFFL,
0x7FFFFFFFFFFFFFFFL
};

protected static final int getLength(long value) {
if (value <= MAX_VALUES[0]) {
return 1;
}
if (value > MAX_VALUES[8]) {
throw new IllegalArgumentException("A var longer than " + UVarInt.MAX_VAR_LENGTH + " has been found. Only vars up to " + UVarInt.MAX_VAR_LENGTH + " are supported.");
}
if (value <= MAX_VALUES[4]) {
if (value <= MAX_VALUES[2]) {
return (value <= MAX_VALUES[1]) ? 2 : 3;
}
return (value <= MAX_VALUES[3]) ? 4 : 5;
}

if (value <= MAX_VALUES[6]) {
return (value <= MAX_VALUES[5]) ? 6 : 7;
}

return (value <= MAX_VALUES[7]) ? 8 : MAX_VAR_LENGTH;
}
}
30 changes: 19 additions & 11 deletions src/test/java/com/apicatalog/uvarint/UVarIntTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ public class UVarIntTest {

@ParameterizedTest(name = "{index}: {0}")
@MethodSource("testData")
void testEncode(Long input, byte[] expedcted) {
void testEncode(Long input, byte[] expected) {
byte[] output = UVarInt.encode(input);
assertArrayEquals(expedcted, output);
assertArrayEquals(expected, output);
}

@ParameterizedTest(name = "{index}: {0}")
Expand All @@ -24,16 +24,24 @@ void testDecode(Long expected, byte[] input) {
long output = UVarInt.decode(input);
assertEquals(expected, output);
}

static Stream<Arguments> testData() {
return Stream.of(
Arguments.of(1l, new byte[] {1}),
Arguments.of(123l, new byte[] {0x7b}),
Arguments.of(127l, new byte[] {0x7f}),
Arguments.of(128l, new byte[] {(byte)0x80, 0x01}),
Arguments.of(255l, new byte[] {(byte)0xff, 0x01}),
Arguments.of(300l, new byte[] {(byte)0xac, 0x02}),
Arguments.of(16384l, new byte[] {(byte)0x80, (byte)0x80, 0x01})
);
Arguments.of(0l, new byte[] { 0 }),
Arguments.of(1l, new byte[] { 1 }),
Arguments.of(123l, new byte[] { 0x7b }),
Arguments.of(127l, new byte[] { 0x7f }),
Arguments.of(128l, new byte[] { (byte) 0x80, 0x01 }),
Arguments.of(255l, new byte[] { (byte) 0xff, 0x01 }),
Arguments.of(300l, new byte[] { (byte) 0xac, 0x02 }),
Arguments.of(16384l, new byte[] { (byte) 0x80, (byte) 0x80, 0x01 }),
Arguments.of(0xffffl, new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0x3 }),
Arguments.of(0xfffffl, new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0x3f }),
Arguments.of(0xffffffl, new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x7 }),
Arguments.of(0xfffffffl, new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x7f }),
Arguments.of(0xffffffffl, new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xf }),
Arguments.of(0xfffffffffl, new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x1 }),
Arguments.of(0xffffffffffl, new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x1f }),
Arguments.of(Long.MAX_VALUE, new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x7f }));
}
}

0 comments on commit 894456a

Please sign in to comment.