Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Add properties to List for byte-based encodings/hashes #924

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion pkl-core/src/main/java/org/pkl/core/runtime/VmList.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -136,6 +136,15 @@ public boolean isEmpty() {
return rrbt.isEmpty();
}

@TruffleBoundary
public byte[] getBytes() {
var result = new byte[rrbt.size()];
for (var i = 0; i < rrbt.size(); i++) {
result[i] = VmUtils.checkByte(rrbt.get(i));
}
return result;
}

@Override
@TruffleBoundary
public boolean isLengthOne() {
Expand Down
8 changes: 8 additions & 0 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,14 @@ public static void checkPositive(long n) {
}
}

public static byte checkByte(Object n) {
if (n instanceof Long l && l >= 0 && l <= 255) {
return l.byteValue();
}
CompilerDirectives.transferToInterpreter();
throw new VmExceptionBuilder().evalError("expectedByte", n).build();
}

public static Source loadSource(ResolvedModuleKey resolvedKey) {
try {
var text = resolvedKey.loadSource();
Expand Down
43 changes: 42 additions & 1 deletion pkl-core/src/main/java/org/pkl/core/stdlib/base/ListNodes.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,6 +19,7 @@
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.LoopNode;
import java.util.Base64;
import org.pkl.core.ast.expression.binary.*;
import org.pkl.core.ast.internal.IsInstanceOfNode;
import org.pkl.core.ast.internal.IsInstanceOfNodeGen;
Expand All @@ -28,6 +29,7 @@
import org.pkl.core.stdlib.base.CollectionNodes.CompareByNode;
import org.pkl.core.stdlib.base.CollectionNodes.CompareNode;
import org.pkl.core.stdlib.base.CollectionNodes.CompareWithNode;
import org.pkl.core.util.ByteArrayUtils;
import org.pkl.core.util.EconomicSets;

// duplication between ListNodes and SetNodes is "intentional"
Expand All @@ -51,6 +53,45 @@ protected boolean eval(VmList self) {
}
}

public abstract static class md5 extends ExternalPropertyNode {
@TruffleBoundary
@Specialization
protected String eval(VmList self) {
return ByteArrayUtils.md5(self.getBytes());
}
}

public abstract static class sha1 extends ExternalPropertyNode {
@TruffleBoundary
@Specialization
protected String eval(VmList self) {
return ByteArrayUtils.sha1(self.getBytes());
}
}

public abstract static class sha256 extends ExternalPropertyNode {
@TruffleBoundary
@Specialization
protected String eval(VmList self) {
return ByteArrayUtils.sha256(self.getBytes());
}
}

public abstract static class sha256Int extends ExternalPropertyNode {
@TruffleBoundary
@Specialization
protected long eval(VmList self) {
return ByteArrayUtils.sha256Int(self.getBytes());
}
}

public abstract static class base64 extends ExternalPropertyNode {
@Specialization
protected String eval(VmList self) {
return Base64.getEncoder().encodeToString(self.getBytes());
}
}

public abstract static class lastIndex extends ExternalPropertyNode {
@Specialization
protected long eval(VmList self) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,9 @@ Int value `{0}` is too large (only Int32 supported here).
expectedPositiveNumber=\
Expected a positive number, but got `{0}`.

expectedByte=\
Expected an Int value between 0 and 255, but got `{0}`.

cannotFindResource=\
Cannot find resource `{0}`.

Expand Down
36 changes: 35 additions & 1 deletion stdlib/base.pkl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -2794,6 +2794,40 @@ external class List<out Element> extends Collection<Element> {

external isEmpty: Boolean

/// The [MD5](https://en.wikipedia.org/wiki/MD5)
/// hash of this list's byte sequence as hexadecimal string.
///
/// MD5 is cryptographically broken and should not be used for secure applications.
///
/// Throws an error when [Element] is not [UInt8].
external md5: String

/// The [SHA-1](https://en.wikipedia.org/wiki/SHA-1)
/// hash of this list's byte sequence.
///
/// SHA-1 is cryptographically broken and should not be used for secure applications.
///
/// Throws an error when [Element] is not [UInt8].
external sha1: String

/// The [SHA-256](https://en.wikipedia.org/wiki/SHA-2)
/// cryptographic hash of this list's byte sequence
/// as hexadecimal string.
///
/// Throws an error when [Element] is not [UInt8].
external sha256: String

/// The first 64 bits of the [SHA-256](https://en.wikipedia.org/wiki/SHA-2)
/// cryptographic hash of this list's byte sequence.
///
/// Throws an error when [Element] is not [UInt8].
external sha256Int: Int

/// The Base64 encoding of this string's UTF-8 byte sequence.
///
/// Throws an error when [Element] is not [UInt8].
external base64: String

/// The index of the last element in this list (same as `length - 1`).
///
/// Returns `-1` for an empty list.
Expand Down