Skip to content

Commit

Permalink
Merge pull request #136 from parsingdata/uuid-and-guid
Browse files Browse the repository at this point in the history
UUID and GUID ValueExpression helper methods
  • Loading branch information
jvdb authored Jan 10, 2017
2 parents 1e85f18 + 2a204ab commit 9a7427d
Show file tree
Hide file tree
Showing 6 changed files with 255 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright 2013-2016 Netherlands Forensic Institute
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.parsingdata.metal.expression.value;

import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.nio.ByteBuffer.allocate;

import static io.parsingdata.metal.Shorthand.cat;
import static io.parsingdata.metal.Shorthand.con;
import static io.parsingdata.metal.Util.checkNotNull;

import java.util.Arrays;

import io.parsingdata.metal.data.Environment;
import io.parsingdata.metal.data.ImmutableList;
import io.parsingdata.metal.encoding.Encoding;

/**
* {@link GUID#guid(String)} creates a ValueExpression to be used as predicate for 16 byte definitions;
*/
public final class GUID {

private static final Encoding BIG_ENDIAN = new Encoding();

private GUID() {}

/**
* Use a String representation of a GUID as predicate.
* {@code eq(guid("caa16737-fa36-4d43-b3b6-33f0aa44e76b"))}
* Note that the byte order in the encoding matters for the output.
* @param guid GUID, for example "caa16737-fa36-4d43-b3b6-33f0aa44e76b"
* @return expression to use as predicate
*/
public static ValueExpression guid(final String guid) {
final String[] parts = checkNotNull(guid, "guid").split("-");
if (parts.length != 5) {
throw new IllegalArgumentException("Invalid GUID string: " + guid);
}
return new ValueExpression() {

@Override
public ImmutableList<OptionalValue> eval(final Environment environment, final Encoding encoding) {
// Note that GUID bytes differ from UUID bytes, as the first 3 parts can be reversed
return cat(
cat(
cat(
four(parts[0], encoding),
two(parts[1], encoding)),
two(parts[2], encoding)),
cat(
two(parts[3], BIG_ENDIAN),
six(parts[4], BIG_ENDIAN))).eval(environment, encoding);
}
};
}

private static ValueExpression four(final String part, final Encoding encoding) {
return encode(allocate(4)
.putInt(0, (int) parseLong(part, 16))
.array(), encoding);
}

private static ValueExpression two(final String part, final Encoding encoding) {
return encode(allocate(2)
.putShort(0, (short) parseInt(part, 16))
.array(), encoding);
}

private static ValueExpression six(final String part, final Encoding encoding) {
return encode(Arrays.copyOfRange(
allocate(8)
.putLong(0, Long.parseLong(part, 16))
.array(),
2, 8), encoding);
}

private static ValueExpression encode(final byte[] bytes, final Encoding encoding) {
return con(ConstantFactory.createFromBytes(encoding.byteOrder.apply(bytes), encoding));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2013-2016 Netherlands Forensic Institute
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.parsingdata.metal.expression.value;

import static io.parsingdata.metal.Shorthand.cat;
import static io.parsingdata.metal.Shorthand.con;
import static io.parsingdata.metal.Util.checkNotNull;

import java.math.BigInteger;

import io.parsingdata.metal.encoding.Encoding;

/**
* {@link UUID#uuid(String)} creates a ValueExpression to be used as predicate for 16 byte definitions;
*/
public final class UUID {
private static final Encoding BIG_ENDIAN = new Encoding();

private UUID() {}

/**
* Use a String representation of a UUID as predicate.
* {@code eq(uuid("caa16737-fa36-4d43-b3b6-33f0aa44e76b"))}
* @param uuid UUID, for example "c79577f6-2ff6-4b48-a252-1c88d4416cd8"
* @return expression to use as predicate
*/
public static ValueExpression uuid(final String uuid) {
final java.util.UUID value = java.util.UUID.fromString(checkNotNull(uuid, "uuid"));
return cat(exactLong(value.getMostSignificantBits()), exactLong(value.getLeastSignificantBits()));
}

/**
* Create {@link ValueExpression} without compacting the bytes.
* @param bits Long to convert to {@link ValueExpression}
* @return {@link ValueExpression} of the bits
*/
private static ValueExpression exactLong(final long bits) {
return con(ConstantFactory.createFromBytes(BigInteger.valueOf(bits).toByteArray(), BIG_ENDIAN));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2013-2016 Netherlands Forensic Institute
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.parsingdata.metal.expression.value;

import static org.junit.Assert.assertTrue;

import static io.parsingdata.metal.Shorthand.def;
import static io.parsingdata.metal.Shorthand.eq;
import static io.parsingdata.metal.expression.value.GUID.guid;
import static io.parsingdata.metal.util.ClassDefinition.checkUtilityClass;
import static io.parsingdata.metal.util.EncodingFactory.enc;
import static io.parsingdata.metal.util.EncodingFactory.le;
import static io.parsingdata.metal.util.EnvironmentFactory.stream;

import java.io.IOException;
import java.net.URISyntaxException;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import io.parsingdata.metal.token.Token;

public class GUIDTest {

@Rule
public ExpectedException _exception = ExpectedException.none();

@Test
public void checkUtility() throws ReflectiveOperationException {
checkUtilityClass(GUID.class);
}

@Test
public void parseGUID() throws IOException, URISyntaxException {
final Token guid = def("guid", 16, eq(guid("00c27766-f623-4200-9d64-115e9bfd4a08")));
assertTrue("be", guid.parse(stream(0x00, 0xc2, 0x77, 0x66, 0xf6, 0x23, 0x42, 0x00, 0x9d, 0x64, 0x11, 0x5e, 0x9b, 0xfd, 0x4a, 0x08), enc()).succeeded);
assertTrue("le", guid.parse(stream(0x66, 0x77, 0xc2, 0x00, 0x23, 0xf6, 0x00, 0x42, 0x9d, 0x64, 0x11, 0x5e, 0x9b, 0xfd, 0x4a, 0x08), le()).succeeded);

_exception.expect(IllegalArgumentException.class);
_exception.expectMessage("Invalid GUID string: test");
guid("test");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2013-2016 Netherlands Forensic Institute
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.parsingdata.metal.expression.value;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import static io.parsingdata.metal.Shorthand.def;
import static io.parsingdata.metal.Shorthand.eq;
import static io.parsingdata.metal.expression.value.UUID.uuid;
import static io.parsingdata.metal.util.ClassDefinition.checkUtilityClass;
import static io.parsingdata.metal.util.EncodingFactory.enc;
import static io.parsingdata.metal.util.EnvironmentFactory.stream;

import org.junit.Test;

import io.parsingdata.metal.token.Token;

public class UUIDTest {

@Test
public void checkUtility() throws ReflectiveOperationException {
checkUtilityClass(UUID.class);
}

@Test
public void parseUUID() throws Exception {
final Token uuid = def("uuid", 16, eq(uuid("00c27766-f623-4200-9d64-115e9bfd4a08")));
assertTrue(uuid.parse(stream(0x00, 0xc2, 0x77, 0x66, 0xf6, 0x23, 0x42, 0x00, 0x9d, 0x64, 0x11, 0x5e, 0x9b, 0xfd, 0x4a, 0x08), enc()).succeeded);
assertFalse(uuid.parse(stream(0x66, 0x77, 0xc2, 0x00, 0x23, 0xf6, 0x00, 0x42, 0x9d, 0x64, 0x11, 0x5e, 0x9b, 0xfd, 0x4a, 0x08), enc()).succeeded);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package io.parsingdata.metal;
package io.parsingdata.metal.format;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package io.parsingdata.metal;
package io.parsingdata.metal.format;

import static io.parsingdata.metal.util.EncodingFactory.enc;
import static io.parsingdata.metal.util.EnvironmentFactory.stream;
Expand All @@ -27,9 +27,6 @@
import org.junit.runners.Parameterized;

import io.parsingdata.metal.encoding.Encoding;
import io.parsingdata.metal.format.JPEG;
import io.parsingdata.metal.format.PNG;
import io.parsingdata.metal.format.ZIP;
import io.parsingdata.metal.token.Token;
import io.parsingdata.metal.util.ParameterizedParse;

Expand Down

0 comments on commit 9a7427d

Please sign in to comment.