mirror of https://github.com/apple/pkl-swift
Compare commits
26 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
d6f08700d6 | |
![]() |
cf45d102cb | |
![]() |
c514843f01 | |
![]() |
9c36448681 | |
![]() |
799b6696d2 | |
![]() |
b7e694ea3c | |
![]() |
dda82f32a7 | |
![]() |
3c5da314c9 | |
![]() |
b253e83f7b | |
![]() |
f0bd189f48 | |
![]() |
c280a0e632 | |
![]() |
162bf61a96 | |
![]() |
52d5fbc5e1 | |
![]() |
64c66aea8e | |
![]() |
7d451c59cd | |
![]() |
1d0bf43b4b | |
![]() |
44a04408df | |
![]() |
e6f6aa818f | |
![]() |
8f050f5938 | |
![]() |
48bdb4f503 | |
![]() |
b23fd2369f | |
![]() |
2bcb25f0b7 | |
![]() |
28d1782e50 | |
![]() |
cec993dc2c | |
![]() |
a754b2a010 | |
![]() |
efbca4eb59 |
|
@ -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.
|
||||
|
@ -13,7 +13,9 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
amends "package://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.circleci@1.0.1#/PklCI.pkl"
|
||||
amends "package://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.circleci@1.1.1#/PklCI.pkl"
|
||||
|
||||
import "pkl:semver"
|
||||
|
||||
local swiftTest = new RunStep {
|
||||
name = "swift test"
|
||||
|
@ -23,59 +25,78 @@ local swiftTest = new RunStep {
|
|||
"""
|
||||
}
|
||||
|
||||
local pklVersion = "0.25.1"
|
||||
local pklBinary = "https://repo1.maven.org/maven2/org/pkl-lang/pkl-cli-linux-amd64/\(pklVersion)/pkl-cli-linux-amd64-\(pklVersion).bin"
|
||||
local class PklDistribution {
|
||||
/// The version of this distribution
|
||||
version: String(semver.isValid(this))
|
||||
|
||||
local downloadPkl = new RunStep {
|
||||
name = "Downloading pkl"
|
||||
command = """
|
||||
mkdir /tmp/pkl
|
||||
curl -L "\(pklBinary)" > /tmp/pkl/pkl
|
||||
chmod +x /tmp/pkl/pkl
|
||||
echo 'export PKL_EXEC=/tmp/pkl/pkl' >> $BASH_ENV
|
||||
"""
|
||||
/// Normalized version for use in task names
|
||||
fixed normalizedVersion: String = version.replaceAll(".", "-")
|
||||
|
||||
/// The URL to download this distribution
|
||||
fixed downloadUrl: String = "https://github.com/apple/pkl/releases/download/\(version)/pkl-linux-amd64"
|
||||
|
||||
fixed downloadRunStep: RunStep = new {
|
||||
name = "Downloading pkl-\(version)"
|
||||
command = """
|
||||
PKL=$(mktemp /tmp/pkl-\(version)-XXXXXX)
|
||||
curl -L "\(downloadUrl)" > $PKL
|
||||
chmod +x $PKL
|
||||
echo "export PKL_EXEC=$PKL" >> $BASH_ENV
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
local pklCurrent: PklDistribution = new {
|
||||
version = "0.27.2"
|
||||
}
|
||||
|
||||
local pklDistributions: Listing<PklDistribution> = new {
|
||||
new { version = "0.25.3" }
|
||||
pklCurrent
|
||||
}
|
||||
|
||||
local testJobs = jobs.keys.filter((it) -> it.startsWith("test"))
|
||||
|
||||
main {
|
||||
jobs {
|
||||
"test"
|
||||
...testJobs
|
||||
}
|
||||
}
|
||||
|
||||
prb {
|
||||
jobs {
|
||||
"test"
|
||||
...testJobs
|
||||
}
|
||||
}
|
||||
|
||||
release {
|
||||
jobs {
|
||||
"test"
|
||||
...testJobs
|
||||
new {
|
||||
["pkl-package"] {
|
||||
requires {
|
||||
"test"
|
||||
...testJobs
|
||||
}
|
||||
}
|
||||
}
|
||||
new {
|
||||
["pkl-gen-swift-macos"] {
|
||||
requires {
|
||||
"test"
|
||||
...testJobs
|
||||
}
|
||||
}
|
||||
}
|
||||
new {
|
||||
["pkl-gen-swift-linux-amd64"] {
|
||||
requires {
|
||||
"test"
|
||||
...testJobs
|
||||
}
|
||||
}
|
||||
}
|
||||
new {
|
||||
["pkl-gen-swift-linux-aarch64"] {
|
||||
requires {
|
||||
"test"
|
||||
...testJobs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,22 +121,53 @@ triggerDocsBuild = "release"
|
|||
triggerPackageDocsBuild = "release"
|
||||
|
||||
jobs {
|
||||
["test"] {
|
||||
for (distribution in pklDistributions) {
|
||||
["test-pkl-\(distribution.normalizedVersion)"] {
|
||||
docker {
|
||||
new {
|
||||
image = "swift:5.9-rhel-ubi9"
|
||||
}
|
||||
}
|
||||
resource_class = "xlarge"
|
||||
steps {
|
||||
"checkout"
|
||||
distribution.downloadRunStep
|
||||
swiftTest
|
||||
new RunStep { command = "make circleci-config" }
|
||||
new RunStep { command = "make test-snippets" }
|
||||
new RunStep { command = "make test-pkl" }
|
||||
new RunStep { command = "make generate-fixtures" }
|
||||
new StoreTestResults {
|
||||
path = ".out/test-results/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
["test-license-headers"] {
|
||||
docker {
|
||||
new {
|
||||
image = "ghcr.io/korandoru/hawkeye"
|
||||
}
|
||||
}
|
||||
steps {
|
||||
"checkout"
|
||||
new RunStep {
|
||||
command = "/bin/hawkeye check --fail-if-unknown"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
["test-format"] {
|
||||
docker {
|
||||
new {
|
||||
image = "swift:5.9-rhel-ubi9"
|
||||
}
|
||||
}
|
||||
resource_class = "xlarge"
|
||||
steps {
|
||||
"checkout"
|
||||
downloadPkl
|
||||
swiftTest
|
||||
new RunStep { command = "make test-snippets" }
|
||||
new RunStep { command = "make test-pkl" }
|
||||
new RunStep { command = "make generate-fixtures" }
|
||||
new StoreTestResults {
|
||||
path = ".out/test-results/"
|
||||
new RunStep {
|
||||
command = "make swiftformat-lint"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,7 +220,7 @@ jobs {
|
|||
}
|
||||
steps {
|
||||
"checkout"
|
||||
downloadPkl
|
||||
pklCurrent.downloadRunStep
|
||||
new RunStep {
|
||||
// TODO remove skip-publish-check after initial release
|
||||
command = #"$PKL_EXEC project package --skip-publish-check --output-path out/pkl-package/ codegen/src/"#
|
||||
|
@ -216,7 +268,7 @@ jobs {
|
|||
--title "${CIRCLE_TAG}" \
|
||||
--target "${CIRCLE_SHA1}" \
|
||||
--verify-tag \
|
||||
--notes "Release notes: https://pkl-lang.org/swift/CHANGELOG.html#release-${CIRCLE_TAG}" \
|
||||
--notes "Release notes: https://pkl-lang.org/swift/current/CHANGELOG.html#release-${CIRCLE_TAG}" \
|
||||
--repo "${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}" \
|
||||
out/pkl-gen-swift/*
|
||||
"""#
|
||||
|
|
|
@ -3,21 +3,23 @@ version: '2.1'
|
|||
orbs:
|
||||
pr-approval: apple/pr-approval@0.1.0
|
||||
jobs:
|
||||
test:
|
||||
test-pkl-0-25-3:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |-
|
||||
mkdir /tmp/pkl
|
||||
curl -L "https://repo1.maven.org/maven2/org/pkl-lang/pkl-cli-linux-amd64/0.25.1/pkl-cli-linux-amd64-0.25.1.bin" > /tmp/pkl/pkl
|
||||
chmod +x /tmp/pkl/pkl
|
||||
echo 'export PKL_EXEC=/tmp/pkl/pkl' >> $BASH_ENV
|
||||
name: Downloading pkl
|
||||
PKL=$(mktemp /tmp/pkl-0.25.3-XXXXXX)
|
||||
curl -L "https://github.com/apple/pkl/releases/download/0.25.3/pkl-linux-amd64" > $PKL
|
||||
chmod +x $PKL
|
||||
echo "export PKL_EXEC=$PKL" >> $BASH_ENV
|
||||
name: Downloading pkl-0.25.3
|
||||
- run:
|
||||
command: |-
|
||||
mkdir -p .out/test-results/
|
||||
swift test -vv --parallel --num-workers 1 --xunit-output .out/test-results/xunit.xml -Xswiftc -warnings-as-errors
|
||||
name: swift test
|
||||
- run:
|
||||
command: make circleci-config
|
||||
- run:
|
||||
command: make test-snippets
|
||||
- run:
|
||||
|
@ -29,6 +31,48 @@ jobs:
|
|||
resource_class: xlarge
|
||||
docker:
|
||||
- image: swift:5.9-rhel-ubi9
|
||||
test-pkl-0-27-2:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |-
|
||||
PKL=$(mktemp /tmp/pkl-0.27.2-XXXXXX)
|
||||
curl -L "https://github.com/apple/pkl/releases/download/0.27.2/pkl-linux-amd64" > $PKL
|
||||
chmod +x $PKL
|
||||
echo "export PKL_EXEC=$PKL" >> $BASH_ENV
|
||||
name: Downloading pkl-0.27.2
|
||||
- run:
|
||||
command: |-
|
||||
mkdir -p .out/test-results/
|
||||
swift test -vv --parallel --num-workers 1 --xunit-output .out/test-results/xunit.xml -Xswiftc -warnings-as-errors
|
||||
name: swift test
|
||||
- run:
|
||||
command: make circleci-config
|
||||
- run:
|
||||
command: make test-snippets
|
||||
- run:
|
||||
command: make test-pkl
|
||||
- run:
|
||||
command: make generate-fixtures
|
||||
- store_test_results:
|
||||
path: .out/test-results/
|
||||
resource_class: xlarge
|
||||
docker:
|
||||
- image: swift:5.9-rhel-ubi9
|
||||
test-license-headers:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: /bin/hawkeye check --fail-if-unknown
|
||||
docker:
|
||||
- image: ghcr.io/korandoru/hawkeye
|
||||
test-format:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: make swiftformat-lint
|
||||
docker:
|
||||
- image: swift:5.9-rhel-ubi9
|
||||
pkl-gen-swift-macos:
|
||||
steps:
|
||||
- checkout
|
||||
|
@ -82,11 +126,11 @@ jobs:
|
|||
- checkout
|
||||
- run:
|
||||
command: |-
|
||||
mkdir /tmp/pkl
|
||||
curl -L "https://repo1.maven.org/maven2/org/pkl-lang/pkl-cli-linux-amd64/0.25.1/pkl-cli-linux-amd64-0.25.1.bin" > /tmp/pkl/pkl
|
||||
chmod +x /tmp/pkl/pkl
|
||||
echo 'export PKL_EXEC=/tmp/pkl/pkl' >> $BASH_ENV
|
||||
name: Downloading pkl
|
||||
PKL=$(mktemp /tmp/pkl-0.27.2-XXXXXX)
|
||||
curl -L "https://github.com/apple/pkl/releases/download/0.27.2/pkl-linux-amd64" > $PKL
|
||||
chmod +x $PKL
|
||||
echo "export PKL_EXEC=$PKL" >> $BASH_ENV
|
||||
name: Downloading pkl-0.27.2
|
||||
- run:
|
||||
command: $PKL_EXEC project package --skip-publish-check --output-path out/pkl-package/ codegen/src/
|
||||
- persist_to_workspace:
|
||||
|
@ -125,7 +169,7 @@ jobs:
|
|||
--title "${CIRCLE_TAG}" \
|
||||
--target "${CIRCLE_SHA1}" \
|
||||
--verify-tag \
|
||||
--notes "Release notes: https://pkl-lang.org/swift/CHANGELOG.html#release-${CIRCLE_TAG}" \
|
||||
--notes "Release notes: https://pkl-lang.org/swift/current/CHANGELOG.html#release-${CIRCLE_TAG}" \
|
||||
--repo "${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}" \
|
||||
out/pkl-gen-swift/*
|
||||
name: Do release
|
||||
|
@ -164,24 +208,53 @@ workflows:
|
|||
type: approval
|
||||
- pr-approval/authenticate:
|
||||
context: pkl-pr-approval
|
||||
- test:
|
||||
- test-pkl-0-25-3:
|
||||
requires:
|
||||
- hold
|
||||
- test-pkl-0-27-2:
|
||||
requires:
|
||||
- hold
|
||||
- test-license-headers:
|
||||
requires:
|
||||
- hold
|
||||
- test-format:
|
||||
requires:
|
||||
- hold
|
||||
- pr-approval/authenticate
|
||||
when:
|
||||
matches:
|
||||
value: << pipeline.git.branch >>
|
||||
pattern: ^pull/\d+(/head)?$
|
||||
main:
|
||||
jobs:
|
||||
- test
|
||||
- test-pkl-0-25-3
|
||||
- test-pkl-0-27-2
|
||||
- test-license-headers
|
||||
- test-format
|
||||
when:
|
||||
equal:
|
||||
- main
|
||||
- << pipeline.git.branch >>
|
||||
release:
|
||||
jobs:
|
||||
- test:
|
||||
- test-pkl-0-25-3:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- test-pkl-0-27-2:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- test-license-headers:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- test-format:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
|
@ -189,7 +262,10 @@ workflows:
|
|||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- pkl-package:
|
||||
requires:
|
||||
- test
|
||||
- test-pkl-0-25-3
|
||||
- test-pkl-0-27-2
|
||||
- test-license-headers
|
||||
- test-format
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
|
@ -197,7 +273,10 @@ workflows:
|
|||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- pkl-gen-swift-macos:
|
||||
requires:
|
||||
- test
|
||||
- test-pkl-0-25-3
|
||||
- test-pkl-0-27-2
|
||||
- test-license-headers
|
||||
- test-format
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
|
@ -205,7 +284,10 @@ workflows:
|
|||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- pkl-gen-swift-linux-amd64:
|
||||
requires:
|
||||
- test
|
||||
- test-pkl-0-25-3
|
||||
- test-pkl-0-27-2
|
||||
- test-license-headers
|
||||
- test-format
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
|
@ -213,7 +295,10 @@ workflows:
|
|||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- pkl-gen-swift-linux-aarch64:
|
||||
requires:
|
||||
- test
|
||||
- test-pkl-0-25-3
|
||||
- test-pkl-0-27-2
|
||||
- test-license-headers
|
||||
- test-format
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
.DS_Store
|
||||
.build
|
||||
.index-build
|
||||
/Packages
|
||||
/*.xcodeproj
|
||||
xcuserdata/
|
||||
|
@ -16,4 +17,5 @@ DerivedData/
|
|||
.out/
|
||||
out/
|
||||
|
||||
.cicd/
|
||||
.cicd/
|
||||
.pkl-lsp/
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
version: 1
|
||||
builder:
|
||||
configs:
|
||||
- documentation_targets: ['PklSwift']
|
|
@ -15,9 +15,8 @@
|
|||
--guardelse same-line
|
||||
--nevertrailing filter
|
||||
--extensionacl on-declarations
|
||||
--header "// ===----------------------------------------------------------------------===//\n// Copyright © {year} Apple Inc. and the Pkl project authors. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ===----------------------------------------------------------------------===//"
|
||||
|
||||
# rules
|
||||
|
||||
--disable spaceAroundOperators
|
||||
--disable wrapMultilineStatementBraces
|
||||
--disable wrapMultilineStatementBraces
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
= Development
|
||||
|
||||
== Running the formatter
|
||||
|
||||
This project uses two formatting tools: https://github.com/korandoru/hawkeye[hawkeye] and https://github.com/nicklockwood/SwiftFormat[SwiftFormat].
|
||||
|
||||
To install swiftformat:
|
||||
|
||||
[source,shell]
|
||||
----
|
||||
brew install swiftformat
|
||||
----
|
||||
|
||||
To install hawkeye locally, you will need to install the https://rustup.rs[Rust toolchain], then run:
|
||||
|
||||
[source,shell]
|
||||
----
|
||||
cargo install hawkeye
|
||||
----
|
||||
|
||||
To run formatters:
|
||||
|
||||
[source,shell]
|
||||
----
|
||||
make format
|
||||
|
||||
# Alternatively, individually:
|
||||
swiftformat .
|
||||
|
||||
hawkeye format
|
||||
----
|
16
Makefile
16
Makefile
|
@ -108,3 +108,19 @@ pkl-gen-swift-release: $(PKL_GEN_SWIFT_RELEASE)
|
|||
.PHONY: pkl-gen-swift-release-output
|
||||
pkl-gen-swift-release-output:
|
||||
@echo "$(PKL_GEN_SWIFT_RELEASE)" | xargs
|
||||
|
||||
.PHONY: circleci-config
|
||||
circleci-config:
|
||||
$(PKL_EXEC) eval .circleci/config.pkl -o .circleci/config.yml
|
||||
git diff --exit-code
|
||||
|
||||
swiftformat:
|
||||
swift package plugin --allow-writing-to-package-directory swiftformat .
|
||||
|
||||
swiftformat-lint:
|
||||
swift package plugin --allow-writing-to-package-directory swiftformat --lint .
|
||||
|
||||
license-format: .build/tools/hawkeye
|
||||
.build/tools/hawkeye format
|
||||
|
||||
format: swiftformat license-format
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
{
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "semanticversion",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/SwiftPackageIndex/SemanticVersion",
|
||||
"state" : {
|
||||
"revision" : "ea8eea9d89842a29af1b8e6c7677f1c86e72fa42",
|
||||
"version" : "0.4.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-argument-parser",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
@ -9,6 +18,24 @@
|
|||
"version" : "1.2.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-docc-plugin",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/swiftlang/swift-docc-plugin",
|
||||
"state" : {
|
||||
"revision" : "85e4bb4e1cd62cec64a4b8e769dcefdf0c5b9d64",
|
||||
"version" : "1.4.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-docc-symbolkit",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/swiftlang/swift-docc-symbolkit",
|
||||
"state" : {
|
||||
"revision" : "b45d1f2ed151d057b54504d653e0da5552844e34",
|
||||
"version" : "1.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-system",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
@ -17,6 +44,15 @@
|
|||
"revision" : "025bcb1165deab2e20d4eaba79967ce73013f496",
|
||||
"version" : "1.2.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swiftformat",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/nicklockwood/SwiftFormat",
|
||||
"state" : {
|
||||
"revision" : "468a7d32dedc8d352c191594b3b45d9fd8ba291b",
|
||||
"version" : "0.55.5"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 2
|
||||
|
|
|
@ -1,4 +1,20 @@
|
|||
// swift-tools-version: 5.9
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// 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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
|
@ -6,7 +22,6 @@ let package = Package(
|
|||
platforms: [
|
||||
// required because of `Duration` API
|
||||
.macOS(.v13),
|
||||
.iOS(.v13),
|
||||
],
|
||||
products: [
|
||||
.library(
|
||||
|
@ -25,11 +40,16 @@ let package = Package(
|
|||
dependencies: [
|
||||
.package(url: "https://github.com/apple/swift-system", from: "1.2.1"),
|
||||
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.2.3"),
|
||||
.package(url: "https://github.com/SwiftPackageIndex/SemanticVersion", from: "0.4.0"),
|
||||
// to enable `swift package generate-documentation --target PklSwift`
|
||||
.package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.1.0"),
|
||||
// to enable `swift package plugin --allow-writing-to-package-directory swiftformat`
|
||||
.package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.55.0"),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "PklSwift",
|
||||
dependencies: ["MessagePack", "PklSwiftInternals"]
|
||||
dependencies: ["MessagePack", "PklSwiftInternals", "SemanticVersion"]
|
||||
),
|
||||
.target(
|
||||
name: "PklSwiftInternals"
|
||||
|
@ -48,6 +68,10 @@ let package = Package(
|
|||
],
|
||||
resources: [.embedInCode("Resources/VERSION.txt")]
|
||||
),
|
||||
.executableTarget(
|
||||
name: "test-external-reader",
|
||||
dependencies: ["PklSwift"]
|
||||
),
|
||||
.testTarget(
|
||||
name: "PklSwiftTests",
|
||||
dependencies: [
|
||||
|
|
|
@ -8,4 +8,4 @@ The full documentation for this library can be found on our link:https://pkl-lan
|
|||
|
||||
To get up and going, reference the link:https://pkl-lang.org/swift/current/quickstart.html[quick start guide].
|
||||
|
||||
When upgrading pkl-swift, reference the link:https://pkl-lang.org/pkl/swift/current/CHANGELOG.html[changelog] for details.
|
||||
When upgrading pkl-swift, reference the link:https://pkl-lang.org/swift/current/CHANGELOG.html[changelog] for details.
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
struct AnyCodingKey: CodingKey, Equatable {
|
||||
let stringValue: String
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
@ -185,7 +185,6 @@ extension MessagePackValue {
|
|||
case .ext:
|
||||
// TODO: implement this?
|
||||
fatalError("Cannot convert \(self) to \(T.self)")
|
||||
|
||||
case .timestamp:
|
||||
// TODO: implement this?
|
||||
fatalError("Cannot convert \(self) to \(T.self)")
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if os(Linux)
|
||||
#if os(Linux) || os(Windows)
|
||||
let NSEC_PER_SEC: UInt64 = 1_000_000_000
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
@ -44,10 +44,13 @@ public final class MessagePackEncoder {
|
|||
try Box<Data>(data).encode(to: encoder)
|
||||
case let date as Date:
|
||||
try Box<Date>(date).encode(to: encoder)
|
||||
case let bytes as [UInt8]:
|
||||
try Box<[UInt8]>(bytes).encode(to: encoder)
|
||||
case let url as URL:
|
||||
try Box<URL>(url).encode(to: encoder)
|
||||
case let bytes as [UInt8]:
|
||||
guard type(of: value) == [UInt8].self else {
|
||||
fallthrough
|
||||
}
|
||||
try Box<[UInt8]>(bytes).encode(to: encoder)
|
||||
default:
|
||||
try value.encode(to: encoder)
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
@ -304,8 +304,6 @@ extension _MessagePackEncoder.SingleValueContainer: SingleValueEncodingContainer
|
|||
try self.encode(data)
|
||||
case let date as Date:
|
||||
try self.encode(date)
|
||||
case let bytes as [UInt8]:
|
||||
try self.encode(bytes)
|
||||
case let url as URL:
|
||||
try self.encode(url)
|
||||
case let bool as Bool:
|
||||
|
@ -334,9 +332,16 @@ extension _MessagePackEncoder.SingleValueContainer: SingleValueEncodingContainer
|
|||
try self.encode(uint64)
|
||||
case let num as any BinaryInteger & Encodable:
|
||||
try self.encode(num)
|
||||
case let bytes as [UInt8]:
|
||||
guard type(of: value) == [UInt8].self else {
|
||||
fallthrough
|
||||
}
|
||||
try self.encode(bytes)
|
||||
default:
|
||||
let writer: Writer = BufferWriter()
|
||||
let encoder = _MessagePackEncoder()
|
||||
encoder.userInfo = userInfo
|
||||
encoder.codingPath = codingPath
|
||||
try value.encode(to: encoder)
|
||||
try encoder.write(into: writer)
|
||||
let data = (writer as! BufferWriter).bytes
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
extension FixedWidthInteger {
|
||||
init(bytes: [UInt8]) {
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
public protocol Writer {
|
||||
/// Write the given bytes into an output somewhere.
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
import MessagePack
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
|
|
@ -1,45 +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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Pair is the Swift representation of Pkl's `pkl.Pair`.
|
||||
public struct Pair<A, B>: Hashable where A: Hashable, B: Hashable {
|
||||
public init(_ first: A, _ second: B) {
|
||||
self.first = first
|
||||
self.second = second
|
||||
}
|
||||
|
||||
/// The value of the first component of this ``Pair``.
|
||||
let first: A
|
||||
|
||||
/// The value of the second component of this ``Pair``.
|
||||
let second: B
|
||||
}
|
||||
|
||||
extension Pair: CustomStringConvertible where A: CustomStringConvertible, B: CustomStringConvertible {
|
||||
public var description: String {
|
||||
"Pair(\(self.first.description), \(self.second.description))"
|
||||
}
|
||||
}
|
||||
|
||||
extension Pair: Decodable where A: Decodable, B: Decodable {
|
||||
public init(from decoder: Decoder) throws {
|
||||
var partsDecoder = try decoder.unkeyedContainer()
|
||||
self.first = try partsDecoder.decode(A.self)
|
||||
self.second = try partsDecoder.decode(B.self)
|
||||
}
|
||||
}
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
import MessagePack
|
||||
|
@ -205,6 +205,7 @@ extension _PklDecoder {
|
|||
))
|
||||
}
|
||||
var arr: [AnyHashable?] = []
|
||||
arr.reserveCapacity(pklArray.count)
|
||||
for v in pklArray {
|
||||
try arr.append(self.decodePolymorphic(v, codingPath: codingPath)?.value)
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import MessagePack
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import MessagePack
|
||||
|
||||
|
@ -37,11 +37,13 @@ class PklSingleValueDecodingContainer: SingleValueDecodingContainer {
|
|||
switch self.value {
|
||||
case .bool(let value): return value
|
||||
default:
|
||||
throw DecodingError.dataCorrupted(
|
||||
throw DecodingError.typeMismatch(
|
||||
Bool.self,
|
||||
.init(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Expected a boolean, but got \(self.value.debugDataTypeDescription)"
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,11 +51,13 @@ class PklSingleValueDecodingContainer: SingleValueDecodingContainer {
|
|||
switch self.value {
|
||||
case .string(let value): return value
|
||||
default:
|
||||
throw DecodingError.dataCorrupted(
|
||||
throw DecodingError.typeMismatch(
|
||||
String.self,
|
||||
.init(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Expected a string, but got \(self.value.debugDataTypeDescription)"
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,11 +65,13 @@ class PklSingleValueDecodingContainer: SingleValueDecodingContainer {
|
|||
switch self.value {
|
||||
case .float(let value): return Double(value)
|
||||
default:
|
||||
throw DecodingError.dataCorrupted(
|
||||
throw DecodingError.typeMismatch(
|
||||
Double.self,
|
||||
.init(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Expected a float, but got \(self.value.debugDataTypeDescription)"
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,11 +79,13 @@ class PklSingleValueDecodingContainer: SingleValueDecodingContainer {
|
|||
switch self.value {
|
||||
case .float(let value): return Float(value)
|
||||
default:
|
||||
throw DecodingError.dataCorrupted(
|
||||
throw DecodingError.typeMismatch(
|
||||
Float.self,
|
||||
.init(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Expected a float, but got \(self.value.debugDataTypeDescription)"
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +132,7 @@ class PklSingleValueDecodingContainer: SingleValueDecodingContainer {
|
|||
func decode<T>(_ type: T.Type) throws -> T where T: Decodable {
|
||||
if type == PklAny.self {
|
||||
guard let result = try _PklDecoder.decodePolymorphic(value, codingPath: codingPath) else {
|
||||
throw DecodingError.dataCorrupted(.init(codingPath: self.codingPath, debugDescription: "Tried to decode but got nil"))
|
||||
throw DecodingError.typeMismatch(T.self, .init(codingPath: self.codingPath, debugDescription: "Tried to decode but got nil"))
|
||||
}
|
||||
return result as! T
|
||||
}
|
||||
|
@ -135,13 +143,25 @@ class PklSingleValueDecodingContainer: SingleValueDecodingContainer {
|
|||
|
||||
private func decodeBinaryInteger<T>() throws -> T where T: BinaryInteger {
|
||||
switch self.value {
|
||||
case .int(let value): return T(value)
|
||||
case .int(let value):
|
||||
guard let result = T(exactly: value) else {
|
||||
throw DecodingError.typeMismatch(
|
||||
T.self,
|
||||
.init(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot fit \(value) into \(String(describing: T.self))"
|
||||
)
|
||||
)
|
||||
}
|
||||
return result
|
||||
default:
|
||||
throw DecodingError.dataCorrupted(
|
||||
throw DecodingError.typeMismatch(
|
||||
T.self,
|
||||
.init(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Expected an int, but got \(self.value.debugDataTypeDescription)"
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import MessagePack
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import MessagePack
|
||||
|
||||
|
@ -49,11 +49,6 @@ extension _PklDecoder {
|
|||
throw error("Expected an array at slot 2, but got \(value[1].debugDataTypeDescription)")
|
||||
}
|
||||
self.members = members
|
||||
} else if value.count == 3 {
|
||||
guard pklType == .pair else {
|
||||
throw error("Expected to find a Pair type marker, but found \(pklType)")
|
||||
}
|
||||
self.members = Array(value[1...2])
|
||||
} else {
|
||||
throw error("Expected 2 or 3 values, but found \(value.count)")
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
@ -36,17 +36,14 @@ public func withEvaluator<T>(_ action: (Evaluator) async throws -> T) async thro
|
|||
try await withEvaluator(options: .preconfigured, action)
|
||||
}
|
||||
|
||||
/// Like ``withProjectEvaluator(projectDir:options:_:)``, but configured with preconfigured otions.
|
||||
/// Like ``withProjectEvaluator(projectBaseURI:options:_:)``, but configured with preconfigured options.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - projectDir: The directory containing the PklProject file.
|
||||
/// - projectBaseURI: The base path containing the PklProject file.
|
||||
/// - action: The action to perform.
|
||||
/// - Returns: The result of the action.
|
||||
public func withProjectEvaluator<T>(
|
||||
projectDir: String,
|
||||
_ action: (Evaluator) async throws -> T
|
||||
) async throws -> T {
|
||||
try await withProjectEvaluator(projectDir: projectDir, options: .preconfigured, action)
|
||||
public func withProjectEvaluator<T>(projectBaseURI: URL, _ action: (Evaluator) async throws -> T) async throws -> T {
|
||||
try await withProjectEvaluator(projectBaseURI: projectBaseURI, options: .preconfigured, action)
|
||||
}
|
||||
|
||||
/// Convenience method for initializing an evaluator from the project.
|
||||
|
@ -56,17 +53,17 @@ public func withProjectEvaluator<T>(
|
|||
///
|
||||
/// After `action` completes, the evaluator is closed.
|
||||
/// - Parameters:
|
||||
/// - projectDir: The directory containing the PklProject file.
|
||||
/// - projectBaseURI: The base path containing the PklProject file.
|
||||
/// - options: The base options used to configure the evaluator.
|
||||
/// - action: The action to perform.
|
||||
/// - Returns: The result of the action.
|
||||
public func withProjectEvaluator<T>(
|
||||
projectDir: String,
|
||||
projectBaseURI: URL,
|
||||
options: EvaluatorOptions,
|
||||
_ action: (Evaluator) async throws -> T
|
||||
) async throws -> T {
|
||||
try await withEvaluatorManager { manager in
|
||||
let evaluator = try await manager.newProjectEvaluator(projectDir: projectDir, options: options)
|
||||
let evaluator = try await manager.newProjectEvaluator(projectBaseURI: projectBaseURI, options: options)
|
||||
return try await action(evaluator)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,31 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
import MessagePack
|
||||
import SemanticVersion
|
||||
#if os(Windows)
|
||||
import WinSDK.System
|
||||
|
||||
let ENV_SEPARATOR=";"
|
||||
let PKL_EXEC_NAME="pkl.exe"
|
||||
#else
|
||||
let ENV_SEPARATOR=":"
|
||||
let PKL_EXEC_NAME="pkl"
|
||||
#endif
|
||||
/// Perfoms `action`, returns its result and then closes the manager.
|
||||
///
|
||||
/// - Parameter action: The action to perform
|
||||
|
@ -37,6 +46,47 @@ public func withEvaluatorManager<T>(_ action: (EvaluatorManager) async throws ->
|
|||
}
|
||||
}
|
||||
|
||||
func getenv(_ key: String) -> String? {
|
||||
#if os(Windows)
|
||||
let key = key.lowercased()
|
||||
return ProcessInfo.processInfo.environment.first { (envKey: String, _: String) in
|
||||
key == envKey.lowercased()
|
||||
}?.value
|
||||
#else
|
||||
return ProcessInfo.processInfo.environment[key]
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Resolve the (CLI) command to invoke Pkl.
|
||||
///
|
||||
/// First, checks the `PKL_EXEC` environment variable. If that is not set, searches the `PATH` for a directory
|
||||
/// containing `pkl`.
|
||||
func getPklCommand() throws -> [String] {
|
||||
if let exec = getenv("PKL_EXEC") {
|
||||
return exec.components(separatedBy: " ")
|
||||
}
|
||||
guard let path = getenv("PATH") else {
|
||||
throw PklError("Unable to read PATH environment variable.")
|
||||
}
|
||||
for dir in path.components(separatedBy: ENV_SEPARATOR) {
|
||||
do {
|
||||
let contents = try FileManager.default.contentsOfDirectory(atPath: dir)
|
||||
if let pkl = contents.first(where: { $0 == PKL_EXEC_NAME }) {
|
||||
let file = NSString.path(withComponents: [dir, pkl])
|
||||
if FileManager.default.isExecutableFile(atPath: file) {
|
||||
return [file]
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
if error._domain == NSCocoaErrorDomain {
|
||||
continue
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
throw PklError("Unable to find `pkl` command on PATH.")
|
||||
}
|
||||
|
||||
/// Provides handlers for managing the lifecycles of Pkl evaluators. If binding to Pkl as a child process, an evaluator
|
||||
/// manager represents a single child process.
|
||||
///
|
||||
|
@ -55,9 +105,11 @@ public actor EvaluatorManager {
|
|||
|
||||
var isClosed: Bool = false
|
||||
|
||||
var pklVersion: String?
|
||||
|
||||
// note; when our C bindings are released, change `init()` based on compiler flags.
|
||||
public init() {
|
||||
self.init(transport: ChildProcessMessageTransport())
|
||||
self.init(transport: ServerMessageTransport())
|
||||
}
|
||||
|
||||
// Used for testing only.
|
||||
|
@ -72,6 +124,31 @@ public actor EvaluatorManager {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the semantic version as a String of the Pkl interpreter being used.
|
||||
func getVersion() throws -> String {
|
||||
if let pklVersion {
|
||||
return pklVersion
|
||||
}
|
||||
|
||||
let pklCommand = try getPklCommand()
|
||||
let process = Process()
|
||||
process.executableURL = URL(fileURLWithPath: pklCommand[0])
|
||||
process.arguments = Array(pklCommand.dropFirst()) + ["--version"]
|
||||
let pipe = Pipe()
|
||||
process.standardOutput = pipe
|
||||
debug("Spawning command \(pklCommand[0]) with arguments \(process.arguments!)")
|
||||
try process.run()
|
||||
guard let outputData = try pipe.fileHandleForReading.readToEnd(),
|
||||
let output = String(data: outputData, encoding: .utf8)?.split(separator: " "),
|
||||
output.count > 2,
|
||||
output[0] == "Pkl" else {
|
||||
throw PklError("Could not get version from Pkl binary")
|
||||
}
|
||||
|
||||
self.pklVersion = String(output[1])
|
||||
return self.pklVersion!
|
||||
}
|
||||
|
||||
private func listenForIncomingMessages() async throws {
|
||||
for try await message in try self.transport.getMessages() {
|
||||
debug("EvaluatorManager got message \(message)")
|
||||
|
@ -127,24 +204,24 @@ public actor EvaluatorManager {
|
|||
/// - options: The options used to configure the evaluator.
|
||||
/// - action: The action to run with the evaluator.
|
||||
public func withEvaluator<T>(options: EvaluatorOptions, _ action: (Evaluator) async throws -> T) async throws -> T {
|
||||
let evalautor = try await newEvaluator(options: options)
|
||||
let evaluator = try await newEvaluator(options: options)
|
||||
var closed = false
|
||||
do {
|
||||
let result = try await action(evalautor)
|
||||
try await evalautor.close()
|
||||
let result = try await action(evaluator)
|
||||
try await evaluator.close()
|
||||
closed = true
|
||||
return result
|
||||
} catch {
|
||||
if !closed {
|
||||
try await evalautor.close()
|
||||
try await evaluator.close()
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience method for constructing a project evaluator with preconfigured base options.
|
||||
public func withProjectEvaluator<T>(projectDir: String, _ action: (Evaluator) async throws -> T) async throws -> T {
|
||||
try await self.withProjectEvaluator(projectDir: projectDir, options: .preconfigured, action)
|
||||
public func withProjectEvaluator<T>(projectBaseURI: URL, _ action: (Evaluator) async throws -> T) async throws -> T {
|
||||
try await self.withProjectEvaluator(projectBaseURI: projectBaseURI, options: .preconfigured, action)
|
||||
}
|
||||
|
||||
/// Constructs an evaluator that is configured by the project within the project dir.
|
||||
|
@ -155,20 +232,20 @@ public actor EvaluatorManager {
|
|||
/// After the action completes or throws, the evaluator is closed.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - projectDir: The project directory that contains the PklProject file.
|
||||
/// - projectBaseURI: The project base path that contains the PklProject file.
|
||||
/// - options: The options used to configure the evaluator.
|
||||
/// - action: The action to run with the evaluator.
|
||||
public func withProjectEvaluator<T>(projectDir: String, options: EvaluatorOptions, _ action: (Evaluator) async throws -> T) async throws -> T {
|
||||
let evalautor = try await newProjectEvaluator(projectDir: projectDir, options: options)
|
||||
public func withProjectEvaluator<T>(projectBaseURI: URL, options: EvaluatorOptions, _ action: (Evaluator) async throws -> T) async throws -> T {
|
||||
let evaluator = try await newProjectEvaluator(projectBaseURI: projectBaseURI, options: options)
|
||||
var closed = false
|
||||
do {
|
||||
let result = try await action(evalautor)
|
||||
try await evalautor.close()
|
||||
let result = try await action(evaluator)
|
||||
try await evaluator.close()
|
||||
closed = true
|
||||
return result
|
||||
} catch {
|
||||
if !closed {
|
||||
try await evalautor.close()
|
||||
try await evaluator.close()
|
||||
}
|
||||
throw error
|
||||
}
|
||||
|
@ -176,13 +253,21 @@ public actor EvaluatorManager {
|
|||
|
||||
/// Creates a new evaluator with the provided options.
|
||||
///
|
||||
/// To create an evaluator that understands project dependencies, use ``newProjectEvaluator(projectDir:options:)``.
|
||||
/// To create an evaluator that understands project dependencies, use
|
||||
/// ``newProjectEvaluator(projectBaseURI:options:)``.
|
||||
///
|
||||
/// - Parameter options: The options used to configure the evaluator.
|
||||
public func newEvaluator(options: EvaluatorOptions) async throws -> Evaluator {
|
||||
if self.isClosed {
|
||||
throw PklError("The evaluator manager is closed")
|
||||
}
|
||||
let version = try SemanticVersion(getVersion())!
|
||||
guard options.http == nil || version >= pklVersion0_26 else {
|
||||
throw PklError("http options are not supported on Pkl versions lower than 0.26")
|
||||
}
|
||||
guard (options.externalModuleReaders == nil && options.externalResourceReaders == nil) || version >= pklVersion0_27 else {
|
||||
throw PklError("external reader options are not supported on Pkl versions lower than 0.27")
|
||||
}
|
||||
let req = options.toMessage()
|
||||
guard let response = try await ask(req) as? CreateEvaluatorResponse else {
|
||||
throw PklBugError.invalidMessageCode(
|
||||
|
@ -209,15 +294,15 @@ public actor EvaluatorManager {
|
|||
// Any `evaluatorSettings` set within the PklProject file overwrites any fields set on `options`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - projectDir: The project directory containing the `PklProject` file.
|
||||
/// - projectBaseURI: The project base path containing the `PklProject` file.
|
||||
/// - options: The base options used to configure the evaluator.
|
||||
public func newProjectEvaluator(projectDir: String, options: EvaluatorOptions) async throws -> Evaluator {
|
||||
public func newProjectEvaluator(projectBaseURI: URL, options: EvaluatorOptions) async throws -> Evaluator {
|
||||
if self.isClosed {
|
||||
throw PklError("The evaluator manager is closed")
|
||||
}
|
||||
return try await self.withEvaluator(options: .preconfigured) { projectEvaluator in
|
||||
let project = try await projectEvaluator.evaluateOutputValue(
|
||||
source: .path("\(projectDir)/PklProject"),
|
||||
source: .path("\(projectBaseURI)/PklProject"),
|
||||
asType: Project.self
|
||||
)
|
||||
return try await self.newEvaluator(options: options.withProject(project))
|
||||
|
@ -287,3 +372,13 @@ enum PklBugError: Error {
|
|||
case invalidEvaluatorId(String)
|
||||
case unknownMessage(String)
|
||||
}
|
||||
|
||||
let pklVersion0_25 = SemanticVersion("0.25.0")!
|
||||
let pklVersion0_26 = SemanticVersion("0.26.0")!
|
||||
let pklVersion0_27 = SemanticVersion("0.27.0")!
|
||||
|
||||
let supportedPklVersions = [
|
||||
pklVersion0_25,
|
||||
pklVersion0_26,
|
||||
pklVersion0_27,
|
||||
]
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
@ -30,8 +30,11 @@ public struct EvaluatorOptions {
|
|||
cacheDir: String? = nil,
|
||||
outputFormat: String? = nil,
|
||||
logger: Logger = Loggers.noop,
|
||||
projectDir: String? = nil,
|
||||
declaredProjectDependencies: [String: ProjectDependency]? = nil
|
||||
projectBaseURI: URL? = nil,
|
||||
http: Http? = nil,
|
||||
declaredProjectDependencies: [String: ProjectDependency]? = nil,
|
||||
externalModuleReaders: [String: ExternalReader]? = nil,
|
||||
externalResourceReaders: [String: ExternalReader]? = nil
|
||||
) {
|
||||
self.allowedModules = allowedModules
|
||||
self.allowedResources = allowedResources
|
||||
|
@ -45,8 +48,11 @@ public struct EvaluatorOptions {
|
|||
self.cacheDir = cacheDir
|
||||
self.outputFormat = outputFormat
|
||||
self.logger = logger
|
||||
self.projectDir = projectDir
|
||||
self.projectBaseURI = projectBaseURI
|
||||
self.http = http
|
||||
self.declaredProjectDependencies = declaredProjectDependencies
|
||||
self.externalModuleReaders = externalModuleReaders
|
||||
self.externalResourceReaders = externalResourceReaders
|
||||
}
|
||||
|
||||
/// Regular expression patterns that control what modules are allowed to be imported in a Pkl program.
|
||||
|
@ -106,15 +112,33 @@ public struct EvaluatorOptions {
|
|||
/// It is meant to be set by lower level logic in Swift code that first evaluates the PklProject,
|
||||
/// which then configures ``EvaluatorOptions`` accordingly.
|
||||
///
|
||||
/// To emulate the CLI's `--project-dir` flag, create an evaluator with ``withProjectEvaluator(projectDir:_:)``,
|
||||
/// To emulate the CLI's `--project-dir` flag, create an evaluator with ``withProjectEvaluator(projectBaseURI:_:)``,
|
||||
/// or ``EvaluatorManager/newProjectEvaluator()``.
|
||||
public var projectDir: String?
|
||||
public var projectBaseURI: URL?
|
||||
|
||||
/// The set of dependencies available to modules within ``projectDir``.
|
||||
/// Settings that control how Pkl talks to HTTP(S) servers.
|
||||
///
|
||||
/// When importing dependencies, a `PklProject.deps.json` file must exist within ``projectDir``
|
||||
/// Added in Pkl 0.26.
|
||||
/// These fields are ignored if targeting Pkl 0.25.
|
||||
public var http: Http?
|
||||
|
||||
/// The set of dependencies available to modules within ``projectBaseURI``.
|
||||
///
|
||||
/// When importing dependencies, a `PklProject.deps.json` file must exist within ``projectBaseURI``
|
||||
/// that contains the project's resolved dependencies.
|
||||
public var declaredProjectDependencies: [String: ProjectDependency]?
|
||||
|
||||
/// Registered external commands that implement module reader schemes.
|
||||
///
|
||||
/// Added in Pkl 0.27.
|
||||
/// If the underlying Pkl does not support external readers, evaluation will fail when a registered scheme is used.
|
||||
public var externalModuleReaders: [String: ExternalReader]?
|
||||
|
||||
/// Registered external commands that implement resource reader schemes.
|
||||
///
|
||||
/// Added in Pkl 0.27.
|
||||
/// If the underlying Pkl does not support external readers, evaluation will fail when a registered scheme is used.
|
||||
public var externalResourceReaders: [String: ExternalReader]?
|
||||
}
|
||||
|
||||
extension EvaluatorOptions {
|
||||
|
@ -153,18 +177,21 @@ extension EvaluatorOptions {
|
|||
rootDir: self.rootDir,
|
||||
cacheDir: self.cacheDir,
|
||||
outputFormat: self.outputFormat,
|
||||
project: self.project()
|
||||
project: self.project(),
|
||||
http: self.http,
|
||||
externalModuleReaders: self.externalModuleReaders,
|
||||
externalResourceReaders: self.externalResourceReaders
|
||||
)
|
||||
}
|
||||
|
||||
func project() -> ProjectOrDependency? {
|
||||
guard let projectDir else {
|
||||
guard let projectBaseURI else {
|
||||
return nil
|
||||
}
|
||||
return .init(
|
||||
packageUri: nil,
|
||||
type: "project",
|
||||
projectFileUri: "file://\(projectDir)/PklProject",
|
||||
projectFileUri: "file://\(projectBaseURI)/PklProject",
|
||||
checksums: nil,
|
||||
dependencies: self.declaredProjectDependenciesToMessage(self.declaredProjectDependencies)
|
||||
)
|
||||
|
@ -227,28 +254,17 @@ extension EvaluatorOptions {
|
|||
/// Builds options that configures the evaluator with settings set on the project.
|
||||
///
|
||||
/// Skips any settings that are nil.
|
||||
public func withProjectEvaluatorSettings(_ evaluatorSettings: Project.EvaluatorSettings) -> EvaluatorOptions {
|
||||
public func withProjectEvaluatorSettings(_ evaluatorSettings: PklEvaluatorSettings) -> EvaluatorOptions {
|
||||
var options = self
|
||||
if evaluatorSettings.externalProperties != nil {
|
||||
options.properties = evaluatorSettings.externalProperties
|
||||
}
|
||||
if evaluatorSettings.env != nil {
|
||||
options.env = evaluatorSettings.env
|
||||
}
|
||||
if evaluatorSettings.allowedModules != nil {
|
||||
options.allowedModules = evaluatorSettings.allowedModules
|
||||
}
|
||||
if evaluatorSettings.allowedResources != nil {
|
||||
options.allowedResources = evaluatorSettings.allowedResources
|
||||
}
|
||||
if evaluatorSettings.noCache == true {
|
||||
options.cacheDir = nil
|
||||
} else if evaluatorSettings.moduleCacheDir != nil {
|
||||
options.cacheDir = evaluatorSettings.moduleCacheDir
|
||||
}
|
||||
if evaluatorSettings.rootDir != nil {
|
||||
options.rootDir = evaluatorSettings.rootDir
|
||||
}
|
||||
options.properties = evaluatorSettings.externalProperties ?? self.properties
|
||||
options.env = evaluatorSettings.env ?? self.env
|
||||
options.allowedModules = evaluatorSettings.allowedModules ?? self.allowedModules
|
||||
options.allowedResources = evaluatorSettings.allowedResources ?? self.allowedResources
|
||||
options.cacheDir = evaluatorSettings.noCache != nil ? nil : (evaluatorSettings.moduleCacheDir ?? self.cacheDir)
|
||||
options.rootDir = evaluatorSettings.rootDir ?? self.rootDir
|
||||
options.http = evaluatorSettings.http ?? self.http
|
||||
options.externalModuleReaders = evaluatorSettings.externalModuleReaders ?? options.externalModuleReaders
|
||||
options.externalResourceReaders = evaluatorSettings.externalResourceReaders ?? options.externalResourceReaders
|
||||
return options
|
||||
}
|
||||
|
||||
|
@ -277,7 +293,8 @@ extension EvaluatorOptions {
|
|||
/// Builds options with dependencies from the input project.
|
||||
public func withProjectDependencies(_ project: Project) -> EvaluatorOptions {
|
||||
var options = self
|
||||
options.projectDir = String(URL(string: project.projectFileUri)!.path.dropLast("/PklProject".count))
|
||||
options.projectBaseURI = URL(string: project.projectFileUri)!
|
||||
options.projectBaseURI?.deleteLastPathComponent()
|
||||
options.declaredProjectDependencies = self.projectDependencies(project)
|
||||
return options
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
import MessagePack
|
||||
|
||||
// Example usage:
|
||||
// import PklSwift
|
||||
// @main
|
||||
// struct Main {
|
||||
// static func main() async throws {
|
||||
// let client = ExternalReaderClient(
|
||||
// options: ExternalReaderClientOptions(
|
||||
// resourceReaders: [MyResourceReader()]
|
||||
// ))
|
||||
// try await client.run()
|
||||
// }
|
||||
// }
|
||||
|
||||
public struct ExternalReaderClientOptions {
|
||||
/// Reader to receive requests.
|
||||
public var requestReader: Reader = FileHandle.standardInput
|
||||
|
||||
/// Writer to publish responses.
|
||||
public var responseWriter: Writer = FileHandle.standardOutput
|
||||
|
||||
/// Readers that allow reading custom resources in Pkl.
|
||||
public var moduleReaders: [ModuleReader] = []
|
||||
|
||||
/// Readers that allow importing custom modules in Pkl.
|
||||
public var resourceReaders: [ResourceReader] = []
|
||||
|
||||
public init(
|
||||
requestReader: Reader = FileHandle.standardInput,
|
||||
responseWriter: Writer = FileHandle.standardOutput,
|
||||
moduleReaders: [ModuleReader] = [],
|
||||
resourceReaders: [ResourceReader] = []
|
||||
) {
|
||||
self.requestReader = requestReader
|
||||
self.responseWriter = responseWriter
|
||||
self.moduleReaders = moduleReaders
|
||||
self.resourceReaders = resourceReaders
|
||||
}
|
||||
}
|
||||
|
||||
public class ExternalReaderClient {
|
||||
private let moduleReaders: [ModuleReader]
|
||||
private let resourceReaders: [ResourceReader]
|
||||
private let transport: MessageTransport
|
||||
|
||||
public init(options: ExternalReaderClientOptions) {
|
||||
self.moduleReaders = options.moduleReaders
|
||||
self.resourceReaders = options.resourceReaders
|
||||
self.transport = ExternalReaderMessageTransport(
|
||||
reader: options.requestReader, writer: options.responseWriter
|
||||
)
|
||||
}
|
||||
|
||||
public func run() async throws {
|
||||
for try await message in try self.transport.getMessages() {
|
||||
switch message {
|
||||
case let message as InitializeModuleReaderRequest:
|
||||
try self.handleInitializeModuleReaderRequest(request: message)
|
||||
case let message as InitializeResourceReaderRequest:
|
||||
try self.handleInitializeResourceReaderRequest(request: message)
|
||||
case let message as ReadModuleRequest:
|
||||
try await self.handleReadModuleRequest(request: message)
|
||||
case let message as ReadResourceRequest:
|
||||
try await self.handleReadResourceRequest(request: message)
|
||||
case let message as ListModulesRequest:
|
||||
try await self.handleListModulesRequest(request: message)
|
||||
case let message as ListResourcesRequest:
|
||||
try await self.handleListResourcesRequest(request: message)
|
||||
case _ as CloseExternalProcess:
|
||||
self.close()
|
||||
default:
|
||||
throw PklBugError.unknownMessage("Got request for unknown message: \(message)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func close() {
|
||||
self.transport.close()
|
||||
}
|
||||
|
||||
func handleInitializeModuleReaderRequest(request: InitializeModuleReaderRequest) throws {
|
||||
var response = InitializeModuleReaderResponse(requestId: request.requestId, spec: nil)
|
||||
guard let reader = moduleReaders.first(where: { $0.scheme == request.scheme }) else {
|
||||
try self.transport.send(response)
|
||||
return
|
||||
}
|
||||
response.spec = reader.toMessage()
|
||||
try self.transport.send(response)
|
||||
}
|
||||
|
||||
func handleInitializeResourceReaderRequest(request: InitializeResourceReaderRequest) throws {
|
||||
var response = InitializeResourceReaderResponse(requestId: request.requestId, spec: nil)
|
||||
guard let reader = resourceReaders.first(where: { $0.scheme == request.scheme }) else {
|
||||
try self.transport.send(response)
|
||||
return
|
||||
}
|
||||
response.spec = reader.toMessage()
|
||||
try self.transport.send(response)
|
||||
}
|
||||
|
||||
func handleReadModuleRequest(request: ReadModuleRequest) async throws {
|
||||
var response = ReadModuleResponse(
|
||||
requestId: request.requestId,
|
||||
evaluatorId: request.evaluatorId,
|
||||
contents: nil,
|
||||
error: nil
|
||||
)
|
||||
guard let reader = moduleReaders.first(where: { $0.scheme == request.uri.scheme }) else {
|
||||
response.error = "No module reader found for scheme \(request.uri.scheme!)"
|
||||
try self.transport.send(response)
|
||||
return
|
||||
}
|
||||
do {
|
||||
let result = try await reader.read(url: request.uri)
|
||||
response.contents = result
|
||||
try self.transport.send(response)
|
||||
} catch {
|
||||
response.error = "\(error)"
|
||||
try self.transport.send(response)
|
||||
}
|
||||
}
|
||||
|
||||
func handleReadResourceRequest(request: ReadResourceRequest) async throws {
|
||||
var response = ReadResourceResponse(
|
||||
requestId: request.requestId,
|
||||
evaluatorId: request.evaluatorId,
|
||||
contents: nil,
|
||||
error: nil
|
||||
)
|
||||
guard
|
||||
let reader = resourceReaders.first(where: { $0.scheme == request.uri.scheme }) else {
|
||||
response.error = "No resource reader found for scheme \(request.uri.scheme!)"
|
||||
try self.transport.send(response)
|
||||
return
|
||||
}
|
||||
do {
|
||||
let result = try await reader.read(url: request.uri)
|
||||
response.contents = result
|
||||
try self.transport.send(response)
|
||||
} catch {
|
||||
response.error = "\(error)"
|
||||
try self.transport.send(response)
|
||||
}
|
||||
}
|
||||
|
||||
func handleListModulesRequest(request: ListModulesRequest) async throws {
|
||||
var response = ListModulesResponse(
|
||||
requestId: request.requestId,
|
||||
evaluatorId: request.evaluatorId,
|
||||
pathElements: nil,
|
||||
error: nil
|
||||
)
|
||||
guard let reader = moduleReaders.first(where: { $0.scheme == request.uri.scheme }) else {
|
||||
response.error = "No module reader found for scheme \(request.uri.scheme!)"
|
||||
try self.transport.send(response)
|
||||
return
|
||||
}
|
||||
do {
|
||||
let elems = try await reader.listElements(uri: request.uri)
|
||||
response.pathElements = elems.map { $0.toMessage() }
|
||||
try self.transport.send(response)
|
||||
} catch {
|
||||
response.error = "\(error)"
|
||||
try self.transport.send(response)
|
||||
}
|
||||
}
|
||||
|
||||
func handleListResourcesRequest(request: ListResourcesRequest) async throws {
|
||||
var response = ListResourcesResponse(
|
||||
requestId: request.requestId,
|
||||
evaluatorId: request.evaluatorId,
|
||||
pathElements: nil,
|
||||
error: nil
|
||||
)
|
||||
guard
|
||||
let reader = resourceReaders.first(where: { $0.scheme == request.uri.scheme }) else {
|
||||
response.error = "No resource reader found for scheme \(request.uri.scheme!)"
|
||||
try self.transport.send(response)
|
||||
return
|
||||
}
|
||||
do {
|
||||
let elems = try await reader.listElements(uri: request.uri)
|
||||
response.pathElements = elems.map { $0.toMessage() }
|
||||
try self.transport.send(response)
|
||||
} catch {
|
||||
response.error = "\(error)"
|
||||
try self.transport.send(response)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
import MessagePack
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
import MessagePack
|
||||
|
@ -62,8 +62,8 @@ enum MessageType: Int, Codable {
|
|||
case CREATE_EVALUATOR_REQUEST = 0x20
|
||||
case CREATE_EVALUATOR_RESPONSE = 0x21
|
||||
case CLOSE_EVALUATOR = 0x22
|
||||
case EVALUATOR_REQUEST = 0x23
|
||||
case EVALUATOR_RESPOSNE = 0x24
|
||||
case EVALUATE_REQUEST = 0x23
|
||||
case EVALUATE_RESPONSE = 0x24
|
||||
case LOG_MESSAGE = 0x25
|
||||
case READ_RESOURCE_REQUEST = 0x26
|
||||
case READ_RESOURCE_RESPONSE = 0x27
|
||||
|
@ -73,6 +73,11 @@ enum MessageType: Int, Codable {
|
|||
case LIST_RESOURCES_RESPONSE = 0x2B
|
||||
case LIST_MODULES_REQUEST = 0x2C
|
||||
case LIST_MODULES_RESPONSE = 0x2D
|
||||
case INITIALIZE_MODULE_READER_REQUEST = 0x2E
|
||||
case INITIALIZE_MODULE_READER_RESPONSE = 0x2F
|
||||
case INITIALIZE_RESOURCE_READER_REQUEST = 0x30
|
||||
case INITIALIZE_RESOURCE_READER_RESPONSE = 0x31
|
||||
case CLOSE_EXTERNAL_PROCESS = 0x32
|
||||
}
|
||||
|
||||
extension MessageType {
|
||||
|
@ -85,9 +90,9 @@ extension MessageType {
|
|||
case is CloseEvaluatorRequest:
|
||||
return MessageType.CLOSE_EVALUATOR
|
||||
case is EvaluateRequest:
|
||||
return MessageType.EVALUATOR_REQUEST
|
||||
return MessageType.EVALUATE_REQUEST
|
||||
case is EvaluateResponse:
|
||||
return MessageType.EVALUATOR_RESPOSNE
|
||||
return MessageType.EVALUATE_RESPONSE
|
||||
case is LogMessage:
|
||||
return MessageType.LOG_MESSAGE
|
||||
case is ListResourcesRequest:
|
||||
|
@ -102,6 +107,16 @@ extension MessageType {
|
|||
return MessageType.READ_MODULE_RESPONSE
|
||||
case is ReadResourceResponse:
|
||||
return MessageType.READ_RESOURCE_RESPONSE
|
||||
case is InitializeModuleReaderRequest:
|
||||
return MessageType.INITIALIZE_MODULE_READER_REQUEST
|
||||
case is InitializeModuleReaderResponse:
|
||||
return MessageType.INITIALIZE_MODULE_READER_RESPONSE
|
||||
case is InitializeResourceReaderRequest:
|
||||
return MessageType.INITIALIZE_RESOURCE_READER_REQUEST
|
||||
case is InitializeResourceReaderResponse:
|
||||
return MessageType.INITIALIZE_RESOURCE_READER_RESPONSE
|
||||
case is CloseExternalProcess:
|
||||
return MessageType.CLOSE_EXTERNAL_PROCESS
|
||||
default:
|
||||
preconditionFailure("Unreachable code")
|
||||
}
|
||||
|
@ -122,6 +137,9 @@ struct CreateEvaluatorRequest: ClientRequestMessage {
|
|||
var cacheDir: String?
|
||||
var outputFormat: String?
|
||||
var project: ProjectOrDependency?
|
||||
var http: Http?
|
||||
var externalModuleReaders: [String: ExternalReader]?
|
||||
var externalResourceReaders: [String: ExternalReader]?
|
||||
}
|
||||
|
||||
struct ProjectOrDependency: Codable {
|
||||
|
@ -230,3 +248,25 @@ struct LogMessage: ServerOneWayMessage {
|
|||
// NOTE: not guaranteed to conform to URL. This might have been transformed by a stack frame transformer.
|
||||
let frameUri: String
|
||||
}
|
||||
|
||||
struct InitializeModuleReaderRequest: ServerRequestMessage {
|
||||
var requestId: Int64
|
||||
let scheme: String
|
||||
}
|
||||
|
||||
struct InitializeModuleReaderResponse: ClientResponseMessage {
|
||||
var requestId: Int64
|
||||
var spec: ModuleReaderSpec?
|
||||
}
|
||||
|
||||
struct InitializeResourceReaderRequest: ServerRequestMessage {
|
||||
var requestId: Int64
|
||||
let scheme: String
|
||||
}
|
||||
|
||||
struct InitializeResourceReaderResponse: ClientResponseMessage {
|
||||
var requestId: Int64
|
||||
var spec: ResourceReaderSpec?
|
||||
}
|
||||
|
||||
struct CloseExternalProcess: ServerOneWayMessage {}
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
import MessagePack
|
||||
import SemanticVersion
|
||||
|
||||
protocol MessageTransport {
|
||||
/// Send a message to the Pkl server.
|
||||
|
@ -30,35 +31,104 @@ protocol MessageTransport {
|
|||
|
||||
extension Pipe: Reader {
|
||||
public func read(into: UnsafeMutableRawBufferPointer) throws -> Int {
|
||||
let data = try fileHandleForReading.read(upToCount: into.count)
|
||||
if data == nil {
|
||||
return 0
|
||||
}
|
||||
data!.copyBytes(to: into)
|
||||
return data!.count
|
||||
try fileHandleForReading.read(into: into)
|
||||
}
|
||||
|
||||
public func close() throws {
|
||||
fileHandleForReading.closeFile()
|
||||
try fileHandleForReading.close()
|
||||
}
|
||||
}
|
||||
|
||||
extension FileHandle: Reader {
|
||||
public func read(into: UnsafeMutableRawBufferPointer) throws -> Int {
|
||||
guard let data = try read(upToCount: into.count) else { return 0 }
|
||||
data.copyBytes(to: into)
|
||||
return data.count
|
||||
}
|
||||
|
||||
public func close() throws {
|
||||
closeFile()
|
||||
}
|
||||
}
|
||||
|
||||
extension Pipe: Writer {
|
||||
public func write(_ buffer: UnsafeRawBufferPointer) throws {
|
||||
try fileHandleForWriting.write(contentsOf: buffer)
|
||||
try fileHandleForWriting.write(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
extension FileHandle: Writer {
|
||||
public func write(_ buffer: UnsafeRawBufferPointer) throws {
|
||||
try self.write(contentsOf: buffer)
|
||||
}
|
||||
}
|
||||
|
||||
/// A ``MessageTransport`` base class that implements core message handling logic
|
||||
public class BaseMessageTransport: MessageTransport {
|
||||
var reader: Reader!
|
||||
var writer: Writer!
|
||||
var encoder: MessagePackEncoder!
|
||||
var decoder: MessagePackDecoder!
|
||||
|
||||
var running: Bool { true }
|
||||
|
||||
func send(_ message: ClientMessage) throws {
|
||||
debug("Sending message: \(message)")
|
||||
|
||||
let messageType = MessageType.getMessageType(message)
|
||||
try self.encoder.encodeArrayHeader(2)
|
||||
try self.encoder.encode(messageType)
|
||||
try self.encoder.encode(message)
|
||||
}
|
||||
|
||||
fileprivate func decodeMessage(_ messageType: MessageType) throws -> ServerMessage {
|
||||
switch messageType {
|
||||
case MessageType.READ_MODULE_REQUEST:
|
||||
return try self.decoder.decode(as: ReadModuleRequest.self)
|
||||
case MessageType.READ_RESOURCE_REQUEST:
|
||||
return try self.decoder.decode(as: ReadResourceRequest.self)
|
||||
case MessageType.LIST_MODULES_REQUEST:
|
||||
return try self.decoder.decode(as: ListModulesRequest.self)
|
||||
case MessageType.LIST_RESOURCES_REQUEST:
|
||||
return try self.decoder.decode(as: ListResourcesRequest.self)
|
||||
default:
|
||||
throw PklBugError.unknownMessage("Received unexpected message: \(messageType)")
|
||||
}
|
||||
}
|
||||
|
||||
func close() {}
|
||||
|
||||
func getMessages() throws -> AsyncThrowingStream<ServerMessage, Error> {
|
||||
AsyncThrowingStream { continuation in
|
||||
Task {
|
||||
while self.running {
|
||||
do {
|
||||
let arrayLength = try decoder.decodeArrayLength()
|
||||
assert(arrayLength == 2)
|
||||
let code = try decoder.decode(as: MessageType.self)
|
||||
let message = try decodeMessage(code)
|
||||
debug("Received message: \(message)")
|
||||
continuation.yield(message)
|
||||
} catch {
|
||||
if self.running {
|
||||
continuation.finish(throwing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
continuation.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A ``MessageTransport`` that sends and receives messages by spawning Pkl as a child process.
|
||||
public class ChildProcessMessageTransport: MessageTransport {
|
||||
var reader: Pipe!
|
||||
var writer: Pipe!
|
||||
var encoder: MessagePackEncoder!
|
||||
var decoder: MessagePackDecoder!
|
||||
public class ServerMessageTransport: BaseMessageTransport {
|
||||
var process: Process?
|
||||
let pklCommand: [String]?
|
||||
|
||||
convenience init() {
|
||||
override var running: Bool { self.process?.isRunning == true }
|
||||
|
||||
override convenience init() {
|
||||
self.init(pklCommand: nil)
|
||||
}
|
||||
|
||||
|
@ -66,32 +136,6 @@ public class ChildProcessMessageTransport: MessageTransport {
|
|||
self.pklCommand = pklCommand
|
||||
}
|
||||
|
||||
private func getPklCommand() throws -> [String] {
|
||||
if let exec = ProcessInfo.processInfo.environment["PKL_EXEC"] {
|
||||
return exec.components(separatedBy: " ")
|
||||
}
|
||||
guard let path = ProcessInfo.processInfo.environment["PATH"] else {
|
||||
throw PklError("Unable to find `pkl` command on PATH.")
|
||||
}
|
||||
for dir in path.components(separatedBy: ":") {
|
||||
do {
|
||||
let contents = try FileManager.default.contentsOfDirectory(atPath: dir)
|
||||
if let pkl = contents.first(where: { $0 == "pkl" }) {
|
||||
let file = NSString.path(withComponents: [dir, pkl])
|
||||
if FileManager.default.isExecutableFile(atPath: file) {
|
||||
return [file]
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
if error._domain == NSCocoaErrorDomain {
|
||||
continue
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
throw PklError("Unable to find `pkl` command on PATH.")
|
||||
}
|
||||
|
||||
private func ensureProcessStarted() throws {
|
||||
if self.process?.isRunning == true { return }
|
||||
let pklCommand = try getPklCommand()
|
||||
|
@ -100,8 +144,8 @@ public class ChildProcessMessageTransport: MessageTransport {
|
|||
var arguments = Array(pklCommand.dropFirst())
|
||||
arguments.append("server")
|
||||
self.process!.arguments = arguments
|
||||
self.reader = .init()
|
||||
self.writer = .init()
|
||||
self.reader = Pipe()
|
||||
self.writer = Pipe()
|
||||
self.encoder = .init(writer: self.writer)
|
||||
self.decoder = .init(reader: self.reader)
|
||||
self.process!.standardOutput = self.reader
|
||||
|
@ -110,17 +154,25 @@ public class ChildProcessMessageTransport: MessageTransport {
|
|||
try self.process!.run()
|
||||
}
|
||||
|
||||
func send(_ message: ClientMessage) throws {
|
||||
override func send(_ message: ClientMessage) throws {
|
||||
try self.ensureProcessStarted()
|
||||
debug("Sending message: \(message)")
|
||||
|
||||
let messageType = MessageType.getMessageType(message)
|
||||
try self.encoder.encodeArrayHeader(2)
|
||||
try self.encoder.encode(messageType)
|
||||
try self.encoder.encode(message)
|
||||
try super.send(message)
|
||||
}
|
||||
|
||||
func close() {
|
||||
override fileprivate func decodeMessage(_ messageType: MessageType) throws -> ServerMessage {
|
||||
switch messageType {
|
||||
case MessageType.CREATE_EVALUATOR_RESPONSE:
|
||||
return try self.decoder.decode(as: CreateEvaluatorResponse.self)
|
||||
case MessageType.EVALUATE_RESPONSE:
|
||||
return try self.decoder.decode(as: EvaluateResponse.self)
|
||||
case MessageType.LOG_MESSAGE:
|
||||
return try self.decoder.decode(as: LogMessage.self)
|
||||
default:
|
||||
return try super.decodeMessage(messageType)
|
||||
}
|
||||
}
|
||||
|
||||
override func close() {
|
||||
if self.process == nil {
|
||||
return
|
||||
}
|
||||
|
@ -136,45 +188,38 @@ public class ChildProcessMessageTransport: MessageTransport {
|
|||
self.process = nil
|
||||
}
|
||||
|
||||
private func decodeMessage(_ messageType: MessageType) throws -> ServerMessage {
|
||||
override func getMessages() throws -> AsyncThrowingStream<ServerMessage, Error> {
|
||||
try self.ensureProcessStarted()
|
||||
return try super.getMessages()
|
||||
}
|
||||
}
|
||||
|
||||
public class ExternalReaderMessageTransport: BaseMessageTransport {
|
||||
override var running: Bool { self._running }
|
||||
private var _running = true
|
||||
|
||||
init(reader: Reader, writer: Writer) {
|
||||
super.init()
|
||||
self.reader = reader
|
||||
self.writer = writer
|
||||
self.encoder = .init(writer: self.writer)
|
||||
self.decoder = .init(reader: self.reader)
|
||||
}
|
||||
|
||||
override fileprivate func decodeMessage(_ messageType: MessageType) throws -> ServerMessage {
|
||||
switch messageType {
|
||||
case MessageType.CREATE_EVALUATOR_RESPONSE:
|
||||
return try self.decoder.decode(as: CreateEvaluatorResponse.self)
|
||||
case MessageType.EVALUATOR_RESPOSNE:
|
||||
return try self.decoder.decode(as: EvaluateResponse.self)
|
||||
case MessageType.READ_MODULE_REQUEST:
|
||||
return try self.decoder.decode(as: ReadModuleRequest.self)
|
||||
case MessageType.LOG_MESSAGE:
|
||||
return try self.decoder.decode(as: LogMessage.self)
|
||||
case MessageType.READ_RESOURCE_REQUEST:
|
||||
return try self.decoder.decode(as: ReadResourceRequest.self)
|
||||
case MessageType.LIST_MODULES_REQUEST:
|
||||
return try self.decoder.decode(as: ListModulesRequest.self)
|
||||
case MessageType.LIST_RESOURCES_REQUEST:
|
||||
return try self.decoder.decode(as: ListResourcesRequest.self)
|
||||
case MessageType.INITIALIZE_MODULE_READER_REQUEST:
|
||||
return try self.decoder.decode(as: InitializeModuleReaderRequest.self)
|
||||
case MessageType.INITIALIZE_RESOURCE_READER_REQUEST:
|
||||
return try self.decoder.decode(as: InitializeResourceReaderRequest.self)
|
||||
case MessageType.CLOSE_EXTERNAL_PROCESS:
|
||||
return try self.decoder.decode(as: CloseExternalProcess.self)
|
||||
default:
|
||||
fatalError("Unreachable code")
|
||||
return try super.decodeMessage(messageType)
|
||||
}
|
||||
}
|
||||
|
||||
func getMessages() throws -> AsyncThrowingStream<ServerMessage, Error> {
|
||||
try self.ensureProcessStarted()
|
||||
return AsyncThrowingStream { continuation in
|
||||
Task {
|
||||
while self.process?.isRunning == true {
|
||||
do {
|
||||
let arrayLength = try decoder.decodeArrayLength()
|
||||
assert(arrayLength == 2)
|
||||
let code = try decoder.decode(as: MessageType.self)
|
||||
let message = try decodeMessage(code)
|
||||
debug("Received message: \(message)")
|
||||
continuation.yield(message)
|
||||
} catch {
|
||||
continuation.finish(throwing: error)
|
||||
}
|
||||
}
|
||||
continuation.finish()
|
||||
}
|
||||
}
|
||||
override func close() {
|
||||
self._running = false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
@ -36,7 +36,7 @@ extension ModuleSource {
|
|||
/// - Parameter path: The file path component.
|
||||
public static func path(_ path: String) -> ModuleSource {
|
||||
let path = resolvePaths(path)
|
||||
return ModuleSource(uri: URL(string: "file://\(path)")!, text: nil)
|
||||
return ModuleSource(uri: URL(fileURLWithPath: path), text: nil)
|
||||
}
|
||||
|
||||
/// Creates a synthetic ``ModuleSource`` with the given text.
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// 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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// The Swift representation of standard library module `pkl.EvaluatorSettings`.
|
||||
public struct PklEvaluatorSettings: Decodable, Hashable {
|
||||
let externalProperties: [String: String]?
|
||||
let env: [String: String]?
|
||||
let allowedModules: [String]?
|
||||
let allowedResources: [String]?
|
||||
let noCache: Bool?
|
||||
let modulePath: [String]?
|
||||
let timeout: Duration?
|
||||
let moduleCacheDir: String?
|
||||
let rootDir: String?
|
||||
let http: Http?
|
||||
|
||||
/// Added in Pkl 0.27
|
||||
let externalModuleReaders: [String: ExternalReader]?
|
||||
|
||||
/// Added in Pkl 0.27
|
||||
let externalResourceReaders: [String: ExternalReader]?
|
||||
|
||||
/// Whether to format messages and test results with ANSI color colors.
|
||||
///
|
||||
/// Added in Pkl 0.27
|
||||
let color: PklEvaluatorSettingsColor?
|
||||
}
|
||||
|
||||
public enum PklEvaluatorSettingsColor: String, CaseIterable, Decodable, Hashable {
|
||||
/// Never format.
|
||||
case never
|
||||
|
||||
/// Format if the process' stdin, stdout, or stderr are connected to a console.
|
||||
case auto
|
||||
|
||||
/// Always format.
|
||||
case always
|
||||
}
|
||||
|
||||
/// Settings that control how Pkl talks to HTTP(S) servers.
|
||||
public struct Http: Codable, Hashable {
|
||||
/// PEM format certificates to trust when making HTTP requests.
|
||||
///
|
||||
/// If empty, Pkl will trust its own built-in certificates.
|
||||
var caCertificates: [UInt8]?
|
||||
|
||||
/// Configuration of the HTTP proxy to use.
|
||||
///
|
||||
/// If `nil`, uses the operating system's proxy configuration.
|
||||
/// Configuration of the HTTP proxy to use.
|
||||
var proxy: Proxy?
|
||||
}
|
||||
|
||||
/// Settings that control how Pkl talks to HTTP proxies.
|
||||
public struct Proxy: Codable, Hashable {
|
||||
/// The proxy to use for HTTP(S) connections.
|
||||
///
|
||||
/// Only HTTP proxies are supported.
|
||||
/// The address must start with `"http://"`, and cannot contain anything other than a host and an optional port.
|
||||
///
|
||||
/// Example:
|
||||
/// ```
|
||||
/// "http://my.proxy.example.com:5080"
|
||||
/// ```
|
||||
var address: String?
|
||||
|
||||
/// Hosts to which all connections should bypass a proxy.
|
||||
///
|
||||
///
|
||||
/// Values can be either hostnames, or IP addresses.
|
||||
/// IP addresses can optionally be provided using
|
||||
/// [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation).
|
||||
///
|
||||
/// The value `"*"` is a wildcard that disables proxying for all hosts.
|
||||
///
|
||||
/// A hostname matches all subdomains.
|
||||
/// For example, `example.com` matches `foo.example.com`, but not `fooexample.com`.
|
||||
/// A hostname that is prefixed with a dot matches the hostname itself,
|
||||
/// so `.example.com` matches `example.com`.
|
||||
///
|
||||
/// Hostnames do not match their resolved IP addresses.
|
||||
/// For example, the hostname `localhost` will not match `127.0.0.1`.
|
||||
///
|
||||
/// Optionally, a port can be specified.
|
||||
/// If a port is omitted, all ports are matched.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// [ "127.0.0.1",
|
||||
/// "169.254.0.0/16",
|
||||
/// "example.com",
|
||||
/// "localhost:5050" ]
|
||||
/// ```
|
||||
var noProxy: [String]?
|
||||
}
|
||||
|
||||
public struct ExternalReader: Codable, Hashable {
|
||||
var executable: String
|
||||
var arguments: [String]? = nil
|
||||
}
|
|
@ -1,28 +1,26 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// The Swift representation of `pkl.Project`
|
||||
public struct Project: PklRegisteredType, Hashable, DependencyDeclaredInProjectFile {
|
||||
public static var registeredIdentifier: String = "pkl.Project"
|
||||
public static let registeredIdentifier: String = "pkl.Project"
|
||||
|
||||
let package: Package?
|
||||
|
||||
let evaluatorSettings: Project.EvaluatorSettings
|
||||
let evaluatorSettings: PklEvaluatorSettings
|
||||
|
||||
let projectFileUri: String
|
||||
|
||||
|
@ -52,7 +50,7 @@ extension Project: Decodable {
|
|||
public init(from decoder: Decoder) throws {
|
||||
let dec = try decoder.container(keyedBy: PklCodingKey.self)
|
||||
let package = try dec.decode(Package?.self, forKey: PklCodingKey(stringValue: "package")!)
|
||||
let evaluatorSettings = try dec.decode(EvaluatorSettings.self, forKey: PklCodingKey(stringValue: "evaluatorSettings")!)
|
||||
let evaluatorSettings = try dec.decode(PklEvaluatorSettings.self, forKey: PklCodingKey(stringValue: "evaluatorSettings")!)
|
||||
let projectFileUri = try dec.decode(String.self, forKey: PklCodingKey(stringValue: "projectFileUri")!)
|
||||
let tests = try dec.decode([String].self, forKey: PklCodingKey(stringValue: "tests")!)
|
||||
let dependencies = try dec.decode([String: PklAny].self, forKey: PklCodingKey(stringValue: "dependencies")!)
|
||||
|
@ -70,7 +68,7 @@ extension Project: Decodable {
|
|||
extension Project {
|
||||
/// The Swift representation of `pkl.Project#RemoteDependency`
|
||||
public struct RemoteDependency: PklRegisteredType, DependencyDeclaredInProjectFile, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "pkl.Project#RemoteDependency"
|
||||
public static let registeredIdentifier: String = "pkl.Project#RemoteDependency"
|
||||
|
||||
let uri: String
|
||||
let checksums: Checksums?
|
||||
|
@ -78,7 +76,7 @@ extension Project {
|
|||
|
||||
/// The Swift representation of `pkl.Project#Package`
|
||||
public struct Package: PklRegisteredType, Hashable {
|
||||
public static var registeredIdentifier: String = "pkl.Project#Package"
|
||||
public static let registeredIdentifier: String = "pkl.Project#Package"
|
||||
|
||||
let name: String
|
||||
let baseUri: String
|
||||
|
@ -98,16 +96,11 @@ extension Project {
|
|||
let uri: String
|
||||
}
|
||||
|
||||
/// The Swift representation of `pkl.Project#EvaluatorSettings
|
||||
public struct EvaluatorSettings: Decodable, Hashable {
|
||||
let externalProperties: [String: String]?
|
||||
let env: [String: String]?
|
||||
let allowedModules: [String]?
|
||||
let allowedResources: [String]?
|
||||
let noCache: Bool?
|
||||
let modulePath: [String]?
|
||||
let timeout: Duration?
|
||||
let moduleCacheDir: String?
|
||||
let rootDir: String?
|
||||
}
|
||||
@available(
|
||||
*,
|
||||
deprecated,
|
||||
message: "Replaced by PklEvaluatorSettings, independent of Project",
|
||||
renamed: "PklEvaluatorSettings"
|
||||
)
|
||||
public typealias EvaluatorSettings = PklEvaluatorSettings
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
@ -35,8 +35,8 @@ public protocol BaseReader {
|
|||
/// birds:catalog/swallow.pkl
|
||||
/// ```
|
||||
///
|
||||
/// The first URI conveys name "fred.pkl" within parent "/persons/". The second URI
|
||||
/// conveys the name "persons/fred.pkl" with no hierarchical meaning.
|
||||
/// The first URI conveys name "swallow.pkl" within parent "/catalog/". The second URI
|
||||
/// conveys the name "catalog/swallow.pkl" with no hierarchical meaning.
|
||||
var hasHierarchicalUris: Bool { get }
|
||||
|
||||
/// Returns elements at a specified path.
|
||||
|
@ -107,6 +107,11 @@ public struct PathElement {
|
|||
|
||||
/// Whether the element is a directory or not.
|
||||
public let isDirectory: Bool
|
||||
|
||||
public init(name: String, isDirectory: Bool) {
|
||||
self.name = name
|
||||
self.isDirectory = isDirectory
|
||||
}
|
||||
}
|
||||
|
||||
extension PathElement {
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import MessagePack
|
||||
import PklSwiftInternals
|
||||
|
|
|
@ -1,25 +1,20 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
#if os(Linux)
|
||||
import Glibc
|
||||
#else
|
||||
import Darwin.C
|
||||
#endif
|
||||
|
||||
let pklDebug = ProcessInfo.processInfo.environment["PKL_DEBUG"]
|
||||
|
||||
|
@ -80,7 +75,7 @@ public func mapEquals<K>(map1: [K: any DynamicallyEquatable], map2: [K: any Dyna
|
|||
public func resolvePaths(_ paths: String...) -> String {
|
||||
var result = FileManager.default.currentDirectoryPath
|
||||
for path in paths {
|
||||
if path.starts(with: "/") {
|
||||
if path.starts(with: "/") || URL(fileURLWithPath: path).path == path {
|
||||
result = path
|
||||
} else {
|
||||
result = NSString.path(withComponents: [result, path])
|
||||
|
@ -90,3 +85,12 @@ public func resolvePaths(_ paths: String...) -> String {
|
|||
}
|
||||
|
||||
public let absoluteUriRegex = try! Regex("\\w+:")
|
||||
|
||||
public func tempDir() throws -> URL {
|
||||
try (FileManager.default.url(for: .itemReplacementDirectory, in: .userDomainMask, appropriateFor: URL(fileURLWithPath: "/"), create: true))
|
||||
}
|
||||
|
||||
public func tempFile(suffix: String) throws -> URL {
|
||||
let fileName = ProcessInfo.processInfo.globallyUniqueString + suffix
|
||||
return try (tempDir()).appendingPathComponent(fileName)
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2024 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
|
||||
//
|
||||
/*
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Discovery.h"
|
||||
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2024 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
|
||||
//
|
||||
/*
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(PKLS_DEFINES_H)
|
||||
#define PKLS_DEFINES_H
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2024 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
|
||||
//
|
||||
/*
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(PKLS_DISCOVERY_H)
|
||||
#define PKLS_DISCOVERY_H
|
||||
|
|
|
@ -6,7 +6,7 @@ public enum GeneratorSettings {}
|
|||
extension GeneratorSettings {
|
||||
/// Settings used to configure code generation.
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "pkl.swift.GeneratorSettings"
|
||||
public static let registeredIdentifier: String = "pkl.swift.GeneratorSettings"
|
||||
|
||||
/// The set of modules to turn into Swift code.
|
||||
///
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import ArgumentParser
|
||||
import Foundation
|
||||
|
@ -77,11 +77,6 @@ struct PklGenSwift: AsyncParsableCommand {
|
|||
)
|
||||
var pklInputModules: [String] = []
|
||||
|
||||
func tempFile() -> URL {
|
||||
let fileName = ProcessInfo.processInfo.globallyUniqueString + ".pkl"
|
||||
return URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(fileName)
|
||||
}
|
||||
|
||||
private func generateScriptUrl() -> String {
|
||||
if let generateScript = self.generateScript {
|
||||
return URL(fileURLWithPath: generateScript).path
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
import PklSwift
|
||||
|
@ -41,11 +41,6 @@ public struct PklSwiftGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
private func tempFile() -> URL {
|
||||
let fileName = ProcessInfo.processInfo.globallyUniqueString + ".pkl"
|
||||
return URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(fileName)
|
||||
}
|
||||
|
||||
private mutating func runModule(evaluator: Evaluator, pklInputModule: String) async throws {
|
||||
let out = resolvePaths(self.settings.outputPath ?? ".out")
|
||||
let moduleToEvaluate = """
|
||||
|
@ -55,7 +50,7 @@ public struct PklSwiftGenerator {
|
|||
|
||||
moduleToGenerate = theModule
|
||||
"""
|
||||
let tempFile = tempFile()
|
||||
let tempFile = try tempFile(suffix: ".pkl")
|
||||
try moduleToEvaluate.write(to: tempFile, atomically: true, encoding: .utf8)
|
||||
let files = try await evaluator.evaluateOutputFiles(source: .url(tempFile))
|
||||
for (filename, contents) in files {
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
import PklSwift
|
||||
|
||||
@main
|
||||
struct TestExternalReader {
|
||||
static func main() async throws {
|
||||
let client = ExternalReaderClient(
|
||||
options: ExternalReaderClientOptions(
|
||||
resourceReaders: [FibReader()]
|
||||
))
|
||||
try await client.run()
|
||||
}
|
||||
}
|
||||
|
||||
struct FibReader: ResourceReader {
|
||||
var scheme: String { "fib" }
|
||||
var isGlobbable: Bool { false }
|
||||
var hasHierarchicalUris: Bool { false }
|
||||
func listElements(uri: URL) async throws -> [PathElement] { throw PklError("not implemented") }
|
||||
func read(url: URL) async throws -> [UInt8] {
|
||||
let key = url.absoluteString.dropFirst(self.scheme.count + 1)
|
||||
guard let n = Int(key), n > 0 else {
|
||||
throw PklError("input uri must be in format fib:<positive integer>")
|
||||
}
|
||||
return Array(String(fibonacci(n: n)).utf8)
|
||||
}
|
||||
}
|
||||
|
||||
func fibonacci(n: Int) -> Int {
|
||||
var (a, b) = (0, 1)
|
||||
for _ in 0..<n {
|
||||
(a, b) = (b, a + b)
|
||||
}
|
||||
return a
|
||||
}
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import XCTest
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import XCTest
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import XCTest
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import PklSwift
|
||||
import XCTest
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import XCTest
|
||||
|
||||
|
@ -43,6 +43,11 @@ final class PklDecoderTests: XCTestCase {
|
|||
XCTAssertEqual(value, 42)
|
||||
}
|
||||
|
||||
func testDecodeInt8Overflow() throws {
|
||||
let bytes: [UInt8] = [0xD2, 0xFF, 0x00, 0x00, 0x00]
|
||||
XCTAssertThrowsError(try PklDecoder.decode(Int8.self, from: bytes), "Cannot fit -16777216 into Int8")
|
||||
}
|
||||
|
||||
func testDecodeString() throws {
|
||||
let bytes: [UInt8] = [
|
||||
0xD9, 0x27, 0x74, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6B, 0x20, 0x66, 0x6F, 0x78,
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
import SemanticVersion
|
||||
import XCTest
|
||||
|
||||
@testable import PklSwift
|
||||
|
@ -55,10 +55,10 @@ class EvaluatorManagerTest: XCTestCase {
|
|||
let manager1 = EvaluatorManager()
|
||||
let manager2 = EvaluatorManager()
|
||||
let manager3 = EvaluatorManager()
|
||||
async let evalautor1 = try manager1.newEvaluator(options: .preconfigured).evaluateOutputText(source: .text("res = \"evaluator 1\""))
|
||||
async let evalautor2 = try manager2.newEvaluator(options: .preconfigured).evaluateOutputText(source: .text("res = \"evaluator 2\""))
|
||||
async let evalautor3 = try manager3.newEvaluator(options: .preconfigured).evaluateOutputText(source: .text("res = \"evaluator 3\""))
|
||||
let (result1, result2, result3) = try await (evalautor1, evalautor2, evalautor3)
|
||||
async let evaluator1 = try manager1.newEvaluator(options: .preconfigured).evaluateOutputText(source: .text("res = \"evaluator 1\""))
|
||||
async let evaluator2 = try manager2.newEvaluator(options: .preconfigured).evaluateOutputText(source: .text("res = \"evaluator 2\""))
|
||||
async let evaluator3 = try manager3.newEvaluator(options: .preconfigured).evaluateOutputText(source: .text("res = \"evaluator 3\""))
|
||||
let (result1, result2, result3) = try await (evaluator1, evaluator2, evaluator3)
|
||||
XCTAssertEqual(result1, "res = \"evaluator 1\"\n")
|
||||
XCTAssertEqual(result2, "res = \"evaluator 2\"\n")
|
||||
XCTAssertEqual(result3, "res = \"evaluator 3\"\n")
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
@testable import MessagePack
|
||||
@testable import PklSwift
|
||||
import SemanticVersion
|
||||
import XCTest
|
||||
|
||||
class TestLogger: Logger {
|
||||
|
@ -91,6 +91,33 @@ final class PklSwiftTests: XCTestCase {
|
|||
XCTAssertEqual(output, "foo = 1\n")
|
||||
}
|
||||
|
||||
func testVersionCoverage() async throws {
|
||||
let output = try await SemanticVersion(EvaluatorManager().getVersion())!
|
||||
XCTAssert(supportedPklVersions.contains { $0.major == output.major && $0.minor == output.minor })
|
||||
}
|
||||
|
||||
func testCustomProxyOptions() async throws {
|
||||
let version = try await SemanticVersion(EvaluatorManager().getVersion())!
|
||||
let expected = version < pklVersion0_26
|
||||
? "http options are not supported on Pkl versions lower than 0.26"
|
||||
: "ConnectException: Error connecting to host `example.com`"
|
||||
var options = EvaluatorOptions.preconfigured
|
||||
options.http = .init(
|
||||
caCertificates: nil,
|
||||
proxy: .init(
|
||||
address: "http://localhost:1",
|
||||
noProxy: ["myhost.com:1337", "myotherhost.org:42"]
|
||||
)
|
||||
)
|
||||
do {
|
||||
let evaluator = try await manager.newEvaluator(options: options)
|
||||
let _ = try await evaluator.evaluateOutputText(source: .uri("https://example.com")!)
|
||||
XCTFail("Should have thrown an error")
|
||||
} catch {
|
||||
XCTAssert("\(error)".contains(expected))
|
||||
}
|
||||
}
|
||||
|
||||
func testCustomModuleReader() async throws {
|
||||
let reader = VirtualModuleReader(
|
||||
read: { _ in
|
||||
|
@ -278,10 +305,10 @@ final class PklSwiftTests: XCTestCase {
|
|||
XCTAssertEqual(logger.logLines, [#"pkl: TRACE: "Hello there" = "Hello there" (repl:text)\#n"#])
|
||||
}
|
||||
|
||||
// TODO re-enable this test when packages are available
|
||||
// TODO: re-enable this test when packages are available
|
||||
//
|
||||
// func testWithProject() async throws {
|
||||
// let project1Dir = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("project1")
|
||||
// let project1Dir = (try tempDir()).appendingPathComponent("project1")
|
||||
// try FileManager.default.createDirectory(at: project1Dir, withIntermediateDirectories: true)
|
||||
// try """
|
||||
// amends "pkl:Project"
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import SemanticVersion
|
||||
import XCTest
|
||||
|
||||
@testable import PklSwift
|
||||
|
||||
class ExternalReaderClientTest: XCTestCase {
|
||||
func testE2E() async throws {
|
||||
let version = try await SemanticVersion(EvaluatorManager().getVersion())!
|
||||
guard version >= pklVersion0_27 else {
|
||||
throw XCTSkip("External readers require Pkl 0.27 or later.")
|
||||
}
|
||||
|
||||
let tempDir = try tempDir()
|
||||
let testFile = tempDir.appendingPathComponent("test.pkl")
|
||||
try #"""
|
||||
import "pkl:test"
|
||||
|
||||
fib5 = read("fib:5").text.toInt()
|
||||
fib10 = read("fib:10").text.toInt()
|
||||
fib20 = read("fib:20").text.toInt()
|
||||
|
||||
fibErrA = test.catch(() -> read("fib:%20"))
|
||||
fibErrB = test.catch(() -> read("fib:abc"))
|
||||
fibErrC = test.catch(() -> read("fib:-10"))
|
||||
"""#.write(to: testFile, atomically: true, encoding: .utf8)
|
||||
|
||||
let expectedResult = """
|
||||
fib5 = 5
|
||||
fib10 = 55
|
||||
fib20 = 6765
|
||||
fibErrA = "I/O error reading resource `fib:%20`. IOException: PklError(message: \\"input uri must be in format fib:<positive integer>\\")"
|
||||
fibErrB = "I/O error reading resource `fib:abc`. IOException: PklError(message: \\"input uri must be in format fib:<positive integer>\\")"
|
||||
fibErrC = "I/O error reading resource `fib:-10`. IOException: PklError(message: \\"input uri must be in format fib:<positive integer>\\")"
|
||||
"""
|
||||
|
||||
let opts = EvaluatorOptions(
|
||||
allowedModules: ["file:", "repl:text"],
|
||||
allowedResources: ["fib:", "prop:"],
|
||||
externalResourceReaders: [
|
||||
"fib": ExternalReader(executable: "./.build/debug/test-external-reader"),
|
||||
]
|
||||
)
|
||||
|
||||
try await withEvaluator(options: opts) { evaluator in
|
||||
let result = try await evaluator.evaluateOutputText(source: .url(testFile))
|
||||
XCTAssertEqual(result.trimmingCharacters(in: .whitespacesAndNewlines), expectedResult.trimmingCharacters(in: .whitespacesAndNewlines))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,2 @@
|
|||
res1: Pair<Int, String> = Pair(42, "Hello")
|
||||
res2: Duration = 10.h
|
||||
res3: DataSize = 1.2345.gib
|
||||
res1: Duration = 10.h
|
||||
res2: DataSize = 1.2345.gib
|
|
@ -5,7 +5,7 @@ public enum AnyType {}
|
|||
|
||||
extension AnyType {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "AnyType"
|
||||
public static let registeredIdentifier: String = "AnyType"
|
||||
|
||||
public var bird: AnyHashable?
|
||||
|
||||
|
@ -63,7 +63,7 @@ extension AnyType {
|
|||
}
|
||||
|
||||
public struct Bird: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "AnyType#Bird"
|
||||
public static let registeredIdentifier: String = "AnyType#Bird"
|
||||
|
||||
public var species: String
|
||||
|
||||
|
|
|
@ -5,18 +5,15 @@ public enum ApiTypes {}
|
|||
|
||||
extension ApiTypes {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "ApiTypes"
|
||||
public static let registeredIdentifier: String = "ApiTypes"
|
||||
|
||||
public var res1: Pair<Int, String>
|
||||
public var res1: Duration
|
||||
|
||||
public var res2: Duration
|
||||
public var res2: DataSize
|
||||
|
||||
public var res3: DataSize
|
||||
|
||||
public init(res1: Pair<Int, String>, res2: Duration, res3: DataSize) {
|
||||
public init(res1: Duration, res2: DataSize) {
|
||||
self.res1 = res1
|
||||
self.res2 = res2
|
||||
self.res3 = res3
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ public enum Classes {}
|
|||
|
||||
extension Classes {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "Classes"
|
||||
public static let registeredIdentifier: String = "Classes"
|
||||
|
||||
public var animals: [Animal]
|
||||
|
||||
|
@ -15,7 +15,7 @@ extension Classes {
|
|||
}
|
||||
|
||||
public struct Animal: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "Classes#Animal"
|
||||
public static let registeredIdentifier: String = "Classes#Animal"
|
||||
|
||||
public var name: String
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ public enum Collections {}
|
|||
|
||||
extension Collections {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "Collections"
|
||||
public static let registeredIdentifier: String = "Collections"
|
||||
|
||||
public var res1: [Int]
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ public enum ExtendedModule {}
|
|||
|
||||
extension ExtendedModule {
|
||||
public struct Module: OpenModule.Module {
|
||||
public static var registeredIdentifier: String = "ExtendedModule"
|
||||
public static let registeredIdentifier: String = "ExtendedModule"
|
||||
|
||||
public var foo: String
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ extension OpenModule {
|
|||
public typealias Module = OpenModule_Module
|
||||
|
||||
public struct ModuleImpl: Module {
|
||||
public static var registeredIdentifier: String = "OpenModule"
|
||||
public static let registeredIdentifier: String = "OpenModule"
|
||||
|
||||
public var foo: String
|
||||
|
||||
|
|
|
@ -7,6 +7,9 @@ public protocol UnionTypes_Animal: PklRegisteredType, DynamicallyEquatable, Hash
|
|||
var name: String { get }
|
||||
}
|
||||
|
||||
public protocol UnionTypes_Shape: PklRegisteredType, DynamicallyEquatable, Hashable {
|
||||
}
|
||||
|
||||
extension UnionTypes {
|
||||
public enum Fruit: Decodable, Hashable {
|
||||
case banana(Banana)
|
||||
|
@ -14,8 +17,9 @@ extension UnionTypes {
|
|||
case apple(Apple)
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
|
||||
switch decoded {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let value = try container.decode(PklSwift.PklAny.self).value
|
||||
switch value?.base {
|
||||
case let decoded as Banana:
|
||||
self = Fruit.banana(decoded)
|
||||
case let decoded as Grape:
|
||||
|
@ -27,14 +31,14 @@ extension UnionTypes {
|
|||
Fruit.self,
|
||||
.init(
|
||||
codingPath: decoder.codingPath,
|
||||
debugDescription: "Expected type Fruit, but got \(String(describing: decoded))"
|
||||
debugDescription: "Expected type Fruit, but got \(String(describing: value))"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum City: String, CaseIterable, Decodable, Hashable {
|
||||
public enum City: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {
|
||||
case sanFrancisco = "San Francisco"
|
||||
case tokyo = "Tokyo"
|
||||
case zurich = "Zurich"
|
||||
|
@ -46,8 +50,9 @@ extension UnionTypes {
|
|||
case donkey(Donkey)
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
|
||||
switch decoded {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let value = try container.decode(PklSwift.PklAny.self).value
|
||||
switch value?.base {
|
||||
case let decoded as Zebra:
|
||||
self = ZebraOrDonkey.zebra(decoded)
|
||||
case let decoded as Donkey:
|
||||
|
@ -57,7 +62,7 @@ extension UnionTypes {
|
|||
ZebraOrDonkey.self,
|
||||
.init(
|
||||
codingPath: decoder.codingPath,
|
||||
debugDescription: "Expected type ZebraOrDonkey, but got \(String(describing: decoded))"
|
||||
debugDescription: "Expected type ZebraOrDonkey, but got \(String(describing: value))"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -80,8 +85,9 @@ extension UnionTypes {
|
|||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
|
||||
switch decoded {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let value = try container.decode(PklSwift.PklAny.self).value
|
||||
switch value?.base {
|
||||
case let decoded as any Animal:
|
||||
self = AnimalOrString.animal(decoded)
|
||||
case let decoded as String:
|
||||
|
@ -91,7 +97,7 @@ extension UnionTypes {
|
|||
AnimalOrString.self,
|
||||
.init(
|
||||
codingPath: decoder.codingPath,
|
||||
debugDescription: "Expected type AnimalOrString, but got \(String(describing: decoded))"
|
||||
debugDescription: "Expected type AnimalOrString, but got \(String(describing: value))"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -107,8 +113,116 @@ extension UnionTypes {
|
|||
}
|
||||
}
|
||||
|
||||
public enum IntOrFloat: Decodable, Hashable {
|
||||
case int(Int)
|
||||
case float64(Float64)
|
||||
|
||||
private static func decodeNumeric(from decoder: Decoder, _ container: any SingleValueDecodingContainer) -> IntOrFloat? {
|
||||
return (try? .int(container.decode(Int.self)))
|
||||
?? (try? .float64(container.decode(Float64.self)))
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let decoded = IntOrFloat.decodeNumeric(from: decoder, container)
|
||||
if decoded != nil {
|
||||
self = decoded!
|
||||
return
|
||||
}
|
||||
let value = try container.decode(PklSwift.PklAny.self).value
|
||||
throw DecodingError.typeMismatch(
|
||||
IntOrFloat.self,
|
||||
.init(
|
||||
codingPath: decoder.codingPath,
|
||||
debugDescription: "Expected type IntOrFloat, but got \(String(describing: value))"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public enum Environment: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {
|
||||
case dev = "dev"
|
||||
case prod = "prod"
|
||||
case qa = "qa"
|
||||
}
|
||||
|
||||
public enum AnimalOrShape: Decodable, Hashable {
|
||||
case animal(any Animal)
|
||||
case shape(any Shape)
|
||||
|
||||
public static func ==(lhs: AnimalOrShape, rhs: AnimalOrShape) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case let (.animal(a), .animal(b)):
|
||||
return a.isDynamicallyEqual(to: b)
|
||||
case let (.shape(a), .shape(b)):
|
||||
return a.isDynamicallyEqual(to: b)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let value = try container.decode(PklSwift.PklAny.self).value
|
||||
switch value?.base {
|
||||
case let decoded as any Animal:
|
||||
self = AnimalOrShape.animal(decoded)
|
||||
case let decoded as any Shape:
|
||||
self = AnimalOrShape.shape(decoded)
|
||||
default:
|
||||
throw DecodingError.typeMismatch(
|
||||
AnimalOrShape.self,
|
||||
.init(
|
||||
codingPath: decoder.codingPath,
|
||||
debugDescription: "Expected type AnimalOrShape, but got \(String(describing: value))"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
switch self {
|
||||
case let .animal(value):
|
||||
hasher.combine(value)
|
||||
case let .shape(value):
|
||||
hasher.combine(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum Numbers: Decodable, Hashable {
|
||||
case int8(Int8)
|
||||
case int16(Int16)
|
||||
case int32(Int32)
|
||||
case int(Int)
|
||||
|
||||
private static func decodeNumeric(from decoder: Decoder, _ container: any SingleValueDecodingContainer) -> Numbers? {
|
||||
return (try? .int8(container.decode(Int8.self)))
|
||||
?? (try? .int16(container.decode(Int16.self)))
|
||||
?? (try? .int32(container.decode(Int32.self)))
|
||||
?? (try? .int(container.decode(Int.self)))
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let decoded = Numbers.decodeNumeric(from: decoder, container)
|
||||
if decoded != nil {
|
||||
self = decoded!
|
||||
return
|
||||
}
|
||||
let value = try container.decode(PklSwift.PklAny.self).value
|
||||
throw DecodingError.typeMismatch(
|
||||
Numbers.self,
|
||||
.init(
|
||||
codingPath: decoder.codingPath,
|
||||
debugDescription: "Expected type Numbers, but got \(String(describing: value))"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "UnionTypes"
|
||||
public static let registeredIdentifier: String = "UnionTypes"
|
||||
|
||||
public var fruit1: Fruit
|
||||
|
||||
|
@ -132,6 +246,26 @@ extension UnionTypes {
|
|||
|
||||
public var animalOrString2: AnimalOrString
|
||||
|
||||
public var intOrFloat1: IntOrFloat
|
||||
|
||||
public var intOrFloat2: IntOrFloat
|
||||
|
||||
public var intOrFloat3: IntOrFloat
|
||||
|
||||
public var config: [Environment: String]
|
||||
|
||||
public var animalOrShape1: AnimalOrShape
|
||||
|
||||
public var animalOrShape2: AnimalOrShape
|
||||
|
||||
public var numbers1: Numbers
|
||||
|
||||
public var numbers2: Numbers
|
||||
|
||||
public var numbers3: Numbers
|
||||
|
||||
public var numbers4: Numbers
|
||||
|
||||
public init(
|
||||
fruit1: Fruit,
|
||||
fruit2: Fruit,
|
||||
|
@ -143,7 +277,17 @@ extension UnionTypes {
|
|||
animal1: ZebraOrDonkey,
|
||||
animal2: ZebraOrDonkey,
|
||||
animalOrString1: AnimalOrString,
|
||||
animalOrString2: AnimalOrString
|
||||
animalOrString2: AnimalOrString,
|
||||
intOrFloat1: IntOrFloat,
|
||||
intOrFloat2: IntOrFloat,
|
||||
intOrFloat3: IntOrFloat,
|
||||
config: [Environment: String],
|
||||
animalOrShape1: AnimalOrShape,
|
||||
animalOrShape2: AnimalOrShape,
|
||||
numbers1: Numbers,
|
||||
numbers2: Numbers,
|
||||
numbers3: Numbers,
|
||||
numbers4: Numbers
|
||||
) {
|
||||
self.fruit1 = fruit1
|
||||
self.fruit2 = fruit2
|
||||
|
@ -156,11 +300,21 @@ extension UnionTypes {
|
|||
self.animal2 = animal2
|
||||
self.animalOrString1 = animalOrString1
|
||||
self.animalOrString2 = animalOrString2
|
||||
self.intOrFloat1 = intOrFloat1
|
||||
self.intOrFloat2 = intOrFloat2
|
||||
self.intOrFloat3 = intOrFloat3
|
||||
self.config = config
|
||||
self.animalOrShape1 = animalOrShape1
|
||||
self.animalOrShape2 = animalOrShape2
|
||||
self.numbers1 = numbers1
|
||||
self.numbers2 = numbers2
|
||||
self.numbers3 = numbers3
|
||||
self.numbers4 = numbers4
|
||||
}
|
||||
}
|
||||
|
||||
public struct Banana: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "UnionTypes#Banana"
|
||||
public static let registeredIdentifier: String = "UnionTypes#Banana"
|
||||
|
||||
public var isRipe: Bool
|
||||
|
||||
|
@ -170,7 +324,7 @@ extension UnionTypes {
|
|||
}
|
||||
|
||||
public struct Grape: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "UnionTypes#Grape"
|
||||
public static let registeredIdentifier: String = "UnionTypes#Grape"
|
||||
|
||||
public var isUsedForWine: Bool
|
||||
|
||||
|
@ -180,7 +334,7 @@ extension UnionTypes {
|
|||
}
|
||||
|
||||
public struct Apple: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "UnionTypes#Apple"
|
||||
public static let registeredIdentifier: String = "UnionTypes#Apple"
|
||||
|
||||
public var isRed: Bool
|
||||
|
||||
|
@ -191,8 +345,20 @@ extension UnionTypes {
|
|||
|
||||
public typealias Animal = UnionTypes_Animal
|
||||
|
||||
public typealias Shape = UnionTypes_Shape
|
||||
|
||||
public struct Square: Shape {
|
||||
public static let registeredIdentifier: String = "UnionTypes#Square"
|
||||
|
||||
public var corners: Int
|
||||
|
||||
public init(corners: Int) {
|
||||
self.corners = corners
|
||||
}
|
||||
}
|
||||
|
||||
public struct Zebra: Animal {
|
||||
public static var registeredIdentifier: String = "UnionTypes#Zebra"
|
||||
public static let registeredIdentifier: String = "UnionTypes#Zebra"
|
||||
|
||||
public var name: String
|
||||
|
||||
|
@ -202,7 +368,7 @@ extension UnionTypes {
|
|||
}
|
||||
|
||||
public struct Donkey: Animal {
|
||||
public static var registeredIdentifier: String = "UnionTypes#Donkey"
|
||||
public static let registeredIdentifier: String = "UnionTypes#Donkey"
|
||||
|
||||
public var name: String
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ public protocol pkl_swift_example_Poly_Animal: pkl_swift_lib1_Being {
|
|||
|
||||
extension pkl_swift_example_Poly {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "pkl.swift.example.Poly"
|
||||
public static let registeredIdentifier: String = "pkl.swift.example.Poly"
|
||||
|
||||
public var beings: [any pkl_swift_lib1.Being]
|
||||
|
||||
|
@ -56,7 +56,7 @@ extension pkl_swift_example_Poly {
|
|||
}
|
||||
|
||||
public struct Dog: Animal {
|
||||
public static var registeredIdentifier: String = "pkl.swift.example.Poly#Dog"
|
||||
public static let registeredIdentifier: String = "pkl.swift.example.Poly#Dog"
|
||||
|
||||
public var barks: Bool
|
||||
|
||||
|
@ -103,7 +103,7 @@ extension pkl_swift_example_Poly {
|
|||
public typealias Animal = pkl_swift_example_Poly_Animal
|
||||
|
||||
public struct AnimalImpl: Animal {
|
||||
public static var registeredIdentifier: String = "pkl.swift.example.Poly#Animal"
|
||||
public static let registeredIdentifier: String = "pkl.swift.example.Poly#Animal"
|
||||
|
||||
public var name: String
|
||||
|
||||
|
@ -116,7 +116,7 @@ extension pkl_swift_example_Poly {
|
|||
}
|
||||
|
||||
public struct Bird: pkl_swift_lib1.Being {
|
||||
public static var registeredIdentifier: String = "pkl.swift.example.Poly#Bird"
|
||||
public static let registeredIdentifier: String = "pkl.swift.example.Poly#Bird"
|
||||
|
||||
public var name: String
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ public protocol pkl_swift_lib1_Being: PklRegisteredType, DynamicallyEquatable, H
|
|||
|
||||
extension pkl_swift_lib1 {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "pkl.swift.lib1"
|
||||
public static let registeredIdentifier: String = "pkl.swift.lib1"
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import "pkl:math"
|
||||
|
||||
class Banana {
|
||||
isRipe: Boolean
|
||||
}
|
||||
|
@ -18,6 +20,12 @@ typealias Fruit = Banana | Grape | Apple
|
|||
|
||||
typealias City = "San Francisco"|"Tokyo"|"Zurich"|"London"
|
||||
|
||||
abstract class Shape
|
||||
|
||||
class Square extends Shape {
|
||||
fixed corners: Int = 4
|
||||
}
|
||||
|
||||
fruit1: Fruit = new Banana {
|
||||
isRipe = true
|
||||
}
|
||||
|
@ -52,4 +60,34 @@ typealias AnimalOrString = Animal|String
|
|||
|
||||
animalOrString1: AnimalOrString = new Zebra {}
|
||||
|
||||
animalOrString2: AnimalOrString = "Zebra"
|
||||
animalOrString2: AnimalOrString = "Zebra"
|
||||
|
||||
typealias IntOrFloat = Int | Float
|
||||
|
||||
intOrFloat1: IntOrFloat = 5.0
|
||||
|
||||
intOrFloat2: IntOrFloat = 5.5
|
||||
|
||||
intOrFloat3: IntOrFloat = 128
|
||||
|
||||
typealias Environment = "dev"|"prod"|"qa"
|
||||
|
||||
config: Mapping<Environment, String> = new {
|
||||
["dev"] = "Imaginary Service Company (ISC) configuration"
|
||||
}
|
||||
|
||||
typealias AnimalOrShape = Animal|Shape
|
||||
|
||||
animalOrShape1: AnimalOrShape = new Donkey {}
|
||||
|
||||
animalOrShape2: AnimalOrShape = new Square {}
|
||||
|
||||
typealias Numbers = Int8 | Int16 | Int32 | Int
|
||||
|
||||
numbers1: Numbers = 5
|
||||
|
||||
numbers2: Numbers = 128
|
||||
|
||||
numbers3: Numbers = 32768
|
||||
|
||||
numbers4: Numbers = math.maxInt
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import PklSwift
|
||||
import XCTest
|
||||
|
@ -77,9 +77,8 @@ class FixturesTest: XCTestCase {
|
|||
XCTAssertEqual(
|
||||
result,
|
||||
ApiTypes.Module(
|
||||
res1: Pair(42, "Hello"),
|
||||
res2: .hours(10),
|
||||
res3: .gibibytes(1.2345)
|
||||
res1: .hours(10),
|
||||
res2: .gibibytes(1.2345)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -161,7 +160,17 @@ class FixturesTest: XCTestCase {
|
|||
animal1: .zebra(UnionTypes.Zebra(name: "Zebra")),
|
||||
animal2: .donkey(UnionTypes.Donkey(name: "Donkey")),
|
||||
animalOrString1: .animal(UnionTypes.Zebra(name: "Zebra")),
|
||||
animalOrString2: .string("Zebra")
|
||||
animalOrString2: .string("Zebra"),
|
||||
intOrFloat1: .float64(5.0),
|
||||
intOrFloat2: .float64(5.5),
|
||||
intOrFloat3: .int(128),
|
||||
config: [.dev : "Imaginary Service Company (ISC) configuration"],
|
||||
animalOrShape1: .animal(UnionTypes.Donkey(name: "Donkey")),
|
||||
animalOrShape2: .shape(UnionTypes.Square(corners: 4)),
|
||||
numbers1: .int8(5),
|
||||
numbers2: .int16(128),
|
||||
numbers3: .int32(32768),
|
||||
numbers4: .int(Int.max)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +1,34 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
import SemanticVersion
|
||||
import XCTest
|
||||
|
||||
@testable import PklSwift
|
||||
|
||||
class ProjectTest: XCTestCase {
|
||||
func testLoadProject() async throws {
|
||||
let tempDir = NSTemporaryDirectory()
|
||||
try FileManager.default.createDirectory(atPath: tempDir + "/subdir", withIntermediateDirectories: true)
|
||||
let otherProjectFile = URL(fileURLWithPath: tempDir, isDirectory: true)
|
||||
.appendingPathComponent("subdir/PklProject")
|
||||
let version = try await SemanticVersion(EvaluatorManager().getVersion())!
|
||||
let tempDir = try tempDir()
|
||||
let subDir = tempDir.appendingPathComponent("subdir")
|
||||
try FileManager.default.createDirectory(at: subDir, withIntermediateDirectories: true)
|
||||
let otherProjectFile = subDir.appendingPathComponent("PklProject")
|
||||
|
||||
try #"""
|
||||
@ModuleInfo { minPklVersion = "0.25.0" }
|
||||
amends "pkl:Project"
|
||||
|
||||
package {
|
||||
|
@ -37,8 +39,53 @@ class ProjectTest: XCTestCase {
|
|||
}
|
||||
"""#.write(to: otherProjectFile, atomically: true, encoding: .utf8)
|
||||
|
||||
let file = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
|
||||
.appendingPathComponent("PklProject")
|
||||
let file = try (PklSwift.tempDir()).appendingPathComponent("PklProject")
|
||||
|
||||
let httpSetting = version < pklVersion0_26 ? "" : """
|
||||
http {
|
||||
proxy {
|
||||
address = "http://localhost:1"
|
||||
noProxy {
|
||||
"example.com"
|
||||
"foo.bar.org"
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
let externalReaderSettings = version < pklVersion0_27 ? "" : """
|
||||
externalModuleReaders {
|
||||
["scheme1"] {
|
||||
executable = "reader1"
|
||||
}
|
||||
["scheme2"] {
|
||||
executable = "reader2"
|
||||
arguments { "with"; "args" }
|
||||
}
|
||||
}
|
||||
externalResourceReaders {
|
||||
["scheme3"] {
|
||||
executable = "reader3"
|
||||
}
|
||||
["scheme4"] {
|
||||
executable = "reader4"
|
||||
arguments { "with"; "args" }
|
||||
}
|
||||
}
|
||||
"""
|
||||
let colorSetting = version < pklVersion0_27 ? "" : #"color = "always""#
|
||||
let httpExpectation = version < pklVersion0_26 ? nil : Http(
|
||||
caCertificates: nil,
|
||||
proxy: .init(address: "http://localhost:1", noProxy: ["example.com", "foo.bar.org"])
|
||||
)
|
||||
let externalModuleReadersExpectation = version < pklVersion0_27 ? nil : [
|
||||
"scheme1": ExternalReader(executable: "reader1"),
|
||||
"scheme2": ExternalReader(executable: "reader2", arguments: ["with", "args"]),
|
||||
]
|
||||
let externalResourceReadersExpectation = version < pklVersion0_27 ? nil : [
|
||||
"scheme3": ExternalReader(executable: "reader3"),
|
||||
"scheme4": ExternalReader(executable: "reader4", arguments: ["with", "args"]),
|
||||
]
|
||||
let color: PklEvaluatorSettingsColor? = version < pklVersion0_27 ? nil : .always
|
||||
try #"""
|
||||
amends "pkl:Project"
|
||||
|
||||
|
@ -83,6 +130,9 @@ class ProjectTest: XCTestCase {
|
|||
timeout = 5.min
|
||||
moduleCacheDir = "/bar/buzz"
|
||||
rootDir = "/buzzy"
|
||||
\#(externalReaderSettings)
|
||||
\#(httpSetting)
|
||||
\#(colorSetting)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@ -97,7 +147,7 @@ class ProjectTest: XCTestCase {
|
|||
source: .url(file),
|
||||
asType: Project.self
|
||||
)
|
||||
let expectedSettings = PklSwift.Project.EvaluatorSettings(
|
||||
let expectedSettings = PklSwift.PklEvaluatorSettings(
|
||||
externalProperties: ["myprop": "1"],
|
||||
env: ["myenv": "2"],
|
||||
allowedModules: ["foo:"],
|
||||
|
@ -106,7 +156,11 @@ class ProjectTest: XCTestCase {
|
|||
modulePath: ["/bar/baz"],
|
||||
timeout: .minutes(5),
|
||||
moduleCacheDir: "/bar/buzz",
|
||||
rootDir: "/buzzy"
|
||||
rootDir: "/buzzy",
|
||||
http: httpExpectation,
|
||||
externalModuleReaders: externalModuleReadersExpectation,
|
||||
externalResourceReaders: externalResourceReadersExpectation,
|
||||
color: color
|
||||
)
|
||||
let expectedPackage = PklSwift.Project.Package(
|
||||
name: "hawk",
|
||||
|
@ -160,7 +214,11 @@ class ProjectTest: XCTestCase {
|
|||
modulePath: nil,
|
||||
timeout: nil,
|
||||
moduleCacheDir: nil,
|
||||
rootDir: nil
|
||||
rootDir: nil,
|
||||
http: nil,
|
||||
externalModuleReaders: nil,
|
||||
externalResourceReaders: nil,
|
||||
color: nil
|
||||
),
|
||||
projectFileUri: "\(otherProjectFile)",
|
||||
tests: [],
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.2.3
|
||||
0.4.2
|
|
@ -9,7 +9,7 @@ public protocol Classes_Animal: PklRegisteredType, DynamicallyEquatable, Hashabl
|
|||
|
||||
extension Classes {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "Classes"
|
||||
public static let registeredIdentifier: String = "Classes"
|
||||
|
||||
public var animals: [any Animal]
|
||||
|
||||
|
@ -38,7 +38,7 @@ extension Classes {
|
|||
public typealias Animal = Classes_Animal
|
||||
|
||||
public struct AnimalImpl: Animal {
|
||||
public static var registeredIdentifier: String = "Classes#Animal"
|
||||
public static let registeredIdentifier: String = "Classes#Animal"
|
||||
|
||||
public var name: String
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ extension EmptyOpenModule {
|
|||
public typealias Module = EmptyOpenModule_Module
|
||||
|
||||
public struct ModuleImpl: Module {
|
||||
public static var registeredIdentifier: String = "EmptyOpenModule"
|
||||
public static let registeredIdentifier: String = "EmptyOpenModule"
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ public enum Enums {}
|
|||
|
||||
extension Enums {
|
||||
/// City is one of these four fantastic cities
|
||||
public enum City: String, CaseIterable, Decodable, Hashable {
|
||||
public enum City: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {
|
||||
case sanFrancisco = "San Francisco"
|
||||
case london = "London"
|
||||
case zurich = "Zurich"
|
||||
|
@ -19,8 +19,9 @@ extension Enums {
|
|||
case monkey(Monkey)
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
|
||||
switch decoded {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let value = try container.decode(PklSwift.PklAny.self).value
|
||||
switch value?.base {
|
||||
case let decoded as Horse:
|
||||
self = Animal.horse(decoded)
|
||||
case let decoded as Zebra:
|
||||
|
@ -32,7 +33,7 @@ extension Enums {
|
|||
Animal.self,
|
||||
.init(
|
||||
codingPath: decoder.codingPath,
|
||||
debugDescription: "Expected type Animal, but got \(String(describing: decoded))"
|
||||
debugDescription: "Expected type Animal, but got \(String(describing: value))"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -45,8 +46,9 @@ extension Enums {
|
|||
case arrayString([String])
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
|
||||
switch decoded {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let value = try container.decode(PklSwift.PklAny.self).value
|
||||
switch value?.base {
|
||||
case let decoded as [String: String]:
|
||||
self = DictOrArray.dictionaryStringString(decoded)
|
||||
case let decoded as [String]:
|
||||
|
@ -56,7 +58,7 @@ extension Enums {
|
|||
DictOrArray.self,
|
||||
.init(
|
||||
codingPath: decoder.codingPath,
|
||||
debugDescription: "Expected type DictOrArray, but got \(String(describing: decoded))"
|
||||
debugDescription: "Expected type DictOrArray, but got \(String(describing: value))"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -69,8 +71,9 @@ extension Enums {
|
|||
case string(String)
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
|
||||
switch decoded {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let value = try container.decode(PklSwift.PklAny.self).value
|
||||
switch value?.base {
|
||||
case let decoded as Horse:
|
||||
self = HorseOrBug.horse(decoded)
|
||||
case let decoded as String:
|
||||
|
@ -82,7 +85,7 @@ extension Enums {
|
|||
HorseOrBug.self,
|
||||
.init(
|
||||
codingPath: decoder.codingPath,
|
||||
debugDescription: "Expected type HorseOrBug, but got \(String(describing: decoded))"
|
||||
debugDescription: "Expected type HorseOrBug, but got \(String(describing: value))"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -94,8 +97,9 @@ extension Enums {
|
|||
case zebra(Zebra)
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value
|
||||
switch decoded {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let value = try container.decode(PklSwift.PklAny.self).value
|
||||
switch value?.base {
|
||||
case let decoded as Horse?:
|
||||
self = MaybeHorseOrDefinitelyZebra.horse(decoded)
|
||||
case let decoded as Zebra:
|
||||
|
@ -105,7 +109,7 @@ extension Enums {
|
|||
MaybeHorseOrDefinitelyZebra.self,
|
||||
.init(
|
||||
codingPath: decoder.codingPath,
|
||||
debugDescription: "Expected type MaybeHorseOrDefinitelyZebra, but got \(String(describing: decoded))"
|
||||
debugDescription: "Expected type MaybeHorseOrDefinitelyZebra, but got \(String(describing: value))"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -113,7 +117,7 @@ extension Enums {
|
|||
}
|
||||
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "Enums"
|
||||
public static let registeredIdentifier: String = "Enums"
|
||||
|
||||
/// City of tomorrow!
|
||||
public var city: City
|
||||
|
@ -145,7 +149,7 @@ extension Enums {
|
|||
}
|
||||
|
||||
public struct Horse: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "Enums#Horse"
|
||||
public static let registeredIdentifier: String = "Enums#Horse"
|
||||
|
||||
public var neigh: Bool
|
||||
|
||||
|
@ -155,7 +159,7 @@ extension Enums {
|
|||
}
|
||||
|
||||
public struct Zebra: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "Enums#Zebra"
|
||||
public static let registeredIdentifier: String = "Enums#Zebra"
|
||||
|
||||
public var stripes: String
|
||||
|
||||
|
@ -165,7 +169,7 @@ extension Enums {
|
|||
}
|
||||
|
||||
public struct Monkey: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "Enums#Monkey"
|
||||
public static let registeredIdentifier: String = "Enums#Monkey"
|
||||
|
||||
public var tail: String
|
||||
|
||||
|
|
|
@ -4,13 +4,13 @@ import PklSwift
|
|||
public enum ExplicitlyCoolName {}
|
||||
|
||||
extension ExplicitlyCoolName {
|
||||
public enum ConfigType: String, CaseIterable, Decodable, Hashable {
|
||||
public enum ConfigType: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {
|
||||
case one = "one"
|
||||
case two = "two"
|
||||
}
|
||||
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "ExplicitName"
|
||||
public static let registeredIdentifier: String = "ExplicitName"
|
||||
|
||||
public var MyCoolProp: SomethingVeryFunny
|
||||
|
||||
|
@ -24,7 +24,7 @@ extension ExplicitlyCoolName {
|
|||
}
|
||||
|
||||
public struct SomethingVeryFunny: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "ExplicitName#SomethingFunny"
|
||||
public static let registeredIdentifier: String = "ExplicitName#SomethingFunny"
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ public enum ExtendModule {}
|
|||
|
||||
extension ExtendModule {
|
||||
public struct Module: MyModule.Module {
|
||||
public static var registeredIdentifier: String = "ExtendModule"
|
||||
public static let registeredIdentifier: String = "ExtendModule"
|
||||
|
||||
public var bar: String
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ public protocol ExtendingOpenClass_MyOpenClass: PklRegisteredType, DynamicallyEq
|
|||
|
||||
extension ExtendingOpenClass {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "ExtendingOpenClass"
|
||||
public static let registeredIdentifier: String = "ExtendingOpenClass"
|
||||
|
||||
public var res1: MyClass
|
||||
|
||||
|
@ -22,7 +22,7 @@ extension ExtendingOpenClass {
|
|||
}
|
||||
|
||||
public struct MyClass: MyOpenClass {
|
||||
public static var registeredIdentifier: String = "ExtendingOpenClass#MyClass"
|
||||
public static let registeredIdentifier: String = "ExtendingOpenClass#MyClass"
|
||||
|
||||
public var myBoolean: Bool
|
||||
|
||||
|
@ -37,7 +37,7 @@ extension ExtendingOpenClass {
|
|||
public typealias MyOpenClass = ExtendingOpenClass_MyOpenClass
|
||||
|
||||
public struct MyOpenClassImpl: MyOpenClass {
|
||||
public static var registeredIdentifier: String = "ExtendingOpenClass#MyOpenClass"
|
||||
public static let registeredIdentifier: String = "ExtendingOpenClass#MyOpenClass"
|
||||
|
||||
public var myStr: String
|
||||
|
||||
|
@ -47,7 +47,7 @@ extension ExtendingOpenClass {
|
|||
}
|
||||
|
||||
public struct MyClass2: lib3.GoGoGo {
|
||||
public static var registeredIdentifier: String = "ExtendingOpenClass#MyClass2"
|
||||
public static let registeredIdentifier: String = "ExtendingOpenClass#MyClass2"
|
||||
|
||||
public var myBoolean: Bool
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ public protocol ExtendsAbstractClass_A: PklRegisteredType, DynamicallyEquatable,
|
|||
|
||||
extension ExtendsAbstractClass {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "ExtendsAbstractClass"
|
||||
public static let registeredIdentifier: String = "ExtendsAbstractClass"
|
||||
|
||||
public var a: any A
|
||||
|
||||
|
@ -36,7 +36,7 @@ extension ExtendsAbstractClass {
|
|||
public typealias A = ExtendsAbstractClass_A
|
||||
|
||||
public struct B: A {
|
||||
public static var registeredIdentifier: String = "ExtendsAbstractClass#B"
|
||||
public static let registeredIdentifier: String = "ExtendsAbstractClass#B"
|
||||
|
||||
public var c: String
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ public protocol Foo_Being: PklRegisteredType, DynamicallyEquatable, Hashable {
|
|||
|
||||
extension Foo {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "Foo"
|
||||
public static let registeredIdentifier: String = "Foo"
|
||||
|
||||
public var animals: [any Animal]
|
||||
|
||||
|
@ -42,7 +42,7 @@ extension Foo {
|
|||
public typealias Animal = Foo_Animal
|
||||
|
||||
public struct AnimalImpl: Animal {
|
||||
public static var registeredIdentifier: String = "Foo#Animal"
|
||||
public static let registeredIdentifier: String = "Foo#Animal"
|
||||
|
||||
public var name: String
|
||||
|
||||
|
@ -57,7 +57,7 @@ extension Foo {
|
|||
public typealias Being = Foo_Being
|
||||
|
||||
public struct Bird: Animal {
|
||||
public static var registeredIdentifier: String = "Foo#Bird"
|
||||
public static let registeredIdentifier: String = "Foo#Bird"
|
||||
|
||||
public var flies: Bool
|
||||
|
||||
|
@ -73,7 +73,7 @@ extension Foo {
|
|||
}
|
||||
|
||||
public struct Dog: Animal {
|
||||
public static var registeredIdentifier: String = "Foo#Dog"
|
||||
public static let registeredIdentifier: String = "Foo#Dog"
|
||||
|
||||
public var barks: Bool
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ public enum HiddenProperties {}
|
|||
|
||||
extension HiddenProperties {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "HiddenProperties"
|
||||
public static let registeredIdentifier: String = "HiddenProperties"
|
||||
|
||||
public var propC: String
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ public enum Imports {}
|
|||
|
||||
extension Imports {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "Imports"
|
||||
public static let registeredIdentifier: String = "Imports"
|
||||
|
||||
public var foo: Foo.Module
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ extension MyModule {
|
|||
public typealias Module = MyModule_Module
|
||||
|
||||
public struct ModuleImpl: Module {
|
||||
public static var registeredIdentifier: String = "MyModule"
|
||||
public static let registeredIdentifier: String = "MyModule"
|
||||
|
||||
public var foo: String
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ extension Override2 {
|
|||
public typealias Module = Override2_Module
|
||||
|
||||
public struct ModuleImpl: Module {
|
||||
public static var registeredIdentifier: String = "Override2"
|
||||
public static let registeredIdentifier: String = "Override2"
|
||||
|
||||
/// Doc comments
|
||||
public var foo: String
|
||||
|
@ -22,7 +22,7 @@ extension Override2 {
|
|||
}
|
||||
|
||||
public struct MySubclass: Module {
|
||||
public static var registeredIdentifier: String = "Override2#MySubclass"
|
||||
public static let registeredIdentifier: String = "Override2#MySubclass"
|
||||
|
||||
/// Doc comments
|
||||
public var foo: String
|
||||
|
|
|
@ -5,7 +5,7 @@ public enum TypeAliased {}
|
|||
|
||||
extension TypeAliased {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "TypeAliased"
|
||||
public static let registeredIdentifier: String = "TypeAliased"
|
||||
|
||||
public var myMap: StringyMap
|
||||
|
||||
|
|
|
@ -4,14 +4,14 @@ import PklSwift
|
|||
public enum UnionNameKeyword {}
|
||||
|
||||
extension UnionNameKeyword {
|
||||
public enum `Type`: String, CaseIterable, Decodable, Hashable {
|
||||
public enum `Type`: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {
|
||||
case one = "one"
|
||||
case two = "two"
|
||||
case three = "three"
|
||||
}
|
||||
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "UnionNameKeyword"
|
||||
public static let registeredIdentifier: String = "UnionNameKeyword"
|
||||
|
||||
public var type: `Type`
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@ public enum com_example_ExtendedSimple {}
|
|||
|
||||
extension com_example_ExtendedSimple {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "com.example.ExtendedSimple"
|
||||
public static let registeredIdentifier: String = "com.example.ExtendedSimple"
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct ExtendedSimple: com_example_Simple.Person {
|
||||
public static var registeredIdentifier: String = "com.example.ExtendedSimple#ExtendedSimple"
|
||||
public static let registeredIdentifier: String = "com.example.ExtendedSimple#ExtendedSimple"
|
||||
|
||||
public var eyeColor: String
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ public protocol com_example_Simple_OpenClassExtendingOpenClass: PklRegisteredTyp
|
|||
|
||||
extension com_example_Simple {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "com.example.Simple"
|
||||
public static let registeredIdentifier: String = "com.example.Simple"
|
||||
|
||||
/// This is truly a person.
|
||||
public var person: any Person
|
||||
|
@ -43,7 +43,7 @@ extension com_example_Simple {
|
|||
public typealias Person = com_example_Simple_Person
|
||||
|
||||
public struct PersonImpl: Person {
|
||||
public static var registeredIdentifier: String = "com.example.Simple#Person"
|
||||
public static let registeredIdentifier: String = "com.example.Simple#Person"
|
||||
|
||||
/// The name of the person
|
||||
public var theName: String
|
||||
|
@ -63,7 +63,7 @@ extension com_example_Simple {
|
|||
}
|
||||
|
||||
public struct ThePerson: Person {
|
||||
public static var registeredIdentifier: String = "com.example.Simple#ThePerson"
|
||||
public static let registeredIdentifier: String = "com.example.Simple#ThePerson"
|
||||
|
||||
public var the: String
|
||||
|
||||
|
@ -89,7 +89,7 @@ extension com_example_Simple {
|
|||
public typealias OpenClassExtendingOpenClass = com_example_Simple_OpenClassExtendingOpenClass
|
||||
|
||||
public struct OpenClassExtendingOpenClassImpl: OpenClassExtendingOpenClass {
|
||||
public static var registeredIdentifier: String = "com.example.Simple#OpenClassExtendingOpenClass"
|
||||
public static let registeredIdentifier: String = "com.example.Simple#OpenClassExtendingOpenClass"
|
||||
|
||||
public var someOtherProp: Bool?
|
||||
|
||||
|
@ -99,7 +99,7 @@ extension com_example_Simple {
|
|||
}
|
||||
|
||||
public struct ClassWithReallyLongConstructor: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "com.example.Simple#ClassWithReallyLongConstructor"
|
||||
public static let registeredIdentifier: String = "com.example.Simple#ClassWithReallyLongConstructor"
|
||||
|
||||
public var theProperty1: String
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ extension lib3 {
|
|||
public typealias GoGoGo = lib3_GoGoGo
|
||||
|
||||
public struct GoGoGoImpl: GoGoGo {
|
||||
public static var registeredIdentifier: String = "lib3#GoGoGo"
|
||||
public static let registeredIdentifier: String = "lib3#GoGoGo"
|
||||
|
||||
public var duck: String
|
||||
|
||||
|
@ -21,7 +21,7 @@ extension lib3 {
|
|||
}
|
||||
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "lib3"
|
||||
public static let registeredIdentifier: String = "lib3"
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ public protocol override_Foo: PklRegisteredType, DynamicallyEquatable, Hashable
|
|||
|
||||
extension override {
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "override"
|
||||
public static let registeredIdentifier: String = "override"
|
||||
|
||||
public var foo: any Foo
|
||||
|
||||
|
@ -36,7 +36,7 @@ extension override {
|
|||
public typealias Foo = override_Foo
|
||||
|
||||
public struct Bar: Foo {
|
||||
public static var registeredIdentifier: String = "override#Bar"
|
||||
public static let registeredIdentifier: String = "override#Bar"
|
||||
|
||||
public var myProp: String
|
||||
|
||||
|
|
|
@ -5,28 +5,28 @@ public enum union {}
|
|||
|
||||
extension union {
|
||||
/// City; e.g. where people live
|
||||
public enum City: String, CaseIterable, Decodable, Hashable {
|
||||
public enum City: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {
|
||||
case sanFrancisco = "San Francisco"
|
||||
case london = "London"
|
||||
case 上海 = "上海"
|
||||
}
|
||||
|
||||
/// Locale that contains cities and towns
|
||||
public enum County: String, CaseIterable, Decodable, Hashable {
|
||||
public enum County: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {
|
||||
case sanFrancisco = "San Francisco"
|
||||
case sanMateo = "San Mateo"
|
||||
case yolo = "Yolo"
|
||||
}
|
||||
|
||||
/// Noodles
|
||||
public enum Noodles: String, CaseIterable, Decodable, Hashable {
|
||||
public enum Noodles: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {
|
||||
case 拉面 = "拉面"
|
||||
case 刀切面 = "刀切面"
|
||||
case 面线 = "面线"
|
||||
case 意大利面 = "意大利面"
|
||||
}
|
||||
|
||||
public enum AccountDisposition: String, CaseIterable, Decodable, Hashable {
|
||||
public enum AccountDisposition: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {
|
||||
case empty = ""
|
||||
case icloud3 = "icloud3"
|
||||
case prod = "prod"
|
||||
|
@ -34,7 +34,7 @@ extension union {
|
|||
}
|
||||
|
||||
public struct Module: PklRegisteredType, Decodable, Hashable {
|
||||
public static var registeredIdentifier: String = "union"
|
||||
public static let registeredIdentifier: String = "union"
|
||||
|
||||
/// A city
|
||||
public var city: City
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
// ===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
// 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.
|
||||
// ===----------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Generates Swift sources from Pkl
|
||||
@swift.Module { name = "pkl_gen_swift" }
|
||||
@ModuleInfo { minPklVersion = "0.24.0" }
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// 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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Settings used to configure code generation.
|
||||
@swift.Module { name = "pkl_gen_swift" }
|
||||
@swift.Name { value = "GeneratorSettings" }
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// 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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
amends "pkl:Project"
|
||||
|
||||
package {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"resolvedDependencies": {}
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue