Compare commits

...

16 Commits
0.3.0 ... main

Author SHA1 Message Date
Daniel Chao d6f08700d6
Prepare 0.4.2 release (#48) 2025-04-14 10:09:19 -07:00
Daniel Chao cf45d102cb
Fix Swift mapping of ints within unions (#47)
This fixes an issue where a union with an int member cannot decode
any value that is out of the Int8 bounds.

Also: make SingleValueDecodingContainer throw `typeMismatch` errors
when the expected type doesn't match.
2025-02-26 09:12:56 -08:00
Daniel Chao c514843f01
Add pkl-lsp to ignored dirs (#46) 2025-02-26 07:13:12 -08:00
Daniel Chao 9c36448681
Make enums of string literals conform to CodingKeyRepresentable (#45)
Fixes an issue where mappings of enums fail to be decoded into Swift
2025-02-25 07:10:50 -08:00
Daniel Chao 799b6696d2
Swiftformat check (#43)
* Add makefile and CI rules to run the swift formatter
* Run swift format on all files
2025-02-24 19:09:46 -08:00
Kushal Pisavadia b7e694ea3c
Configure `hawkeye` to update license headers (#38)
Adds configuration to format/check license headers with hawkeye.

Also, runs the formatter on the repo.
2025-02-17 12:45:41 -08:00
Daniel Chao dda82f32a7
Add DocC auto generation (#41)
This will add pkl-swift docs to the Swift Package Index.

See: https://swiftpackageindex.com/blog/auto-generating-auto-hosting-and-auto-updating-docc-documentation

This also adds `swift-docc-plugin` as a dependency, which enables
running command `swift package generate-documentation --target PklSwift`.
2025-02-12 06:28:28 -08:00
Daniel Chao 3c5da314c9
Prepare 0.4.1 release (#40) 2025-02-04 09:53:29 -08:00
Daniel Chao b253e83f7b
Fix enum decoding (#39)
Fixes an issue where `5.0` in Pkl can possibly be cast to `Int`
2025-02-03 10:50:36 -08:00
Kushal Pisavadia f0bd189f48
Make sure CircleCI config is up-to-date (#37) 2025-02-03 13:43:40 +01:00
Daniel Chao c280a0e632
Add PR links (#34) 2025-01-24 08:10:27 -08:00
Daniel Chao 162bf61a96
Prepare 0.4.0 release (#33) 2025-01-23 08:42:40 -08:00
Daniel Chao 52d5fbc5e1
Add color to PklEvaluatorSettings (#32)
This adds a field that was added in Pkl 0.27
2025-01-23 06:59:31 -08:00
Josh B 64c66aea8e
Implement SPICE-0009 External Readers (#26)
* Add `EvaluatorOptions.externalModuleReaders` and `EvaluatorOptions.externalResourceReaders`.
* Add `ExternalReaderClient` to host the child process side of the external reader workflow.
2025-01-17 06:34:34 -08:00
Javier Cuesta 7d451c59cd
Make PathElement initializer explicitly public (#31)
Also, fix doc comments
2024-12-13 14:18:23 -08:00
Josh B 1d0bf43b4b
Fix temporary directory creation to avoid failing pkl-core tests (#28) 2024-12-04 16:54:32 +00:00
101 changed files with 1733 additions and 498 deletions

View File

@ -1,5 +1,5 @@
// ===----------------------------------------------------------------------===// // ===----------------------------------------------------------------------===//
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. // Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // 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" import "pkl:semver"
@ -47,7 +47,7 @@ local class PklDistribution {
} }
local pklCurrent: PklDistribution = new { local pklCurrent: PklDistribution = new {
version = "0.26.0" version = "0.27.2"
} }
local pklDistributions: Listing<PklDistribution> = new { local pklDistributions: Listing<PklDistribution> = new {
@ -133,6 +133,7 @@ jobs {
"checkout" "checkout"
distribution.downloadRunStep distribution.downloadRunStep
swiftTest swiftTest
new RunStep { command = "make circleci-config" }
new RunStep { command = "make test-snippets" } new RunStep { command = "make test-snippets" }
new RunStep { command = "make test-pkl" } new RunStep { command = "make test-pkl" }
new RunStep { command = "make generate-fixtures" } new RunStep { command = "make generate-fixtures" }
@ -143,6 +144,34 @@ jobs {
} }
} }
["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"
}
}
steps {
"checkout"
new RunStep {
command = "make swiftformat-lint"
}
}
}
["pkl-gen-swift-macos"] { ["pkl-gen-swift-macos"] {
macos { macos {
xcode = "15.2.0" xcode = "15.2.0"

View File

@ -18,6 +18,8 @@ jobs:
mkdir -p .out/test-results/ mkdir -p .out/test-results/
swift test -vv --parallel --num-workers 1 --xunit-output .out/test-results/xunit.xml -Xswiftc -warnings-as-errors swift test -vv --parallel --num-workers 1 --xunit-output .out/test-results/xunit.xml -Xswiftc -warnings-as-errors
name: swift test name: swift test
- run:
command: make circleci-config
- run: - run:
command: make test-snippets command: make test-snippets
- run: - run:
@ -29,21 +31,23 @@ jobs:
resource_class: xlarge resource_class: xlarge
docker: docker:
- image: swift:5.9-rhel-ubi9 - image: swift:5.9-rhel-ubi9
test-pkl-0-26-0: test-pkl-0-27-2:
steps: steps:
- checkout - checkout
- run: - run:
command: |- command: |-
PKL=$(mktemp /tmp/pkl-0.26.0-XXXXXX) PKL=$(mktemp /tmp/pkl-0.27.2-XXXXXX)
curl -L "https://github.com/apple/pkl/releases/download/0.26.0/pkl-linux-amd64" > $PKL curl -L "https://github.com/apple/pkl/releases/download/0.27.2/pkl-linux-amd64" > $PKL
chmod +x $PKL chmod +x $PKL
echo "export PKL_EXEC=$PKL" >> $BASH_ENV echo "export PKL_EXEC=$PKL" >> $BASH_ENV
name: Downloading pkl-0.26.0 name: Downloading pkl-0.27.2
- run: - run:
command: |- command: |-
mkdir -p .out/test-results/ mkdir -p .out/test-results/
swift test -vv --parallel --num-workers 1 --xunit-output .out/test-results/xunit.xml -Xswiftc -warnings-as-errors swift test -vv --parallel --num-workers 1 --xunit-output .out/test-results/xunit.xml -Xswiftc -warnings-as-errors
name: swift test name: swift test
- run:
command: make circleci-config
- run: - run:
command: make test-snippets command: make test-snippets
- run: - run:
@ -55,6 +59,20 @@ jobs:
resource_class: xlarge resource_class: xlarge
docker: docker:
- image: swift:5.9-rhel-ubi9 - 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: pkl-gen-swift-macos:
steps: steps:
- checkout - checkout
@ -108,11 +126,11 @@ jobs:
- checkout - checkout
- run: - run:
command: |- command: |-
PKL=$(mktemp /tmp/pkl-0.26.0-XXXXXX) PKL=$(mktemp /tmp/pkl-0.27.2-XXXXXX)
curl -L "https://github.com/apple/pkl/releases/download/0.26.0/pkl-linux-amd64" > $PKL curl -L "https://github.com/apple/pkl/releases/download/0.27.2/pkl-linux-amd64" > $PKL
chmod +x $PKL chmod +x $PKL
echo "export PKL_EXEC=$PKL" >> $BASH_ENV echo "export PKL_EXEC=$PKL" >> $BASH_ENV
name: Downloading pkl-0.26.0 name: Downloading pkl-0.27.2
- run: - run:
command: $PKL_EXEC project package --skip-publish-check --output-path out/pkl-package/ codegen/src/ command: $PKL_EXEC project package --skip-publish-check --output-path out/pkl-package/ codegen/src/
- persist_to_workspace: - persist_to_workspace:
@ -193,11 +211,15 @@ workflows:
- test-pkl-0-25-3: - test-pkl-0-25-3:
requires: requires:
- hold - hold
- pr-approval/authenticate - test-pkl-0-27-2:
- test-pkl-0-26-0: requires:
- hold
- test-license-headers:
requires:
- hold
- test-format:
requires: requires:
- hold - hold
- pr-approval/authenticate
when: when:
matches: matches:
value: << pipeline.git.branch >> value: << pipeline.git.branch >>
@ -205,7 +227,9 @@ workflows:
main: main:
jobs: jobs:
- test-pkl-0-25-3 - test-pkl-0-25-3
- test-pkl-0-26-0 - test-pkl-0-27-2
- test-license-headers
- test-format
when: when:
equal: equal:
- main - main
@ -218,7 +242,19 @@ workflows:
ignore: /.*/ ignore: /.*/
tags: tags:
only: /^v?\d+\.\d+\.\d+$/ only: /^v?\d+\.\d+\.\d+$/
- test-pkl-0-26-0: - 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: filters:
branches: branches:
ignore: /.*/ ignore: /.*/
@ -227,7 +263,9 @@ workflows:
- pkl-package: - pkl-package:
requires: requires:
- test-pkl-0-25-3 - test-pkl-0-25-3
- test-pkl-0-26-0 - test-pkl-0-27-2
- test-license-headers
- test-format
filters: filters:
branches: branches:
ignore: /.*/ ignore: /.*/
@ -236,7 +274,9 @@ workflows:
- pkl-gen-swift-macos: - pkl-gen-swift-macos:
requires: requires:
- test-pkl-0-25-3 - test-pkl-0-25-3
- test-pkl-0-26-0 - test-pkl-0-27-2
- test-license-headers
- test-format
filters: filters:
branches: branches:
ignore: /.*/ ignore: /.*/
@ -245,7 +285,9 @@ workflows:
- pkl-gen-swift-linux-amd64: - pkl-gen-swift-linux-amd64:
requires: requires:
- test-pkl-0-25-3 - test-pkl-0-25-3
- test-pkl-0-26-0 - test-pkl-0-27-2
- test-license-headers
- test-format
filters: filters:
branches: branches:
ignore: /.*/ ignore: /.*/
@ -254,7 +296,9 @@ workflows:
- pkl-gen-swift-linux-aarch64: - pkl-gen-swift-linux-aarch64:
requires: requires:
- test-pkl-0-25-3 - test-pkl-0-25-3
- test-pkl-0-26-0 - test-pkl-0-27-2
- test-license-headers
- test-format
filters: filters:
branches: branches:
ignore: /.*/ ignore: /.*/

4
.gitignore vendored
View File

@ -1,5 +1,6 @@
.DS_Store .DS_Store
.build .build
.index-build
/Packages /Packages
/*.xcodeproj /*.xcodeproj
xcuserdata/ xcuserdata/
@ -16,4 +17,5 @@ DerivedData/
.out/ .out/
out/ out/
.cicd/ .cicd/
.pkl-lsp/

4
.spi.yml Normal file
View File

@ -0,0 +1,4 @@
version: 1
builder:
configs:
- documentation_targets: ['PklSwift']

View File

@ -15,9 +15,8 @@
--guardelse same-line --guardelse same-line
--nevertrailing filter --nevertrailing filter
--extensionacl on-declarations --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 # rules
--disable spaceAroundOperators --disable spaceAroundOperators
--disable wrapMultilineStatementBraces --disable wrapMultilineStatementBraces

31
DEVELOPMENT.adoc Normal file
View File

@ -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
----

View File

@ -108,3 +108,19 @@ pkl-gen-swift-release: $(PKL_GEN_SWIFT_RELEASE)
.PHONY: pkl-gen-swift-release-output .PHONY: pkl-gen-swift-release-output
pkl-gen-swift-release-output: pkl-gen-swift-release-output:
@echo "$(PKL_GEN_SWIFT_RELEASE)" | xargs @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

View File

@ -18,6 +18,24 @@
"version" : "1.2.3" "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", "identity" : "swift-system",
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
@ -26,6 +44,15 @@
"revision" : "025bcb1165deab2e20d4eaba79967ce73013f496", "revision" : "025bcb1165deab2e20d4eaba79967ce73013f496",
"version" : "1.2.1" "version" : "1.2.1"
} }
},
{
"identity" : "swiftformat",
"kind" : "remoteSourceControl",
"location" : "https://github.com/nicklockwood/SwiftFormat",
"state" : {
"revision" : "468a7d32dedc8d352c191594b3b45d9fd8ba291b",
"version" : "0.55.5"
}
} }
], ],
"version" : 2 "version" : 2

View File

@ -1,4 +1,20 @@
// swift-tools-version: 5.9 // 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 import PackageDescription
let package = Package( let package = Package(
@ -25,6 +41,10 @@ let package = Package(
.package(url: "https://github.com/apple/swift-system", from: "1.2.1"), .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/apple/swift-argument-parser", from: "1.2.3"),
.package(url: "https://github.com/SwiftPackageIndex/SemanticVersion", from: "0.4.0"), .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: [ targets: [
.target( .target(
@ -48,6 +68,10 @@ let package = Package(
], ],
resources: [.embedInCode("Resources/VERSION.txt")] resources: [.embedInCode("Resources/VERSION.txt")]
), ),
.executableTarget(
name: "test-external-reader",
dependencies: ["PklSwift"]
),
.testTarget( .testTarget(
name: "PklSwiftTests", name: "PklSwiftTests",
dependencies: [ dependencies: [

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
struct AnyCodingKey: CodingKey, Equatable { struct AnyCodingKey: CodingKey, Equatable {
let stringValue: String let stringValue: String

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation
@ -44,10 +44,13 @@ public final class MessagePackEncoder {
try Box<Data>(data).encode(to: encoder) try Box<Data>(data).encode(to: encoder)
case let date as Date: case let date as Date:
try Box<Date>(date).encode(to: encoder) try Box<Date>(date).encode(to: encoder)
case let bytes as [UInt8]:
try Box<[UInt8]>(bytes).encode(to: encoder)
case let url as URL: case let url as URL:
try Box<URL>(url).encode(to: encoder) 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: default:
try value.encode(to: encoder) try value.encode(to: encoder)
} }

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation
@ -304,8 +304,6 @@ extension _MessagePackEncoder.SingleValueContainer: SingleValueEncodingContainer
try self.encode(data) try self.encode(data)
case let date as Date: case let date as Date:
try self.encode(date) try self.encode(date)
case let bytes as [UInt8]:
try self.encode(bytes)
case let url as URL: case let url as URL:
try self.encode(url) try self.encode(url)
case let bool as Bool: case let bool as Bool:
@ -334,9 +332,16 @@ extension _MessagePackEncoder.SingleValueContainer: SingleValueEncodingContainer
try self.encode(uint64) try self.encode(uint64)
case let num as any BinaryInteger & Encodable: case let num as any BinaryInteger & Encodable:
try self.encode(num) try self.encode(num)
case let bytes as [UInt8]:
guard type(of: value) == [UInt8].self else {
fallthrough
}
try self.encode(bytes)
default: default:
let writer: Writer = BufferWriter() let writer: Writer = BufferWriter()
let encoder = _MessagePackEncoder() let encoder = _MessagePackEncoder()
encoder.userInfo = userInfo
encoder.codingPath = codingPath
try value.encode(to: encoder) try value.encode(to: encoder)
try encoder.write(into: writer) try encoder.write(into: writer)
let data = (writer as! BufferWriter).bytes let data = (writer as! BufferWriter).bytes

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
extension FixedWidthInteger { extension FixedWidthInteger {
init(bytes: [UInt8]) { init(bytes: [UInt8]) {

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
public protocol Writer { public protocol Writer {
/// Write the given bytes into an output somewhere. /// Write the given bytes into an output somewhere.

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation
import MessagePack import MessagePack

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation
import MessagePack import MessagePack

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import MessagePack import MessagePack

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import MessagePack import MessagePack
@ -37,11 +37,13 @@ class PklSingleValueDecodingContainer: SingleValueDecodingContainer {
switch self.value { switch self.value {
case .bool(let value): return value case .bool(let value): return value
default: default:
throw DecodingError.dataCorrupted( throw DecodingError.typeMismatch(
Bool.self,
.init( .init(
codingPath: self.codingPath, codingPath: self.codingPath,
debugDescription: "Expected a boolean, but got \(self.value.debugDataTypeDescription)" debugDescription: "Expected a boolean, but got \(self.value.debugDataTypeDescription)"
)) )
)
} }
} }
@ -49,11 +51,13 @@ class PklSingleValueDecodingContainer: SingleValueDecodingContainer {
switch self.value { switch self.value {
case .string(let value): return value case .string(let value): return value
default: default:
throw DecodingError.dataCorrupted( throw DecodingError.typeMismatch(
String.self,
.init( .init(
codingPath: self.codingPath, codingPath: self.codingPath,
debugDescription: "Expected a string, but got \(self.value.debugDataTypeDescription)" debugDescription: "Expected a string, but got \(self.value.debugDataTypeDescription)"
)) )
)
} }
} }
@ -61,11 +65,13 @@ class PklSingleValueDecodingContainer: SingleValueDecodingContainer {
switch self.value { switch self.value {
case .float(let value): return Double(value) case .float(let value): return Double(value)
default: default:
throw DecodingError.dataCorrupted( throw DecodingError.typeMismatch(
Double.self,
.init( .init(
codingPath: self.codingPath, codingPath: self.codingPath,
debugDescription: "Expected a float, but got \(self.value.debugDataTypeDescription)" debugDescription: "Expected a float, but got \(self.value.debugDataTypeDescription)"
)) )
)
} }
} }
@ -73,11 +79,13 @@ class PklSingleValueDecodingContainer: SingleValueDecodingContainer {
switch self.value { switch self.value {
case .float(let value): return Float(value) case .float(let value): return Float(value)
default: default:
throw DecodingError.dataCorrupted( throw DecodingError.typeMismatch(
Float.self,
.init( .init(
codingPath: self.codingPath, codingPath: self.codingPath,
debugDescription: "Expected a float, but got \(self.value.debugDataTypeDescription)" 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 { func decode<T>(_ type: T.Type) throws -> T where T: Decodable {
if type == PklAny.self { if type == PklAny.self {
guard let result = try _PklDecoder.decodePolymorphic(value, codingPath: codingPath) else { 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 return result as! T
} }
@ -135,13 +143,25 @@ class PklSingleValueDecodingContainer: SingleValueDecodingContainer {
private func decodeBinaryInteger<T>() throws -> T where T: BinaryInteger { private func decodeBinaryInteger<T>() throws -> T where T: BinaryInteger {
switch self.value { 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: default:
throw DecodingError.dataCorrupted( throw DecodingError.typeMismatch(
T.self,
.init( .init(
codingPath: self.codingPath, codingPath: self.codingPath,
debugDescription: "Expected an int, but got \(self.value.debugDataTypeDescription)" debugDescription: "Expected an int, but got \(self.value.debugDataTypeDescription)"
)) )
)
} }
} }
} }

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import MessagePack import MessagePack

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import MessagePack import MessagePack

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -1,29 +1,30 @@
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// 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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation
import MessagePack import MessagePack
import SemanticVersion import SemanticVersion
#if os(Windows) #if os(Windows)
import WinSDK.System import WinSDK.System
let ENV_SEPARATOR=";"
let PKL_EXEC_NAME="pkl.exe" let ENV_SEPARATOR=";"
let PKL_EXEC_NAME="pkl.exe"
#else #else
let ENV_SEPARATOR=":" let ENV_SEPARATOR=":"
let PKL_EXEC_NAME="pkl" let PKL_EXEC_NAME="pkl"
#endif #endif
/// Perfoms `action`, returns its result and then closes the manager. /// Perfoms `action`, returns its result and then closes the manager.
/// ///
@ -46,14 +47,14 @@ public func withEvaluatorManager<T>(_ action: (EvaluatorManager) async throws ->
} }
func getenv(_ key: String) -> String? { func getenv(_ key: String) -> String? {
#if os(Windows) #if os(Windows)
let key = key.lowercased() let key = key.lowercased()
return ProcessInfo.processInfo.environment.first { (envKey: String, value: String) in return ProcessInfo.processInfo.environment.first { (envKey: String, _: String) in
return key == envKey.lowercased() key == envKey.lowercased()
}?.value }?.value
#else #else
return ProcessInfo.processInfo.environment[key] return ProcessInfo.processInfo.environment[key]
#endif #endif
} }
/// Resolve the (CLI) command to invoke Pkl. /// Resolve the (CLI) command to invoke Pkl.
@ -108,7 +109,7 @@ public actor EvaluatorManager {
// note; when our C bindings are released, change `init()` based on compiler flags. // note; when our C bindings are released, change `init()` based on compiler flags.
public init() { public init() {
self.init(transport: ChildProcessMessageTransport()) self.init(transport: ServerMessageTransport())
} }
// Used for testing only. // Used for testing only.
@ -264,6 +265,9 @@ public actor EvaluatorManager {
guard options.http == nil || version >= pklVersion0_26 else { guard options.http == nil || version >= pklVersion0_26 else {
throw PklError("http options are not supported on Pkl versions lower than 0.26") 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() let req = options.toMessage()
guard let response = try await ask(req) as? CreateEvaluatorResponse else { guard let response = try await ask(req) as? CreateEvaluatorResponse else {
throw PklBugError.invalidMessageCode( throw PklBugError.invalidMessageCode(
@ -371,8 +375,10 @@ enum PklBugError: Error {
let pklVersion0_25 = SemanticVersion("0.25.0")! let pklVersion0_25 = SemanticVersion("0.25.0")!
let pklVersion0_26 = SemanticVersion("0.26.0")! let pklVersion0_26 = SemanticVersion("0.26.0")!
let pklVersion0_27 = SemanticVersion("0.27.0")!
let supportedPklVersions = [ let supportedPklVersions = [
pklVersion0_25, pklVersion0_25,
pklVersion0_26, pklVersion0_26,
pklVersion0_27,
] ]

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation
@ -32,7 +32,9 @@ public struct EvaluatorOptions {
logger: Logger = Loggers.noop, logger: Logger = Loggers.noop,
projectBaseURI: URL? = nil, projectBaseURI: URL? = nil,
http: Http? = nil, http: Http? = nil,
declaredProjectDependencies: [String: ProjectDependency]? = nil declaredProjectDependencies: [String: ProjectDependency]? = nil,
externalModuleReaders: [String: ExternalReader]? = nil,
externalResourceReaders: [String: ExternalReader]? = nil
) { ) {
self.allowedModules = allowedModules self.allowedModules = allowedModules
self.allowedResources = allowedResources self.allowedResources = allowedResources
@ -49,6 +51,8 @@ public struct EvaluatorOptions {
self.projectBaseURI = projectBaseURI self.projectBaseURI = projectBaseURI
self.http = http self.http = http
self.declaredProjectDependencies = declaredProjectDependencies 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. /// Regular expression patterns that control what modules are allowed to be imported in a Pkl program.
@ -123,6 +127,18 @@ public struct EvaluatorOptions {
/// When importing dependencies, a `PklProject.deps.json` file must exist within ``projectBaseURI`` /// When importing dependencies, a `PklProject.deps.json` file must exist within ``projectBaseURI``
/// that contains the project's resolved dependencies. /// that contains the project's resolved dependencies.
public var declaredProjectDependencies: [String: ProjectDependency]? 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 { extension EvaluatorOptions {
@ -162,7 +178,9 @@ extension EvaluatorOptions {
cacheDir: self.cacheDir, cacheDir: self.cacheDir,
outputFormat: self.outputFormat, outputFormat: self.outputFormat,
project: self.project(), project: self.project(),
http: self.http http: self.http,
externalModuleReaders: self.externalModuleReaders,
externalResourceReaders: self.externalResourceReaders
) )
} }
@ -245,6 +263,8 @@ extension EvaluatorOptions {
options.cacheDir = evaluatorSettings.noCache != nil ? nil : (evaluatorSettings.moduleCacheDir ?? self.cacheDir) options.cacheDir = evaluatorSettings.noCache != nil ? nil : (evaluatorSettings.moduleCacheDir ?? self.cacheDir)
options.rootDir = evaluatorSettings.rootDir ?? self.rootDir options.rootDir = evaluatorSettings.rootDir ?? self.rootDir
options.http = evaluatorSettings.http ?? self.http options.http = evaluatorSettings.http ?? self.http
options.externalModuleReaders = evaluatorSettings.externalModuleReaders ?? options.externalModuleReaders
options.externalResourceReaders = evaluatorSettings.externalResourceReaders ?? options.externalResourceReaders
return options return options
} }

View File

@ -0,0 +1,208 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//
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)
}
}
}

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation
import MessagePack import MessagePack

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation
import MessagePack import MessagePack
@ -62,8 +62,8 @@ enum MessageType: Int, Codable {
case CREATE_EVALUATOR_REQUEST = 0x20 case CREATE_EVALUATOR_REQUEST = 0x20
case CREATE_EVALUATOR_RESPONSE = 0x21 case CREATE_EVALUATOR_RESPONSE = 0x21
case CLOSE_EVALUATOR = 0x22 case CLOSE_EVALUATOR = 0x22
case EVALUATOR_REQUEST = 0x23 case EVALUATE_REQUEST = 0x23
case EVALUATOR_RESPONSE = 0x24 case EVALUATE_RESPONSE = 0x24
case LOG_MESSAGE = 0x25 case LOG_MESSAGE = 0x25
case READ_RESOURCE_REQUEST = 0x26 case READ_RESOURCE_REQUEST = 0x26
case READ_RESOURCE_RESPONSE = 0x27 case READ_RESOURCE_RESPONSE = 0x27
@ -73,6 +73,11 @@ enum MessageType: Int, Codable {
case LIST_RESOURCES_RESPONSE = 0x2B case LIST_RESOURCES_RESPONSE = 0x2B
case LIST_MODULES_REQUEST = 0x2C case LIST_MODULES_REQUEST = 0x2C
case LIST_MODULES_RESPONSE = 0x2D 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 { extension MessageType {
@ -85,9 +90,9 @@ extension MessageType {
case is CloseEvaluatorRequest: case is CloseEvaluatorRequest:
return MessageType.CLOSE_EVALUATOR return MessageType.CLOSE_EVALUATOR
case is EvaluateRequest: case is EvaluateRequest:
return MessageType.EVALUATOR_REQUEST return MessageType.EVALUATE_REQUEST
case is EvaluateResponse: case is EvaluateResponse:
return MessageType.EVALUATOR_RESPONSE return MessageType.EVALUATE_RESPONSE
case is LogMessage: case is LogMessage:
return MessageType.LOG_MESSAGE return MessageType.LOG_MESSAGE
case is ListResourcesRequest: case is ListResourcesRequest:
@ -102,6 +107,16 @@ extension MessageType {
return MessageType.READ_MODULE_RESPONSE return MessageType.READ_MODULE_RESPONSE
case is ReadResourceResponse: case is ReadResourceResponse:
return MessageType.READ_RESOURCE_RESPONSE 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: default:
preconditionFailure("Unreachable code") preconditionFailure("Unreachable code")
} }
@ -123,6 +138,8 @@ struct CreateEvaluatorRequest: ClientRequestMessage {
var outputFormat: String? var outputFormat: String?
var project: ProjectOrDependency? var project: ProjectOrDependency?
var http: Http? var http: Http?
var externalModuleReaders: [String: ExternalReader]?
var externalResourceReaders: [String: ExternalReader]?
} }
struct ProjectOrDependency: Codable { struct ProjectOrDependency: Codable {
@ -231,3 +248,25 @@ struct LogMessage: ServerOneWayMessage {
// NOTE: not guaranteed to conform to URL. This might have been transformed by a stack frame transformer. // NOTE: not guaranteed to conform to URL. This might have been transformed by a stack frame transformer.
let frameUri: String 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 {}

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation
import MessagePack import MessagePack
@ -31,35 +31,104 @@ protocol MessageTransport {
extension Pipe: Reader { extension Pipe: Reader {
public func read(into: UnsafeMutableRawBufferPointer) throws -> Int { public func read(into: UnsafeMutableRawBufferPointer) throws -> Int {
let data = try fileHandleForReading.read(upToCount: into.count) try fileHandleForReading.read(into: into)
if data == nil {
return 0
}
data!.copyBytes(to: into)
return data!.count
} }
public func close() throws { 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 { extension Pipe: Writer {
public func write(_ buffer: UnsafeRawBufferPointer) throws { 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. /// A ``MessageTransport`` that sends and receives messages by spawning Pkl as a child process.
public class ChildProcessMessageTransport: MessageTransport { public class ServerMessageTransport: BaseMessageTransport {
var reader: Pipe!
var writer: Pipe!
var encoder: MessagePackEncoder!
var decoder: MessagePackDecoder!
var process: Process? var process: Process?
let pklCommand: [String]? let pklCommand: [String]?
convenience init() { override var running: Bool { self.process?.isRunning == true }
override convenience init() {
self.init(pklCommand: nil) self.init(pklCommand: nil)
} }
@ -75,8 +144,8 @@ public class ChildProcessMessageTransport: MessageTransport {
var arguments = Array(pklCommand.dropFirst()) var arguments = Array(pklCommand.dropFirst())
arguments.append("server") arguments.append("server")
self.process!.arguments = arguments self.process!.arguments = arguments
self.reader = .init() self.reader = Pipe()
self.writer = .init() self.writer = Pipe()
self.encoder = .init(writer: self.writer) self.encoder = .init(writer: self.writer)
self.decoder = .init(reader: self.reader) self.decoder = .init(reader: self.reader)
self.process!.standardOutput = self.reader self.process!.standardOutput = self.reader
@ -85,17 +154,25 @@ public class ChildProcessMessageTransport: MessageTransport {
try self.process!.run() try self.process!.run()
} }
func send(_ message: ClientMessage) throws { override func send(_ message: ClientMessage) throws {
try self.ensureProcessStarted() try self.ensureProcessStarted()
debug("Sending message: \(message)") try super.send(message)
let messageType = MessageType.getMessageType(message)
try self.encoder.encodeArrayHeader(2)
try self.encoder.encode(messageType)
try self.encoder.encode(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 { if self.process == nil {
return return
} }
@ -111,45 +188,38 @@ public class ChildProcessMessageTransport: MessageTransport {
self.process = nil 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 { switch messageType {
case MessageType.CREATE_EVALUATOR_RESPONSE: case MessageType.INITIALIZE_MODULE_READER_REQUEST:
return try self.decoder.decode(as: CreateEvaluatorResponse.self) return try self.decoder.decode(as: InitializeModuleReaderRequest.self)
case MessageType.EVALUATOR_RESPONSE: case MessageType.INITIALIZE_RESOURCE_READER_REQUEST:
return try self.decoder.decode(as: EvaluateResponse.self) return try self.decoder.decode(as: InitializeResourceReaderRequest.self)
case MessageType.READ_MODULE_REQUEST: case MessageType.CLOSE_EXTERNAL_PROCESS:
return try self.decoder.decode(as: ReadModuleRequest.self) return try self.decoder.decode(as: CloseExternalProcess.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)
default: default:
fatalError("Unreachable code") return try super.decodeMessage(messageType)
} }
} }
func getMessages() throws -> AsyncThrowingStream<ServerMessage, Error> { override func close() {
try self.ensureProcessStarted() self._running = false
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()
}
}
} }
} }

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// The Swift representation of standard library module `pkl.EvaluatorSettings`. /// The Swift representation of standard library module `pkl.EvaluatorSettings`.
public struct PklEvaluatorSettings: Decodable, Hashable { public struct PklEvaluatorSettings: Decodable, Hashable {
@ -26,6 +26,28 @@ public struct PklEvaluatorSettings: Decodable, Hashable {
let moduleCacheDir: String? let moduleCacheDir: String?
let rootDir: String? let rootDir: String?
let http: Http? 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. /// Settings that control how Pkl talks to HTTP(S) servers.
@ -85,3 +107,8 @@ public struct Proxy: Codable, Hashable {
/// ``` /// ```
var noProxy: [String]? var noProxy: [String]?
} }
public struct ExternalReader: Codable, Hashable {
var executable: String
var arguments: [String]? = nil
}

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// The Swift representation of `pkl.Project` /// The Swift representation of `pkl.Project`
public struct Project: PklRegisteredType, Hashable, DependencyDeclaredInProjectFile { public struct Project: PklRegisteredType, Hashable, DependencyDeclaredInProjectFile {

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation
@ -35,8 +35,8 @@ public protocol BaseReader {
/// birds:catalog/swallow.pkl /// birds:catalog/swallow.pkl
/// ``` /// ```
/// ///
/// The first URI conveys name "fred.pkl" within parent "/persons/". The second URI /// The first URI conveys name "swallow.pkl" within parent "/catalog/". The second URI
/// conveys the name "persons/fred.pkl" with no hierarchical meaning. /// conveys the name "catalog/swallow.pkl" with no hierarchical meaning.
var hasHierarchicalUris: Bool { get } var hasHierarchicalUris: Bool { get }
/// Returns elements at a specified path. /// Returns elements at a specified path.
@ -107,6 +107,11 @@ public struct PathElement {
/// Whether the element is a directory or not. /// Whether the element is a directory or not.
public let isDirectory: Bool public let isDirectory: Bool
public init(name: String, isDirectory: Bool) {
self.name = name
self.isDirectory = isDirectory
}
} }
extension PathElement { extension PathElement {

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import MessagePack import MessagePack
import PklSwiftInternals import PklSwiftInternals

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation
@ -85,3 +85,12 @@ public func resolvePaths(_ paths: String...) -> String {
} }
public let absoluteUriRegex = try! Regex("\\w+:") 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)
}

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //

View File

@ -1,12 +1,18 @@
// /*
// This source file is part of the Swift.org open source project * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
// *
// Copyright (c) 2024 Apple Inc. and the Swift project authors * Licensed under the Apache License, Version 2.0 (the "License");
// Licensed under Apache License v2.0 with Runtime Library Exception * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// See https://swift.org/LICENSE.txt for license information *
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors * 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" #include "Discovery.h"

View File

@ -1,12 +1,18 @@
// /*
// This source file is part of the Swift.org open source project * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
// *
// Copyright (c) 2024 Apple Inc. and the Swift project authors * Licensed under the Apache License, Version 2.0 (the "License");
// Licensed under Apache License v2.0 with Runtime Library Exception * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// See https://swift.org/LICENSE.txt for license information *
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors * 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) #if !defined(PKLS_DEFINES_H)
#define PKLS_DEFINES_H #define PKLS_DEFINES_H

View File

@ -1,12 +1,18 @@
// /*
// This source file is part of the Swift.org open source project * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
// *
// Copyright (c) 2024 Apple Inc. and the Swift project authors * Licensed under the Apache License, Version 2.0 (the "License");
// Licensed under Apache License v2.0 with Runtime Library Exception * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// See https://swift.org/LICENSE.txt for license information *
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors * 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) #if !defined(PKLS_DISCOVERY_H)
#define PKLS_DISCOVERY_H #define PKLS_DISCOVERY_H

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import ArgumentParser import ArgumentParser
import Foundation import Foundation
@ -77,11 +77,6 @@ struct PklGenSwift: AsyncParsableCommand {
) )
var pklInputModules: [String] = [] var pklInputModules: [String] = []
func tempFile() -> URL {
let fileName = ProcessInfo.processInfo.globallyUniqueString + ".pkl"
return URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(fileName)
}
private func generateScriptUrl() -> String { private func generateScriptUrl() -> String {
if let generateScript = self.generateScript { if let generateScript = self.generateScript {
return URL(fileURLWithPath: generateScript).path return URL(fileURLWithPath: generateScript).path

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import Foundation import Foundation
import PklSwift 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 { private mutating func runModule(evaluator: Evaluator, pklInputModule: String) async throws {
let out = resolvePaths(self.settings.outputPath ?? ".out") let out = resolvePaths(self.settings.outputPath ?? ".out")
let moduleToEvaluate = """ let moduleToEvaluate = """
@ -55,7 +50,7 @@ public struct PklSwiftGenerator {
moduleToGenerate = theModule moduleToGenerate = theModule
""" """
let tempFile = tempFile() let tempFile = try tempFile(suffix: ".pkl")
try moduleToEvaluate.write(to: tempFile, atomically: true, encoding: .utf8) try moduleToEvaluate.write(to: tempFile, atomically: true, encoding: .utf8)
let files = try await evaluator.evaluateOutputFiles(source: .url(tempFile)) let files = try await evaluator.evaluateOutputFiles(source: .url(tempFile))
for (filename, contents) in files { for (filename, contents) in files {

View File

@ -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
}

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import XCTest import XCTest

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import XCTest import XCTest

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import XCTest import XCTest

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import PklSwift import PklSwift
import XCTest import XCTest

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import XCTest import XCTest
@ -43,6 +43,11 @@ final class PklDecoderTests: XCTestCase {
XCTAssertEqual(value, 42) 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 { func testDecodeString() throws {
let bytes: [UInt8] = [ let bytes: [UInt8] = [
0xD9, 0x27, 0x74, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6B, 0x20, 0x66, 0x6F, 0x78, 0xD9, 0x27, 0x74, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6B, 0x20, 0x66, 0x6F, 0x78,

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import SemanticVersion import SemanticVersion
import XCTest import XCTest

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@testable import MessagePack @testable import MessagePack
@testable import PklSwift @testable import PklSwift
@ -305,10 +305,10 @@ final class PklSwiftTests: XCTestCase {
XCTAssertEqual(logger.logLines, [#"pkl: TRACE: "Hello there" = "Hello there" (repl:text)\#n"#]) 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 { // 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 FileManager.default.createDirectory(at: project1Dir, withIntermediateDirectories: true)
// try """ // try """
// amends "pkl:Project" // amends "pkl:Project"

View File

@ -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))
}
}
}

View File

@ -7,6 +7,9 @@ public protocol UnionTypes_Animal: PklRegisteredType, DynamicallyEquatable, Hash
var name: String { get } var name: String { get }
} }
public protocol UnionTypes_Shape: PklRegisteredType, DynamicallyEquatable, Hashable {
}
extension UnionTypes { extension UnionTypes {
public enum Fruit: Decodable, Hashable { public enum Fruit: Decodable, Hashable {
case banana(Banana) case banana(Banana)
@ -14,8 +17,9 @@ extension UnionTypes {
case apple(Apple) case apple(Apple)
public init(from decoder: Decoder) throws { public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value let container = try decoder.singleValueContainer()
switch decoded { let value = try container.decode(PklSwift.PklAny.self).value
switch value?.base {
case let decoded as Banana: case let decoded as Banana:
self = Fruit.banana(decoded) self = Fruit.banana(decoded)
case let decoded as Grape: case let decoded as Grape:
@ -27,14 +31,14 @@ extension UnionTypes {
Fruit.self, Fruit.self,
.init( .init(
codingPath: decoder.codingPath, 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 sanFrancisco = "San Francisco"
case tokyo = "Tokyo" case tokyo = "Tokyo"
case zurich = "Zurich" case zurich = "Zurich"
@ -46,8 +50,9 @@ extension UnionTypes {
case donkey(Donkey) case donkey(Donkey)
public init(from decoder: Decoder) throws { public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value let container = try decoder.singleValueContainer()
switch decoded { let value = try container.decode(PklSwift.PklAny.self).value
switch value?.base {
case let decoded as Zebra: case let decoded as Zebra:
self = ZebraOrDonkey.zebra(decoded) self = ZebraOrDonkey.zebra(decoded)
case let decoded as Donkey: case let decoded as Donkey:
@ -57,7 +62,7 @@ extension UnionTypes {
ZebraOrDonkey.self, ZebraOrDonkey.self,
.init( .init(
codingPath: decoder.codingPath, 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 { public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value let container = try decoder.singleValueContainer()
switch decoded { let value = try container.decode(PklSwift.PklAny.self).value
switch value?.base {
case let decoded as any Animal: case let decoded as any Animal:
self = AnimalOrString.animal(decoded) self = AnimalOrString.animal(decoded)
case let decoded as String: case let decoded as String:
@ -91,7 +97,7 @@ extension UnionTypes {
AnimalOrString.self, AnimalOrString.self,
.init( .init(
codingPath: decoder.codingPath, codingPath: decoder.codingPath,
debugDescription: "Expected type AnimalOrString, but got \(String(describing: decoded))" debugDescription: "Expected type AnimalOrString, but got \(String(describing: value))"
) )
) )
} }
@ -107,6 +113,114 @@ 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 struct Module: PklRegisteredType, Decodable, Hashable {
public static let registeredIdentifier: String = "UnionTypes" public static let registeredIdentifier: String = "UnionTypes"
@ -132,6 +246,26 @@ extension UnionTypes {
public var animalOrString2: AnimalOrString 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( public init(
fruit1: Fruit, fruit1: Fruit,
fruit2: Fruit, fruit2: Fruit,
@ -143,7 +277,17 @@ extension UnionTypes {
animal1: ZebraOrDonkey, animal1: ZebraOrDonkey,
animal2: ZebraOrDonkey, animal2: ZebraOrDonkey,
animalOrString1: AnimalOrString, 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.fruit1 = fruit1
self.fruit2 = fruit2 self.fruit2 = fruit2
@ -156,6 +300,16 @@ extension UnionTypes {
self.animal2 = animal2 self.animal2 = animal2
self.animalOrString1 = animalOrString1 self.animalOrString1 = animalOrString1
self.animalOrString2 = animalOrString2 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
} }
} }
@ -191,6 +345,18 @@ extension UnionTypes {
public typealias Animal = UnionTypes_Animal 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 struct Zebra: Animal {
public static let registeredIdentifier: String = "UnionTypes#Zebra" public static let registeredIdentifier: String = "UnionTypes#Zebra"

View File

@ -1,3 +1,5 @@
import "pkl:math"
class Banana { class Banana {
isRipe: Boolean isRipe: Boolean
} }
@ -18,6 +20,12 @@ typealias Fruit = Banana | Grape | Apple
typealias City = "San Francisco"|"Tokyo"|"Zurich"|"London" typealias City = "San Francisco"|"Tokyo"|"Zurich"|"London"
abstract class Shape
class Square extends Shape {
fixed corners: Int = 4
}
fruit1: Fruit = new Banana { fruit1: Fruit = new Banana {
isRipe = true isRipe = true
} }
@ -52,4 +60,34 @@ typealias AnimalOrString = Animal|String
animalOrString1: AnimalOrString = new Zebra {} 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

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import PklSwift import PklSwift
import XCTest import XCTest
@ -160,7 +160,17 @@ class FixturesTest: XCTestCase {
animal1: .zebra(UnionTypes.Zebra(name: "Zebra")), animal1: .zebra(UnionTypes.Zebra(name: "Zebra")),
animal2: .donkey(UnionTypes.Donkey(name: "Donkey")), animal2: .donkey(UnionTypes.Donkey(name: "Donkey")),
animalOrString1: .animal(UnionTypes.Zebra(name: "Zebra")), 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)
)) ))
} }
} }

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import SemanticVersion import SemanticVersion
import XCTest import XCTest
@ -22,12 +22,13 @@ import XCTest
class ProjectTest: XCTestCase { class ProjectTest: XCTestCase {
func testLoadProject() async throws { func testLoadProject() async throws {
let version = try await SemanticVersion(EvaluatorManager().getVersion())! let version = try await SemanticVersion(EvaluatorManager().getVersion())!
let tempDir = NSTemporaryDirectory() let tempDir = try tempDir()
try FileManager.default.createDirectory(atPath: tempDir + "/subdir", withIntermediateDirectories: true) let subDir = tempDir.appendingPathComponent("subdir")
let otherProjectFile = URL(fileURLWithPath: tempDir, isDirectory: true) try FileManager.default.createDirectory(at: subDir, withIntermediateDirectories: true)
.appendingPathComponent("subdir/PklProject") let otherProjectFile = subDir.appendingPathComponent("PklProject")
try #""" try #"""
@ModuleInfo { minPklVersion = "0.25.0" }
amends "pkl:Project" amends "pkl:Project"
package { package {
@ -38,8 +39,8 @@ class ProjectTest: XCTestCase {
} }
"""#.write(to: otherProjectFile, atomically: true, encoding: .utf8) """#.write(to: otherProjectFile, atomically: true, encoding: .utf8)
let file = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) let file = try (PklSwift.tempDir()).appendingPathComponent("PklProject")
.appendingPathComponent("PklProject")
let httpSetting = version < pklVersion0_26 ? "" : """ let httpSetting = version < pklVersion0_26 ? "" : """
http { http {
proxy { proxy {
@ -51,10 +52,40 @@ class ProjectTest: XCTestCase {
} }
} }
""" """
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( let httpExpectation = version < pklVersion0_26 ? nil : Http(
caCertificates: nil, caCertificates: nil,
proxy: .init(address: "http://localhost:1", noProxy: ["example.com", "foo.bar.org"]) 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 #""" try #"""
amends "pkl:Project" amends "pkl:Project"
@ -99,7 +130,9 @@ class ProjectTest: XCTestCase {
timeout = 5.min timeout = 5.min
moduleCacheDir = "/bar/buzz" moduleCacheDir = "/bar/buzz"
rootDir = "/buzzy" rootDir = "/buzzy"
\#(externalReaderSettings)
\#(httpSetting) \#(httpSetting)
\#(colorSetting)
} }
dependencies { dependencies {
@ -124,7 +157,10 @@ class ProjectTest: XCTestCase {
timeout: .minutes(5), timeout: .minutes(5),
moduleCacheDir: "/bar/buzz", moduleCacheDir: "/bar/buzz",
rootDir: "/buzzy", rootDir: "/buzzy",
http: httpExpectation http: httpExpectation,
externalModuleReaders: externalModuleReadersExpectation,
externalResourceReaders: externalResourceReadersExpectation,
color: color
) )
let expectedPackage = PklSwift.Project.Package( let expectedPackage = PklSwift.Project.Package(
name: "hawk", name: "hawk",
@ -179,7 +215,10 @@ class ProjectTest: XCTestCase {
timeout: nil, timeout: nil,
moduleCacheDir: nil, moduleCacheDir: nil,
rootDir: nil, rootDir: nil,
http: nil http: nil,
externalModuleReaders: nil,
externalResourceReaders: nil,
color: nil
), ),
projectFileUri: "\(otherProjectFile)", projectFileUri: "\(otherProjectFile)",
tests: [], tests: [],

View File

@ -1 +1 @@
0.3.0 0.4.2

View File

@ -5,7 +5,7 @@ public enum Enums {}
extension Enums { extension Enums {
/// City is one of these four fantastic cities /// 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 sanFrancisco = "San Francisco"
case london = "London" case london = "London"
case zurich = "Zurich" case zurich = "Zurich"
@ -19,8 +19,9 @@ extension Enums {
case monkey(Monkey) case monkey(Monkey)
public init(from decoder: Decoder) throws { public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value let container = try decoder.singleValueContainer()
switch decoded { let value = try container.decode(PklSwift.PklAny.self).value
switch value?.base {
case let decoded as Horse: case let decoded as Horse:
self = Animal.horse(decoded) self = Animal.horse(decoded)
case let decoded as Zebra: case let decoded as Zebra:
@ -32,7 +33,7 @@ extension Enums {
Animal.self, Animal.self,
.init( .init(
codingPath: decoder.codingPath, 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]) case arrayString([String])
public init(from decoder: Decoder) throws { public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value let container = try decoder.singleValueContainer()
switch decoded { let value = try container.decode(PklSwift.PklAny.self).value
switch value?.base {
case let decoded as [String: String]: case let decoded as [String: String]:
self = DictOrArray.dictionaryStringString(decoded) self = DictOrArray.dictionaryStringString(decoded)
case let decoded as [String]: case let decoded as [String]:
@ -56,7 +58,7 @@ extension Enums {
DictOrArray.self, DictOrArray.self,
.init( .init(
codingPath: decoder.codingPath, 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) case string(String)
public init(from decoder: Decoder) throws { public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value let container = try decoder.singleValueContainer()
switch decoded { let value = try container.decode(PklSwift.PklAny.self).value
switch value?.base {
case let decoded as Horse: case let decoded as Horse:
self = HorseOrBug.horse(decoded) self = HorseOrBug.horse(decoded)
case let decoded as String: case let decoded as String:
@ -82,7 +85,7 @@ extension Enums {
HorseOrBug.self, HorseOrBug.self,
.init( .init(
codingPath: decoder.codingPath, 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) case zebra(Zebra)
public init(from decoder: Decoder) throws { public init(from decoder: Decoder) throws {
let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value let container = try decoder.singleValueContainer()
switch decoded { let value = try container.decode(PklSwift.PklAny.self).value
switch value?.base {
case let decoded as Horse?: case let decoded as Horse?:
self = MaybeHorseOrDefinitelyZebra.horse(decoded) self = MaybeHorseOrDefinitelyZebra.horse(decoded)
case let decoded as Zebra: case let decoded as Zebra:
@ -105,7 +109,7 @@ extension Enums {
MaybeHorseOrDefinitelyZebra.self, MaybeHorseOrDefinitelyZebra.self,
.init( .init(
codingPath: decoder.codingPath, codingPath: decoder.codingPath,
debugDescription: "Expected type MaybeHorseOrDefinitelyZebra, but got \(String(describing: decoded))" debugDescription: "Expected type MaybeHorseOrDefinitelyZebra, but got \(String(describing: value))"
) )
) )
} }

View File

@ -4,7 +4,7 @@ import PklSwift
public enum ExplicitlyCoolName {} public enum ExplicitlyCoolName {}
extension ExplicitlyCoolName { extension ExplicitlyCoolName {
public enum ConfigType: String, CaseIterable, Decodable, Hashable { public enum ConfigType: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {
case one = "one" case one = "one"
case two = "two" case two = "two"
} }

View File

@ -4,7 +4,7 @@ import PklSwift
public enum UnionNameKeyword {} public enum UnionNameKeyword {}
extension UnionNameKeyword { extension UnionNameKeyword {
public enum `Type`: String, CaseIterable, Decodable, Hashable { public enum `Type`: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {
case one = "one" case one = "one"
case two = "two" case two = "two"
case three = "three" case three = "three"

View File

@ -5,28 +5,28 @@ public enum union {}
extension union { extension union {
/// City; e.g. where people live /// 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 sanFrancisco = "San Francisco"
case london = "London" case london = "London"
case = "上海" case = "上海"
} }
/// Locale that contains cities and towns /// 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 sanFrancisco = "San Francisco"
case sanMateo = "San Mateo" case sanMateo = "San Mateo"
case yolo = "Yolo" case yolo = "Yolo"
} }
/// Noodles /// Noodles
public enum Noodles: String, CaseIterable, Decodable, Hashable { public enum Noodles: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {
case = "拉面" case = "拉面"
case = "刀切面" case = "刀切面"
case 线 = "面线" case 线 = "面线"
case = "意大利面" case = "意大利面"
} }
public enum AccountDisposition: String, CaseIterable, Decodable, Hashable { public enum AccountDisposition: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {
case empty = "" case empty = ""
case icloud3 = "icloud3" case icloud3 = "icloud3"
case prod = "prod" case prod = "prod"

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// Generates Swift sources from Pkl /// Generates Swift sources from Pkl
@swift.Module { name = "pkl_gen_swift" } @swift.Module { name = "pkl_gen_swift" }
@ModuleInfo { minPklVersion = "0.24.0" } @ModuleInfo { minPklVersion = "0.24.0" }

View File

@ -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. /// Settings used to configure code generation.
@swift.Module { name = "pkl_gen_swift" } @swift.Module { name = "pkl_gen_swift" }
@swift.Name { value = "GeneratorSettings" } @swift.Name { value = "GeneratorSettings" }

View File

@ -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" amends "pkl:Project"
package { package {

View File

@ -1,4 +1,4 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"resolvedDependencies": {} "resolvedDependencies": {}
} }

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@Unlisted @Unlisted
module pkl.swift.internal.ClassGen module pkl.swift.internal.ClassGen

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@Unlisted @Unlisted
module pkl.swift.internal.EnumGen module pkl.swift.internal.EnumGen
@ -57,6 +58,10 @@ local enumNormalMembers = enumBaseMembers.map((it) -> (it) {
else baseName else baseName
}) })
local enumNonNumericMembers = enumNormalMembers.filter((it) -> !it.type.isNumeric)
local enumNumericMembers = enumNormalMembers.filter((it) -> it.type.isNumeric)
contents = contents =
if (isStringLiteralUnion) stringLiteralEnumContents if (isStringLiteralUnion) stringLiteralEnumContents
else enumContents else enumContents
@ -66,7 +71,7 @@ local stringLiteralEnumContents =
when (alias.docComment != null) { when (alias.docComment != null) {
utils.renderDocComment(alias.docComment!!, "") utils.renderDocComment(alias.docComment!!, "")
} }
"public enum \(module.mapping.name): String, CaseIterable, Decodable, Hashable {" "public enum \(module.mapping.name): String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {"
for (member in enumStringLiteralMembers) { for (member in enumStringLiteralMembers) {
"\(module.indent)case \(member.name) = \(utils.toSwiftString((member.pklType as reflect.StringLiteralType).value))" "\(module.indent)case \(member.name) = \(utils.toSwiftString((member.pklType as reflect.StringLiteralType).value))"
} }
@ -79,33 +84,19 @@ local enumContents =
utils.renderDocComment(alias.docComment!!, "") utils.renderDocComment(alias.docComment!!, "")
} }
"public enum \(module.mapping.name): Decodable, Hashable {" "public enum \(module.mapping.name): Decodable, Hashable {"
for (member in enumNormalMembers) { for (member: EnumMember in enumNormalMembers) {
"\(module.indent)case \(member.name)(\(member.renderedType))" "\(module.indent)case \(member.name)(\(member.renderedType))"
} }
"" ""
when (!enumNumericMembers.isEmpty) {
decodeNumeric
""
}
when (enumNormalMembers.any((it) -> it.type.isPolymorphic)) { when (enumNormalMembers.any((it) -> it.type.isPolymorphic)) {
synthesizedEquals synthesizedEquals
"" ""
} }
"\(module.indent)public init(from decoder: Decoder) throws {" initMethod
"\(module.indent.repeat(2))let decoded = try decoder.singleValueContainer().decode(PklSwift.PklAny.self).value"
"\(module.indent.repeat(2))switch decoded {"
for (member in enumNormalMembers) {
"\(module.indent.repeat(2))case let decoded as \(member.renderedType):"
"\(module.indent.repeat(3))self = \(module.mapping.name).\(member.name)(decoded)"
}
"""
\(module.indent.repeat(2))default:
\(module.indent.repeat(3))throw DecodingError.typeMismatch(
\(module.indent.repeat(4))\(module.mapping.name).self,
\(module.indent.repeat(4)).init(
\(module.indent.repeat(5))codingPath: decoder.codingPath,
\(module.indent.repeat(5))debugDescription: "Expected type \(module.mapping.name), but got \\(String(describing: decoded))"
\(module.indent.repeat(4)))
\(module.indent.repeat(3)))
\(module.indent.repeat(2))}
\(module.indent)}
"""
when (enumNormalMembers.any((it) -> it.type.isPolymorphic)) { when (enumNormalMembers.any((it) -> it.type.isPolymorphic)) {
"" ""
synthesizedHash synthesizedHash
@ -113,6 +104,44 @@ local enumContents =
"}" "}"
}.join("\n") }.join("\n")
local throwTypeMismatch = new Listing {
"\(module.indent.repeat(2))throw DecodingError.typeMismatch("
"\(module.indent.repeat(3))\(module.mapping.name).self,"
"\(module.indent.repeat(3)).init("
"\(module.indent.repeat(4))codingPath: decoder.codingPath,"
"\(module.indent.repeat(4))debugDescription: \"Expected type \(module.mapping.name), but got \\(String(describing: value))\""
"\(module.indent.repeat(3)))"
"\(module.indent.repeat(2)))"
}.join("\n")
local initMethod = new Listing {
"\(module.indent)public init(from decoder: Decoder) throws {"
"\(module.indent.repeat(2))let container = try decoder.singleValueContainer()"
when (!enumNumericMembers.isEmpty) {
"\(module.indent.repeat(2))let decoded = \(module.mapping.name).decodeNumeric(from: decoder, container)"
"\(module.indent.repeat(2))if decoded != nil {"
"\(module.indent.repeat(3))self = decoded!"
"\(module.indent.repeat(3))return"
"\(module.indent.repeat(2))}"
}
"\(module.indent.repeat(2))let value = try container.decode(PklSwift.PklAny.self).value"
when (!enumNonNumericMembers.isEmpty) {
"\(module.indent.repeat(2))switch value?.base {"
for (member in enumNonNumericMembers) {
"\(module.indent.repeat(2))case let decoded as \(member.renderedType):"
"\(module.indent.repeat(3))self = \(module.mapping.name).\(member.name)(decoded)"
}
"\(module.indent.repeat(2))default:"
// indent one more level
module.indent + throwTypeMismatch.split("\n").join("\n" + module.indent)
"\(module.indent.repeat(2))}"
} else {
throwTypeMismatch
}
"\(module.indent)}"
}
.join("\n")
local synthesizedEquals = new Listing { local synthesizedEquals = new Listing {
"\(module.indent)public static func ==(lhs: \(module.mapping.name), rhs: \(module.mapping.name)) -> Bool {" "\(module.indent)public static func ==(lhs: \(module.mapping.name), rhs: \(module.mapping.name)) -> Bool {"
"\(module.indent.repeat(2))switch (lhs, rhs) {" "\(module.indent.repeat(2))switch (lhs, rhs) {"
@ -141,6 +170,23 @@ local synthesizedHash = new Listing {
"\(module.indent)}" "\(module.indent)}"
}.join("\n") }.join("\n")
local decodeNumeric = new Listing {
"\(module.indent)private static func decodeNumeric(from decoder: Decoder, _ container: any SingleValueDecodingContainer) -> \(module.mapping.name)? {"
when (enumNumericMembers.length == 1) {
local member = enumNumericMembers.first
"\(module.indent.repeat(2))return try? .\(member.name)(container.decode(\(member.renderedType).self))"
} else {
for (idx, member in enumNumericMembers) {
when (idx == 0) {
"\(module.indent.repeat(2))return (try? .\(member.name)(container.decode(\(member.renderedType).self)))"
} else {
"\(module.indent.repeat(3))?? (try? .\(member.name)(container.decode(\(member.renderedType).self)))"
}
}
}
"\(module.indent)}"
}.join("\n")
local class EnumMember { local class EnumMember {
name: String name: String
type: Type type: Type

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@Unlisted @Unlisted
abstract module pkl.swift.internal.Gen abstract module pkl.swift.internal.Gen

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@Unlisted @Unlisted
abstract module pkl.swift.internal.SwiftMapping abstract module pkl.swift.internal.SwiftMapping

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@Unlisted @Unlisted
module pkl.swift.internal.SwiftNamespace module pkl.swift.internal.SwiftNamespace

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// Representation of a type in Swift. /// Representation of a type in Swift.
@Unlisted @Unlisted
abstract module pkl.swift.internal.Type abstract module pkl.swift.internal.Type
@ -28,6 +29,9 @@ isPolymorphic: Boolean = false
/// True if this type represents a Pkl Any /// True if this type represents a Pkl Any
isAny: Boolean = false isAny: Boolean = false
/// Tells if this type represents a number (int or float) or not
isNumeric: Boolean = false
/// Renders this type into source code. /// Renders this type into source code.
/// ///
/// [swiftModuleName] is the full path of the package that this type appears in. /// [swiftModuleName] is the full path of the package that this type appears in.

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@Unlisted @Unlisted
module pkl.swift.internal.TypeAliasGen module pkl.swift.internal.TypeAliasGen

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@Unlisted @Unlisted
module pkl.swift.internal.gatherer module pkl.swift.internal.gatherer

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// Utilities for generating Swift types from Pkl. /// Utilities for generating Swift types from Pkl.
@Unlisted @Unlisted
module pkl.swift.internal.typegen module pkl.swift.internal.typegen
@ -76,16 +77,16 @@ anyType: Type.Nullable = new { elem = builtInType("AnyHashable") }
local neverType: Type.Declared = builtInType("Never") local neverType: Type.Declared = builtInType("Never")
mappedTypes: Mapping<Class|TypeAlias, Type> = new { mappedTypes: Mapping<Class|TypeAlias, Type> = new {
[Int] = new Type.Declared { typeName = "Int" } [Int] = new Type.Declared { typeName = "Int"; isNumeric = true }
[Int8] = new Type.Declared { typeName = "Int8" } [Int8] = new Type.Declared { typeName = "Int8"; isNumeric = true }
[Int16] = new Type.Declared { typeName = "Int16" } [Int16] = new Type.Declared { typeName = "Int16"; isNumeric = true }
[Int32] = new Type.Declared { typeName = "Int32" } [Int32] = new Type.Declared { typeName = "Int32"; isNumeric = true }
[UInt] = new Type.Declared { typeName = "UInt" } [UInt] = new Type.Declared { typeName = "UInt"; isNumeric = true }
[UInt8] = new Type.Declared { typeName = "UInt8" } [UInt8] = new Type.Declared { typeName = "UInt8"; isNumeric = true }
[UInt16] = new Type.Declared { typeName = "UInt16" } [UInt16] = new Type.Declared { typeName = "UInt16"; isNumeric = true }
[UInt32] = new Type.Declared { typeName = "UInt32" } [UInt32] = new Type.Declared { typeName = "UInt32"; isNumeric = true }
[Number] = new Type.Declared { typeName = "Float64" } [Number] = new Type.Declared { typeName = "Float64"; isNumeric = true }
[Float] = new Type.Declared { typeName = "Float64" } [Float] = new Type.Declared { typeName = "Float64"; isNumeric = true }
[String] = new Type.Declared { typeName = "String" } [String] = new Type.Declared { typeName = "String" }
[Boolean] = new Type.Declared { typeName = "Bool" } [Boolean] = new Type.Declared { typeName = "Bool" }
[Null] = new Type.Declared { typeName = "Optional"; typeArguments = List(neverType) } [Null] = new Type.Declared { typeName = "Optional"; typeArguments = List(neverType) }

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@Unlisted @Unlisted
module pkl.swift.internal.utils module pkl.swift.internal.utils

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@Module { name = "pkl_gen_swift" } @Module { name = "pkl_gen_swift" }
module pkl.swift.swift module pkl.swift.swift

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
amends "pkl:test" amends "pkl:test"
import ".../internal/ClassGen.pkl" import ".../internal/ClassGen.pkl"

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
class Bike { class Bike {
isFixie: Boolean isFixie: Boolean
} }

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
import "types3.pkl" import "types3.pkl"
class Person { class Person {

View File

@ -1,16 +1,17 @@
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// 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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
class Bike class Bike

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
class Foo { class Foo {
bar: Listing<Int|String> bar: Listing<Int|String>
} }

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
amends "pkl:test" amends "pkl:test"
import "pkl:reflect" import "pkl:reflect"

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
amends "pkl:test" amends "pkl:test"
import "pkl:reflect" import "pkl:reflect"

View File

@ -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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // 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 // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// ===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
amends "pkl:test" amends "pkl:test"
import "../internal/utils.pkl" import "../internal/utils.pkl"

View File

@ -1,5 +1,5 @@
name: swift name: swift
title: Pkl Swift Bindings title: Pkl Swift Bindings
version: 0.3.0 version: 0.4.2
nav: nav:
- nav.adoc - nav.adoc

View File

@ -1,5 +1,46 @@
= Changelog = Changelog
[[release-0.4.2]]
== 0.4.2 (2025-04-14)
=== Fixes
* Fixes an issue where enum keys fail to be decoded (https://github.com/apple/pkl-swift/pull/45[#45]).
* Fixes an issue where unions of ints can possibly be decoded incorrectly (https://github.com/apple/pkl-swift/pull/47[#47]).
=== Miscellaneous
* Auto-generate DocC documentation in the Swift Package Index (https://github.com/apple/pkl-swift/pull/41[#41]).
* Update license headers (https://github.com/apple/pkl-swift/pull/43[#43]).
[[release-0.4.1]]
== 0.4.1 (2025-02-04)
=== Fixes
* Fixes an issue where union types might get decoded as the wrong Swift type (https://github.com/apple/pkl-swift/pull/39[#39]).
[[release-0.4.0]]
== 0.4.0 (2025-01-24)
=== Additions
* Add a new API for creating external readers, called `ExternalReaderClient` (https://github.com/apple/pkl-swift/pull/26[#26]).
* Add new fields to support new options available in Pkl 0.27 (https://github.com/apple/pkl-swift/pull/26[#26], https://github.com/apple/pkl-swift/pull/32[#32]):
- In struct `EvaluatorOptions`: `externalModuleReaders` and `externalResourceReaders`.
- In struct `PklEvaluatorSettings`: `externalModuleReaders`, `externalResourceReaders`, and `color`.
=== Changes
* Make `PathElement.init` public (https://github.com/apple/pkl-swift/pull/31[#31]).
=== Contributors ❤️
Thank you to all our contributors!
* https://github.com/HT154[@HT154]
* https://github.com/jcubit[@jcubit]
[[release-0.3.0]] [[release-0.3.0]]
== 0.3.0 (2024-10-10) == 0.3.0 (2024-10-10)

View File

@ -0,0 +1,37 @@
= External Readers
pkl-swift provides APIs that aid in implementing xref:main:language-reference:index.adoc#external-readers[External Readers].
In this mode of execution, the program built with pkl-swift runs as a child process of the Pkl evaluator, rather than a parent process.
The `PklSwift.ExternalReaderClient` type provides a set of tools for building external readers.
Much like implementing xref:ROOT:evaluation.adoc#custom-readers[Custom Readers], external readers are implemented by providing one or more instances of the `PklSwift.ResourceReader` and `pkl.ModuleReader` protocols.
== Example
.main.swift
[source,swift]
----
import Foundation
import PklSwift
@main struct Main {
static func main() async throws {
let client = ExternalReaderClient(
options: ExternalReaderClientOptions(
resourceReaders: [MyResourceReader()]
))
try await client.run()
}
}
struct MyResourceReader: ResourceReader {
var scheme: String { "env2" }
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(scheme.count + 1)
return Array((ProcessInfo.processInfo.environment[String(key)] ?? "").utf8)
}
}
----

View File

@ -1,4 +1,5 @@
* xref:ROOT:quickstart.adoc[Quickstart] * xref:ROOT:quickstart.adoc[Quickstart]
* xref:ROOT:evaluation.adoc[Evaluator API] * xref:ROOT:evaluation.adoc[Evaluator API]
* xref:ROOT:codegen.adoc[Code Generation] * xref:ROOT:codegen.adoc[Code Generation]
* xref:ROOT:external-readers.adoc[External Readers]
* xref:ROOT:CHANGELOG.adoc[Changelog] * xref:ROOT:CHANGELOG.adoc[Changelog]

View File

@ -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 "codegen/src/GeneratorSettings.pkl" amends "codegen/src/GeneratorSettings.pkl"
generateScript = "codegen/src/Generator.pkl" generateScript = "codegen/src/Generator.pkl"

29
licenserc.toml Normal file
View File

@ -0,0 +1,29 @@
additionalHeaders = ["scripts/pkl-header-style.toml"]
headerPath = "scripts/license-header.txt"
includes = [
"*.swift",
"*.pkl",
"*.h",
"*.cpp",
"*.sh",
"PklProject",
]
excludes = [
"Sources/pkl-gen-swift/Generated",
"Tests/PklSwiftTests/Fixtures",
"codegen/snippet-tests",
"doc",
]
[git]
attrs = 'enable'
ignore = 'enable'
[properties]
copyrightOwner = "Apple Inc. and the Pkl project authors"
[mapping.SWIFT_STYLE]
extensions = ["swift"]

View File

@ -0,0 +1,13 @@
Copyright ©{{ " " }}{%- if attrs.git_file_modified_year != attrs.git_file_created_year -%}{{ attrs.git_file_created_year }}-{{ attrs.git_file_modified_year }}{%- else -%}{{ attrs.git_file_created_year }}{%- endif -%}{{ " " }}{{ props["copyrightOwner"] }}. 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.

View File

@ -0,0 +1,11 @@
[SWIFT_STYLE]
firstLine = '//===----------------------------------------------------------------------===//'
endLine = "//===----------------------------------------------------------------------===//\n"
beforeEachLine = '// '
afterEachLine = ''
allowBlankLines = false
multipleLines = true
padLines = false
firstLineDetectionPattern = '//\s?==='
lastLineDetectionPattern = '//\s?==='
skipLinePattern = '// swift-tools-version'

Some files were not shown because too many files have changed in this diff Show More