Introduces Bytes class (#1019)

This introduces a new `Bytes` standard library class, for working with
binary data.

* Add Bytes class to the standard library
* Change CLI to eval `output.bytes`
* Change code generators to map Bytes to respective underlying type
* Add subscript and concat operator support
* Add binary encoding for Bytes
* Add PCF and Plist rendering for Bytes

Co-authored-by: Kushal Pisavadia <kushi.p@gmail.com>
This commit is contained in:
Daniel Chao
2025-06-11 16:23:55 -07:00
committed by GitHub
parent 3bd8a88506
commit e9320557b7
104 changed files with 2210 additions and 545 deletions

View File

@@ -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.
@@ -53,6 +53,15 @@ public interface Evaluator extends AutoCloseable {
*/
String evaluateOutputText(ModuleSource moduleSource);
/**
* Evaluates a module's {@code output.bytes} property.
*
* @throws PklException if an error occurs during evaluation
* @throws IllegalStateException if this evaluator has already been closed
* @since 0.29.0
*/
byte[] evaluateOutputBytes(ModuleSource moduleSource);
/**
* Evaluates a module's {@code output.value} property.
*
@@ -143,6 +152,10 @@ public interface Evaluator extends AutoCloseable {
* <td>TypeAlias</td>
* <td>{@link TypeAlias}</td>
* </tr>
* <tr>
* <td>Bytes</td>
* <td>{@code byte[]}</td>
* </tr>
* </tbody>
* </table>
*

View File

@@ -144,6 +144,16 @@ public class EvaluatorImpl implements Evaluator {
});
}
public byte[] evaluateOutputBytes(ModuleSource moduleSource) {
return doEvaluate(
moduleSource,
(module) -> {
var output = readModuleOutput(module);
var vmBytes = VmUtils.readBytesProperty(output);
return vmBytes.export();
});
}
@Override
public Object evaluateOutputValue(ModuleSource moduleSource) {
return doEvaluate(
@@ -183,32 +193,31 @@ public class EvaluatorImpl implements Evaluator {
@Override
public Object evaluateExpression(ModuleSource moduleSource, String expression) {
// optimization: if the expression is `output.text` or `output.value` (the common cases), read
// members directly instead of creating new truffle nodes.
if (expression.equals("output.text")) {
return evaluateOutputText(moduleSource);
}
if (expression.equals("output.value")) {
return evaluateOutputValue(moduleSource);
}
return doEvaluate(
moduleSource,
(module) -> {
var expressionResult =
VmUtils.evaluateExpression(module, expression, securityManager, moduleResolver);
if (expressionResult instanceof VmValue value) {
value.force(false);
return value.export();
}
return expressionResult;
});
// optimization: if the expression is `output.text`, `output.value` or `output.bytes` (the
// common cases), read members directly instead of creating new truffle nodes.
return switch (expression) {
case "output.text" -> evaluateOutputText(moduleSource);
case "output.value" -> evaluateOutputValue(moduleSource);
case "output.bytes" -> evaluateOutputBytes(moduleSource);
default ->
doEvaluate(
moduleSource,
(module) -> {
var expressionResult =
VmUtils.evaluateExpression(module, expression, securityManager, moduleResolver);
if (expressionResult instanceof VmValue value) {
value.force(false);
return value.export();
}
return expressionResult;
});
};
}
@Override
public String evaluateExpressionString(ModuleSource moduleSource, String expression) {
// optimization: if the expression is `output.text` (the common case), read members
// directly
// instead of creating new truffle nodes.
// directly instead of creating new truffle nodes.
if (expression.equals("output.text")) {
return evaluateOutputText(moduleSource);
}
@@ -280,6 +289,10 @@ public class EvaluatorImpl implements Evaluator {
return doEvaluate(() -> VmUtils.readTextProperty(fileOutput));
}
byte[] evaluateOutputBytes(VmTyped fileOutput) {
return doEvaluate(() -> VmUtils.readBytesProperty(fileOutput).export());
}
private <T> T doEvaluate(Supplier<T> supplier) {
@Nullable TimeoutTask timeoutTask = null;
logger.clear();

View File

@@ -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.
@@ -20,7 +20,14 @@ public interface FileOutput {
/**
* Returns the text content of this file.
*
* @throws PklException if an error occurs during evaluation
* @throws PklException if an error occurs during evaluation.
*/
String getText();
/**
* Returns the byte contents of this file.
*
* @throws PklException if an error occurs during evaluation.
*/
byte[] getBytes();
}

View File

@@ -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.
@@ -44,4 +44,16 @@ final class FileOutputImpl implements FileOutput {
throw new PklBugException(e);
}
}
@Override
public byte[] getBytes() {
try {
return evaluator.evaluateOutputBytes(fileOutput);
} catch (PolyglotException e) {
if (e.isCancelled()) {
throw new PklException("The evaluator is no longer available", e);
}
throw new PklBugException(e);
}
}
}

View File

@@ -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.
@@ -102,6 +102,12 @@ final class JsonRenderer implements ValueRenderer {
String.format("Values of type `DataSize` cannot be rendered as JSON. Value: %s", value));
}
@Override
public void visitBytes(byte[] value) {
throw new RendererException(
String.format("Values of type `Bytes` cannot be rendered as JSON. Value: %s", value));
}
@Override
public void visitPair(Pair<?, ?> value) {
try {

View File

@@ -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.
@@ -49,6 +49,7 @@ public final class PClassInfo<T> implements Serializable {
public static final PClassInfo<Double> Float = pklBaseClassInfo("Float", double.class);
public static final PClassInfo<Duration> Duration = pklBaseClassInfo("Duration", Duration.class);
public static final PClassInfo<DataSize> DataSize = pklBaseClassInfo("DataSize", DataSize.class);
public static final PClassInfo<byte[]> Bytes = pklBaseClassInfo("Bytes", byte[].class);
public static final PClassInfo<Pair> Pair = pklBaseClassInfo("Pair", Pair.class);
public static final PClassInfo<Void> Collection = pklBaseClassInfo("Collection", Void.class);
public static final PClassInfo<ArrayList> List = pklBaseClassInfo("List", ArrayList.class);
@@ -115,6 +116,7 @@ public final class PClassInfo<T> implements Serializable {
if (value instanceof Set) return (PClassInfo<T>) Set;
if (value instanceof Map) return (PClassInfo<T>) Map;
if (value instanceof Pattern) return (PClassInfo<T>) Regex;
if (value instanceof byte[]) return (PClassInfo<T>) Bytes;
throw new IllegalArgumentException("Not a Pkl value: " + value);
}

View File

@@ -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.
@@ -21,6 +21,7 @@ import java.io.Writer;
import java.util.*;
import java.util.regex.Pattern;
import org.pkl.core.util.ArrayCharEscaper;
import org.pkl.core.util.ByteArrayUtils;
// To instantiate this class, use ValueRenderers.plist().
final class PListRenderer implements ValueRenderer {
@@ -136,6 +137,13 @@ final class PListRenderer implements ValueRenderer {
value));
}
@Override
public void visitBytes(byte[] value) {
write("<data>");
write(ByteArrayUtils.base64(value));
write("</data>");
}
@Override
public void visitPair(Pair<?, ?> value) {
doVisitIterable(value, false);

View File

@@ -92,6 +92,21 @@ final class PcfRenderer implements ValueRenderer {
write(value.toString());
}
@Override
public void visitBytes(byte[] value) {
write("Bytes(\"");
var isFirst = true;
for (var byt : value) {
if (isFirst) {
isFirst = false;
} else {
write(", ");
}
write(Integer.valueOf(Byte.toUnsignedInt(byt)).toString());
}
write(")");
}
@Override
public void visitPair(Pair<?, ?> value) {
doVisitIterable(value, "Pair(");

View File

@@ -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.
@@ -106,6 +106,13 @@ final class PropertiesRenderer implements ValueRenderer {
"Values of type `DataSize` cannot be rendered as Properties. Value: %s", value));
}
@Override
public String convertBytes(byte[] value) {
throw new RendererException(
String.format(
"Values of type `Bytes` cannot be rendered as Properties. Value: %s", value));
}
@Override
public String convertPair(Pair<?, ?> value) {
throw new RendererException(

View File

@@ -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.
@@ -37,6 +37,8 @@ public interface ValueConverter<T> {
T convertDataSize(DataSize value);
T convertBytes(byte[] value);
T convertPair(Pair<?, ?> value);
T convertList(List<?> value);

View File

@@ -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.
@@ -53,6 +53,10 @@ public interface ValueVisitor {
visitDefault(value);
}
default void visitBytes(byte[] value) {
visitDefault(value);
}
default void visitPair(Pair<?, ?> value) {
visitDefault(value);
}
@@ -108,6 +112,8 @@ public interface ValueVisitor {
visitMap(map);
} else if (value instanceof Pattern pattern) {
visitRegex(pattern);
} else if (value instanceof byte[] bytes) {
visitBytes(bytes);
} else {
throw new IllegalArgumentException("Cannot visit value with unexpected type: " + value);
}

View File

@@ -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.
@@ -151,6 +151,12 @@ final class YamlRenderer implements ValueRenderer {
String.format("Values of type `DataSize` cannot be rendered as YAML. Value: %s", value));
}
@Override
public void visitBytes(byte[] value) {
throw new RendererException(
String.format("Values of type `Bytes` cannot be rendered as YAML. Value: %s", value));
}
@Override
public void visitPair(Pair<?, ?> value) {
doVisitIterable(value, null);

View File

@@ -0,0 +1,41 @@
/*
* Copyright © 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.
* You may obtain a copy of the License at
*
* https://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 org.pkl.core.ast;
import com.oracle.truffle.api.frame.VirtualFrame;
public class ByteConstantValueNode extends ExpressionNode implements ConstantNode {
private final byte value;
public ByteConstantValueNode(byte value) {
this.value = value;
}
@Override
public Long getValue() {
return (long) value;
}
public byte getByteValue() {
return value;
}
@Override
public Object executeGeneric(VirtualFrame frame) {
return getValue();
}
}

View File

@@ -29,6 +29,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.graalvm.collections.EconomicMap;
@@ -37,6 +38,7 @@ import org.pkl.core.PklBugException;
import org.pkl.core.SecurityManagerException;
import org.pkl.core.TypeParameter;
import org.pkl.core.TypeParameter.Variance;
import org.pkl.core.ast.ByteConstantValueNode;
import org.pkl.core.ast.ConstantNode;
import org.pkl.core.ast.ConstantValueNode;
import org.pkl.core.ast.ExpressionNode;
@@ -77,6 +79,7 @@ import org.pkl.core.ast.expression.generator.GeneratorSpreadNodeGen;
import org.pkl.core.ast.expression.generator.GeneratorWhenNode;
import org.pkl.core.ast.expression.generator.RestoreForBindingsNode;
import org.pkl.core.ast.expression.literal.AmendModuleNodeGen;
import org.pkl.core.ast.expression.literal.BytesLiteralNode;
import org.pkl.core.ast.expression.literal.CheckIsAnnotationClassNode;
import org.pkl.core.ast.expression.literal.ConstantEntriesLiteralNodeGen;
import org.pkl.core.ast.expression.literal.ElementsEntriesLiteralNodeGen;
@@ -160,6 +163,7 @@ import org.pkl.core.packages.PackageLoadError;
import org.pkl.core.runtime.BaseModule;
import org.pkl.core.runtime.ModuleInfo;
import org.pkl.core.runtime.ModuleResolver;
import org.pkl.core.runtime.VmBytes;
import org.pkl.core.runtime.VmClass;
import org.pkl.core.runtime.VmContext;
import org.pkl.core.runtime.VmDataSize;
@@ -524,9 +528,7 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
}
}
@Override
public IntLiteralNode visitIntLiteralExpr(IntLiteralExpr expr) {
var section = createSourceSection(expr);
private <T> T parseNumber(IntLiteralExpr expr, BiFunction<String, Integer, T> parser) {
var text = remove_(expr.getNumber());
var radix = 10;
@@ -547,11 +549,17 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
// also moves negation from runtime to parse time
text = "-" + text;
}
return parser.apply(text, radix);
}
@Override
public IntLiteralNode visitIntLiteralExpr(IntLiteralExpr expr) {
var section = createSourceSection(expr);
try {
var num = Long.parseLong(text, radix);
var num = parseNumber(expr, Long::parseLong);
return new IntLiteralNode(section, num);
} catch (NumberFormatException e) {
var text = expr.getNumber();
throw exceptionBuilder().evalError("intTooLarge", text).withSourceSection(section).build();
}
}
@@ -637,8 +645,8 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
}
// TODO: make sure that no user-defined List/Set/Map method is in scope
// TODO: support qualified calls (e.g., `import "pkl:base"; x = base.List()/Set()/Map()`) for
// correctness
// TODO: support qualified calls (e.g., `import "pkl:base"; x =
// base.List()/Set()/Map()/Bytes()`) for correctness
if (identifier == org.pkl.core.runtime.Identifier.LIST) {
return doVisitListLiteral(expr, argList);
}
@@ -651,6 +659,10 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
return doVisitMapLiteral(expr, argList);
}
if (identifier == org.pkl.core.runtime.Identifier.BYTES_CONSTRUCTOR) {
return doVisitBytesLiteral(expr, argList);
}
var scope = symbolTable.getCurrentScope();
return new ResolveMethodNode(
@@ -1083,6 +1095,18 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
: new MapLiteralNode(createSourceSection(expr), keyAndValueNodes.first);
}
private ExpressionNode doVisitBytesLiteral(Expr expr, ArgumentList argList) {
var elementNodes = createCollectionArgumentBytesNodes(argList);
if (elementNodes.first.length == 0) {
return new ConstantValueNode(VmBytes.EMPTY);
}
return elementNodes.second
? new ConstantValueNode(
createSourceSection(expr), VmBytes.createFromConstantNodes(elementNodes.first))
: new BytesLiteralNode(createSourceSection(expr), elementNodes.first);
}
private Pair<ExpressionNode[], Boolean> createCollectionArgumentNodes(ArgumentList exprs) {
var args = exprs.getArguments();
var elementNodes = new ExpressionNode[args.size()];
@@ -1097,6 +1121,32 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
return Pair.of(elementNodes, isConstantNodes);
}
private Pair<ExpressionNode[], Boolean> createCollectionArgumentBytesNodes(ArgumentList exprs) {
var args = exprs.getArguments();
var expressionNodes = new ExpressionNode[args.size()];
var isAllByteLiterals = true;
for (var i = 0; i < args.size(); i++) {
var expr = args.get(i);
if (expr instanceof IntLiteralExpr intLiteralExpr && isAllByteLiterals) {
try {
var byt = parseNumber(intLiteralExpr, Byte::parseByte);
expressionNodes[i] = new ByteConstantValueNode(byt);
} catch (NumberFormatException e) {
// proceed with initializing a constant value node; we'll throw an error inside
// BytesLiteralNode.
isAllByteLiterals = false;
expressionNodes[i] = visitExpr(expr);
}
} else {
isAllByteLiterals = false;
expressionNodes[i] = visitExpr(expr);
}
}
return Pair.of(expressionNodes, isAllByteLiterals);
}
public GeneratorMemberNode visitObjectMember(org.pkl.parser.syntax.ObjectMember member) {
return (GeneratorMemberNode) member.accept(this);
}

View File

@@ -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.
@@ -78,4 +78,9 @@ public abstract class AdditionNode extends BinaryExpressionNode {
protected VmMap eval(VmMap left, VmMap right) {
return left.concatenate(right);
}
@Specialization
protected VmBytes eval(VmBytes left, VmBytes right) {
return left.concatenate(right);
}
}

View File

@@ -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.
@@ -98,6 +98,18 @@ public abstract class SubscriptNode extends BinaryExpressionNode {
return readMember(dynamic, key, callNode);
}
@Specialization
protected long eval(VmBytes receiver, long index) {
if (index < 0 || index >= receiver.getLength()) {
CompilerDirectives.transferToInterpreter();
throw exceptionBuilder()
.evalError("elementIndexOutOfRange", index, 0, receiver.getLength() - 1)
.withProgramValue("Value", receiver)
.build();
}
return receiver.get(index);
}
private Object readMember(VmObject object, Object key, IndirectCallNode callNode) {
var result = VmUtils.readMemberOrNull(object, key, callNode);
if (result != null) return result;

View File

@@ -118,6 +118,14 @@ public abstract class GeneratorForNode extends GeneratorMemberNode {
}
}
@Specialization
protected void eval(VirtualFrame frame, Object parent, ObjectData data, VmBytes iterable) {
long idx = 0;
for (var byt : iterable.getBytes()) {
executeIteration(frame, parent, data, idx++, (long) byt);
}
}
@Fallback
@SuppressWarnings("unused")
protected void fallback(VirtualFrame frame, Object parent, ObjectData data, Object iterable) {

View File

@@ -29,6 +29,7 @@ import org.pkl.core.ast.member.ObjectMember;
import org.pkl.core.runtime.BaseModule;
import org.pkl.core.runtime.Identifier;
import org.pkl.core.runtime.Iterators.TruffleIterator;
import org.pkl.core.runtime.VmBytes;
import org.pkl.core.runtime.VmClass;
import org.pkl.core.runtime.VmCollection;
import org.pkl.core.runtime.VmDynamic;
@@ -161,6 +162,16 @@ public abstract class GeneratorSpreadNode extends GeneratorMemberNode {
doEvalIntSeq(frame, parent, data, iterable);
}
@Specialization
protected void eval(VirtualFrame frame, VmObject parent, ObjectData data, VmBytes iterable) {
doEvalBytes(frame, parent.getVmClass(), data, iterable);
}
@Specialization
protected void eval(VirtualFrame frame, VmClass parent, ObjectData data, VmBytes iterable) {
doEvalBytes(frame, parent, data, iterable);
}
@Fallback
@SuppressWarnings("unused")
protected void fallback(VirtualFrame frame, Object parent, ObjectData data, Object iterable) {
@@ -266,6 +277,18 @@ public abstract class GeneratorSpreadNode extends GeneratorMemberNode {
spreadIterable(frame, data, iterable);
}
private void doEvalBytes(VirtualFrame frame, VmClass parent, ObjectData data, VmBytes iterable) {
if (isTypedObjectClass(parent) || parent == getMappingClass()) {
CompilerDirectives.transferToInterpreter();
throw exceptionBuilder()
.evalError("cannotSpreadObject", iterable.getVmClass(), parent)
.withHint("`Bytes` can only be spread into objects of type `Dynamic` and `Listing`.")
.withProgramValue("Value", iterable)
.build();
}
spreadIterable(frame, data, iterable);
}
private void cannotHaveMember(VmClass clazz, ObjectMember member) {
CompilerDirectives.transferToInterpreter();
var builder = exceptionBuilder();

View File

@@ -0,0 +1,71 @@
/*
* Copyright © 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.
* You may obtain a copy of the License at
*
* https://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 org.pkl.core.ast.expression.literal;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.source.SourceSection;
import org.pkl.core.ast.ExpressionNode;
import org.pkl.core.ast.type.TypeNode;
import org.pkl.core.ast.type.TypeNode.UInt8TypeAliasTypeNode;
import org.pkl.core.ast.type.VmTypeMismatchException;
import org.pkl.core.runtime.VmBytes;
import org.pkl.core.runtime.VmUtils;
import org.pkl.core.util.LateInit;
@NodeInfo(shortName = "Bytes()")
public final class BytesLiteralNode extends ExpressionNode {
@Children private final ExpressionNode[] elements;
@Child @LateInit private TypeNode typeNode;
public BytesLiteralNode(SourceSection sourceSection, ExpressionNode[] elements) {
super(sourceSection);
this.elements = elements;
}
private TypeNode getTypeNode() {
if (typeNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
typeNode = new UInt8TypeAliasTypeNode();
}
return typeNode;
}
@Override
@ExplodeLoop
public Object executeGeneric(VirtualFrame frame) {
var bytes = new byte[elements.length];
var typeNode = getTypeNode();
for (var i = 0; i < elements.length; i++) {
var elem = elements[i];
try {
var result = (Long) typeNode.execute(frame, elem.executeGeneric(frame));
bytes[i] = result.byteValue();
} catch (VmTypeMismatchException err) {
// optimization: don't create a new stack frame to check the type, but pretend that one
// exists.
err.putInsertedStackFrame(
getRootNode().getCallTarget(),
VmUtils.createStackFrame(elem.getSourceSection(), getRootNode().getName()));
throw err.toVmException();
}
}
return new VmBytes(bytes);
}
}

View File

@@ -2153,52 +2153,71 @@ public abstract class TypeNode extends PklNode {
}
}
public static final class UIntTypeAliasTypeNode extends IntSlotTypeNode {
private final VmTypeAlias typeAlias;
private final long mask;
public UIntTypeAliasTypeNode(VmTypeAlias typeAlias, long mask) {
protected abstract static class IntMaskSlotTypeNode extends IntSlotTypeNode {
protected final long mask;
IntMaskSlotTypeNode(long mask) {
super(VmUtils.unavailableSourceSection());
this.typeAlias = typeAlias;
this.mask = mask;
}
@Override
protected Object executeLazily(VirtualFrame frame, Object value) {
protected final Object executeLazily(VirtualFrame frame, Object value) {
var typealias = getVmTypeAlias();
assert typealias != null;
if (value instanceof Long l) {
if ((l & mask) == l) return value;
throw new VmTypeMismatchException.Constraint(typeAlias.getConstraintSection(), value);
throw new VmTypeMismatchException.Constraint(typealias.getConstraintSection(), value);
}
throw new VmTypeMismatchException.Simple(
typeAlias.getBaseTypeSection(), value, BaseModule.getIntClass());
typealias.getBaseTypeSection(), value, BaseModule.getIntClass());
}
@Override
public VmClass getVmClass() {
public final VmClass getVmClass() {
return BaseModule.getIntClass();
}
@Override
public final VmTyped getMirror() {
return MirrorFactories.typeAliasTypeFactory.create(this);
}
@Override
public final boolean doIsEquivalentTo(TypeNode other) {
return other instanceof UIntTypeAliasTypeNode aliasTypeNode && mask == aliasTypeNode.mask;
}
@Override
protected final boolean acceptTypeNode(TypeNodeConsumer consumer) {
return consumer.accept(this);
}
}
public static final class UIntTypeAliasTypeNode extends IntMaskSlotTypeNode {
private final VmTypeAlias typeAlias;
public UIntTypeAliasTypeNode(VmTypeAlias typeAlias, long mask) {
super(mask);
this.typeAlias = typeAlias;
}
@Override
public VmTypeAlias getVmTypeAlias() {
return typeAlias;
}
}
@Override
public VmTyped getMirror() {
return MirrorFactories.typeAliasTypeFactory.create(this);
public static final class UInt8TypeAliasTypeNode extends IntMaskSlotTypeNode {
public UInt8TypeAliasTypeNode() {
super(0x00000000000000FFL);
}
@Override
public boolean doIsEquivalentTo(TypeNode other) {
return other instanceof UIntTypeAliasTypeNode aliasTypeNode && mask == aliasTypeNode.mask;
}
@Override
protected boolean acceptTypeNode(TypeNodeConsumer consumer) {
return consumer.accept(this);
public VmTypeAlias getVmTypeAlias() {
return BaseModule.getUInt8TypeAlias();
}
}

View File

@@ -174,7 +174,7 @@ public abstract class UnresolvedTypeNode extends PklNode {
case "Int8":
return new Int8TypeAliasTypeNode();
case "UInt8":
return new UIntTypeAliasTypeNode(alias, 0x00000000000000FFL);
return new UInt8TypeAliasTypeNode();
case "Int16":
return new Int16TypeAliasTypeNode();
case "UInt16":

View File

@@ -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.
@@ -17,7 +17,7 @@ package org.pkl.core.resource;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import org.pkl.core.util.ByteArrayUtils;
/** An external (file, HTTP, etc.) resource. */
public record Resource(URI uri, byte[] bytes) {
@@ -44,6 +44,6 @@ public record Resource(URI uri, byte[] bytes) {
/** Returns the content of this resource in Base64. */
public String getBase64() {
return Base64.getEncoder().encodeToString(bytes);
return ByteArrayUtils.base64(bytes);
}
}

View File

@@ -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.
@@ -71,6 +71,10 @@ public final class BaseModule extends StdLibModule {
return DataSizeClass.instance;
}
public static VmClass getBytesClass() {
return BytesClass.instance;
}
public static VmClass getIntSeqClass() {
return IntSeqClass.instance;
}
@@ -219,6 +223,10 @@ public final class BaseModule extends StdLibModule {
return MixinTypeAlias.instance;
}
public static VmTypeAlias getUInt8TypeAlias() {
return UInt8TypeAlias.instance;
}
private static final class AnyClass {
static final VmClass instance = loadClass("Any");
}
@@ -259,6 +267,10 @@ public final class BaseModule extends StdLibModule {
static final VmClass instance = loadClass("DataSize");
}
private static final class BytesClass {
static final VmClass instance = loadClass("Bytes");
}
private static final class IntSeqClass {
static final VmClass instance = loadClass("IntSeq");
}
@@ -383,6 +395,10 @@ public final class BaseModule extends StdLibModule {
static final VmTypeAlias instance = loadTypeAlias("Int32");
}
private static final class UInt8TypeAlias {
static final VmTypeAlias instance = loadTypeAlias("UInt8");
}
private static final class MixinTypeAlias {
static final VmTypeAlias instance = loadTypeAlias("Mixin");
}

View File

@@ -75,6 +75,11 @@ public final class Identifier implements Comparable<Identifier> {
// XmlCData}
public static final Identifier TEXT = get("text");
public static final Identifier BYTES_CONSTRUCTOR = get("Bytes");
// members of pkl.base#{FileOutput}
public static final Identifier BYTES = get("bytes");
// members of pkl.base#ModuleOutput, pkl.base#Resource, pkl.base#String
public static final Identifier BASE64 = get("base64");

View File

@@ -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.
@@ -53,7 +53,7 @@ public final class ResourceManager {
new VmObjectFactory<Resource>(BaseModule::getResourceClass)
.addProperty("uri", resource -> resource.uri().toString())
.addProperty("text", Resource::getText)
.addProperty("base64", Resource::getBase64);
.addProperty("bytes", resource -> new VmBytes(resource.bytes()));
}
@TruffleBoundary

View File

@@ -0,0 +1,208 @@
/*
* Copyright © 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.
* You may obtain a copy of the License at
*
* https://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 org.pkl.core.runtime;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.CompilerDirectives.ValueType;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.PrimitiveIterator;
import org.pkl.core.DataSizeUnit;
import org.pkl.core.ast.ByteConstantValueNode;
import org.pkl.core.ast.ExpressionNode;
import org.pkl.core.util.ByteArrayUtils;
import org.pkl.core.util.Nullable;
@ValueType
public final class VmBytes extends VmValue implements Iterable<Long> {
private @Nullable VmList vmList;
private @Nullable String base64;
private @Nullable String hex;
private final byte[] bytes;
private @Nullable VmDataSize size;
public static VmBytes EMPTY = new VmBytes(new byte[0]);
@TruffleBoundary
public static VmBytes createFromConstantNodes(ExpressionNode[] elements) {
if (elements.length == 0) {
return EMPTY;
}
var bytes = new byte[elements.length];
for (var i = 0; i < elements.length; i++) {
var exprNode = elements[i];
// guaranteed by AstBuilder
assert exprNode instanceof ByteConstantValueNode;
bytes[i] = ((ByteConstantValueNode) exprNode).getByteValue();
}
return new VmBytes(bytes);
}
public VmBytes(byte[] bytes) {
this.bytes = bytes;
}
public VmBytes(VmList vmList, byte[] bytes) {
this.vmList = vmList;
this.bytes = bytes;
}
@Override
public VmClass getVmClass() {
return BaseModule.getBytesClass();
}
@Override
public void force(boolean allowUndefinedValues) {
// do nothing
}
@Override
public byte[] export() {
return bytes;
}
@Override
public void accept(VmValueVisitor visitor) {
visitor.visitBytes(this);
}
@Override
public <T> T accept(VmValueConverter<T> converter, Iterable<Object> path) {
return converter.convertBytes(this, path);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof VmBytes vmBytes)) {
return false;
}
return Arrays.equals(bytes, vmBytes.bytes);
}
@Override
public int hashCode() {
return Arrays.hashCode(bytes);
}
public byte[] getBytes() {
return bytes;
}
public long get(long index) {
return getBytes()[(int) index];
}
public VmBytes concatenate(VmBytes right) {
if (bytes.length == 0) return right;
if (right.bytes.length == 0) return this;
var newBytes = new byte[bytes.length + right.bytes.length];
System.arraycopy(bytes, 0, newBytes, 0, bytes.length);
System.arraycopy(right.bytes, 0, newBytes, bytes.length, right.bytes.length);
return new VmBytes(newBytes);
}
public VmList toList() {
if (vmList == null) {
vmList = VmList.create(bytes);
}
return vmList;
}
public String base64() {
if (base64 == null) {
base64 = ByteArrayUtils.base64(bytes);
}
return base64;
}
public String hex() {
if (hex == null) {
hex = ByteArrayUtils.toHex(bytes);
}
return hex;
}
public int getLength() {
return bytes.length;
}
public VmDataSize getSize() {
if (size == null) {
if (getLength() == 0) {
// avoid log10(0), which gives us -Infinity
size = new VmDataSize(0, DataSizeUnit.BYTES);
} else {
var magnitude = (int) Math.floor(Math.log10(getLength()));
var unit =
switch (magnitude) {
case 0, 1, 2 -> DataSizeUnit.BYTES;
case 3, 4, 5 -> DataSizeUnit.KILOBYTES;
case 6, 7, 8 -> DataSizeUnit.MEGABYTES;
case 9, 10, 11 -> DataSizeUnit.GIGABYTES;
// in practice, can never happen (Java can only hold at most math.maxInt bytes).
case 12, 13, 14 -> DataSizeUnit.TERABYTES;
default -> DataSizeUnit.PETABYTES;
};
size = new VmDataSize(getLength(), DataSizeUnit.BYTES).convertTo(unit);
}
}
return size;
}
@Override
public String toString() {
var sb = new StringBuilder("Bytes(");
var isFirst = true;
for (var byt : bytes) {
if (isFirst) {
isFirst = false;
} else {
sb.append(", ");
}
sb.append(Byte.toUnsignedInt(byt));
}
sb.append(")");
return sb.toString();
}
@Override
public Iterator<Long> iterator() {
return new PrimitiveIterator.OfLong() {
int index = 0;
@Override
public boolean hasNext() {
return index < bytes.length;
}
@Override
public long nextLong() {
if (!hasNext()) {
CompilerDirectives.transferToInterpreter();
throw new NoSuchElementException();
}
var result = Byte.toUnsignedLong(bytes[index]);
index += 1;
return result;
}
};
}
}

View File

@@ -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.
@@ -98,6 +98,16 @@ public final class VmList extends VmCollection {
return new VmList(vector.immutable());
}
@TruffleBoundary
public static VmList create(byte[] elements) {
if (elements.length == 0) return EMPTY;
var vector = RrbTree.emptyMutable();
for (var elem : elements) {
vector.append(Byte.toUnsignedLong(elem));
}
return new VmList(vector.immutable());
}
@TruffleBoundary
public static VmList create(Object[] elements, int length) {
if (elements.length == 0) return EMPTY;

View File

@@ -175,6 +175,10 @@ public final class VmUtils {
return (String) VmUtils.readMember((VmObjectLike) receiver, Identifier.TEXT);
}
public static VmBytes readBytesProperty(VmObjectLike receiver) {
return (VmBytes) VmUtils.readMember(receiver, Identifier.BYTES);
}
@TruffleBoundary
public static Object readMember(VmObjectLike receiver, Object memberKey) {
var result = readMemberOrNull(receiver, memberKey);

View File

@@ -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.
@@ -52,6 +52,8 @@ public interface VmValueConverter<T> {
T convertDataSize(VmDataSize value, Iterable<Object> path);
T convertBytes(VmBytes vmBytes, Iterable<Object> path);
T convertIntSeq(VmIntSeq value, Iterable<Object> path);
T convertList(VmList value, Iterable<Object> path);

View File

@@ -114,6 +114,45 @@ public final class VmValueRenderer {
append(value);
}
private void renderByteSize(VmDataSize size) {
var value = size.getValue();
if (value % 1 == 0) {
append((int) value);
} else if ((value * 10) % 1 == 0) {
append(String.format("%.1f", value));
} else {
append(String.format("%.2f", value));
}
append(".");
append(size.getUnit());
}
@Override
public void visitBytes(VmBytes value) {
append("Bytes(");
// truncate bytes if over 8 bytes
renderByteElems(value, Math.min(value.getLength(), 8));
if (value.getLength() > 8) {
append(", ... <total size: ");
renderByteSize(value.getSize());
append(">");
}
append(")");
}
private void renderByteElems(VmBytes value, int limit) {
var isFirst = true;
var bytes = value.getBytes();
for (var i = 0; i < limit; i++) {
if (isFirst) {
isFirst = false;
} else {
append(", ");
}
append(Byte.toUnsignedInt(bytes[i]));
}
}
@Override
public void visitPair(VmPair value) {
append("Pair(");

View File

@@ -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.
@@ -30,6 +30,8 @@ public interface VmValueVisitor {
void visitDataSize(VmDataSize value);
void visitBytes(VmBytes value);
void visitIntSeq(VmIntSeq value);
void visitList(VmList value);

View File

@@ -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.
@@ -30,6 +30,7 @@ public final class PklConverter implements VmValueConverter<Object> {
private final @Nullable VmFunction floatConverter;
private final @Nullable VmFunction durationConverter;
private final @Nullable VmFunction dataSizeConverter;
private final @Nullable VmFunction bytesConverter;
private final @Nullable VmFunction intSeqConverter;
private final @Nullable VmFunction listConverter;
private final @Nullable VmFunction setConverter;
@@ -56,6 +57,7 @@ public final class PklConverter implements VmValueConverter<Object> {
floatConverter = typeConverters.get(BaseModule.getFloatClass());
durationConverter = typeConverters.get(BaseModule.getDurationClass());
dataSizeConverter = typeConverters.get(BaseModule.getDataSizeClass());
bytesConverter = typeConverters.get(BaseModule.getBytesClass());
intSeqConverter = typeConverters.get(BaseModule.getIntSeqClass());
listConverter = typeConverters.get(BaseModule.getListClass());
setConverter = typeConverters.get(BaseModule.getSetClass());
@@ -100,6 +102,11 @@ public final class PklConverter implements VmValueConverter<Object> {
return doConvert(value, path, dataSizeConverter);
}
@Override
public Object convertBytes(VmBytes value, Iterable<Object> path) {
return doConvert(value, path, bytesConverter);
}
@Override
public Object convertIntSeq(VmIntSeq value, Iterable<Object> path) {
return doConvert(value, path, intSeqConverter);

View File

@@ -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.
@@ -142,4 +142,13 @@ public final class BaseNodes {
return new VmIntSeq(first, second, 1L);
}
}
public abstract static class Bytes extends ExternalMethod1Node {
@Specialization
protected VmList eval(VirtualFrame frame, VmTyped self, Object args) {
// invocations of this method are handled specially in AstBuilder
CompilerDirectives.transferToInterpreter();
throw exceptionBuilder().bug("Node `BaseNodes.Bytes` should never be executed.").build();
}
}
}

View File

@@ -0,0 +1,121 @@
/*
* Copyright © 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.
* You may obtain a copy of the License at
*
* https://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 org.pkl.core.stdlib.base;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Specialization;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import org.pkl.core.runtime.VmBytes;
import org.pkl.core.runtime.VmDataSize;
import org.pkl.core.runtime.VmList;
import org.pkl.core.runtime.VmNull;
import org.pkl.core.stdlib.ExternalMethod0Node;
import org.pkl.core.stdlib.ExternalMethod1Node;
import org.pkl.core.stdlib.ExternalPropertyNode;
import org.pkl.core.util.ByteArrayUtils;
public final class BytesNodes {
private BytesNodes() {}
public abstract static class toList extends ExternalMethod0Node {
@Specialization
protected VmList eval(VmBytes self) {
return self.toList();
}
}
public abstract static class length extends ExternalPropertyNode {
@Specialization
protected long eval(VmBytes self) {
return self.getLength();
}
}
public abstract static class size extends ExternalPropertyNode {
@Specialization
protected VmDataSize eval(VmBytes self) {
return self.getSize();
}
}
public abstract static class base64 extends ExternalPropertyNode {
@Specialization
protected String eval(VmBytes self) {
return self.base64();
}
}
public abstract static class hex extends ExternalPropertyNode {
@Specialization
protected String eval(VmBytes self) {
return self.hex();
}
}
public abstract static class md5 extends ExternalPropertyNode {
@Specialization
protected String eval(VmBytes self) {
return ByteArrayUtils.md5(self.getBytes());
}
}
public abstract static class sha1 extends ExternalPropertyNode {
@Specialization
protected String eval(VmBytes self) {
return ByteArrayUtils.sha1(self.getBytes());
}
}
public abstract static class sha256 extends ExternalPropertyNode {
@Specialization
protected String eval(VmBytes self) {
return ByteArrayUtils.sha256(self.getBytes());
}
}
public abstract static class sha256Int extends ExternalPropertyNode {
@Specialization
protected long eval(VmBytes self) {
return ByteArrayUtils.sha256Int(self.getBytes());
}
}
public abstract static class getOrNull extends ExternalMethod1Node {
@Specialization
protected Object eval(VmBytes self, long index) {
if (index < 0 || index >= self.getLength()) {
return VmNull.withoutDefault();
}
return self.get(index);
}
}
public abstract static class decodeToString extends ExternalMethod1Node {
@Specialization
protected String eval(VmBytes self, String charset) {
try {
var byteBuffer = ByteBuffer.wrap(self.getBytes());
var decoder = Charset.forName(charset).newDecoder();
return decoder.decode(byteBuffer).toString();
} catch (CharacterCodingException e) {
CompilerDirectives.transferToInterpreter();
throw exceptionBuilder().evalError("characterCodingException", charset).build();
}
}
}
}

View File

@@ -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.
@@ -126,6 +126,11 @@ public final class JsonRendererNodes {
cannotRenderTypeAddConverter(value);
}
@Override
public void visitBytes(VmBytes value) {
cannotRenderTypeAddConverter(value);
}
@Override
public void visitRegex(VmRegex value) {
cannotRenderTypeAddConverter(value);

View File

@@ -18,17 +18,22 @@ package org.pkl.core.stdlib.base;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.LoopNode;
import org.pkl.core.ast.expression.binary.*;
import org.pkl.core.ast.internal.IsInstanceOfNode;
import org.pkl.core.ast.internal.IsInstanceOfNodeGen;
import org.pkl.core.ast.lambda.*;
import org.pkl.core.ast.type.TypeNode;
import org.pkl.core.ast.type.TypeNode.UInt8TypeAliasTypeNode;
import org.pkl.core.ast.type.VmTypeMismatchException;
import org.pkl.core.runtime.*;
import org.pkl.core.stdlib.*;
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.EconomicSets;
import org.pkl.core.util.LateInit;
// duplication between ListNodes and SetNodes is "intentional"
// (sharing nodes between VmCollection subtypes results in
@@ -1321,4 +1326,34 @@ public final class ListNodes {
return self.toDynamic();
}
}
public abstract static class toBytes extends ExternalMethod0Node {
@Child @LateInit private TypeNode typeNode;
private TypeNode getTypeNode() {
if (typeNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
typeNode = new UInt8TypeAliasTypeNode();
}
return typeNode;
}
@Specialization
protected VmBytes eval(VirtualFrame frame, VmList self) {
var typeNode = getTypeNode();
var bytes = new byte[self.getLength()];
try {
for (var i = 0; i < self.getLength(); i++) {
var elem = self.get(i);
var num = (Long) typeNode.executeEagerly(frame, elem);
bytes[i] = num.byteValue();
}
} catch (VmTypeMismatchException e) {
CompilerDirectives.transferToInterpreter();
throw e.toVmException();
}
return new VmBytes(self, bytes);
}
}
}

View File

@@ -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.
@@ -54,7 +54,6 @@ public final class PListRendererNodes {
}
// keep in sync with org.pkl.core.PListRenderer
@SuppressWarnings("HttpUrlsUsage")
private static final class PListRenderer extends AbstractRenderer {
// it's safe (though not required) to escape all the following characters in XML text nodes
@@ -124,6 +123,13 @@ public final class PListRendererNodes {
.build();
}
@Override
public void visitBytes(VmBytes value) {
builder.append("<data>");
builder.append(value.base64());
builder.append("</data>");
}
@Override
public void visitRegex(VmRegex value) {
throw new VmExceptionBuilder()

View File

@@ -17,6 +17,7 @@ package org.pkl.core.stdlib.base;
import org.pkl.core.ValueFormatter;
import org.pkl.core.runtime.Identifier;
import org.pkl.core.runtime.VmBytes;
import org.pkl.core.runtime.VmDataSize;
import org.pkl.core.runtime.VmDuration;
import org.pkl.core.runtime.VmDynamic;
@@ -99,6 +100,11 @@ public final class PcfRenderer extends AbstractRenderer {
builder.append(value);
}
@Override
public void visitBytes(VmBytes value) {
builder.append(value);
}
@Override
public void visitPair(VmPair value) {
builder.append("Pair(");

View File

@@ -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.
@@ -18,6 +18,7 @@ package org.pkl.core.stdlib.base;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Specialization;
import org.pkl.core.runtime.Identifier;
import org.pkl.core.runtime.VmBytes;
import org.pkl.core.runtime.VmDataSize;
import org.pkl.core.runtime.VmDuration;
import org.pkl.core.runtime.VmDynamic;
@@ -117,6 +118,11 @@ public final class PropertiesRendererNodes {
cannotRenderTypeAddConverter(value);
}
@Override
public void visitBytes(VmBytes value) {
cannotRenderTypeAddConverter(value);
}
@Override
public void visitIntSeq(VmIntSeq value) {
cannotRenderTypeAddConverter(value);

View File

@@ -1,102 +0,0 @@
/*
* Copyright © 2024 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.
* You may obtain a copy of the License at
*
* https://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 org.pkl.core.stdlib.base;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Specialization;
import java.util.*;
import org.pkl.core.resource.Resource;
import org.pkl.core.runtime.Identifier;
import org.pkl.core.runtime.VmTyped;
import org.pkl.core.runtime.VmUtils;
import org.pkl.core.stdlib.ExternalPropertyNode;
import org.pkl.core.util.ByteArrayUtils;
public final class ResourceNodes {
private ResourceNodes() {}
public abstract static class md5 extends ExternalPropertyNode {
@TruffleBoundary
@Specialization(guards = "self.hasExtraStorage()")
protected String evalWithExtraStorage(VmTyped self) {
var resource = (Resource) self.getExtraStorage();
return ByteArrayUtils.md5(resource.bytes());
}
@TruffleBoundary
@Specialization(guards = "!self.hasExtraStorage()")
protected String evalWithoutExtraStorage(VmTyped self) {
// `pkl.base#Resource` is designed to allow direct instantiation,
// in which case it isn't backed by a `org.pkl.core.resource.Resource`.
// It seems the best we can do here
// is to expect `pkl.base#Resource.base64` to be set and decode it.
var base64 = (String) VmUtils.readMember(self, Identifier.BASE64);
var bytes = Base64.getDecoder().decode(base64);
return ByteArrayUtils.md5(bytes);
}
}
public abstract static class sha1 extends ExternalPropertyNode {
@TruffleBoundary
@Specialization(guards = "self.hasExtraStorage()")
protected String evalWithExtraStorage(VmTyped self) {
var resource = (Resource) self.getExtraStorage();
return ByteArrayUtils.sha1(resource.bytes());
}
@TruffleBoundary
@Specialization(guards = "!self.hasExtraStorage()")
protected String evalWithoutExtraStorage(VmTyped self) {
var base64 = (String) VmUtils.readMember(self, Identifier.BASE64);
var bytes = Base64.getDecoder().decode(base64);
return ByteArrayUtils.sha1(bytes);
}
}
public abstract static class sha256 extends ExternalPropertyNode {
@TruffleBoundary
@Specialization(guards = "self.hasExtraStorage()")
protected String evalWithExtraStorage(VmTyped self) {
var resource = (Resource) self.getExtraStorage();
return ByteArrayUtils.sha256(resource.bytes());
}
@TruffleBoundary
@Specialization(guards = "!self.hasExtraStorage()")
protected String evalWithoutExtraStorage(VmTyped self) {
var base64 = (String) VmUtils.readMember(self, Identifier.BASE64);
var bytes = Base64.getDecoder().decode(base64);
return ByteArrayUtils.sha256(bytes);
}
}
public abstract static class sha256Int extends ExternalPropertyNode {
@TruffleBoundary
@Specialization(guards = "self.hasExtraStorage()")
protected long evalWithExtraStorage(VmTyped self) {
var resource = (Resource) self.getExtraStorage();
return ByteArrayUtils.sha256Int(resource.bytes());
}
@TruffleBoundary
@Specialization(guards = "!self.hasExtraStorage()")
protected long evalWithoutExtraStorage(VmTyped self) {
var base64 = (String) VmUtils.readMember(self, Identifier.BASE64);
var bytes = Base64.getDecoder().decode(base64);
return ByteArrayUtils.sha256Int(bytes);
}
}
}

View File

@@ -19,9 +19,11 @@ import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.LoopNode;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.*;
import org.pkl.core.PklBugException;
import org.pkl.core.ast.lambda.ApplyVmFunction1Node;
import org.pkl.core.ast.lambda.ApplyVmFunction1NodeGen;
import org.pkl.core.runtime.*;
@@ -149,6 +151,19 @@ public final class StringNodes {
}
}
public abstract static class isBase64 extends ExternalPropertyNode {
@Specialization
@TruffleBoundary
protected boolean eval(String self) {
try {
Base64.getDecoder().decode(self);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
}
public abstract static class chars extends ExternalPropertyNode {
@Specialization
@TruffleBoundary
@@ -900,7 +915,7 @@ public final class StringNodes {
@TruffleBoundary
@Specialization
protected String eval(String self) {
return Base64.getEncoder().encodeToString(self.getBytes(StandardCharsets.UTF_8));
return ByteArrayUtils.base64(self.getBytes(StandardCharsets.UTF_8));
}
}
@@ -920,6 +935,35 @@ public final class StringNodes {
}
}
public abstract static class base64DecodedBytes extends ExternalPropertyNode {
@TruffleBoundary
@Specialization
protected VmBytes eval(String self) {
try {
return new VmBytes(Base64.getDecoder().decode(self));
} catch (IllegalArgumentException e) {
throw exceptionBuilder()
.adhocEvalError(e.getMessage())
.withProgramValue("String", self)
.withCause(e)
.build();
}
}
}
public abstract static class encodeToBytes extends ExternalMethod1Node {
@TruffleBoundary
@Specialization
protected VmBytes eval(String self, String charsetName) {
try {
var bytes = self.getBytes(charsetName);
return new VmBytes(bytes);
} catch (UnsupportedEncodingException e) {
throw PklBugException.unreachableCode();
}
}
}
@TruffleBoundary
private static String substringFrom(String string, int start) {
return string.substring(start);

View File

@@ -18,6 +18,7 @@ package org.pkl.core.stdlib.base;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Specialization;
import org.pkl.core.runtime.Identifier;
import org.pkl.core.runtime.VmBytes;
import org.pkl.core.runtime.VmCollection;
import org.pkl.core.runtime.VmDataSize;
import org.pkl.core.runtime.VmDuration;
@@ -177,6 +178,11 @@ public final class YamlRendererNodes {
cannotRenderTypeAddConverter(value);
}
@Override
public void visitBytes(VmBytes value) {
cannotRenderTypeAddConverter(value);
}
@Override
public void visitRegex(VmRegex value) {
cannotRenderTypeAddConverter(value);

View File

@@ -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.
@@ -21,6 +21,7 @@ import java.util.Set;
import java.util.regex.Pattern;
import org.pkl.core.runtime.Identifier;
import org.pkl.core.runtime.JsonnetModule;
import org.pkl.core.runtime.VmBytes;
import org.pkl.core.runtime.VmDataSize;
import org.pkl.core.runtime.VmDuration;
import org.pkl.core.runtime.VmDynamic;
@@ -199,6 +200,11 @@ public final class RendererNodes {
cannotRenderTypeAddConverter(value);
}
@Override
public void visitBytes(VmBytes value) {
cannotRenderTypeAddConverter(value);
}
@Override
public void visitIntSeq(VmIntSeq value) {
cannotRenderTypeAddConverter(value);

View File

@@ -44,6 +44,7 @@ import org.pkl.core.ast.type.TypeNode.UnionOfStringLiteralsTypeNode;
import org.pkl.core.ast.type.TypeNode.UnionTypeNode;
import org.pkl.core.ast.type.VmTypeMismatchException;
import org.pkl.core.runtime.Identifier;
import org.pkl.core.runtime.VmBytes;
import org.pkl.core.runtime.VmClass;
import org.pkl.core.runtime.VmDataSize;
import org.pkl.core.runtime.VmDuration;
@@ -522,6 +523,14 @@ public final class RendererNodes {
.build();
}
@Override
public void visitBytes(VmBytes value) {
throw new VmExceptionBuilder()
.evalError("cannotRenderTypeAddConverter", "Bytes", "Protobuf")
.withProgramValue("Value", value)
.build();
}
@Override
public void visitIntSeq(VmIntSeq value) {
writePropertyName();

View File

@@ -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.
@@ -154,6 +154,11 @@ public final class RendererNodes {
cannotRenderTypeAddConverter(value);
}
@Override
public void visitBytes(VmBytes value) {
cannotRenderTypeAddConverter(value);
}
@Override
public void visitPair(VmPair value) {
cannotRenderTypeAddConverter(value);

View File

@@ -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.
@@ -17,11 +17,16 @@ package org.pkl.core.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import org.pkl.core.runtime.VmExceptionBuilder;
public final class ByteArrayUtils {
private ByteArrayUtils() {}
public static String base64(byte[] input) {
return Base64.getEncoder().encodeToString(input);
}
public static String md5(byte[] input) {
return hash(input, "MD5");
}

View File

@@ -1064,3 +1064,9 @@ External reader process has already terminated.
invalidOpaqueFileUri=\
File URIs must have a path that starts with `/` (e.g. file:/path/to/my_module.pkl).\n\
To resolve relative paths, remove the scheme prefix (remove "file:").
invalidStringBase64=\
`{0}` is not in base64 encoding.
characterCodingException=\
Invalid bytes for charset "{0}".

View File

@@ -0,0 +1,51 @@
amends "../snippetTest.pkl"
local megaBytes = IntSeq(0, 999).map((_) -> 0).toBytes()
examples {
["md5"] {
Bytes(1, 2, 3, 4).md5
Bytes().md5
}
["sha256"] {
Bytes(1, 2, 3, 4).sha256
Bytes().sha256
}
["sha1"] {
Bytes(1, 2, 3, 4).sha1
Bytes().sha1
}
["toString"] {
Bytes(1, 2, 3, 4).toString()
Bytes().toString()
}
["base64"] {
Bytes(1, 2, 3, 4).base64
Bytes().base64
"AQIDBA==".base64DecodedBytes.base64
}
["hex"] {
Bytes(1, 2, 3, 4).hex
Bytes().hex
}
["length"] {
Bytes().length
Bytes(1, 2, 3, 4).length
megaBytes.length
}
["size"] {
Bytes().size
Bytes(1, 2, 3, 4).size
megaBytes.size
}
["decodeToString()"] {
Bytes(0x66, 0x6f, 0x6f, 0x20, 0x62, 0x61, 0x72).decodeToString("UTF-8")
"foo bar".encodeToBytes("UTF-8").decodeToString("UTF-8")
}
["getOrNull()"] {
Bytes(1, 2, 3).getOrNull(0)
Bytes(1, 2, 3).getOrNull(1)
Bytes(1, 2, 3).getOrNull(2)
Bytes(1, 2, 3).getOrNull(3)
}
}

View File

@@ -357,6 +357,13 @@ examples {
list1.toDynamic()
List().toDynamic()
}
["toBytes()"] {
list1.toBytes()
List().toBytes()
module.catch(() -> List(null).toBytes())
module.catch(() -> List(-1).toBytes())
}
["filterNonNull()"] {
list1.filterNonNull()

View File

@@ -18,6 +18,12 @@ facts {
!str1.isBlank
}
["isBase64"] {
"".isBase64
"AQIDBA==".isBase64
!"hello there".isBase64
}
["lastIndex"] {
for (s in List(str1, str2, str3)) {
s.length == s.lastIndex + 1
@@ -28,6 +34,10 @@ facts {
"".base64.base64Decoded == ""
quickBrownFox.base64.base64Decoded == quickBrownFox
}
["base64DecodedBytes"] {
"AQIDBA==".base64DecodedBytes == Bytes(1, 2, 3, 4)
}
["contains()"] {
str1.contains(str2)
@@ -487,4 +497,19 @@ examples {
["base64Decoded"] {
module.catch(() -> "~~~".base64Decoded)
}
["base64DecodedBytes"] {
module.catch(() -> "~~~".base64DecodedBytes)
"AQIDBA==".base64DecodedBytes
}
["encodeToBytes()"] {
"~~~".encodeToBytes("UTF-8")
"🏀".encodeToBytes("UTF-8")
"~~~".encodeToBytes("UTF-16")
"🏀".encodeToBytes("UTF-16")
"~~~".encodeToBytes("ISO-8859-1")
"🏀".encodeToBytes("ISO-8859-1")
"Parrot".encodeToBytes("UTF-8")
}
}

View File

@@ -0,0 +1,70 @@
amends ".../snippetTest.pkl"
local bytes1 = Bytes(1, 2, 3)
local bytes2 = Bytes(1, 2, 4)
examples {
["basic"] {
Bytes(0, 255)
}
["bytes from constant value nodes"] {
Bytes(0, 1, 2, 3, 4, 5, 6, 7)
Bytes(
0b000,
0b001,
0b010,
0b011,
0b100,
0b101,
0b110,
0b111
)
Bytes(0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7)
Bytes(0o0, 0o1, 0o2, 0o3, 0o4, 0o5, 0o6, 0o7)
Bytes(0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7)
}
["bytes from non-constant value nodes"] {
local one = 1
local two = 2
Bytes(one, two)
}
["incorrectly sized constant values"] {
module.catch(() -> Bytes(0, 1, 2, 0xffff))
}
["equality"] {
bytes1 == bytes1
bytes1 == bytes2
bytes1 == bytes1.toList()
bytes1 == Bytes(1, 2, 3)
}
["inequality"] {
bytes1 != bytes1
bytes1 != bytes2
bytes1 != bytes1.toList()
bytes1 != Bytes(1, 2, 3)
}
["addition"] {
bytes1 + bytes2
Bytes() + Bytes()
bytes1 + Bytes()
Bytes() + bytes2
module.catch(() -> bytes1 + bytes2.toList())
}
["subscript"] {
bytes1[0]
bytes1[1]
bytes1[2]
module.catch(() -> bytes1[3])
}
["all bytes"] {
IntSeq(0, 255).toList().toBytes()
}
}

View File

@@ -37,5 +37,3 @@ examples {
module.catch(() -> list1[3])
}
}

View File

@@ -0,0 +1 @@
res = Bytes(0xc0, 0xc1).decodeToString("UTF-8")

View File

@@ -0,0 +1 @@
foo = Bytes(0, 1, 2, 3, 0xffff)

View File

@@ -0,0 +1,3 @@
local num = 0xfff
res = Bytes(0, 1, 2, 3, num)

View File

@@ -0,0 +1 @@
bytes = Bytes(0, 1, 2, 3, 0xffff)

View File

@@ -0,0 +1 @@
res = List(1, 2, 3, 0xffff).toBytes()

View File

@@ -326,6 +326,18 @@ res11d = new Dynamic {
for (i, n in IntSeq(1, 3)) { Pair(i, n) }
}
res12a = new Listing {
for (i in Bytes(1, 2, 3, 4)) {
i
}
}
res12b = new Listing {
for (i in Bytes()) {
i
}
}
local dynamicWithOnlyProperties = new Dynamic {
foo = "Foo!"
bar = 42

View File

@@ -15,6 +15,7 @@ local list: List<Int> = List(1, 2, 3)
local map: Map<String, Int> = Map("zz", 1, "yy", 2)
local intseq: IntSeq = IntSeq(0, 5).step(2)
local set: Set<Int> = Set(10, 20, 30)
local bytes: Bytes = Bytes(1, 2, 3, 4)
examples {
["inferred Dynamic parent"] {
@@ -29,6 +30,7 @@ examples {
...map
...intseq
...set
...bytes
}
}
["explicit Dynamic type"] {
@@ -43,6 +45,7 @@ examples {
...map
...intseq
...set
...bytes
}
}
["legacy syntax"] {
@@ -52,6 +55,7 @@ examples {
(Dynamic) { ...map }
(Dynamic) { ...intseq }
(Dynamic) { ...set }
(Dynamic) { ...bytes }
}
}

View File

@@ -6,6 +6,7 @@ local list: List<Int> = List(1, 2, 3)
local map: Map<String, Int> = Map("a", 1, "b", 2)
local intseq: IntSeq = IntSeq(0, 5).step(2)
local set: Set<Int> = Set(10, 20, 30)
local bytes: Bytes = Bytes(1, 2, 3, 4)
res1: Listing = new {
0
@@ -72,3 +73,15 @@ res16 = new Listing {
}
res17 = res16.length
res18 = new Listing {
...bytes
}
res19 = new Listing {
0
...bytes
0
0
0
}

View File

@@ -15,6 +15,7 @@ local list: List<Int> = List(1, 2, 3)
local map: Map<String, Int> = Map("a", 1, "b", 2)
local intseq: IntSeq = IntSeq(0, 5).step(2)
local set: Set<Int> = Set(10, 20, 30)
local bytes: Bytes = Bytes(1, 2, 3, 4)
class Foo {
names: Listing<String>
@@ -108,3 +109,5 @@ local foos = (makeFoos(List("bar"))) {
res17 = new Mapping {
...foos
}
res18 = test.catch(() -> new Mapping { ...bytes })

View File

@@ -0,0 +1,47 @@
examples {
["md5"] {
"08d6c05a21512a79a1dfeb9d2a8f262f"
"d41d8cd98f00b204e9800998ecf8427e"
}
["sha256"] {
"9f64a747e1b97f131fabb6b447296c9b6f0201e79fb3c5356e6c77e89b6a806a"
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
["sha1"] {
"12dada1fff4d4787ade3333147202c3b443e376f"
"da39a3ee5e6b4b0d3255bfef95601890afd80709"
}
["toString"] {
"Bytes(1, 2, 3, 4)"
"Bytes()"
}
["base64"] {
"AQIDBA=="
""
"AQIDBA=="
}
["hex"] {
"01020304"
""
}
["length"] {
0
4
1000
}
["size"] {
0.b
4.b
1.kb
}
["decodeToString()"] {
"foo bar"
"foo bar"
}
["getOrNull()"] {
1
2
3
null
}
}

View File

@@ -303,6 +303,12 @@ examples {
}
new {}
}
["toBytes()"] {
Bytes(1, 2, 3)
Bytes()
"Expected value of type `Int`, but got `null`."
"Type constraint `isBetween(0, 255)` violated. Value: -1"
}
["filterNonNull()"] {
List(1, 2, 3)
List()

View File

@@ -13,9 +13,9 @@ alias {
members = List(new {
referent {
location {
line = 1040
line = 1056
column = 1
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1040"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1056"
}
docComment = """
A boolean value, either [true] or [false].
@@ -197,9 +197,9 @@ alias {
properties = Map()
methods = Map("xor", new {
location {
line = 1050
line = 1066
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1050"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1066"
}
docComment = """
Tells if exactly one of [this] and [other] is [true] (exclusive or).
@@ -221,9 +221,9 @@ alias {
})
}, "implies", new {
location {
line = 1063
line = 1079
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1063"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1079"
}
docComment = """
Tells if [this] implies [other] (logical consequence).
@@ -251,9 +251,9 @@ alias {
}, new {
referent {
location {
line = 1076
line = 1092
column = 1
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1076"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1092"
}
docComment = """
A sequence of Unicode characters (code points).
@@ -433,9 +433,9 @@ alias {
}
properties = Map("length", new {
location {
line = 1087
line = 1103
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1087"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1103"
}
docComment = """
The number of characters in this string.
@@ -458,9 +458,9 @@ alias {
name = "length"
}, "lastIndex", new {
location {
line = 1100
line = 1116
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1100"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1116"
}
docComment = """
The index of the last character in this string (same as `length - 1`).
@@ -480,9 +480,9 @@ alias {
name = "lastIndex"
}, "isEmpty", new {
location {
line = 1110
line = 1126
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1110"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1126"
}
docComment = """
Tells whether this string is empty.
@@ -499,9 +499,9 @@ alias {
name = "isEmpty"
}, "isBlank", new {
location {
line = 1121
line = 1137
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1121"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1137"
}
docComment = """
Tells if all characters in this string have Unicode property "White_Space".
@@ -519,19 +519,39 @@ alias {
name = "isBlank"
}, "isRegex", new {
location {
line = 1124
line = 1140
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1124"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1140"
}
docComment = "Tells if this string is a valid regular expression according to [Regex]."
annotations = List()
modifiers = Set()
name = "isRegex"
}, "isBase64", new {
location {
line = 1150
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1150"
}
docComment = """
Tells if this is a valid base64-encoded string.
Facts:
```
"AQIDBA==".isBase64
!"hello there".isBase64
```
"""
annotations = List(new {
version = "0.29.0"
})
modifiers = Set()
name = "isBase64"
}, "md5", new {
location {
line = 1131
line = 1157
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1131"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1157"
}
docComment = """
The [MD5](https://en.wikipedia.org/wiki/MD5)
@@ -545,9 +565,9 @@ alias {
name = "md5"
}, "sha1", new {
location {
line = 1137
line = 1163
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1137"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1163"
}
docComment = """
The [SHA-1](https://en.wikipedia.org/wiki/SHA-1)
@@ -560,9 +580,9 @@ alias {
name = "sha1"
}, "sha256", new {
location {
line = 1142
line = 1168
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1142"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1168"
}
docComment = """
The [SHA-256](https://en.wikipedia.org/wiki/SHA-2)
@@ -574,9 +594,9 @@ alias {
name = "sha256"
}, "sha256Int", new {
location {
line = 1146
line = 1172
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1146"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1172"
}
docComment = """
The first 64 bits of the [SHA-256](https://en.wikipedia.org/wiki/SHA-2)
@@ -587,9 +607,9 @@ alias {
name = "sha256Int"
}, "base64", new {
location {
line = 1149
line = 1175
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1149"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1175"
}
docComment = "The Base64 encoding of this string's UTF-8 byte sequence."
annotations = List()
@@ -597,9 +617,9 @@ alias {
name = "base64"
}, "base64Decoded", new {
location {
line = 1157
line = 1183
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1157"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1183"
}
docComment = """
The inverse of [base64].
@@ -612,11 +632,30 @@ alias {
annotations = List()
modifiers = Set()
name = "base64Decoded"
}, "base64DecodedBytes", new {
location {
line = 1192
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1192"
}
docComment = """
Converts this base64-format string into [Bytes].
Facts:
```
"AQIDBA==".base64DecodedBytes = Bytes(1, 2, 3, 4)
```
"""
annotations = List(new {
version = "0.29.0"
})
modifiers = Set()
name = "base64DecodedBytes"
}, "chars", new {
location {
line = 1165
line = 1200
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1165"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1200"
}
docComment = """
The Unicode characters in this string.
@@ -631,9 +670,9 @@ alias {
name = "chars"
}, "codePoints", new {
location {
line = 1173
line = 1208
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1173"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1208"
}
docComment = """
The Unicode code points in this string.
@@ -649,9 +688,9 @@ alias {
})
methods = Map("getOrNull", new {
location {
line = 1185
line = 1220
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1185"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1220"
}
docComment = """
Returns the character at [index], or [null] if [index] is out of range.
@@ -674,9 +713,9 @@ alias {
})
}, "substring", new {
location {
line = 1199
line = 1234
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1199"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1234"
}
docComment = """
Returns the substring from [start] until [exclusiveEnd].
@@ -703,9 +742,9 @@ alias {
})
}, "substringOrNull", new {
location {
line = 1217
line = 1252
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1217"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1252"
}
docComment = """
Returns the substring from [start] until [exclusiveEnd].
@@ -736,9 +775,9 @@ alias {
})
}, "repeat", new {
location {
line = 1227
line = 1262
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1227"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1262"
}
docComment = """
Concatenates [count] copies of this string.
@@ -759,9 +798,9 @@ alias {
})
}, "contains", new {
location {
line = 1230
line = 1265
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1230"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1265"
}
docComment = "Tells whether this string contains [pattern]."
annotations = List()
@@ -773,9 +812,9 @@ alias {
})
}, "matches", new {
location {
line = 1234
line = 1269
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1234"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1269"
}
docComment = "Tells whether this string matches [regex] in its entirety."
annotations = List(new {
@@ -791,9 +830,9 @@ alias {
})
}, "startsWith", new {
location {
line = 1237
line = 1272
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1237"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1272"
}
docComment = "Tells whether this string starts with [pattern]."
annotations = List()
@@ -805,9 +844,9 @@ alias {
})
}, "endsWith", new {
location {
line = 1240
line = 1275
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1240"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1275"
}
docComment = "Tells whether this string ends with [pattern]."
annotations = List()
@@ -819,9 +858,9 @@ alias {
})
}, "indexOf", new {
location {
line = 1246
line = 1281
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1246"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1281"
}
docComment = """
Returns the zero-based index of the first occurrence of [pattern]
@@ -838,9 +877,9 @@ alias {
})
}, "indexOfOrNull", new {
location {
line = 1250
line = 1285
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1250"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1285"
}
docComment = """
Returns the zero-based index of the first occurrence of [pattern]
@@ -855,9 +894,9 @@ alias {
})
}, "lastIndexOf", new {
location {
line = 1256
line = 1291
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1256"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1291"
}
docComment = """
Returns the zero-based index of the last occurrence of [pattern]
@@ -874,9 +913,9 @@ alias {
})
}, "lastIndexOfOrNull", new {
location {
line = 1260
line = 1295
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1260"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1295"
}
docComment = """
Returns the zero-based index of the last occurrence of [pattern]
@@ -891,9 +930,9 @@ alias {
})
}, "take", new {
location {
line = 1266
line = 1301
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1266"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1301"
}
docComment = """
Returns the first [n] characters of this string.
@@ -913,9 +952,9 @@ alias {
})
}, "takeWhile", new {
location {
line = 1269
line = 1304
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1269"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1304"
}
docComment = "Returns the longest prefix of this string that satisfies [predicate]."
annotations = List()
@@ -927,9 +966,9 @@ alias {
})
}, "takeLast", new {
location {
line = 1274
line = 1309
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1274"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1309"
}
docComment = """
Returns the last [n] characters of this string.
@@ -945,9 +984,9 @@ alias {
})
}, "takeLastWhile", new {
location {
line = 1277
line = 1312
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1277"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1312"
}
docComment = "Returns the longest suffix of this string that satisfies [predicate]."
annotations = List()
@@ -959,9 +998,9 @@ alias {
})
}, "drop", new {
location {
line = 1283
line = 1318
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1283"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1318"
}
docComment = """
Removes the first [n] characters of this string.
@@ -981,9 +1020,9 @@ alias {
})
}, "dropWhile", new {
location {
line = 1287
line = 1322
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1287"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1322"
}
docComment = "Removes the longest prefix of this string that satisfies [predicate]."
annotations = List(new {
@@ -999,9 +1038,9 @@ alias {
})
}, "dropLast", new {
location {
line = 1293
line = 1328
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1293"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1328"
}
docComment = """
Removes the last [n] characters of this string.
@@ -1021,9 +1060,9 @@ alias {
})
}, "dropLastWhile", new {
location {
line = 1297
line = 1332
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1297"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1332"
}
docComment = "Removes the longest suffix of this string that satisfies [predicate]."
annotations = List(new {
@@ -1039,9 +1078,9 @@ alias {
})
}, "replaceFirst", new {
location {
line = 1302
line = 1337
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1302"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1337"
}
docComment = """
Replaces the first occurrence of [pattern] in this string with [replacement].
@@ -1059,9 +1098,9 @@ alias {
})
}, "replaceLast", new {
location {
line = 1307
line = 1342
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1307"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1342"
}
docComment = """
Replaces the last occurrence of [pattern] in this string with [replacement].
@@ -1079,9 +1118,9 @@ alias {
})
}, "replaceAll", new {
location {
line = 1312
line = 1347
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1312"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1347"
}
docComment = """
Replaces all occurrences of [pattern] in this string with [replacement].
@@ -1099,9 +1138,9 @@ alias {
})
}, "replaceFirstMapped", new {
location {
line = 1317
line = 1352
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1317"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1352"
}
docComment = """
Replaces the first occurrence of [pattern] in this string with the return value of [mapper].
@@ -1119,9 +1158,9 @@ alias {
})
}, "replaceLastMapped", new {
location {
line = 1322
line = 1357
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1322"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1357"
}
docComment = """
Replaces the last occurrence of [pattern] in this string with the return value of [mapper].
@@ -1139,9 +1178,9 @@ alias {
})
}, "replaceAllMapped", new {
location {
line = 1327
line = 1362
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1327"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1362"
}
docComment = """
Replaces all occurrences of [pattern] in this string with the return value of [mapper].
@@ -1159,9 +1198,9 @@ alias {
})
}, "replaceRange", new {
location {
line = 1332
line = 1367
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1332"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1367"
}
docComment = """
Replaces the characters between [start] and [exclusiveEnd] with [replacement].
@@ -1181,9 +1220,9 @@ alias {
})
}, "toUpperCase", new {
location {
line = 1335
line = 1370
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1335"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1370"
}
docComment = "Performs a locale-independent character-by-character conversion of this string to uppercase."
annotations = List()
@@ -1193,9 +1232,9 @@ alias {
parameters = Map()
}, "toLowerCase", new {
location {
line = 1338
line = 1373
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1338"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1373"
}
docComment = "Performs a locale-independent character-by-character conversion of this string to lowercase."
annotations = List()
@@ -1205,9 +1244,9 @@ alias {
parameters = Map()
}, "reverse", new {
location {
line = 1341
line = 1376
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1341"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1376"
}
docComment = "Reverses the order of characters in this string."
annotations = List()
@@ -1217,9 +1256,9 @@ alias {
parameters = Map()
}, "trim", new {
location {
line = 1345
line = 1380
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1345"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1380"
}
docComment = "Removes any leading and trailing characters with Unicode property \"White_Space\" from this string."
annotations = List(new {
@@ -1233,9 +1272,9 @@ alias {
parameters = Map()
}, "trimStart", new {
location {
line = 1349
line = 1384
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1349"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1384"
}
docComment = "Removes any leading characters with Unicode property \"White_Space\" from this string."
annotations = List(new {
@@ -1253,9 +1292,9 @@ alias {
parameters = Map()
}, "trimEnd", new {
location {
line = 1353
line = 1388
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1353"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1388"
}
docComment = "Removes any trailing characters with Unicode property \"White_Space\" from this string."
annotations = List(new {
@@ -1273,9 +1312,9 @@ alias {
parameters = Map()
}, "padStart", new {
location {
line = 1359
line = 1394
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1359"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1394"
}
docComment = """
Increases the length of this string to [width] by adding leading [char]s.
@@ -1297,9 +1336,9 @@ alias {
})
}, "padEnd", new {
location {
line = 1365
line = 1400
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1365"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1400"
}
docComment = """
Increases the length of this string to [width] by adding trailing [char]s.
@@ -1321,9 +1360,9 @@ alias {
})
}, "split", new {
location {
line = 1368
line = 1403
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1368"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1403"
}
docComment = "Splits this string around matches of [pattern]."
annotations = List()
@@ -1335,9 +1374,9 @@ alias {
})
}, "splitLimit", new {
location {
line = 1383
line = 1418
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1383"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1418"
}
docComment = """
Splits this string matches of [pattern], up to [limit] substrings.
@@ -1366,9 +1405,9 @@ alias {
})
}, "capitalize", new {
location {
line = 1393
line = 1428
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1393"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1428"
}
docComment = """
Converts the first character of this string to title case.
@@ -1387,9 +1426,9 @@ alias {
parameters = Map()
}, "decapitalize", new {
location {
line = 1403
line = 1438
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1403"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1438"
}
docComment = """
Converts the first character of this string to lower case.
@@ -1408,9 +1447,9 @@ alias {
parameters = Map()
}, "toInt", new {
location {
line = 1409
line = 1444
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1409"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1444"
}
docComment = """
Parses this string as a signed decimal (base 10) integer.
@@ -1425,9 +1464,9 @@ alias {
parameters = Map()
}, "toIntOrNull", new {
location {
line = 1415
line = 1450
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1415"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1450"
}
docComment = """
Parses this string as a signed decimal (base 10) integer.
@@ -1442,9 +1481,9 @@ alias {
parameters = Map()
}, "toFloat", new {
location {
line = 1420
line = 1455
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1420"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1455"
}
docComment = """
Parses this string as a floating point number.
@@ -1458,9 +1497,9 @@ alias {
parameters = Map()
}, "toFloatOrNull", new {
location {
line = 1425
line = 1460
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1425"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1460"
}
docComment = """
Parses this string as a floating point number.
@@ -1474,9 +1513,9 @@ alias {
parameters = Map()
}, "toBoolean", new {
location {
line = 1430
line = 1465
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1430"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1465"
}
docComment = """
Parses `"true"` to [true] and `"false"` to [false] (case-insensitive).
@@ -1490,9 +1529,9 @@ alias {
parameters = Map()
}, "toBooleanOrNull", new {
location {
line = 1435
line = 1470
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1435"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1470"
}
docComment = """
Parses `"true"` to [true] and `"false"` to [false] (case-insensitive).
@@ -1504,6 +1543,29 @@ alias {
name = "toBooleanOrNull"
typeParameters = List()
parameters = Map()
}, "encodeToBytes", new {
location {
line = 1479
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1479"
}
docComment = """
Returns the bytes of this string, encoded using [charset].
Facts:
```
"Parrot".encodeToBytes("UTF-8") == Bytes(80, 97, 114, 114, 111, 116)
```
"""
annotations = List(new {
version = "0.29.0"
})
modifiers = Set()
name = "encodeToBytes"
typeParameters = List()
parameters = Map("charset", new {
name = "charset"
})
})
}
typeArguments = List()
@@ -1524,9 +1586,9 @@ rec {
typeParameters = List()
superclass {
location {
line = 1721
line = 1773
column = 1
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1721"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1773"
}
docComment = """
Base class for objects whose members are described by a class definition.
@@ -1539,9 +1601,9 @@ rec {
typeParameters = List()
superclass {
location {
line = 1716
line = 1768
column = 1
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1716"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1768"
}
docComment = """
A composite value containing members (properties, elements, entries).
@@ -1765,9 +1827,9 @@ rec {
supertype {
referent {
location {
line = 1716
line = 1768
column = 1
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1716"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1768"
}
docComment = """
A composite value containing members (properties, elements, entries).
@@ -1993,9 +2055,9 @@ rec {
properties = Map()
methods = Map("hasProperty", new {
location {
line = 1723
line = 1775
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1723"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1775"
}
docComment = "Tells if this object has a property with the given [name]."
annotations = List()
@@ -2007,9 +2069,9 @@ rec {
})
}, "getProperty", new {
location {
line = 1728
line = 1780
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1728"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1780"
}
docComment = """
Returns the value of the property with the given [name].
@@ -2025,9 +2087,9 @@ rec {
})
}, "getPropertyOrNull", new {
location {
line = 1733
line = 1785
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1733"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1785"
}
docComment = """
Returns the value of the property with the given [name].
@@ -2043,9 +2105,9 @@ rec {
})
}, "toDynamic", new {
location {
line = 1736
line = 1788
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1736"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1788"
}
docComment = "Converts this object to a [Dynamic] object."
annotations = List()
@@ -2055,9 +2117,9 @@ rec {
parameters = Map()
}, "toMap", new {
location {
line = 1739
line = 1791
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1739"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1791"
}
docComment = "Converts this object to a [Map]."
annotations = List()
@@ -2070,9 +2132,9 @@ rec {
supertype {
referent {
location {
line = 1721
line = 1773
column = 1
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1721"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1773"
}
docComment = """
Base class for objects whose members are described by a class definition.
@@ -2085,9 +2147,9 @@ rec {
typeParameters = List()
superclass {
location {
line = 1716
line = 1768
column = 1
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1716"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1768"
}
docComment = """
A composite value containing members (properties, elements, entries).
@@ -2311,9 +2373,9 @@ rec {
supertype {
referent {
location {
line = 1716
line = 1768
column = 1
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1716"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1768"
}
docComment = """
A composite value containing members (properties, elements, entries).
@@ -2539,9 +2601,9 @@ rec {
properties = Map()
methods = Map("hasProperty", new {
location {
line = 1723
line = 1775
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1723"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1775"
}
docComment = "Tells if this object has a property with the given [name]."
annotations = List()
@@ -2553,9 +2615,9 @@ rec {
})
}, "getProperty", new {
location {
line = 1728
line = 1780
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1728"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1780"
}
docComment = """
Returns the value of the property with the given [name].
@@ -2571,9 +2633,9 @@ rec {
})
}, "getPropertyOrNull", new {
location {
line = 1733
line = 1785
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1733"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1785"
}
docComment = """
Returns the value of the property with the given [name].
@@ -2589,9 +2651,9 @@ rec {
})
}, "toDynamic", new {
location {
line = 1736
line = 1788
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1736"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1788"
}
docComment = "Converts this object to a [Dynamic] object."
annotations = List()
@@ -2601,9 +2663,9 @@ rec {
parameters = Map()
}, "toMap", new {
location {
line = 1739
line = 1791
column = 3
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1739"
displayUri = "https://github.com/apple/pkl/blob/$commitId/stdlib/base.pkl#L1791"
}
docComment = "Converts this object to a [Map]."
annotations = List()

View File

@@ -9,6 +9,11 @@ facts {
true
true
}
["isBase64"] {
true
true
true
}
["lastIndex"] {
true
true
@@ -18,6 +23,9 @@ facts {
true
true
}
["base64DecodedBytes"] {
true
}
["contains()"] {
true
true
@@ -417,4 +425,17 @@ examples {
["base64Decoded"] {
"Illegal base64 character 7e String: \"~~~\""
}
["base64DecodedBytes"] {
"Illegal base64 character 7e String: \"~~~\""
Bytes(1, 2, 3, 4)
}
["encodeToBytes()"] {
Bytes(126, 126, 126)
Bytes(240, 159, 143, 128)
Bytes(254, 255, 0, 126, 0, 126, 0, 126)
Bytes(254, 255, 216, 60, 223, 192)
Bytes(126, 126, 126)
Bytes(63)
Bytes(80, 97, 114, 114, 111, 116)
}
}

View File

@@ -0,0 +1,46 @@
examples {
["basic"] {
Bytes(0, 255)
}
["bytes from constant value nodes"] {
Bytes(0, 1, 2, 3, 4, 5, 6, 7)
Bytes(0, 1, 2, 3, 4, 5, 6, 7)
Bytes(0, 1, 2, 3, 4, 5, 6, 7)
Bytes(0, 1, 2, 3, 4, 5, 6, 7)
Bytes(0, 1, 2, 3, 4, 5, 6, 7)
}
["bytes from non-constant value nodes"] {
Bytes(1, 2)
}
["incorrectly sized constant values"] {
"Type constraint `isBetween(0, 255)` violated. Value: 65535"
}
["equality"] {
true
false
false
true
}
["inequality"] {
false
true
true
false
}
["addition"] {
Bytes(1, 2, 3, 1, 2, 4)
Bytes()
Bytes(1, 2, 3)
Bytes(1, 2, 4)
"Operator `+` is not defined for operand types `Bytes` and `List`. Left operand : Bytes(1, 2, 3) Right operand: List(1, 2, 4)"
}
["subscript"] {
1
2
3
"Element index `3` is out of range `0`..`2`. Value: Bytes(1, 2, 3)"
}
["all bytes"] {
Bytes(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255)
}
}

View File

@@ -22,7 +22,7 @@ examples {
file1
"""
base64 = "ZmlsZTEK"
bytes = Bytes(102, 105, 108, 101, 49, 10)
}
"Cannot find resource `other.txt`."
new {
@@ -31,7 +31,7 @@ examples {
file1
"""
base64 = "ZmlsZTEK"
bytes = Bytes(102, 105, 108, 101, 49, 10)
}
null
}
@@ -42,7 +42,7 @@ examples {
resource
"""
base64 = "cmVzb3VyY2UK"
bytes = Bytes(114, 101, 115, 111, 117, 114, 99, 101, 10)
}
new {
uri = "file:///$snippetsDir/input-helper/basic/read/resource.txt"
@@ -50,7 +50,7 @@ examples {
resource
"""
base64 = "cmVzb3VyY2UK"
bytes = Bytes(114, 101, 115, 111, 117, 114, 99, 101, 10)
}
}
["read non-allowed resource"] {
@@ -64,7 +64,7 @@ examples {
file1
"""
base64 = "ZmlsZTEK"
bytes = Bytes(102, 105, 108, 101, 49, 10)
}
new {
uri = "file:///$snippetsDir/input/basic/globtest/file2.txt"
@@ -72,7 +72,7 @@ examples {
file2
"""
base64 = "ZmlsZTIK"
bytes = Bytes(102, 105, 108, 101, 50, 10)
}
}
["read different resources with same relative resource URI"] {
@@ -82,7 +82,7 @@ examples {
resource
"""
base64 = "cmVzb3VyY2UK"
bytes = Bytes(114, 101, 115, 111, 117, 114, 99, 101, 10)
}
new {
uri = "file:///$snippetsDir/input-helper/basic/read/child/resource.txt"
@@ -90,7 +90,7 @@ examples {
child resource
"""
base64 = "Y2hpbGQgcmVzb3VyY2UK"
bytes = Bytes(99, 104, 105, 108, 100, 32, 114, 101, 115, 111, 117, 114, 99, 101, 10)
}
}
}

View File

@@ -4,7 +4,7 @@ examples {
["../../input-helper/globtest/module with [weird] ~!characters.pkl"] {
uri = "file:///$snippetsDir/input-helper/globtest/module%20with%20%5Bweird%5D%20~!characters.pkl"
text = ""
base64 = ""
bytes = Bytes()
}
["../../input-helper/globtest/moduleA.pkl"] {
uri = "file:///$snippetsDir/input-helper/globtest/moduleA.pkl"
@@ -12,7 +12,7 @@ examples {
name = "moduleA"
"""
base64 = "bmFtZSA9ICJtb2R1bGVBIgo="
bytes = Bytes(110, 97, 109, 101, 32, 61, 32, 34, 109, 111, 100, 117, 108, 101, 65, 34, 10)
}
["../../input-helper/globtest/moduleB.pkl"] {
uri = "file:///$snippetsDir/input-helper/globtest/moduleB.pkl"
@@ -20,7 +20,7 @@ examples {
name = "moduleB"
"""
base64 = "bmFtZSA9ICJtb2R1bGVCIgo="
bytes = Bytes(110, 97, 109, 101, 32, 61, 32, 34, 109, 111, 100, 117, 108, 101, 66, 34, 10)
}
["../../input-helper/globtest/child/moduleC.pkl"] {
uri = "file:///$snippetsDir/input-helper/globtest/child/moduleC.pkl"
@@ -28,7 +28,7 @@ examples {
name = "child/moduleC"
"""
base64 = "bmFtZSA9ICJjaGlsZC9tb2R1bGVDIgo="
bytes = Bytes(110, 97, 109, 101, 32, 61, 32, 34, 99, 104, 105, 108, 100, 47, 109, 111, 100, 117, 108, 101, 67, 34, 10)
}
}
new {
@@ -38,7 +38,7 @@ examples {
file1
"""
base64 = "ZmlsZTEK"
bytes = Bytes(102, 105, 108, 101, 49, 10)
}
["globtest/file2.txt"] {
uri = "file:///$snippetsDir/input/basic/globtest/file2.txt"
@@ -46,7 +46,7 @@ examples {
file2
"""
base64 = "ZmlsZTIK"
bytes = Bytes(102, 105, 108, 101, 50, 10)
}
}
}
@@ -55,22 +55,22 @@ examples {
["../../input-helper/globtest/module with [weird] ~!characters.pkl"] {
uri = "file:///$snippetsDir/input-helper/globtest/module%20with%20%5Bweird%5D%20~!characters.pkl"
text = "hi"
base64 = ""
bytes = Bytes()
}
["../../input-helper/globtest/moduleA.pkl"] {
uri = "file:///$snippetsDir/input-helper/globtest/moduleA.pkl"
text = "hi"
base64 = "bmFtZSA9ICJtb2R1bGVBIgo="
bytes = Bytes(110, 97, 109, 101, 32, 61, 32, 34, 109, 111, 100, 117, 108, 101, 65, 34, 10)
}
["../../input-helper/globtest/moduleB.pkl"] {
uri = "file:///$snippetsDir/input-helper/globtest/moduleB.pkl"
text = "hi"
base64 = "bmFtZSA9ICJtb2R1bGVCIgo="
bytes = Bytes(110, 97, 109, 101, 32, 61, 32, 34, 109, 111, 100, 117, 108, 101, 66, 34, 10)
}
["../../input-helper/globtest/child/moduleC.pkl"] {
uri = "file:///$snippetsDir/input-helper/globtest/child/moduleC.pkl"
text = "hi"
base64 = "bmFtZSA9ICJjaGlsZC9tb2R1bGVDIgo="
bytes = Bytes(110, 97, 109, 101, 32, 61, 32, 34, 99, 104, 105, 108, 100, 47, 109, 111, 100, 117, 108, 101, 67, 34, 10)
}
}
}
@@ -132,7 +132,7 @@ examples {
favoriteFruit: Fruit
"""
base64 = "b3BlbiBtb2R1bGUgYmlyZHMuQmlyZAoKaW1wb3J0ICJAZnJ1aXRpZXMvRnJ1aXQucGtsIgoKbmFtZTogU3RyaW5nCgpmYXZvcml0ZUZydWl0OiBGcnVpdAo="
bytes = Bytes(111, 112, 101, 110, 32, 109, 111, 100, 117, 108, 101, 32, 98, 105, 114, 100, 115, 46, 66, 105, 114, 100, 10, 10, 105, 109, 112, 111, 114, 116, 32, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 70, 114, 117, 105, 116, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 58, 32, 83, 116, 114, 105, 110, 103, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 58, 32, 70, 114, 117, 105, 116, 10)
}
["package://localhost:0/birds@0.5.0#/allFruit.pkl"] {
uri = "package://localhost:0/birds@0.5.0#/allFruit.pkl"
@@ -143,7 +143,7 @@ examples {
fruitFiles = read*("@fruities/catalog/*.pkl")
"""
base64 = "bW9kdWxlIGJpcmRzLmFsbEZydWl0CgpmcnVpdCA9IGltcG9ydCooIkBmcnVpdGllcy9jYXRhbG9nLyoucGtsIikKZnJ1aXRGaWxlcyA9IHJlYWQqKCJAZnJ1aXRpZXMvY2F0YWxvZy8qLnBrbCIpCg=="
bytes = Bytes(109, 111, 100, 117, 108, 101, 32, 98, 105, 114, 100, 115, 46, 97, 108, 108, 70, 114, 117, 105, 116, 10, 10, 102, 114, 117, 105, 116, 32, 61, 32, 105, 109, 112, 111, 114, 116, 42, 40, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 42, 46, 112, 107, 108, 34, 41, 10, 102, 114, 117, 105, 116, 70, 105, 108, 101, 115, 32, 61, 32, 114, 101, 97, 100, 42, 40, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 42, 46, 112, 107, 108, 34, 41, 10)
}
["package://localhost:0/birds@0.5.0#/catalog.pkl"] {
uri = "package://localhost:0/birds@0.5.0#/catalog.pkl"
@@ -154,7 +154,7 @@ examples {
catalogFiles = read*("catalog/*.pkl")
"""
base64 = "bW9kdWxlIGJpcmRzLmNhdGFsb2cKCmNhdGFsb2cgPSBpbXBvcnQqKCJjYXRhbG9nLyoucGtsIikKY2F0YWxvZ0ZpbGVzID0gcmVhZCooImNhdGFsb2cvKi5wa2wiKQo="
bytes = Bytes(109, 111, 100, 117, 108, 101, 32, 98, 105, 114, 100, 115, 46, 99, 97, 116, 97, 108, 111, 103, 10, 10, 99, 97, 116, 97, 108, 111, 103, 32, 61, 32, 105, 109, 112, 111, 114, 116, 42, 40, 34, 99, 97, 116, 97, 108, 111, 103, 47, 42, 46, 112, 107, 108, 34, 41, 10, 99, 97, 116, 97, 108, 111, 103, 70, 105, 108, 101, 115, 32, 61, 32, 114, 101, 97, 100, 42, 40, 34, 99, 97, 116, 97, 108, 111, 103, 47, 42, 46, 112, 107, 108, 34, 41, 10)
}
["package://localhost:0/birds@0.5.0#/catalog/Ostrich.pkl"] {
uri = "package://localhost:0/birds@0.5.0#/catalog/Ostrich.pkl"
@@ -168,7 +168,7 @@ examples {
}
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCm5hbWUgPSAiT3N0cmljaCIKCmZhdm9yaXRlRnJ1aXQgewogIG5hbWUgPSAiT3JhbmdlIgp9Cg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 79, 115, 116, 114, 105, 99, 104, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 123, 10, 32, 32, 110, 97, 109, 101, 32, 61, 32, 34, 79, 114, 97, 110, 103, 101, 34, 10, 125, 10)
}
["package://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"] {
uri = "package://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"
@@ -182,7 +182,7 @@ examples {
favoriteFruit = apple
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCmltcG9ydCAiQGZydWl0aWVzL2NhdGFsb2cvYXBwbGUucGtsIgoKbmFtZSA9ICJTd2FsbG93IgoKZmF2b3JpdGVGcnVpdCA9IGFwcGxlCg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 105, 109, 112, 111, 114, 116, 32, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 97, 112, 112, 108, 101, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 83, 119, 97, 108, 108, 111, 119, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 61, 32, 97, 112, 112, 108, 101, 10)
}
["package://localhost:0/birds@0.5.0#/some/dir/Bird.pkl"] {
uri = "package://localhost:0/birds@0.5.0#/some/dir/Bird.pkl"
@@ -196,7 +196,7 @@ examples {
}
"""
base64 = "YW1lbmRzICIuLi4iCgpuYW1lID0gIkJpcmQiCgpmYXZvcml0ZUZydWl0IHsKICBuYW1lID0gIkZydWl0Igp9Cg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 46, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 66, 105, 114, 100, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 123, 10, 32, 32, 110, 97, 109, 101, 32, 61, 32, 34, 70, 114, 117, 105, 116, 34, 10, 125, 10)
}
}
}
@@ -208,7 +208,7 @@ examples {
file1
"""
base64 = "ZmlsZTEK"
bytes = Bytes(102, 105, 108, 101, 49, 10)
}
["globtest/file2.txt"] {
uri = "file:///$snippetsDir/input/basic/globtest/file2.txt"
@@ -216,7 +216,7 @@ examples {
file2
"""
base64 = "ZmlsZTIK"
bytes = Bytes(102, 105, 108, 101, 50, 10)
}
}
new {
@@ -226,7 +226,7 @@ examples {
file1
"""
base64 = "ZmlsZTEK"
bytes = Bytes(102, 105, 108, 101, 49, 10)
}
}
new {
@@ -236,7 +236,7 @@ examples {
file2
"""
base64 = "ZmlsZTIK"
bytes = Bytes(102, 105, 108, 101, 50, 10)
}
}
}
@@ -248,7 +248,7 @@ examples {
resource
"""
base64 = "cmVzb3VyY2UK"
bytes = Bytes(114, 101, 115, 111, 117, 114, 99, 101, 10)
}
}
new {
@@ -258,7 +258,7 @@ examples {
child resource
"""
base64 = "Y2hpbGQgcmVzb3VyY2UK"
bytes = Bytes(99, 104, 105, 108, 100, 32, 114, 101, 115, 111, 117, 114, 99, 101, 10)
}
}
}

View File

@@ -0,0 +1,10 @@
Pkl Error
Invalid bytes for charset "UTF-8".
x | res = Bytes(0xc0, 0xc1).decodeToString("UTF-8")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at decodingException#res (file:///$snippetsDir/input/errors/decodingException.pkl)
xxx | text = renderer.renderDocument(value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at pkl.base#Module.output.text (pkl:base)

View File

@@ -0,0 +1,15 @@
Pkl Error
Type constraint `isBetween(0, 255)` violated.
Value: 65535
xxx | typealias UInt8 = Int(isBetween(0, 255))
^^^^^^^^^^^^^^^^^
at invalidBytes1#foo (pkl:base)
x | foo = Bytes(0, 1, 2, 3, 0xffff)
^^^^^^
at invalidBytes1#foo (file:///$snippetsDir/input/errors/invalidBytes1.pkl)
xxx | text = renderer.renderDocument(value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at pkl.base#Module.output.text (pkl:base)

View File

@@ -0,0 +1,15 @@
Pkl Error
Type constraint `isBetween(0, 255)` violated.
Value: 4095
xxx | typealias UInt8 = Int(isBetween(0, 255))
^^^^^^^^^^^^^^^^^
at invalidBytes2#res (pkl:base)
x | res = Bytes(0, 1, 2, 3, num)
^^^
at invalidBytes2#res (file:///$snippetsDir/input/errors/invalidBytes2.pkl)
xxx | text = renderer.renderDocument(value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at pkl.base#Module.output.text (pkl:base)

View File

@@ -0,0 +1,15 @@
Pkl Error
Type constraint `isBetween(0, 255)` violated.
Value: 65535
xxx | typealias UInt8 = Int(isBetween(0, 255))
^^^^^^^^^^^^^^^^^
at invalidBytes3#bytes (pkl:base)
x | bytes = Bytes(0, 1, 2, 3, 0xffff)
^^^^^^
at invalidBytes3#bytes (file:///$snippetsDir/input/errors/invalidBytes3.pkl)
xxx | text = renderer.renderDocument(value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at pkl.base#Module.output.text (pkl:base)

View File

@@ -0,0 +1,15 @@
Pkl Error
Type constraint `isBetween(0, 255)` violated.
Value: 65535
xxx | typealias UInt8 = Int(isBetween(0, 255))
^^^^^^^^^^^^^^^^^
at pkl.base#List.toBytes (pkl:base)
x | res = List(1, 2, 3, 0xffff).toBytes()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at invalidBytes4#res (file:///$snippetsDir/input/errors/invalidBytes4.pkl)
xxx | text = renderer.renderDocument(value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at pkl.base#Module.output.text (pkl:base)

View File

@@ -226,6 +226,13 @@ res11d {
Pair(1, 2)
Pair(2, 3)
}
res12a {
1
2
3
4
}
res12b {}
valueForOverProperties {
["Foo!"] = "Foo!"
[42] = 42

View File

@@ -37,6 +37,10 @@ examples {
10
20
30
1
2
3
4
}
}
["explicit Dynamic type"] {
@@ -69,6 +73,10 @@ examples {
10
20
30
1
2
3
4
}
}
["legacy syntax"] {
@@ -105,5 +113,11 @@ examples {
20
30
}
new {
1
2
3
4
}
}
}

View File

@@ -103,3 +103,19 @@ res16 {
0
}
res17 = 7
res18 {
1
2
3
4
}
res19 {
0
1
2
3
4
0
0
0
}

View File

@@ -55,3 +55,4 @@ res17 {
}
}
}
res18 = "Cannot spread value of type `Bytes` into object of type `Mapping`. Value: Bytes(1, 2, 3, 4)"

View File

@@ -7,6 +7,11 @@ at invalidAmend6#resource (file:///$snippetsDir/input/modules/invalidAmend6.pkl)
Available properties:
base64
bytes
md5
sha1
sha256
sha256Int
text
uri

View File

@@ -40,7 +40,7 @@ examples {
favoriteFruit: Fruit
"""
base64 = "b3BlbiBtb2R1bGUgYmlyZHMuQmlyZAoKaW1wb3J0ICJAZnJ1aXRpZXMvRnJ1aXQucGtsIgoKbmFtZTogU3RyaW5nCgpmYXZvcml0ZUZydWl0OiBGcnVpdAo="
bytes = Bytes(111, 112, 101, 110, 32, 109, 111, 100, 117, 108, 101, 32, 98, 105, 114, 100, 115, 46, 66, 105, 114, 100, 10, 10, 105, 109, 112, 111, 114, 116, 32, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 70, 114, 117, 105, 116, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 58, 32, 83, 116, 114, 105, 110, 103, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 58, 32, 70, 114, 117, 105, 116, 10)
}
new {
uri = "package://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"
@@ -54,7 +54,7 @@ examples {
favoriteFruit = apple
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCmltcG9ydCAiQGZydWl0aWVzL2NhdGFsb2cvYXBwbGUucGtsIgoKbmFtZSA9ICJTd2FsbG93IgoKZmF2b3JpdGVGcnVpdCA9IGFwcGxlCg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 105, 109, 112, 111, 114, 116, 32, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 97, 112, 112, 108, 101, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 83, 119, 97, 108, 108, 111, 119, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 61, 32, 97, 112, 112, 108, 101, 10)
}
new {
uri = "package://localhost:0/birds@0.5.0#/catalog/Ostrich.pkl"
@@ -68,7 +68,7 @@ examples {
}
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCm5hbWUgPSAiT3N0cmljaCIKCmZhdm9yaXRlRnJ1aXQgewogIG5hbWUgPSAiT3JhbmdlIgp9Cg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 79, 115, 116, 114, 105, 99, 104, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 123, 10, 32, 32, 110, 97, 109, 101, 32, 61, 32, 34, 79, 114, 97, 110, 103, 101, 34, 10, 125, 10)
}
}
}

View File

@@ -52,7 +52,7 @@ examples {
}
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCm5hbWUgPSAiT3N0cmljaCIKCmZhdm9yaXRlRnJ1aXQgewogIG5hbWUgPSAiT3JhbmdlIgp9Cg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 79, 115, 116, 114, 105, 99, 104, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 123, 10, 32, 32, 110, 97, 109, 101, 32, 61, 32, 34, 79, 114, 97, 110, 103, 101, 34, 10, 125, 10)
}
["package://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"] {
uri = "package://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"
@@ -66,7 +66,7 @@ examples {
favoriteFruit = apple
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCmltcG9ydCAiQGZydWl0aWVzL2NhdGFsb2cvYXBwbGUucGtsIgoKbmFtZSA9ICJTd2FsbG93IgoKZmF2b3JpdGVGcnVpdCA9IGFwcGxlCg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 105, 109, 112, 111, 114, 116, 32, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 97, 112, 112, 108, 101, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 83, 119, 97, 108, 108, 111, 119, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 61, 32, 97, 112, 112, 108, 101, 10)
}
}
}
@@ -84,7 +84,7 @@ examples {
}
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCm5hbWUgPSAiT3N0cmljaCIKCmZhdm9yaXRlRnJ1aXQgewogIG5hbWUgPSAiT3JhbmdlIgp9Cg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 79, 115, 116, 114, 105, 99, 104, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 123, 10, 32, 32, 110, 97, 109, 101, 32, 61, 32, 34, 79, 114, 97, 110, 103, 101, 34, 10, 125, 10)
}
["catalog/Swallow.pkl"] {
uri = "package://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"
@@ -98,7 +98,7 @@ examples {
favoriteFruit = apple
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCmltcG9ydCAiQGZydWl0aWVzL2NhdGFsb2cvYXBwbGUucGtsIgoKbmFtZSA9ICJTd2FsbG93IgoKZmF2b3JpdGVGcnVpdCA9IGFwcGxlCg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 105, 109, 112, 111, 114, 116, 32, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 97, 112, 112, 108, 101, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 83, 119, 97, 108, 108, 111, 119, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 61, 32, 97, 112, 112, 108, 101, 10)
}
}
}
@@ -112,7 +112,7 @@ examples {
name = "Apple"
"""
base64 = "YW1lbmRzICIuLi9GcnVpdC5wa2wiCgpuYW1lID0gIkFwcGxlIgo="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 70, 114, 117, 105, 116, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 65, 112, 112, 108, 101, 34, 10)
}
}
}

View File

@@ -44,7 +44,7 @@ examples {
Swallow.pkl
"""
base64 = "T3N0cmljaC5wa2wKU3dhbGxvdy5wa2wK"
bytes = Bytes(79, 115, 116, 114, 105, 99, 104, 46, 112, 107, 108, 10, 83, 119, 97, 108, 108, 111, 119, 46, 112, 107, 108, 10)
}
new {
uri = "projectpackage://localhost:0/birds@0.5.0#/"
@@ -56,7 +56,7 @@ examples {
some
"""
base64 = "QmlyZC5wa2wKYWxsRnJ1aXQucGtsCmNhdGFsb2cKY2F0YWxvZy5wa2wKc29tZQo="
bytes = Bytes(66, 105, 114, 100, 46, 112, 107, 108, 10, 97, 108, 108, 70, 114, 117, 105, 116, 46, 112, 107, 108, 10, 99, 97, 116, 97, 108, 111, 103, 10, 99, 97, 116, 97, 108, 111, 103, 46, 112, 107, 108, 10, 115, 111, 109, 101, 10)
}
}
}

View File

@@ -62,7 +62,7 @@ examples {
}
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCm5hbWUgPSAiT3N0cmljaCIKCmZhdm9yaXRlRnJ1aXQgewogIG5hbWUgPSAiT3JhbmdlIgp9Cg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 79, 115, 116, 114, 105, 99, 104, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 123, 10, 32, 32, 110, 97, 109, 101, 32, 61, 32, 34, 79, 114, 97, 110, 103, 101, 34, 10, 125, 10)
}
["@birds/catalog/Swallow.pkl"] {
uri = "projectpackage://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"
@@ -76,7 +76,7 @@ examples {
favoriteFruit = apple
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCmltcG9ydCAiQGZydWl0aWVzL2NhdGFsb2cvYXBwbGUucGtsIgoKbmFtZSA9ICJTd2FsbG93IgoKZmF2b3JpdGVGcnVpdCA9IGFwcGxlCg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 105, 109, 112, 111, 114, 116, 32, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 97, 112, 112, 108, 101, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 83, 119, 97, 108, 108, 111, 119, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 61, 32, 97, 112, 112, 108, 101, 10)
}
}
new {
@@ -92,7 +92,7 @@ examples {
favoriteFruit: Fruit
"""
base64 = "b3BlbiBtb2R1bGUgYmlyZHMuQmlyZAoKaW1wb3J0ICJAZnJ1aXRpZXMvRnJ1aXQucGtsIgoKbmFtZTogU3RyaW5nCgpmYXZvcml0ZUZydWl0OiBGcnVpdAo="
bytes = Bytes(111, 112, 101, 110, 32, 109, 111, 100, 117, 108, 101, 32, 98, 105, 114, 100, 115, 46, 66, 105, 114, 100, 10, 10, 105, 109, 112, 111, 114, 116, 32, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 70, 114, 117, 105, 116, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 58, 32, 83, 116, 114, 105, 110, 103, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 58, 32, 70, 114, 117, 105, 116, 10)
}
["@birds/allFruit.pkl"] {
uri = "projectpackage://localhost:0/birds@0.5.0#/allFruit.pkl"
@@ -103,7 +103,7 @@ examples {
fruitFiles = read*("@fruities/catalog/*.pkl")
"""
base64 = "bW9kdWxlIGJpcmRzLmFsbEZydWl0CgpmcnVpdCA9IGltcG9ydCooIkBmcnVpdGllcy9jYXRhbG9nLyoucGtsIikKZnJ1aXRGaWxlcyA9IHJlYWQqKCJAZnJ1aXRpZXMvY2F0YWxvZy8qLnBrbCIpCg=="
bytes = Bytes(109, 111, 100, 117, 108, 101, 32, 98, 105, 114, 100, 115, 46, 97, 108, 108, 70, 114, 117, 105, 116, 10, 10, 102, 114, 117, 105, 116, 32, 61, 32, 105, 109, 112, 111, 114, 116, 42, 40, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 42, 46, 112, 107, 108, 34, 41, 10, 102, 114, 117, 105, 116, 70, 105, 108, 101, 115, 32, 61, 32, 114, 101, 97, 100, 42, 40, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 42, 46, 112, 107, 108, 34, 41, 10)
}
["@birds/catalog.pkl"] {
uri = "projectpackage://localhost:0/birds@0.5.0#/catalog.pkl"
@@ -114,7 +114,7 @@ examples {
catalogFiles = read*("catalog/*.pkl")
"""
base64 = "bW9kdWxlIGJpcmRzLmNhdGFsb2cKCmNhdGFsb2cgPSBpbXBvcnQqKCJjYXRhbG9nLyoucGtsIikKY2F0YWxvZ0ZpbGVzID0gcmVhZCooImNhdGFsb2cvKi5wa2wiKQo="
bytes = Bytes(109, 111, 100, 117, 108, 101, 32, 98, 105, 114, 100, 115, 46, 99, 97, 116, 97, 108, 111, 103, 10, 10, 99, 97, 116, 97, 108, 111, 103, 32, 61, 32, 105, 109, 112, 111, 114, 116, 42, 40, 34, 99, 97, 116, 97, 108, 111, 103, 47, 42, 46, 112, 107, 108, 34, 41, 10, 99, 97, 116, 97, 108, 111, 103, 70, 105, 108, 101, 115, 32, 61, 32, 114, 101, 97, 100, 42, 40, 34, 99, 97, 116, 97, 108, 111, 103, 47, 42, 46, 112, 107, 108, 34, 41, 10)
}
}
new {
@@ -130,7 +130,7 @@ examples {
favoriteFruit: Fruit
"""
base64 = "b3BlbiBtb2R1bGUgYmlyZHMuQmlyZAoKaW1wb3J0ICJAZnJ1aXRpZXMvRnJ1aXQucGtsIgoKbmFtZTogU3RyaW5nCgpmYXZvcml0ZUZydWl0OiBGcnVpdAo="
bytes = Bytes(111, 112, 101, 110, 32, 109, 111, 100, 117, 108, 101, 32, 98, 105, 114, 100, 115, 46, 66, 105, 114, 100, 10, 10, 105, 109, 112, 111, 114, 116, 32, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 70, 114, 117, 105, 116, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 58, 32, 83, 116, 114, 105, 110, 103, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 58, 32, 70, 114, 117, 105, 116, 10)
}
["@birds/allFruit.pkl"] {
uri = "projectpackage://localhost:0/birds@0.5.0#/allFruit.pkl"
@@ -141,7 +141,7 @@ examples {
fruitFiles = read*("@fruities/catalog/*.pkl")
"""
base64 = "bW9kdWxlIGJpcmRzLmFsbEZydWl0CgpmcnVpdCA9IGltcG9ydCooIkBmcnVpdGllcy9jYXRhbG9nLyoucGtsIikKZnJ1aXRGaWxlcyA9IHJlYWQqKCJAZnJ1aXRpZXMvY2F0YWxvZy8qLnBrbCIpCg=="
bytes = Bytes(109, 111, 100, 117, 108, 101, 32, 98, 105, 114, 100, 115, 46, 97, 108, 108, 70, 114, 117, 105, 116, 10, 10, 102, 114, 117, 105, 116, 32, 61, 32, 105, 109, 112, 111, 114, 116, 42, 40, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 42, 46, 112, 107, 108, 34, 41, 10, 102, 114, 117, 105, 116, 70, 105, 108, 101, 115, 32, 61, 32, 114, 101, 97, 100, 42, 40, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 42, 46, 112, 107, 108, 34, 41, 10)
}
["@birds/catalog.pkl"] {
uri = "projectpackage://localhost:0/birds@0.5.0#/catalog.pkl"
@@ -152,7 +152,7 @@ examples {
catalogFiles = read*("catalog/*.pkl")
"""
base64 = "bW9kdWxlIGJpcmRzLmNhdGFsb2cKCmNhdGFsb2cgPSBpbXBvcnQqKCJjYXRhbG9nLyoucGtsIikKY2F0YWxvZ0ZpbGVzID0gcmVhZCooImNhdGFsb2cvKi5wa2wiKQo="
bytes = Bytes(109, 111, 100, 117, 108, 101, 32, 98, 105, 114, 100, 115, 46, 99, 97, 116, 97, 108, 111, 103, 10, 10, 99, 97, 116, 97, 108, 111, 103, 32, 61, 32, 105, 109, 112, 111, 114, 116, 42, 40, 34, 99, 97, 116, 97, 108, 111, 103, 47, 42, 46, 112, 107, 108, 34, 41, 10, 99, 97, 116, 97, 108, 111, 103, 70, 105, 108, 101, 115, 32, 61, 32, 114, 101, 97, 100, 42, 40, 34, 99, 97, 116, 97, 108, 111, 103, 47, 42, 46, 112, 107, 108, 34, 41, 10)
}
["@birds/catalog/Ostrich.pkl"] {
uri = "projectpackage://localhost:0/birds@0.5.0#/catalog/Ostrich.pkl"
@@ -166,7 +166,7 @@ examples {
}
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCm5hbWUgPSAiT3N0cmljaCIKCmZhdm9yaXRlRnJ1aXQgewogIG5hbWUgPSAiT3JhbmdlIgp9Cg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 79, 115, 116, 114, 105, 99, 104, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 123, 10, 32, 32, 110, 97, 109, 101, 32, 61, 32, 34, 79, 114, 97, 110, 103, 101, 34, 10, 125, 10)
}
["@birds/catalog/Swallow.pkl"] {
uri = "projectpackage://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"
@@ -180,7 +180,7 @@ examples {
favoriteFruit = apple
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCmltcG9ydCAiQGZydWl0aWVzL2NhdGFsb2cvYXBwbGUucGtsIgoKbmFtZSA9ICJTd2FsbG93IgoKZmF2b3JpdGVGcnVpdCA9IGFwcGxlCg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 105, 109, 112, 111, 114, 116, 32, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 97, 112, 112, 108, 101, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 83, 119, 97, 108, 108, 111, 119, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 61, 32, 97, 112, 112, 108, 101, 10)
}
["@birds/some/dir/Bird.pkl"] {
uri = "projectpackage://localhost:0/birds@0.5.0#/some/dir/Bird.pkl"
@@ -194,7 +194,7 @@ examples {
}
"""
base64 = "YW1lbmRzICIuLi4iCgpuYW1lID0gIkJpcmQiCgpmYXZvcml0ZUZydWl0IHsKICBuYW1lID0gIkZydWl0Igp9Cg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 46, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 66, 105, 114, 100, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 123, 10, 32, 32, 110, 97, 109, 101, 32, 61, 32, 34, 70, 114, 117, 105, 116, 34, 10, 125, 10)
}
}
}
@@ -212,7 +212,7 @@ examples {
}
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCm5hbWUgPSAiT3N0cmljaCIKCmZhdm9yaXRlRnJ1aXQgewogIG5hbWUgPSAiT3JhbmdlIgp9Cg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 79, 115, 116, 114, 105, 99, 104, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 123, 10, 32, 32, 110, 97, 109, 101, 32, 61, 32, 34, 79, 114, 97, 110, 103, 101, 34, 10, 125, 10)
}
["catalog/Swallow.pkl"] {
uri = "projectpackage://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"
@@ -226,7 +226,7 @@ examples {
favoriteFruit = apple
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCmltcG9ydCAiQGZydWl0aWVzL2NhdGFsb2cvYXBwbGUucGtsIgoKbmFtZSA9ICJTd2FsbG93IgoKZmF2b3JpdGVGcnVpdCA9IGFwcGxlCg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 105, 109, 112, 111, 114, 116, 32, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 97, 112, 112, 108, 101, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 83, 119, 97, 108, 108, 111, 119, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 61, 32, 97, 112, 112, 108, 101, 10)
}
}
}
@@ -244,7 +244,7 @@ examples {
}
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCm5hbWUgPSAiT3N0cmljaCIKCmZhdm9yaXRlRnJ1aXQgewogIG5hbWUgPSAiT3JhbmdlIgp9Cg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 79, 115, 116, 114, 105, 99, 104, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 123, 10, 32, 32, 110, 97, 109, 101, 32, 61, 32, 34, 79, 114, 97, 110, 103, 101, 34, 10, 125, 10)
}
["package://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"] {
uri = "package://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"
@@ -258,7 +258,7 @@ examples {
favoriteFruit = apple
"""
base64 = "YW1lbmRzICIuLi9CaXJkLnBrbCIKCmltcG9ydCAiQGZydWl0aWVzL2NhdGFsb2cvYXBwbGUucGtsIgoKbmFtZSA9ICJTd2FsbG93IgoKZmF2b3JpdGVGcnVpdCA9IGFwcGxlCg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 46, 46, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 105, 109, 112, 111, 114, 116, 32, 34, 64, 102, 114, 117, 105, 116, 105, 101, 115, 47, 99, 97, 116, 97, 108, 111, 103, 47, 97, 112, 112, 108, 101, 46, 112, 107, 108, 34, 10, 10, 110, 97, 109, 101, 32, 61, 32, 34, 83, 119, 97, 108, 108, 111, 119, 34, 10, 10, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 61, 32, 97, 112, 112, 108, 101, 10)
}
}
}

View File

@@ -29,7 +29,7 @@ res2 {
}
"""
base64 = "YW1lbmRzICJwa2w6UHJvamVjdCIKCnBhY2thZ2UgewogIG5hbWUgPSAicHJvamVjdDIiCiAgYmFzZVVyaSA9ICJwYWNrYWdlOi8vbG9jYWxob3N0OjAvcHJvamVjdDIiCiAgdmVyc2lvbiA9ICIxLjAuMCIKICBwYWNrYWdlWmlwVXJsID0gImh0dHBzOi8vbG9jYWxob3N0OjAvcHJvamVjdDIvcHJvamVjdDItXCh2ZXJzaW9uKS56aXAiCn0KCmRlcGVuZGVuY2llcyB7CiAgWyJidXJkcyJdIHsKICAgIHVyaSA9ICJwYWNrYWdlOi8vbG9jYWxob3N0OjAvYmlyZHNAMC41LjAiCiAgfQp9Cg=="
bytes = Bytes(97, 109, 101, 110, 100, 115, 32, 34, 112, 107, 108, 58, 80, 114, 111, 106, 101, 99, 116, 34, 10, 10, 112, 97, 99, 107, 97, 103, 101, 32, 123, 10, 32, 32, 110, 97, 109, 101, 32, 61, 32, 34, 112, 114, 111, 106, 101, 99, 116, 50, 34, 10, 32, 32, 98, 97, 115, 101, 85, 114, 105, 32, 61, 32, 34, 112, 97, 99, 107, 97, 103, 101, 58, 47, 47, 108, 111, 99, 97, 108, 104, 111, 115, 116, 58, 48, 47, 112, 114, 111, 106, 101, 99, 116, 50, 34, 10, 32, 32, 118, 101, 114, 115, 105, 111, 110, 32, 61, 32, 34, 49, 46, 48, 46, 48, 34, 10, 32, 32, 112, 97, 99, 107, 97, 103, 101, 90, 105, 112, 85, 114, 108, 32, 61, 32, 34, 104, 116, 116, 112, 115, 58, 47, 47, 108, 111, 99, 97, 108, 104, 111, 115, 116, 58, 48, 47, 112, 114, 111, 106, 101, 99, 116, 50, 47, 112, 114, 111, 106, 101, 99, 116, 50, 45, 92, 40, 118, 101, 114, 115, 105, 111, 110, 41, 46, 122, 105, 112, 34, 10, 125, 10, 10, 100, 101, 112, 101, 110, 100, 101, 110, 99, 105, 101, 115, 32, 123, 10, 32, 32, 91, 34, 98, 117, 114, 100, 115, 34, 93, 32, 123, 10, 32, 32, 32, 32, 117, 114, 105, 32, 61, 32, 34, 112, 97, 99, 107, 97, 103, 101, 58, 47, 47, 108, 111, 99, 97, 108, 104, 111, 115, 116, 58, 48, 47, 98, 105, 114, 100, 115, 64, 48, 46, 53, 46, 48, 34, 10, 32, 32, 125, 10, 125, 10)
}
["@project2/PklProject.deps.json"] {
uri = "file:/$snippetsDir/input/projects/project2/PklProject.deps.json"
@@ -55,7 +55,7 @@ res2 {
}
"""
base64 = "ewogICJzY2hlbWFWZXJzaW9uIjogMSwKICAicmVzb2x2ZWREZXBlbmRlbmNpZXMiOiB7CiAgICAicGFja2FnZTovL2xvY2FsaG9zdDowL2JpcmRzQDAiOiB7CiAgICAgICJ0eXBlIjogInJlbW90ZSIsCiAgICAgICJ1cmkiOiAicHJvamVjdHBhY2thZ2U6Ly9sb2NhbGhvc3Q6MC9iaXJkc0AwLjUuMCIsCiAgICAgICJjaGVja3N1bXMiOiB7CiAgICAgICAgInNoYTI1NiI6ICIkc2tpcENoZWNrc3VtVmVyaWZpY2F0aW9uIgogICAgICB9CiAgICB9LAogICAgInBhY2thZ2U6Ly9sb2NhbGhvc3Q6MC9mcnVpdEAxIjogewogICAgICAidHlwZSI6ICJyZW1vdGUiLAogICAgICAidXJpIjogInByb2plY3RwYWNrYWdlOi8vbG9jYWxob3N0OjAvZnJ1aXRAMS4xLjAiLAogICAgICAiY2hlY2tzdW1zIjogewogICAgICAgICJzaGEyNTYiOiAiJHNraXBDaGVja3N1bVZlcmlmaWNhdGlvbiIKICAgICAgfQogICAgfQogIH0KfQo="
bytes = Bytes(123, 10, 32, 32, 34, 115, 99, 104, 101, 109, 97, 86, 101, 114, 115, 105, 111, 110, 34, 58, 32, 49, 44, 10, 32, 32, 34, 114, 101, 115, 111, 108, 118, 101, 100, 68, 101, 112, 101, 110, 100, 101, 110, 99, 105, 101, 115, 34, 58, 32, 123, 10, 32, 32, 32, 32, 34, 112, 97, 99, 107, 97, 103, 101, 58, 47, 47, 108, 111, 99, 97, 108, 104, 111, 115, 116, 58, 48, 47, 98, 105, 114, 100, 115, 64, 48, 34, 58, 32, 123, 10, 32, 32, 32, 32, 32, 32, 34, 116, 121, 112, 101, 34, 58, 32, 34, 114, 101, 109, 111, 116, 101, 34, 44, 10, 32, 32, 32, 32, 32, 32, 34, 117, 114, 105, 34, 58, 32, 34, 112, 114, 111, 106, 101, 99, 116, 112, 97, 99, 107, 97, 103, 101, 58, 47, 47, 108, 111, 99, 97, 108, 104, 111, 115, 116, 58, 48, 47, 98, 105, 114, 100, 115, 64, 48, 46, 53, 46, 48, 34, 44, 10, 32, 32, 32, 32, 32, 32, 34, 99, 104, 101, 99, 107, 115, 117, 109, 115, 34, 58, 32, 123, 10, 32, 32, 32, 32, 32, 32, 32, 32, 34, 115, 104, 97, 50, 53, 54, 34, 58, 32, 34, 36, 115, 107, 105, 112, 67, 104, 101, 99, 107, 115, 117, 109, 86, 101, 114, 105, 102, 105, 99, 97, 116, 105, 111, 110, 34, 10, 32, 32, 32, 32, 32, 32, 125, 10, 32, 32, 32, 32, 125, 44, 10, 32, 32, 32, 32, 34, 112, 97, 99, 107, 97, 103, 101, 58, 47, 47, 108, 111, 99, 97, 108, 104, 111, 115, 116, 58, 48, 47, 102, 114, 117, 105, 116, 64, 49, 34, 58, 32, 123, 10, 32, 32, 32, 32, 32, 32, 34, 116, 121, 112, 101, 34, 58, 32, 34, 114, 101, 109, 111, 116, 101, 34, 44, 10, 32, 32, 32, 32, 32, 32, 34, 117, 114, 105, 34, 58, 32, 34, 112, 114, 111, 106, 101, 99, 116, 112, 97, 99, 107, 97, 103, 101, 58, 47, 47, 108, 111, 99, 97, 108, 104, 111, 115, 116, 58, 48, 47, 102, 114, 117, 105, 116, 64, 49, 46, 49, 46, 48, 34, 44, 10, 32, 32, 32, 32, 32, 32, 34, 99, 104, 101, 99, 107, 115, 117, 109, 115, 34, 58, 32, 123, 10, 32, 32, 32, 32, 32, 32, 32, 32, 34, 115, 104, 97, 50, 53, 54, 34, 58, 32, 34, 36, 115, 107, 105, 112, 67, 104, 101, 99, 107, 115, 117, 109, 86, 101, 114, 105, 102, 105, 99, 97, 116, 105, 111, 110, 34, 10, 32, 32, 32, 32, 32, 32, 125, 10, 32, 32, 32, 32, 125, 10, 32, 32, 125, 10, 125, 10)
}
["@project2/penguin.pkl"] {
uri = "file:/$snippetsDir/input/projects/project2/penguin.pkl"
@@ -70,6 +70,6 @@ res2 {
}
"""
base64 = "aW1wb3J0ICJAYnVyZHMvQmlyZC5wa2wiCgpiaXJkOiBCaXJkID0gbmV3IHsKICBuYW1lID0gIlBlbmd1aW4iCiAgZmF2b3JpdGVGcnVpdCB7CiAgICBuYW1lID0gIkljZSBGcnVpdCIKICB9Cn0K"
bytes = Bytes(105, 109, 112, 111, 114, 116, 32, 34, 64, 98, 117, 114, 100, 115, 47, 66, 105, 114, 100, 46, 112, 107, 108, 34, 10, 10, 98, 105, 114, 100, 58, 32, 66, 105, 114, 100, 32, 61, 32, 110, 101, 119, 32, 123, 10, 32, 32, 110, 97, 109, 101, 32, 61, 32, 34, 80, 101, 110, 103, 117, 105, 110, 34, 10, 32, 32, 102, 97, 118, 111, 114, 105, 116, 101, 70, 114, 117, 105, 116, 32, 123, 10, 32, 32, 32, 32, 110, 97, 109, 101, 32, 61, 32, 34, 73, 99, 101, 32, 70, 114, 117, 105, 116, 34, 10, 32, 32, 125, 10, 125, 10)
}
}

View File

@@ -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.
@@ -49,9 +49,13 @@ class EvaluateMultipleFileOutputTest {
val output = evaluator.evaluateOutputFiles(text(program))
assertThat(output.keys).isEqualTo(setOf("foo.yml", "bar.yml", "bar/biz.yml", "bar/../bark.yml"))
assertThat(output["foo.yml"]?.text).isEqualTo("foo: foo text")
assertThat(output["foo.yml"]?.bytes).isEqualTo("foo: foo text".toByteArray())
assertThat(output["bar.yml"]?.text).isEqualTo("bar: bar text")
assertThat(output["bar.yml"]?.bytes).isEqualTo("bar: bar text".toByteArray())
assertThat(output["bar/biz.yml"]?.text).isEqualTo("biz: bar biz")
assertThat(output["bar/biz.yml"]?.bytes).isEqualTo("biz: bar biz".toByteArray())
assertThat(output["bar/../bark.yml"]?.text).isEqualTo("bark: bark bark")
assertThat(output["bar/../bark.yml"]?.bytes).isEqualTo("bark: bark bark".toByteArray())
}
@Test

View File

@@ -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.
@@ -32,4 +32,26 @@ class VmValueRendererTest {
val none = VmNull.withDefault("default")
assertThat(renderer.render(none)).isEqualTo("null")
}
@Test
fun `render bytes`() {
val bytes = VmBytes((-128..127).map { it.toByte() }.toByteArray())
assertThat(renderer.render(bytes))
.isEqualTo("Bytes(128, 129, 130, 131, 132, 133, 134, 135, ... <total size: 256.b>)")
}
@Test
fun `render bytes - precisions`() {
val oneKbExactly = VmBytes(ByteArray(1000))
assertThat(renderer.render(oneKbExactly))
.isEqualTo("Bytes(0, 0, 0, 0, 0, 0, 0, 0, ... <total size: 1.kb>)")
val over1Kb = VmBytes(ByteArray(123467))
assertThat(renderer.render(over1Kb))
.isEqualTo("Bytes(0, 0, 0, 0, 0, 0, 0, 0, ... <total size: 123.47.kb>)")
val oneTenthPrecision = VmBytes(ByteArray(1100))
assertThat(renderer.render(oneTenthPrecision))
.isEqualTo("Bytes(0, 0, 0, 0, 0, 0, 0, 0, ... <total size: 1.1.kb>)")
}
}