diff --git a/.clusterfuzzlite/Dockerfile b/.clusterfuzzlite/Dockerfile
index 42026362f..3d01d2e62 100644
--- a/.clusterfuzzlite/Dockerfile
+++ b/.clusterfuzzlite/Dockerfile
@@ -1,4 +1,4 @@
-FROM gcr.io/oss-fuzz-base/base-builder@sha256:5e1404dc68c77c2a8fdefd8c50f21d069aee193fe3648a9e4fe1ef4d45e3f732
+FROM gcr.io/oss-fuzz-base/base-builder@sha256:6c61e467be42d10170ab0c4715d25805829e7c97aa60ce7b408687a02cd40c2d
RUN apt-get update && apt-get upgrade -y --no-install-recommends \
ninja-build \
diff --git a/.clusterfuzzlite/build.sh b/.clusterfuzzlite/build.sh
index 5cfed44fe..b185aec90 100644
--- a/.clusterfuzzlite/build.sh
+++ b/.clusterfuzzlite/build.sh
@@ -1,6 +1,6 @@
#!/bin/bash -eu
-cmake --preset Fuzzing
-cmake --build --preset Fuzzing
+cmake --preset fuzzing
+cmake --build --preset fuzzing
-cp build/Fuzzing/infra/syntax/fuzz/infra.syntax_json_fuzzer $OUT/infra-syntax_json_fuzzer
+cp build/fuzzing/infra/syntax/fuzz/infra.syntax_json_fuzzer $OUT/infra-syntax_json_fuzzer
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index df9f970f3..b91420f74 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -2,7 +2,7 @@
// This devcontainer has been set-up to run docker-from-docker scenarios as per
// https://github.com/microsoft/vscode-dev-containers/tree/main/containers/docker-from-docker
"name": "amp-devcontainer",
- "image": "ghcr.io/philips-software/amp-devcontainer:2.2.0",
+ "image": "ghcr.io/philips-software/amp-devcontainer:2.5.0",
"runArgs": ["--add-host=host.docker.internal:host-gateway"],
"remoteEnv": { "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" },
"mounts": [
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d6c8f95ff..8a8a9a1b7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -22,30 +22,31 @@ jobs:
name: Host Build & Test (ubuntu-latest)
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- uses: hendrikmuhs/ccache-action@6d1841ec156c39a52b1b23a810da917ab98da1f4 # v1.2.10
with:
key: ${{ github.job }}-ubuntu-latest
variant: sccache
+ - uses: seanmiddleditch/gha-setup-ninja@8b297075da4cd2a5f1fd21fe011b499edf06e9d2 # v4
- uses: lukka/run-cmake@c2b72aff009141774c5a5fabe74ea46c8c04d9c4 # v10.6
with:
- configurePreset: "ContinuousIntegration"
- buildPreset: "ContinuousIntegrationWithPackage"
- testPreset: "ContinuousIntegration"
+ configurePreset: "host"
+ buildPreset: "host-Debug-WithPackage"
+ testPreset: "host"
configurePresetAdditionalArgs: "['-DCMAKE_C_COMPILER_LAUNCHER=sccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=sccache']"
- uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: emil
- path: build/ContinuousIntegration/emil-*-Linux.tar.gz
+ path: build/host/emil-*-Linux.tar.gz
if-no-files-found: error
- name: Upload test logs
if: ${{ failure() }}
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: test-logs
- path: build/ContinuousIntegration/Testing/Temporary/
+ path: build/host/Testing/Temporary/
host_build_test:
name: Host Build & Test
runs-on: ${{ matrix.os }}
@@ -53,7 +54,7 @@ jobs:
matrix:
os: [macos-latest, windows-latest, windows-2019]
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- uses: hendrikmuhs/ccache-action@6d1841ec156c39a52b1b23a810da917ab98da1f4 # v1.2.10
@@ -62,16 +63,16 @@ jobs:
variant: sccache
- uses: lukka/run-cmake@c2b72aff009141774c5a5fabe74ea46c8c04d9c4 # v10.6
with:
- configurePreset: "ContinuousIntegration"
- buildPreset: "ContinuousIntegration"
- testPreset: "ContinuousIntegration"
+ configurePreset: "host-single-Debug"
+ buildPreset: "host-single-Debug"
+ testPreset: "host-single-Debug"
configurePresetAdditionalArgs: "['-DCMAKE_C_COMPILER_LAUNCHER=sccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=sccache']"
- name: Upload test logs
if: ${{ failure() }}
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: test-logs
- path: build/ContinuousIntegration/Testing/Temporary/
+ path: build/host/Testing/Temporary/
embedded_build:
name: Embedded Build
runs-on: ubuntu-latest
@@ -81,11 +82,11 @@ jobs:
gcc: ["7-2018-q2", "8-2019-q3", "9-2020-q2", "10.3-2021.10"]
configuration: ["RelWithDebInfo"]
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- name: Install GNU Arm Embedded Toolchain ${{ matrix.gcc }}
- uses: carlosperate/arm-none-eabi-gcc-action@6a221d7c85f5b36647d6e9b25e874abf187409d3 # v1.7.1
+ uses: carlosperate/arm-none-eabi-gcc-action@e9cd61b92edb079b14b2d0449b21f8a517121fe8 # v1.8.0
with:
release: ${{ matrix.gcc }}
- run: sudo apt-get update && sudo apt-get install ninja-build
@@ -99,8 +100,8 @@ jobs:
- run: mkdir install && mv emil-*/* install/
- uses: lukka/run-cmake@c2b72aff009141774c5a5fabe74ea46c8c04d9c4 # v10.6
with:
- configurePreset: "Embedded"
- buildPreset: "Embedded-${{ matrix.configuration }}"
+ configurePreset: "embedded"
+ buildPreset: "embedded-${{ matrix.configuration }}"
configurePresetAdditionalArgs: "['-DCMAKE_C_COMPILER_LAUNCHER=ccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=ccache']"
rtos:
name: Embedded Build - RTOS
@@ -110,11 +111,11 @@ jobs:
matrix:
rtos: ["FreeRTOS", "ThreadX"]
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- name: Install GNU Arm Embedded Toolchain "10.3-2021.10"
- uses: carlosperate/arm-none-eabi-gcc-action@6a221d7c85f5b36647d6e9b25e874abf187409d3 # v1.7.1
+ uses: carlosperate/arm-none-eabi-gcc-action@e9cd61b92edb079b14b2d0449b21f8a517121fe8 # v1.8.0
with:
release: "10.3-2021.10"
- run: sudo apt-get update && sudo apt-get install ninja-build
@@ -128,6 +129,6 @@ jobs:
- run: mkdir install && mv emil-*/* install/
- uses: lukka/run-cmake@c2b72aff009141774c5a5fabe74ea46c8c04d9c4 # v10.6
with:
- configurePreset: "Embedded-${{ matrix.rtos }}"
- buildPreset: "Embedded-${{ matrix.rtos }}-RelWithDebInfo"
+ configurePreset: "embedded-${{ matrix.rtos }}"
+ buildPreset: "embedded-${{ matrix.rtos }}-RelWithDebInfo"
configurePresetAdditionalArgs: "['-DCMAKE_C_COMPILER_LAUNCHER=ccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=ccache']"
diff --git a/.github/workflows/dependency-scanner.yml b/.github/workflows/dependency-scanner.yml
index 36efe6a3c..f6936d907 100644
--- a/.github/workflows/dependency-scanner.yml
+++ b/.github/workflows/dependency-scanner.yml
@@ -16,16 +16,16 @@ jobs:
contents: write
pull-requests: write
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: philips-forks/cmake-dependency-submission@72880580a7cafc16145d82268f1892c0ece3da2a # main
dependency-review:
runs-on: ubuntu-latest
- if: github.event_name == 'pull_request'
+ if: ${{ github.event_name == 'pull_request' }}
needs: [dependency-submission]
permissions:
pull-requests: write
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/dependency-review-action@6c5ccdad469c9f8a2996bfecaec55a631a347034 # v3.1.0
with:
comment-summary-in-pr: true
diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml
index 7da7a10ac..3ac1685c6 100644
--- a/.github/workflows/documentation.yml
+++ b/.github/workflows/documentation.yml
@@ -16,7 +16,7 @@ jobs:
if: ${{ github.ref == 'refs/heads/main' }}
steps:
- name: Checkout
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0
persist-credentials: false
@@ -44,7 +44,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0
persist-credentials: false
@@ -69,7 +69,7 @@ jobs:
name: Publish to GitHub Pages
steps:
- name: Checkout
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Retrieve Antora Site
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
with:
diff --git a/.github/workflows/linting-formatting.yml b/.github/workflows/linting-formatting.yml
index a68c358f9..7293c1151 100644
--- a/.github/workflows/linting-formatting.yml
+++ b/.github/workflows/linting-formatting.yml
@@ -21,7 +21,7 @@ jobs:
contents: read
pull-requests: write
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- uses: DoozyX/clang-format-lint-action@a83a8fb7d371f66da7dd1c4f33a193023899494b # v0.16
@@ -42,21 +42,21 @@ jobs:
pull-requests: write
security-events: write
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0
persist-credentials: false
- - uses: oxsecurity/megalinter@fda6ac3a38be0e969820709ac16e442464e5a035 # v7.3.0
+ - uses: oxsecurity/megalinter@b48455a119cc28045eee8f1e9d0a542a85e71f4f # v7.5.0
env:
APPLY_FIXES: all
VALIDATE_ALL_CODEBASE: true
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- - uses: github/codeql-action/upload-sarif@701f152f28d4350ad289a5e31435e9ab6169a7ca # v2.21.6
- if: ${{ success() }} || ${{ failure() }}
+ - uses: github/codeql-action/upload-sarif@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
+ if: ${{ success() || failure() }}
with:
sarif_file: megalinter-reports/megalinter-report.sarif
- uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
- if: ${{ success() }} || ${{ failure() }}
+ if: ${{ success() || failure() }}
with:
name: linter
path: |
diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml
index 0778da3c1..78a43de67 100644
--- a/.github/workflows/release-please.yml
+++ b/.github/workflows/release-please.yml
@@ -26,7 +26,7 @@ jobs:
app_id: ${{ secrets.FOREST_RELEASER_APP_ID }}
app_base64_private_key: ${{ secrets.FOREST_RELEASER_APP_PRIVATE_KEY_BASE64 }}
auth_type: installation
- - uses: google-github-actions/release-please-action@ca6063f4ed81b55db15b8c42d1b6f7925866342d # v3.7.11
+ - uses: google-github-actions/release-please-action@4c5670f886fe259db4d11222f7dff41c1382304d # v3.7.12
id: release
with:
command: manifest
@@ -43,7 +43,7 @@ jobs:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- uses: hendrikmuhs/ccache-action@6d1841ec156c39a52b1b23a810da917ab98da1f4 # v1.2.10
@@ -52,8 +52,8 @@ jobs:
variant: sccache
- uses: lukka/run-cmake@c2b72aff009141774c5a5fabe74ea46c8c04d9c4 # v10.6
with:
- configurePreset: "Package"
- buildPreset: "Package"
+ configurePreset: "host-single-MinSizeRel"
+ buildPreset: "release-package"
configurePresetAdditionalArgs: "['-DCMAKE_C_COMPILER_LAUNCHER=sccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=sccache']"
- run: gh release upload ${{ needs.release_please.outputs.tag_name }} build/**/emil-*.zip --clobber
shell: bash
diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml
index a47c33359..c6e0973d5 100644
--- a/.github/workflows/security.yml
+++ b/.github/workflows/security.yml
@@ -21,16 +21,16 @@ jobs:
actions: read
contents: read
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- name: Analysis
- uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0
+ uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
with:
results_file: scorecards.sarif
results_format: sarif
repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
publish_results: true
- - uses: github/codeql-action/upload-sarif@701f152f28d4350ad289a5e31435e9ab6169a7ca # v2.21.6
+ - uses: github/codeql-action/upload-sarif@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
with:
sarif_file: scorecards.sarif
diff --git a/.github/workflows/social-interaction.yml b/.github/workflows/social-interaction.yml
index f03c75c26..ab77aaa8c 100644
--- a/.github/workflows/social-interaction.yml
+++ b/.github/workflows/social-interaction.yml
@@ -14,7 +14,7 @@ jobs:
pull-requests: write
if: ${{ github.actor != 'dependabot[bot]' }}
steps:
- - uses: actions/first-interaction@1d8459ca65b335265f1285568221e229d45a995e
+ - uses: actions/first-interaction@1dbfe1ba5525b8257e1f259b09745bee346d62d8
continue-on-error: true
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
index 6853e071e..5c458a844 100644
--- a/.github/workflows/static-analysis.yml
+++ b/.github/workflows/static-analysis.yml
@@ -18,47 +18,42 @@ jobs:
sonar:
name: SonarCloud
runs-on: ubuntu-latest
+ container: ghcr.io/philips-software/amp-devcontainer:2.5.0
env:
- SONAR_SCANNER_VERSION: 4.7.0.2747
+ SONAR_SCANNER_VERSION: 5.0.1.3006
SONAR_SERVER_URL: "https://sonarcloud.io"
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0 # Disable shallow clone to enable blame information
persist-credentials: false
- - run: sudo apt-get update && sudo apt-get install --no-install-recommends jq ninja-build xsltproc
- - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0
- - uses: BSFishy/pip-action@8f2d471d809dc20b6ada98c91910b6ae6243f318
- with:
- packages: gcovr==5.2
- - name: Install Sonar Scanner & Mull
+ - name: Install Sonar Scanner
run: |
wget -qN "https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${{ env.SONAR_SCANNER_VERSION }}-linux.zip"
unzip -qqo "sonar-scanner-cli-${{ env.SONAR_SCANNER_VERSION }}-linux.zip"
echo "${PWD}/sonar-scanner-${{ env.SONAR_SCANNER_VERSION }}-linux/bin" >> "$GITHUB_PATH"
- wget -qN https://github.com/mull-project/mull/releases/download/0.18.0/Mull-12-0.18.0-LLVM-12.0-ubuntu-20.04.deb
- sudo dpkg -i Mull-12-0.18.0-LLVM-12.0-ubuntu-20.04.deb
- uses: hendrikmuhs/ccache-action@6d1841ec156c39a52b1b23a810da917ab98da1f4 # v1.2.10
with:
key: ${{ github.job }}
max-size: 2G
- name: Build & Collect Coverage
run: |
- cmake --preset Coverage -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
- cmake --build --preset Coverage
- GTEST_OUTPUT="xml:${PWD}/testresults/" ctest --preset Coverage
- gcovr --sonarqube=coverage.xml --exclude-lines-by-pattern '.*assert\(.*\);|.*really_assert\(.*\);|.*std::abort();' --exclude-unreachable-branches --exclude-throw-branches -j 2 --exclude=.*/generated/.* --exclude=.*/examples/.* --exclude=.*/external/.* --exclude=.*/lwip/.* --exclude=.*/tracing/.* --exclude=.*/test/.*
- - name: Build & Run Mutation Tests
- run: |
- cmake --preset MutationTesting -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
- cmake --build --preset MutationTesting
- ctest --preset MutationTesting
+ cmake --preset coverage -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
+ cmake --build --preset coverage
+ GTEST_OUTPUT="xml:${PWD}/testresults/" ctest --preset coverage
+ gcovr --sonarqube=coverage.xml --exclude-lines-by-pattern '.*assert\(.*\);|.*really_assert\(.*\);|.*std::abort();' --exclude-unreachable-branches --exclude-throw-branches -j "$(nproc)" --exclude=.*/generated/.* --exclude=.*/examples/.* --exclude=.*/external/.* --exclude=.*/lwip/.* --exclude=.*/tracing/.* --exclude=.*/test/.*
+ - uses: lukka/run-cmake@c2b72aff009141774c5a5fabe74ea46c8c04d9c4 # v10.6
+ with:
+ configurePreset: "mutation-testing"
+ buildPreset: "mutation-testing"
+ testPreset: "mutation-testing"
+ configurePresetAdditionalArgs: "['-DCMAKE_C_COMPILER_LAUNCHER=ccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=ccache']"
- name: Convert Results
run: |
{ echo ''; xsltproc .github/formatters/gtest-to-generic-execution.xslt testresults/*.xml; echo ''; } | tee execution.xml > /dev/null
jq -s 'reduce .[] as $item ({}; . * $item)' reports/mull/*.json > reports/mull/merged-mutation.json
jq --arg workspace "$GITHUB_WORKSPACE" -f .github/formatters/mutation-report-to-generic-issue.jq reports/mull/merged-mutation.json > mutation-sonar.json
- cp build/Coverage/compile_commands.json compile_commands.json
+ cp build/coverage/compile_commands.json compile_commands.json
- name: Run Analysis
# skip the analysis step for dependabot PRs since dependabot does not have access to secrets
if: ${{ github.actor != 'dependabot[bot]' }}
@@ -70,20 +65,22 @@ jobs:
codeql:
name: CodeQL
runs-on: ubuntu-latest
+ container: ghcr.io/philips-software/amp-devcontainer:2.5.0
permissions:
security-events: write
steps:
- - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- - run: sudo apt-get update && sudo apt-get install ninja-build
- uses: hendrikmuhs/ccache-action@6d1841ec156c39a52b1b23a810da917ab98da1f4 # v1.2.10
with:
key: ${{ github.job }}
- - uses: github/codeql-action/init@701f152f28d4350ad289a5e31435e9ab6169a7ca # v2.21.6
+ - uses: github/codeql-action/init@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
with:
languages: cpp
- - run: |
- cmake --preset ContinuousIntegration -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
- cmake --build --preset ContinuousIntegration
- - uses: github/codeql-action/analyze@701f152f28d4350ad289a5e31435e9ab6169a7ca # v2.21.6
+ - uses: lukka/run-cmake@c2b72aff009141774c5a5fabe74ea46c8c04d9c4 # v10.6
+ with:
+ configurePreset: "host"
+ buildPreset: "host-Debug"
+ configurePresetAdditionalArgs: "['-DCMAKE_C_COMPILER_LAUNCHER=ccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=ccache']"
+ - uses: github/codeql-action/analyze@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
diff --git a/.github/workflows/validate-pr.yml b/.github/workflows/validate-pr.yml
index 209866b5d..d85172744 100644
--- a/.github/workflows/validate-pr.yml
+++ b/.github/workflows/validate-pr.yml
@@ -11,7 +11,7 @@ jobs:
conventional_commit:
runs-on: ubuntu-latest
steps:
- - uses: Namchee/conventional-pr@5d1221ff603c491a4abb1e614a0f4ded41d4b397 # v0.14.0
+ - uses: Namchee/conventional-pr@93f510707dd4ef011c5e8fe7c94c93c59fc86d4c # v0.15.1
with:
access_token: ${{ secrets.GITHUB_TOKEN }}
body: false
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 34a1aacd3..e80f35eb0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -88,7 +88,7 @@ option(EMIL_BUILD_TESTS "Enable building the tests" ${EMIL_DEFAULTOPT})
option(EMIL_BUILD_EXAMPLES "Enable building the examples" ${EMIL_DEFAULTOPT})
option(EMIL_ENABLE_FUZZING "Enable building the fuzzing targets" Off)
option(EMIL_ENABLE_DOCKER_TOOLS "Enable shift-left tools (e.g. linters, formatters) that are run using Docker" On)
-option(EMIL_GENERATE_PACKAGE_CONFIG "Enable generation of package configuration and install files" ${EMIL_HOST_BUILD})
+option(EMIL_BUILD_ECHO_COMPILERS "Build and install the Protobuf ECHO compilers" ${EMIL_DEFAULTOPT})
# Enable or disable optional features.
option(EMIL_INCLUDE_MBEDTLS "Include MbedTLS as part of EmIL" On)
@@ -148,18 +148,12 @@ if (EMIL_STANDALONE)
emil_folderize_all_targets()
endif()
-if (EMIL_GENERATE_PACKAGE_CONFIG)
+if (EMIL_BUILD_ECHO_COMPILERS)
function(generate_export_targets name)
- # Generate and install export file
install(EXPORT emil${name}Targets
FILE emil${name}Targets.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/emil
)
-
- # Generate the export targets for the build tree
- export(EXPORT emil${name}Targets
- FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/emil${name}Targets.cmake"
- )
endfunction()
foreach(target IN ITEMS Protobuf)
@@ -184,20 +178,20 @@ if (EMIL_GENERATE_PACKAGE_CONFIG)
"${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
-
- set(CPACK_GENERATOR "ZIP;TGZ")
- set(CPACK_SOURCE_IGNORE_FILES ".vs/;.git/;build/")
- set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
- set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
- set(CPACK_PACKAGE_VENDOR "Koninklijke Philips N.V")
- set(CPACK_PACKAGE_DESCRIPTION "${PROJECT_DESCRIPTION}")
- set(CPACK_DEBIAN_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")
- set(CPACK_RPM_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")
- set(CPACK_PACKAGE_HOMEPAGE_URL "${PROJECT_HOMEPAGE_URL}")
- set(CPACK_PACKAGE_MAINTAINER "${CPACK_PACKAGE_VENDOR}")
- set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_PACKAGE_VENDOR}")
- set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.md")
- set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
-
- include(CPack)
endif()
+
+set(CPACK_GENERATOR "ZIP;TGZ")
+set(CPACK_SOURCE_IGNORE_FILES ".vs/;.git/;build/")
+set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
+set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
+set(CPACK_PACKAGE_VENDOR "Koninklijke Philips N.V")
+set(CPACK_PACKAGE_DESCRIPTION "${PROJECT_DESCRIPTION}")
+set(CPACK_DEBIAN_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")
+set(CPACK_RPM_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")
+set(CPACK_PACKAGE_HOMEPAGE_URL "${PROJECT_HOMEPAGE_URL}")
+set(CPACK_PACKAGE_MAINTAINER "${CPACK_PACKAGE_VENDOR}")
+set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_PACKAGE_VENDOR}")
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.md")
+set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
+
+include(CPack)
diff --git a/CMakePresets.json b/CMakePresets.json
index 99cdfaf78..1442446cf 100644
--- a/CMakePresets.json
+++ b/CMakePresets.json
@@ -12,51 +12,57 @@
}
},
{
- "name": "ContinuousIntegration",
- "displayName": "Configuration for Continuous Integration",
+ "name": "host",
+ "displayName": "Configuration for Host Tooling and Tests",
+ "inherits": "defaults",
+ "cacheVariables": {
+ "CMAKE_CONFIGURATION_TYPES": "Debug;Release;RelWithDebInfo;MinSizeRel"
+ },
+ "generator": "Ninja Multi-Config"
+ },
+ {
+ "name": "host-single-Debug",
+ "displayName": "Configuration for Host Tooling and Tests, Single Config Generator, Debug",
"inherits": "defaults",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
- "EMIL_ENABLE_DOCKER_TOOLS": "Off",
- "EMIL_BUILD_EXAMPLES": "On"
+ "EMIL_ENABLE_DOCKER_TOOLS": "Off"
}
},
{
- "name": "Package",
- "displayName": "Configuration for CPack package generation",
+ "name": "host-single-MinSizeRel",
+ "displayName": "Configuration for Host Tooling and Tests, Single Config Generator, MinSizeRel",
"inherits": "defaults",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "MinSizeRel",
- "EMIL_ENABLE_DOCKER_TOOLS": "Off",
- "EMIL_BUILD_TESTS": "Off",
- "EMIL_BUILD_EXAMPLES": "Off"
+ "EMIL_ENABLE_DOCKER_TOOLS": "Off"
}
},
{
- "name": "Coverage",
+ "name": "coverage",
"displayName": "Configuration for Code Coverage",
- "inherits": "ContinuousIntegration",
+ "inherits": "host",
"cacheVariables": {
"EMIL_ENABLE_COVERAGE": "On"
},
"generator": "Ninja"
},
{
- "name": "MutationTesting",
+ "name": "mutation-testing",
"displayName": "Configuration for Mutation Testing",
- "inherits": "ContinuousIntegration",
+ "inherits": "host",
"cacheVariables": {
- "CMAKE_C_COMPILER": "clang-12",
- "CMAKE_CXX_COMPILER": "clang++-12",
+ "CMAKE_C_COMPILER": "clang",
+ "CMAKE_CXX_COMPILER": "clang++",
"EMIL_ENABLE_MUTATION_TESTING": "On",
- "EMIL_MUTATION_TESTING_RUNNER_ARGUMENTS": "--reporters;Elements;--report-dir;${sourceDir}/reports/mull"
+ "EMIL_MUTATION_TESTING_RUNNER_ARGUMENTS": "--allow-surviving;--reporters;Elements;--report-dir;${sourceDir}/reports/mull"
},
"generator": "Ninja"
},
{
- "name": "Fuzzing",
+ "name": "fuzzing",
"displayName": "Configuration for Fuzzing",
- "inherits": "ContinuousIntegration",
+ "inherits": "host",
"cacheVariables": {
"CMAKE_C_COMPILER": "clang",
"CMAKE_CXX_COMPILER": "clang++",
@@ -67,18 +73,7 @@
"generator": "Ninja"
},
{
- "name": "Host",
- "displayName": "Configuration for Host Tooling",
- "inherits": "defaults",
- "cacheVariables": {
- "CMAKE_CONFIGURATION_TYPES": "Debug;Release;RelWithDebInfo;MinSizeRel",
- "EMIL_BUILD_TESTS": "Off",
- "EMIL_BUILD_EXAMPLES": "Off"
- },
- "generator": "Ninja Multi-Config"
- },
- {
- "name": "HostClangMsvc",
+ "name": "host-ClangMsvc",
"displayName": "Configuration for Host Tooling using clang-cl to target Windows",
"inherits": "defaults",
"toolchainFile": "${sourceDir}/cmake/toolchain-clang-x86_64-pc-windows-msvc.cmake",
@@ -91,8 +86,8 @@
"generator": "Ninja Multi-Config"
},
{
- "name": "Embedded",
- "displayName": "Configuration for Embedded",
+ "name": "embedded",
+ "displayName": "Configuration for embedded",
"inherits": "defaults",
"toolchainFile": "${sourceDir}/cmake/toolchain-arm-gcc-m4-fpv4-sp-d16.cmake",
"cacheVariables": {
@@ -102,18 +97,18 @@
"generator": "Ninja Multi-Config"
},
{
- "name": "Embedded-FreeRTOS",
- "displayName": "Configuration for Embedded with FreeRTOS",
- "inherits": "Embedded",
+ "name": "embedded-FreeRTOS",
+ "displayName": "Configuration for embedded with FreeRTOS",
+ "inherits": "embedded",
"cacheVariables": {
"EMIL_INCLUDE_FREERTOS": "On",
"FREERTOS_CONFIG_FILE_DIRECTORY": "${sourceDir}/examples/threading/config"
}
},
{
- "name": "Embedded-ThreadX",
- "displayName": "Configuration for Embedded with ThreadX",
- "inherits": "Embedded",
+ "name": "embedded-ThreadX",
+ "displayName": "Configuration for embedded with ThreadX",
+ "inherits": "embedded",
"cacheVariables": {
"EMIL_INCLUDE_THREADX": "On"
}
@@ -121,96 +116,96 @@
],
"buildPresets": [
{
- "name": "ContinuousIntegration",
+ "name": "host-Debug",
"configuration": "Debug",
- "configurePreset": "ContinuousIntegration"
+ "configurePreset": "host"
},
{
- "name": "ContinuousIntegrationWithPackage",
+ "name": "host-Debug-WithPackage",
"configuration": "Debug",
- "configurePreset": "ContinuousIntegration",
+ "configurePreset": "host",
"targets": ["all", "package"]
},
{
- "name": "Package",
- "configuration": "MinSizeRel",
- "configurePreset": "Package",
- "targets": ["package"]
+ "name": "host-Release",
+ "configuration": "Release",
+ "configurePreset": "host"
},
{
- "name": "Coverage",
- "configuration": "Debug",
- "configurePreset": "Coverage"
+ "name": "host-RelWithDebInfo",
+ "configuration": "RelWithDebInfo",
+ "configurePreset": "host"
},
{
- "name": "MutationTesting",
- "configuration": "Debug",
- "configurePreset": "MutationTesting"
+ "name": "host-MinSizeRel",
+ "configuration": "MinSizeRel",
+ "configurePreset": "host"
},
{
- "name": "Fuzzing",
+ "name": "host-single-Debug",
"configuration": "Debug",
- "configurePreset": "Fuzzing"
+ "configurePreset": "host-single-Debug"
},
{
- "name": "Host-Debug",
- "configuration": "Debug",
- "configurePreset": "Host"
+ "name": "release-package",
+ "configuration": "MinSizeRel",
+ "configurePreset": "host-single-MinSizeRel",
+ "targets": ["package"]
},
{
- "name": "Host-Release",
- "configuration": "Release",
- "configurePreset": "Host"
+ "name": "coverage",
+ "configuration": "Debug",
+ "configurePreset": "coverage"
},
{
- "name": "Host-RelWithDebInfo",
- "configuration": "RelWithDebInfo",
- "configurePreset": "Host"
+ "name": "mutation-testing",
+ "configuration": "Debug",
+ "configurePreset": "mutation-testing"
},
{
- "name": "Host-MinSizeRel",
- "configuration": "MinSizeRel",
- "configurePreset": "Host"
+ "name": "fuzzing",
+ "configuration": "Debug",
+ "configurePreset": "fuzzing"
},
{
- "name": "HostClangMsvc-Debug",
+ "name": "host-ClangMsvc-Debug",
"configuration": "Debug",
- "configurePreset": "HostClangMsvc"
+ "configurePreset": "host-ClangMsvc"
},
{
- "name": "HostClangMsvc-RelWithDebInfo",
+ "name": "host-ClangMsvc-RelWithDebInfo",
"configuration": "RelWithDebInfo",
- "configurePreset": "HostClangMsvc"
+ "configurePreset": "host-ClangMsvc"
},
{
- "name": "Embedded-Debug",
+ "name": "embedded-Debug",
"configuration": "Debug",
- "configurePreset": "Embedded"
+ "configurePreset": "embedded"
},
{
- "name": "Embedded-Release",
+ "name": "embedded-Release",
"configuration": "Release",
- "configurePreset": "Embedded"
+ "configurePreset": "embedded"
},
{
- "name": "Embedded-RelWithDebInfo",
+ "name": "embedded-RelWithDebInfo",
"configuration": "RelWithDebInfo",
- "configurePreset": "Embedded"
+ "configurePreset": "embedded"
},
{
- "name": "Embedded-MinSizeRel",
+ "name": "embedded-MinSizeRel",
"configuration": "MinSizeRel",
- "configurePreset": "Embedded"
+ "configurePreset": "embedded"
},
{
- "name": "Embedded-FreeRTOS-RelWithDebInfo",
+ "name": "embedded-FreeRTOS-RelWithDebInfo",
"configuration": "RelWithDebInfo",
- "configurePreset": "Embedded-FreeRTOS"
+ "configurePreset": "embedded-FreeRTOS"
},
{
- "name": "Embedded-ThreadX-RelWithDebInfo",
+ "name": "embedded-ThreadX-RelWithDebInfo",
"configuration": "RelWithDebInfo",
- "configurePreset": "Embedded-ThreadX"
+ "configurePreset": "embedded-ThreadX"
}
],
"testPresets": [
@@ -226,20 +221,26 @@
}
},
{
- "name": "ContinuousIntegration",
- "configurePreset": "ContinuousIntegration",
+ "name": "host",
+ "configurePreset": "host",
+ "configuration": "Debug",
+ "inherits": "defaults"
+ },
+ {
+ "name": "host-single-Debug",
+ "configurePreset": "host-single-Debug",
"configuration": "Debug",
"inherits": "defaults"
},
{
- "name": "Coverage",
- "configurePreset": "Coverage",
+ "name": "coverage",
+ "configurePreset": "coverage",
"configuration": "Debug",
"inherits": "defaults"
},
{
- "name": "MutationTesting",
- "configurePreset": "MutationTesting",
+ "name": "mutation-testing",
+ "configurePreset": "mutation-testing",
"configuration": "Debug",
"inherits": "defaults",
"output": {
diff --git a/cmake/emil_build_for.cmake b/cmake/emil_build_for.cmake
index 0aa6e90da..282ce81cb 100644
--- a/cmake/emil_build_for.cmake
+++ b/cmake/emil_build_for.cmake
@@ -88,3 +88,10 @@ function(emil_build_for target)
endif()
endfunction()
+
+function(emil_install target)
+ get_target_property(exclude ${target} EXCLUDE_FROM_ALL)
+ if (NOT ${exclude})
+ install(TARGETS ${target} ${ARGN})
+ endif()
+endfunction()
diff --git a/cmake/emil_test_helpers.cmake b/cmake/emil_test_helpers.cmake
index 5be8b44f7..3336f6ee7 100644
--- a/cmake/emil_test_helpers.cmake
+++ b/cmake/emil_test_helpers.cmake
@@ -2,12 +2,10 @@ option(EMIL_ENABLE_COVERAGE "Enable compiler flags for code coverage measurement
option(EMIL_ENABLE_MUTATION_TESTING "Enable compiler flags for mutation testing" Off)
set(EMIL_MUTATION_TESTING_RUNNER_ARGUMENTS "" CACHE STRING "Additional arguments for the mutation testing runner")
-function(emil_enable_testing)
- include(GoogleTest)
-
+function(emil_fetch_googletest)
FetchContent_Declare(
googletest
- GIT_REPOSITORY https://github.com/google/googletest.git
+ GIT_REPOSITORY https://github.com/google/googletest
GIT_TAG release-1.12.1
)
@@ -18,6 +16,12 @@ function(emil_enable_testing)
set_target_properties(gtest gtest_main gmock gmock_main PROPERTIES FOLDER External/GoogleTest)
mark_as_advanced(BUILD_GMOCK BUILD_GTEST BUILD_SHARED_LIBS gmock_build_tests gtest_build_samples test_build_tests gtest_disable_pthreads gtest_force_shared_crt gtest_hide_internal_symbols)
+endfunction()
+
+function(emil_enable_testing)
+ include(GoogleTest)
+
+ emil_fetch_googletest()
if (EMIL_ENABLE_COVERAGE)
add_compile_options(
@@ -34,19 +38,10 @@ function(emil_enable_testing)
if (EMIL_ENABLE_MUTATION_TESTING)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE CLANG_VERSION)
-
- if(CLANG_VERSION VERSION_GREATER 15.0 OR CLANG_VERSION VERSION_EQUAL 15.0)
- add_compile_options(
- -g -O0 -grecord-command-line -fprofile-instr-generate -fcoverage-mapping
- -fexperimental-new-pass-manager -fpass-plugin=/usr/lib/mull-ir-frontend
- )
- else()
- add_compile_options(
- -g -O0 -grecord-command-line -fprofile-instr-generate -fcoverage-mapping
- -fexperimental-new-pass-manager -fpass-plugin=/usr/lib/mull-ir-frontend-12
- )
- endif()
+ add_compile_options(
+ -g -O0 -grecord-command-line -fprofile-instr-generate -fcoverage-mapping
+ -fexperimental-new-pass-manager -fpass-plugin=/usr/lib/mull-ir-frontend
+ )
add_link_options(-fprofile-instr-generate)
else()
@@ -68,13 +63,7 @@ function(emil_add_test target)
get_target_property(exclude ${target} EXCLUDE_FROM_ALL)
if (NOT ${exclude})
if (EMIL_ENABLE_MUTATION_TESTING)
- execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE CLANG_VERSION)
-
- if(CLANG_VERSION VERSION_GREATER 15.0 OR CLANG_VERSION VERSION_EQUAL 15.0)
- add_test(NAME ${target} COMMAND mull-runner ${EMIL_MUTATION_TESTING_RUNNER_ARGUMENTS} $)
- else()
- add_test(NAME ${target} COMMAND mull-runner-12 ${EMIL_MUTATION_TESTING_RUNNER_ARGUMENTS} $)
- endif()
+ add_test(NAME ${target} COMMAND mull-runner ${EMIL_MUTATION_TESTING_RUNNER_ARGUMENTS} $)
else()
add_test(NAME ${target} COMMAND ${target})
endif()
diff --git a/external/crypto/mbedtls/CMakeLists.txt b/external/crypto/mbedtls/CMakeLists.txt
index db0eb2144..e44c96cd6 100644
--- a/external/crypto/mbedtls/CMakeLists.txt
+++ b/external/crypto/mbedtls/CMakeLists.txt
@@ -11,12 +11,36 @@ set(ENABLE_TESTING Off CACHE INTERNAL "")
set(ENABLE_PROGRAMS Off CACHE INTERNAL "")
set(GEN_FILES Off CACHE INTERNAL "")
+# mbedtls uses CMAKE_C_COMPILER_ID to determine the type of compiler used.
+# When compiling with clang-cl, mbedtls thinks the clang compiler
+# is used, and sets flags according to what clang expects as arguments.
+# However, clang-cl expects MSVC like arguments. Therefore we have to trick mbedtls
+# in to thinking MSVC is being used as a compiler.
+# After making mbedtls available the original COMPILER_ID will be restored
+set(ORIGINAL_C_COMPILER_ID ${CMAKE_C_COMPILER_ID})
+set(ORIGINAL_CXX_COMPILER_ID ${CMAKE_CXX_COMPILER_ID})
+
+if (CMAKE_C_SIMULATE_ID)
+ set(CMAKE_C_COMPILER_ID ${CMAKE_C_SIMULATE_ID})
+endif()
+
+if (CMAKE_CXX_SIMULATE_ID)
+ set(CMAKE_CXX_COMPILER_ID ${CMAKE_CXX_SIMULATE_ID})
+endif()
+
FetchContent_MakeAvailable(mbedtls)
+set(CMAKE_C_COMPILER_ID ${ORIGINAL_C_COMPILER_ID})
+set(CMAKE_CXX_COMPILER_ID ${ORIGINAL_CXX_COMPILER_ID})
+
function(add_mbedtls_target_properties)
foreach(target ${ARGN})
target_compile_options(${target} PUBLIC
-DMBEDTLS_CONFIG_FILE="mbedtls/mbedtls_emil_config.h"
+ # see https://github.com/Mbed-TLS/mbedtls/pull/6966
+ # mbedtls sets the -Wdocumentation flag, which is throwing warnings
+ # since clang-15
+ $<$:-Wno-documentation>
)
target_include_directories(${target} PUBLIC
diff --git a/hal/interfaces/CMakeLists.txt b/hal/interfaces/CMakeLists.txt
index f163c562f..0d94b4dcd 100644
--- a/hal/interfaces/CMakeLists.txt
+++ b/hal/interfaces/CMakeLists.txt
@@ -18,7 +18,6 @@ target_sources(hal.interfaces PRIVATE
Can.cpp
Can.hpp
CommunicationConfigurator.hpp
- Dac.hpp
DigitalToAnalogPin.hpp
Ethernet.hpp
Flash.cpp
diff --git a/hal/interfaces/Dac.hpp b/hal/interfaces/Dac.hpp
deleted file mode 100644
index 930247590..000000000
--- a/hal/interfaces/Dac.hpp
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef HAL_DAC_HPP
-#define HAL_DAC_HPP
-
-#include "infra/util/Unit.hpp"
-
-namespace hal
-{
- template
- class Dac
- {
- protected:
- Dac() = default;
-
- Dac(const Dac&) = delete;
- Dac& operator=(const Dac&) = delete;
- ~Dac() = default;
-
- public:
- virtual void SetOutput(infra::Quantity value) = 0;
- };
-
- class DacImplBase
- {
- protected:
- ~DacImplBase() = default;
-
- public:
- virtual void SetOutput(uint16_t value) = 0;
- };
-
- template
- class DacConverter
- : public Dac
- , public Impl
- {
- public:
- template
- DacConverter(Args&&... args);
-
- void SetOutput(infra::Quantity value);
- };
-
- //// Implementation ////
-
- template
- template
- DacConverter::DacConverter(Args&&... args)
- : Impl(std::forward(args)...)
- {}
-
- template
- void DacConverter::SetOutput(infra::Quantity value)
- {
- infra::Quantity convertedValue(value * infra::Quantity(1));
- Impl::SetOutput(convertedValue.Value());
- }
-}
-
-#endif
diff --git a/infra/stream/BufferingStreamReader.cpp b/infra/stream/BufferingStreamReader.cpp
new file mode 100644
index 000000000..a2c2289ce
--- /dev/null
+++ b/infra/stream/BufferingStreamReader.cpp
@@ -0,0 +1,107 @@
+#include "infra/stream/BufferingStreamReader.hpp"
+
+namespace infra
+{
+ BufferingStreamReader::BufferingStreamReader(infra::BoundedDeque& buffer, infra::StreamReaderWithRewinding& input)
+ : buffer(buffer)
+ , input(input)
+ {}
+
+ BufferingStreamReader::~BufferingStreamReader()
+ {
+ StoreRemainder();
+ }
+
+ void BufferingStreamReader::Extract(infra::ByteRange range, infra::StreamErrorPolicy& errorPolicy)
+ {
+ if (index != buffer.size())
+ {
+ Read(infra::Head(buffer.contiguous_range(buffer.begin() + index), range.size()), range);
+ // Perhaps the deque just wrapped around, try once more
+ Read(infra::Head(buffer.contiguous_range(buffer.begin() + index), range.size()), range);
+ }
+
+ if (!range.empty())
+ Read(input.ExtractContiguousRange(range.size()), range);
+
+ errorPolicy.ReportResult(range.empty());
+ }
+
+ uint8_t BufferingStreamReader::Peek(infra::StreamErrorPolicy& errorPolicy)
+ {
+ auto range = PeekContiguousRange(0);
+
+ errorPolicy.ReportResult(!range.empty());
+
+ if (range.empty())
+ return 0;
+ else
+ return range.front();
+ }
+
+ infra::ConstByteRange BufferingStreamReader::ExtractContiguousRange(std::size_t max)
+ {
+ if (index < buffer.size())
+ {
+ auto from = infra::Head(buffer.contiguous_range(buffer.begin() + index), max);
+ index += from.size();
+ return from;
+ }
+
+ return input.ExtractContiguousRange(max);
+ }
+
+ infra::ConstByteRange BufferingStreamReader::PeekContiguousRange(std::size_t start)
+ {
+ if (index + start < buffer.size())
+ return buffer.contiguous_range(buffer.begin() + index + start);
+
+ return input.PeekContiguousRange(index + start - buffer.size());
+ }
+
+ bool BufferingStreamReader::Empty() const
+ {
+ return Available() == 0;
+ }
+
+ std::size_t BufferingStreamReader::Available() const
+ {
+ return buffer.size() + input.Available();
+ }
+
+ std::size_t BufferingStreamReader::ConstructSaveMarker() const
+ {
+ return index;
+ }
+
+ void BufferingStreamReader::Rewind(std::size_t marker)
+ {
+ if (index > buffer.size())
+ {
+ auto rewindAmount = std::min(index - marker, index - buffer.size());
+ input.Rewind(input.ConstructSaveMarker() - rewindAmount);
+ index -= rewindAmount;
+ }
+
+ if (marker < buffer.size())
+ index = marker;
+ }
+
+ void BufferingStreamReader::Read(infra::ConstByteRange from, infra::ByteRange& to)
+ {
+ infra::Copy(from, infra::Head(to, from.size()));
+ to.pop_front(from.size());
+ index += from.size();
+ }
+
+ void BufferingStreamReader::StoreRemainder()
+ {
+ std::size_t bufferDecrease = std::min(buffer.size(), index);
+ buffer.erase(buffer.begin(), buffer.begin() + bufferDecrease);
+ while (!input.Empty())
+ {
+ auto range = input.ExtractContiguousRange(std::numeric_limits::max());
+ buffer.insert(buffer.end(), range.begin(), range.end());
+ }
+ }
+}
diff --git a/infra/stream/BufferingStreamReader.hpp b/infra/stream/BufferingStreamReader.hpp
new file mode 100644
index 000000000..3df25964f
--- /dev/null
+++ b/infra/stream/BufferingStreamReader.hpp
@@ -0,0 +1,39 @@
+#ifndef INFRA_BUFFERING_STREAM_READER_HPP
+#define INFRA_BUFFERING_STREAM_READER_HPP
+
+#include "infra/stream/InputStream.hpp"
+#include "infra/util/BoundedDeque.hpp"
+
+namespace infra
+{
+ // Usage: Everything that is not read from the inputData is stored into the buffer upon destruction of the BufferingStreamReader
+ // Any data already present in the buffer is read first from the reader
+ class BufferingStreamReader
+ : public infra::StreamReaderWithRewinding
+ {
+ public:
+ BufferingStreamReader(infra::BoundedDeque& buffer, infra::StreamReaderWithRewinding& input);
+ ~BufferingStreamReader() override;
+
+ // Implementation of StreamReaderWithRewinding
+ void Extract(infra::ByteRange range, infra::StreamErrorPolicy& errorPolicy) override;
+ uint8_t Peek(infra::StreamErrorPolicy& errorPolicy) override;
+ infra::ConstByteRange ExtractContiguousRange(std::size_t max) override;
+ infra::ConstByteRange PeekContiguousRange(std::size_t start) override;
+ bool Empty() const override;
+ std::size_t Available() const override;
+ std::size_t ConstructSaveMarker() const override;
+ void Rewind(std::size_t marker) override;
+
+ private:
+ void Read(infra::ConstByteRange range, infra::ByteRange& to);
+ void StoreRemainder();
+
+ private:
+ infra::BoundedDeque& buffer;
+ infra::StreamReaderWithRewinding& input;
+ std::size_t index = 0;
+ };
+}
+
+#endif
diff --git a/infra/stream/BufferingStreamWriter.cpp b/infra/stream/BufferingStreamWriter.cpp
new file mode 100644
index 000000000..c66445491
--- /dev/null
+++ b/infra/stream/BufferingStreamWriter.cpp
@@ -0,0 +1,65 @@
+#include "infra/stream/BufferingStreamWriter.hpp"
+
+namespace infra
+{
+ BufferingStreamWriter::BufferingStreamWriter(infra::BoundedDeque& buffer, infra::StreamWriter& output)
+ : buffer(buffer)
+ , output(output)
+ {
+ LoadRemainder();
+ }
+
+ void BufferingStreamWriter::Insert(infra::ConstByteRange range, infra::StreamErrorPolicy& errorPolicy)
+ {
+ auto first = infra::Head(range, output.Available());
+ output.Insert(first, errorPolicy);
+ index += first.size();
+ range.pop_front(first.size());
+
+ buffer.insert(buffer.end(), range.begin(), range.end());
+ index += range.size();
+ }
+
+ std::size_t BufferingStreamWriter::Available() const
+ {
+ return output.Available() + buffer.max_size() - buffer.size();
+ }
+
+ std::size_t BufferingStreamWriter::ConstructSaveMarker() const
+ {
+ return index;
+ }
+
+ std::size_t BufferingStreamWriter::GetProcessedBytesSince(std::size_t marker) const
+ {
+ return index - marker;
+ }
+
+ [[noreturn]] infra::ByteRange BufferingStreamWriter::SaveState(std::size_t marker)
+ {
+ std::abort();
+ }
+
+ [[noreturn]] void BufferingStreamWriter::RestoreState(infra::ByteRange range)
+ {
+ std::abort();
+ }
+
+ [[noreturn]] infra::ByteRange BufferingStreamWriter::Overwrite(std::size_t marker)
+ {
+ std::abort();
+ }
+
+ void BufferingStreamWriter::LoadRemainder()
+ {
+ infra::StreamErrorPolicy errorPolicy;
+ auto from = infra::Head(buffer.contiguous_range(buffer.begin()), output.Available());
+ output.Insert(from, errorPolicy);
+ buffer.erase(buffer.begin(), buffer.begin() + from.size());
+ from = infra::Head(buffer.contiguous_range(buffer.begin()), output.Available());
+ output.Insert(from, errorPolicy);
+ buffer.erase(buffer.begin(), buffer.begin() + from.size());
+
+ index = buffer.size();
+ }
+}
diff --git a/infra/stream/BufferingStreamWriter.hpp b/infra/stream/BufferingStreamWriter.hpp
new file mode 100644
index 000000000..79f2d4216
--- /dev/null
+++ b/infra/stream/BufferingStreamWriter.hpp
@@ -0,0 +1,36 @@
+#ifndef INFRA_BUFFERING_STREAM_WRITER_HPP
+#define INFRA_BUFFERING_STREAM_WRITER_HPP
+
+#include "infra/stream/OutputStream.hpp"
+#include "infra/util/BoundedDeque.hpp"
+
+namespace infra
+{
+ // Usage: Any data that does not fit into the output stream is written to the buffer
+ // Any data already present in the buffer is written to the output stream upon construction of BufferingStreamWriter
+ class BufferingStreamWriter
+ : public infra::StreamWriter
+ {
+ public:
+ BufferingStreamWriter(infra::BoundedDeque& buffer, infra::StreamWriter& output);
+
+ // Implementation of StreamWriter
+ void Insert(infra::ConstByteRange range, infra::StreamErrorPolicy& errorPolicy) override;
+ std::size_t Available() const override;
+ std::size_t ConstructSaveMarker() const override;
+ std::size_t GetProcessedBytesSince(std::size_t marker) const override;
+ [[noreturn]] infra::ByteRange SaveState(std::size_t marker) override;
+ [[noreturn]] void RestoreState(infra::ByteRange range) override;
+ [[noreturn]] infra::ByteRange Overwrite(std::size_t marker) override;
+
+ private:
+ void LoadRemainder();
+
+ private:
+ infra::BoundedDeque& buffer;
+ infra::StreamWriter& output;
+ std::size_t index = 0;
+ };
+}
+
+#endif
diff --git a/infra/stream/CMakeLists.txt b/infra/stream/CMakeLists.txt
index eab26fd3f..4b3537a71 100644
--- a/infra/stream/CMakeLists.txt
+++ b/infra/stream/CMakeLists.txt
@@ -13,6 +13,10 @@ target_sources(infra.stream PRIVATE
BoundedVectorInputStream.hpp
BoundedVectorOutputStream.cpp
BoundedVectorOutputStream.hpp
+ BufferingStreamReader.cpp
+ BufferingStreamReader.hpp
+ BufferingStreamWriter.cpp
+ BufferingStreamWriter.hpp
ByteInputStream.cpp
ByteInputStream.hpp
ByteOutputStream.cpp
diff --git a/infra/stream/test/CMakeLists.txt b/infra/stream/test/CMakeLists.txt
index 957be3ce4..c3bfcaece 100644
--- a/infra/stream/test/CMakeLists.txt
+++ b/infra/stream/test/CMakeLists.txt
@@ -12,6 +12,8 @@ target_sources(infra.stream_test PRIVATE
StreamMock.hpp
TestBoundedDequeInputStream.cpp
TestBoundedVectorOutputStream.cpp
+ TestBufferingStreamReader.cpp
+ TestBufferingStreamWriter.cpp
TestByteInputStream.cpp
TestByteOutputStream.cpp
TestCountingInputStream.cpp
diff --git a/infra/stream/test/TestBufferingStreamReader.cpp b/infra/stream/test/TestBufferingStreamReader.cpp
new file mode 100644
index 000000000..1d58c3b79
--- /dev/null
+++ b/infra/stream/test/TestBufferingStreamReader.cpp
@@ -0,0 +1,206 @@
+#include "infra/stream/BufferingStreamReader.hpp"
+#include "infra/stream/test/StreamMock.hpp"
+#include "gmock/gmock.h"
+
+class BufferingStreamReaderTest
+ : public testing::Test
+{
+public:
+ ~BufferingStreamReaderTest()
+ {
+ EXPECT_CALL(input, Empty()).WillOnce(testing::Return(true));
+ }
+
+ void Extract(std::size_t amount)
+ {
+ std::vector data(amount, 0);
+ std::vector inputData;
+ EXPECT_CALL(input, ExtractContiguousRange(testing::_)).Times(testing::AnyNumber()).WillRepeatedly(testing::Invoke([&](std::size_t max)
+ {
+ inputData.resize(max);
+ return infra::MakeRange(inputData);
+ }));
+ reader.Extract(infra::MakeRange(data), errorPolicy);
+ }
+
+ void ExpectBuffer(const std::vector contents)
+ {
+ EXPECT_EQ(infra::BoundedDeque::WithMaxSize<100>(contents.begin(), contents.end()), buffer);
+ }
+
+ infra::BoundedDeque::WithMaxSize<4> buffer{ std::initializer_list{ 1, 2 } };
+ testing::StrictMock input;
+ infra::StreamErrorPolicy errorPolicy{ infra::noFail };
+ infra::BufferingStreamReader reader{ buffer, input };
+};
+
+TEST_F(BufferingStreamReaderTest, Extract_from_empty_buffer)
+{
+ buffer.clear();
+ std::array data;
+ EXPECT_CALL(input, ExtractContiguousRange(2)).WillOnce(testing::Return(infra::ConstByteRange()));
+ reader.Extract(data, errorPolicy);
+ EXPECT_TRUE(errorPolicy.Failed());
+}
+
+TEST_F(BufferingStreamReaderTest, Extract_from_buffer)
+{
+ std::array data;
+ reader.Extract(data, errorPolicy);
+ EXPECT_EQ((std::array{ 1, 2 }), data);
+ EXPECT_FALSE(errorPolicy.Failed());
+}
+
+TEST_F(BufferingStreamReaderTest, Extract_from_wrapped_buffer)
+{
+ buffer.push_back(3);
+ buffer.push_back(4);
+ buffer.pop_front();
+ buffer.pop_front();
+ buffer.push_back(5);
+ buffer.push_back(6);
+
+ std::array data;
+ reader.Extract(data, errorPolicy);
+ EXPECT_EQ((std::array{ 3, 4, 5, 6 }), data);
+}
+
+TEST_F(BufferingStreamReaderTest, Extract_from_buffer_and_input)
+{
+ std::array data;
+ std::array inputData{ 3, 4 };
+ EXPECT_CALL(input, ExtractContiguousRange(2)).WillOnce(testing::Invoke([&](std::size_t max)
+ {
+ return infra::MakeRange(inputData);
+ }));
+ reader.Extract(data, errorPolicy);
+ EXPECT_EQ((std::array{ 1, 2, 3, 4 }), data);
+}
+
+TEST_F(BufferingStreamReaderTest, PeekContiguous_range_from_buffer_head)
+{
+ EXPECT_EQ((std::array{ 1, 2 }), reader.PeekContiguousRange(0));
+}
+
+TEST_F(BufferingStreamReaderTest, PeekContiguous_range_from_buffer_1)
+{
+ EXPECT_EQ((std::array{ 2 }), reader.PeekContiguousRange(1));
+}
+
+TEST_F(BufferingStreamReaderTest, PeekContiguous_range_from_input)
+{
+ std::array inputData{ 3, 4 };
+ EXPECT_CALL(input, PeekContiguousRange(0)).WillOnce(testing::Invoke([&](std::size_t start)
+ {
+ return infra::MakeRange(inputData);
+ }));
+ EXPECT_EQ((std::array{ 3, 4 }), reader.PeekContiguousRange(2));
+}
+
+TEST_F(BufferingStreamReaderTest, Peek_from_buffer)
+{
+ EXPECT_EQ(1, reader.Peek(errorPolicy));
+ reader.ExtractContiguousRange(2);
+
+ std::array inputData{ 3, 4 };
+ EXPECT_CALL(input, PeekContiguousRange(0)).WillOnce(testing::Invoke([&](std::size_t start)
+ {
+ return infra::MakeRange(inputData);
+ }));
+ EXPECT_EQ(3, reader.Peek(errorPolicy));
+}
+
+TEST_F(BufferingStreamReaderTest, Available)
+{
+ EXPECT_CALL(input, Available()).WillOnce(testing::Return(1));
+ EXPECT_EQ(3, reader.Available());
+
+ EXPECT_CALL(input, Available()).WillOnce(testing::Return(1));
+ EXPECT_FALSE(reader.Empty());
+}
+
+TEST_F(BufferingStreamReaderTest, ConstructSaveMarker)
+{
+ EXPECT_EQ(0, reader.ConstructSaveMarker());
+
+ reader.ExtractContiguousRange(2);
+ EXPECT_EQ(2, reader.ConstructSaveMarker());
+}
+
+TEST_F(BufferingStreamReaderTest, Rewind_in_buffer)
+{
+ reader.ExtractContiguousRange(2);
+ reader.Rewind(1);
+ EXPECT_EQ(2, reader.Peek(errorPolicy));
+}
+
+TEST_F(BufferingStreamReaderTest, Rewind_from_input_to_input)
+{
+ Extract(4);
+
+ EXPECT_CALL(input, ConstructSaveMarker()).WillOnce(testing::Return(100));
+ EXPECT_CALL(input, Rewind(99));
+ reader.Rewind(3);
+ std::array inputData2{ 4 };
+ EXPECT_CALL(input, PeekContiguousRange(1)).WillOnce(testing::Invoke([&](std::size_t start)
+ {
+ return infra::MakeRange(inputData2);
+ }));
+ EXPECT_EQ(4, reader.Peek(errorPolicy));
+}
+
+TEST_F(BufferingStreamReaderTest, Rewind_from_input_to_buffer)
+{
+ Extract(4);
+
+ EXPECT_CALL(input, ConstructSaveMarker()).WillOnce(testing::Return(100));
+ EXPECT_CALL(input, Rewind(98));
+ reader.Rewind(1);
+ EXPECT_EQ(2, reader.Peek(errorPolicy));
+}
+
+TEST_F(BufferingStreamReaderTest, destruction_reduces_buffer)
+{
+ Extract(1);
+
+ EXPECT_CALL(input, Empty()).WillOnce(testing::Return(true));
+ infra::ReConstruct(reader, buffer, input);
+
+ ExpectBuffer({ 2 });
+}
+
+TEST_F(BufferingStreamReaderTest, destruction_consumes_buffer)
+{
+ Extract(3);
+
+ EXPECT_CALL(input, Empty()).WillOnce(testing::Return(true));
+ infra::ReConstruct(reader, buffer, input);
+
+ ExpectBuffer({});
+}
+
+TEST_F(BufferingStreamReaderTest, destruction_stores_input)
+{
+ EXPECT_CALL(input, Empty()).WillOnce(testing::Return(false)).WillOnce(testing::Return(true));
+ std::array inputData{ 3, 4 };
+ EXPECT_CALL(input, ExtractContiguousRange(std::numeric_limits::max())).WillOnce(testing::Invoke([&](std::size_t max)
+ {
+ return infra::MakeRange(inputData);
+ }));
+ infra::ReConstruct(reader, buffer, input);
+
+ ExpectBuffer({ 1, 2, 3, 4 });
+}
+
+TEST_F(BufferingStreamReaderTest, destruction_stores_input_until_empty)
+{
+ EXPECT_CALL(input, Empty()).WillOnce(testing::Return(false)).WillOnce(testing::Return(false)).WillOnce(testing::Return(true));
+ std::array inputData{ 3 };
+ EXPECT_CALL(input, ExtractContiguousRange(std::numeric_limits::max())).WillRepeatedly(testing::Invoke([&](std::size_t max)
+ {
+ return infra::MakeRange(inputData);
+ }));
+ infra::ReConstruct(reader, buffer, input);
+
+ ExpectBuffer({ 1, 2, 3, 3 });
+}
diff --git a/infra/stream/test/TestBufferingStreamWriter.cpp b/infra/stream/test/TestBufferingStreamWriter.cpp
new file mode 100644
index 000000000..2bb6db290
--- /dev/null
+++ b/infra/stream/test/TestBufferingStreamWriter.cpp
@@ -0,0 +1,103 @@
+#include "infra/stream/BufferingStreamWriter.hpp"
+#include "infra/stream/test/StreamMock.hpp"
+#include "infra/util/test_helper/MemoryRangeMatcher.hpp"
+#include "gmock/gmock.h"
+
+class BufferingStreamWriterTest
+ : public testing::Test
+{
+public:
+ void ExpectBuffer(const std::vector contents)
+ {
+ EXPECT_EQ(infra::BoundedDeque::WithMaxSize<100>(contents.begin(), contents.end()), buffer);
+ }
+
+ infra::BoundedDeque::WithMaxSize<4> buffer;
+ testing::StrictMock output;
+ infra::StreamErrorPolicy errorPolicy{ infra::noFail };
+ infra::Execute execute{ [this]()
+ {
+ EXPECT_CALL(output, Available()).WillRepeatedly(testing::Return(0));
+ EXPECT_CALL(output, Insert(testing::_, testing::_)).Times(2);
+ } };
+ infra::BufferingStreamWriter writer{ buffer, output };
+};
+
+TEST_F(BufferingStreamWriterTest, Insert_into_output)
+{
+ std::array data{ 3, 4 };
+ EXPECT_CALL(output, Available()).WillOnce(testing::Return(10));
+ EXPECT_CALL(output, Insert(infra::ContentsEqual(data), testing::Ref(errorPolicy)));
+ writer.Insert(data, errorPolicy);
+
+ ExpectBuffer({});
+ EXPECT_EQ(2, writer.ConstructSaveMarker());
+}
+
+TEST_F(BufferingStreamWriterTest, Insert_overflows_output)
+{
+ std::array data{ 3, 4 };
+ EXPECT_CALL(output, Available()).WillOnce(testing::Return(1));
+ EXPECT_CALL(output, Insert(infra::ByteRangeContentsEqual(infra::Head(infra::MakeRange(data), 1)), testing::Ref(errorPolicy)));
+ writer.Insert(data, errorPolicy);
+
+ ExpectBuffer({ 4 });
+ EXPECT_EQ(2, writer.ConstructSaveMarker());
+}
+
+TEST_F(BufferingStreamWriterTest, GetProcessedBytesSince)
+{
+ EXPECT_EQ(0, writer.GetProcessedBytesSince(0));
+
+ std::array data{ 3, 4 };
+ EXPECT_CALL(output, Available()).WillOnce(testing::Return(10));
+ EXPECT_CALL(output, Insert(infra::ContentsEqual(data), testing::Ref(errorPolicy)));
+ writer.Insert(data, errorPolicy);
+
+ EXPECT_EQ(2, writer.GetProcessedBytesSince(0));
+ EXPECT_EQ(1, writer.GetProcessedBytesSince(1));
+}
+
+TEST_F(BufferingStreamWriterTest, LoadRemainder_loads_from_buffer)
+{
+ std::array data{ 1, 2 };
+ buffer.insert(buffer.end(), data.begin(), data.end());
+
+ EXPECT_CALL(output, Available()).WillOnce(testing::Return(2)).WillOnce(testing::Return(0));
+ EXPECT_CALL(output, Insert(infra::ContentsEqual(data), testing::_));
+ EXPECT_CALL(output, Insert(infra::ByteRangeContentsEqual(infra::ConstByteRange()), testing::_));
+ infra::ReConstruct(writer, buffer, output);
+}
+
+TEST_F(BufferingStreamWriterTest, LoadRemainder_loads_from_circular_buffer)
+{
+ std::array data1{ 1, 2 };
+ std::array data2{ 3, 4 };
+ std::array data3{ 5, 6 };
+ buffer.insert(buffer.end(), data1.begin(), data1.end());
+ buffer.insert(buffer.end(), data2.begin(), data2.end());
+ buffer.pop_front();
+ buffer.pop_front();
+ buffer.insert(buffer.end(), data3.begin(), data3.end());
+
+ EXPECT_CALL(output, Available()).WillOnce(testing::Return(4)).WillOnce(testing::Return(2));
+ EXPECT_CALL(output, Insert(infra::ContentsEqual(data2), testing::_));
+ EXPECT_CALL(output, Insert(infra::ContentsEqual(data3), testing::_));
+ infra::ReConstruct(writer, buffer, output);
+}
+
+TEST_F(BufferingStreamWriterTest, LoadRemainder_constrained_by_output_writes_in_chunks)
+{
+ std::array data{ 1, 2 };
+ buffer.insert(buffer.end(), data.begin(), data.end());
+
+ EXPECT_CALL(output, Available()).WillOnce(testing::Return(1)).WillOnce(testing::Return(0));
+ EXPECT_CALL(output, Insert(infra::ByteRangeContentsEqual(infra::Head(infra::MakeRange(data), 1)), testing::_));
+ EXPECT_CALL(output, Insert(infra::ByteRangeContentsEqual(infra::ConstByteRange()), testing::_));
+ infra::ReConstruct(writer, buffer, output);
+
+ EXPECT_CALL(output, Available()).WillOnce(testing::Return(1)).WillOnce(testing::Return(0));
+ EXPECT_CALL(output, Insert(infra::ByteRangeContentsEqual(infra::DiscardHead(infra::MakeRange(data), 1)), testing::_));
+ EXPECT_CALL(output, Insert(infra::ByteRangeContentsEqual(infra::ConstByteRange()), testing::_));
+ infra::ReConstruct(writer, buffer, output);
+}
diff --git a/infra/syntax/ProtoFormatter.cpp b/infra/syntax/ProtoFormatter.cpp
index efb630d04..7b3e9d99a 100644
--- a/infra/syntax/ProtoFormatter.cpp
+++ b/infra/syntax/ProtoFormatter.cpp
@@ -130,6 +130,12 @@ namespace infra
PutBytes(bytes);
}
+ void ProtoFormatter::PutLengthDelimitedSize(std::size_t size, uint32_t fieldNumber)
+ {
+ PutVarInt((fieldNumber << 3) | 2);
+ PutVarInt(size);
+ }
+
ProtoLengthDelimitedFormatter ProtoFormatter::LengthDelimitedFormatter(uint32_t fieldNumber)
{
return ProtoLengthDelimitedFormatter(*this, fieldNumber);
diff --git a/infra/syntax/ProtoFormatter.hpp b/infra/syntax/ProtoFormatter.hpp
index 45748075b..7c717ce3c 100644
--- a/infra/syntax/ProtoFormatter.hpp
+++ b/infra/syntax/ProtoFormatter.hpp
@@ -14,6 +14,7 @@ namespace infra
{
public:
ProtoLengthDelimitedFormatter(ProtoFormatter& formatter, uint32_t fieldNumber);
+ ProtoLengthDelimitedFormatter(ProtoFormatter& formatter, uint32_t fieldNumber, std::size_t size);
ProtoLengthDelimitedFormatter(const ProtoLengthDelimitedFormatter& other) = delete;
ProtoLengthDelimitedFormatter(ProtoLengthDelimitedFormatter&& other) noexcept;
ProtoLengthDelimitedFormatter& operator=(const ProtoLengthDelimitedFormatter& other) = delete;
@@ -43,6 +44,7 @@ namespace infra
void PutLengthDelimitedField(infra::ConstByteRange range, uint32_t fieldNumber);
void PutStringField(infra::BoundedConstString string, uint32_t fieldNumber);
void PutBytesField(infra::ConstByteRange bytes, uint32_t fieldNumber);
+ void PutLengthDelimitedSize(std::size_t size, uint32_t fieldNumber);
ProtoLengthDelimitedFormatter LengthDelimitedFormatter(uint32_t fieldNumber);
private:
diff --git a/infra/syntax/ProtoParser.cpp b/infra/syntax/ProtoParser.cpp
index 513ebf7a6..8b5e09fb5 100644
--- a/infra/syntax/ProtoParser.cpp
+++ b/infra/syntax/ProtoParser.cpp
@@ -116,7 +116,40 @@ namespace infra
return result;
}
+ struct MakeFullField
+ : infra::StaticVisitor
+ {
+ MakeFullField(infra::DataInputStream inputStream, infra::StreamErrorPolicy& formatErrorPolicy, uint32_t fieldNumber)
+ : inputStream(inputStream)
+ , formatErrorPolicy(formatErrorPolicy)
+ , fieldNumber(fieldNumber)
+ {}
+
+ template
+ ProtoParser::Field operator()(T value) const
+ {
+ return { value, fieldNumber };
+ }
+
+ ProtoParser::Field operator()(PartialProtoLengthDelimited value) const
+ {
+ return { ProtoLengthDelimited(inputStream, formatErrorPolicy, value.length), fieldNumber };
+ }
+
+ private:
+ infra::DataInputStream inputStream;
+ infra::StreamErrorPolicy& formatErrorPolicy;
+ uint32_t fieldNumber;
+ };
+
ProtoParser::Field ProtoParser::GetField()
+ {
+ auto [value, fieldNumber] = GetPartialField();
+ MakeFullField visitor(input, formatErrorPolicy, fieldNumber);
+ return infra::ApplyVisitor(visitor, value);
+ }
+
+ ProtoParser::PartialField ProtoParser::GetPartialField()
{
uint32_t x = static_cast(GetVarInt());
uint8_t type = x & 7;
@@ -129,7 +162,7 @@ namespace infra
case 1:
return std::make_pair(GetFixed64(), fieldNumber);
case 2:
- return std::make_pair(ProtoLengthDelimited(input, formatErrorPolicy, static_cast(GetVarInt())), fieldNumber);
+ return std::make_pair(PartialProtoLengthDelimited{ static_cast(GetVarInt()) }, fieldNumber);
case 5:
return std::make_pair(GetFixed32(), fieldNumber);
default:
diff --git a/infra/syntax/ProtoParser.hpp b/infra/syntax/ProtoParser.hpp
index 3cb6d8306..652041edc 100644
--- a/infra/syntax/ProtoParser.hpp
+++ b/infra/syntax/ProtoParser.hpp
@@ -34,10 +34,18 @@ namespace infra
infra::StreamErrorPolicy& formatErrorPolicy;
};
+ struct PartialProtoLengthDelimited
+ {
+ uint32_t length;
+ };
+
class ProtoParser
{
public:
- using Field = std::pair, uint32_t>;
+ using FieldVariant = infra::Variant;
+ using Field = std::pair;
+ using PartialFieldVariant = infra::Variant;
+ using PartialField = std::pair;
explicit ProtoParser(infra::DataInputStream inputStream);
ProtoParser(infra::DataInputStream inputStream, infra::StreamErrorPolicy& formatErrorPolicy);
@@ -48,6 +56,7 @@ namespace infra
uint64_t GetFixed64();
Field GetField();
+ PartialField GetPartialField();
void ReportFormatResult(bool ok);
bool FormatFailed() const;
diff --git a/infra/syntax/test/TestProtoFormatter.cpp b/infra/syntax/test/TestProtoFormatter.cpp
index 6b34a148a..e42384893 100644
--- a/infra/syntax/test/TestProtoFormatter.cpp
+++ b/infra/syntax/test/TestProtoFormatter.cpp
@@ -76,6 +76,17 @@ TEST(ProtoFormatterTest, PutBytesField)
EXPECT_EQ((std::array{ 4 << 3 | 2, 1, 5 }), stream.Writer().Processed());
}
+TEST(ProtoFormatterTest, PutSubObjectOfKnownSize)
+{
+ infra::ByteOutputStream::WithStorage<20> stream;
+ infra::ProtoFormatter formatter(stream);
+
+ formatter.PutLengthDelimitedSize(2, 4);
+ formatter.PutVarIntField(2, 4);
+
+ EXPECT_EQ((std::array{ 4 << 3 | 2, 2, 4 << 3, 2 }), stream.Writer().Processed());
+}
+
TEST(ProtoFormatterTest, PutSubObject)
{
infra::ByteOutputStream::WithStorage<20> stream;
diff --git a/infra/util/ConstructBin.cpp b/infra/util/ConstructBin.cpp
index ce30b8fff..001ae1dce 100644
--- a/infra/util/ConstructBin.cpp
+++ b/infra/util/ConstructBin.cpp
@@ -32,6 +32,13 @@ namespace infra
return *this;
}
+ ConstructBin& ConstructBin::Repeat(std::size_t amount, std::initializer_list v)
+ {
+ for (size_t i = 0; i != amount; ++i)
+ contents.insert(contents.end(), v.begin(), v.end());
+ return *this;
+ }
+
ConstructBin& ConstructBin::RepeatString(std::size_t amount, const std::string& v)
{
for (size_t i = 0; i != amount; ++i)
diff --git a/infra/util/ConstructBin.hpp b/infra/util/ConstructBin.hpp
index ba514fd4e..83631f5c4 100644
--- a/infra/util/ConstructBin.hpp
+++ b/infra/util/ConstructBin.hpp
@@ -17,6 +17,7 @@ namespace infra
ConstructBin& operator()(std::initializer_list v);
ConstructBin& Repeat(std::size_t amount, uint8_t v);
+ ConstructBin& Repeat(std::size_t amount, std::initializer_list v);
ConstructBin& RepeatString(std::size_t amount, const std::string& v);
template
diff --git a/infra/util/WithStorage.hpp b/infra/util/WithStorage.hpp
index 52f78eb9e..1b199ef7a 100644
--- a/infra/util/WithStorage.hpp
+++ b/infra/util/WithStorage.hpp
@@ -26,6 +26,8 @@ namespace infra
WithStorage();
template
WithStorage(InPlace, StorageArg&& storageArg, Args&&... args);
+ template
+ WithStorage(InPlace, std::initializer_list initializerList);
template
WithStorage(Arg&& arg, std::enable_if_t>>, std::nullptr_t> = nullptr);
template
@@ -89,6 +91,13 @@ namespace infra
, Base(detail::StorageHolder::storage, std::forward(args)...)
{}
+ template
+ template
+ WithStorage::WithStorage(InPlace, std::initializer_list initializerList)
+ : detail::StorageHolder(initializerList)
+ , Base(detail::StorageHolder::storage)
+ {}
+
template
template
WithStorage::WithStorage(Arg&& arg, std::enable_if_t>>, std::nullptr_t>)
diff --git a/protobuf/CMakeLists.txt b/protobuf/CMakeLists.txt
index da2d6f17d..e6fe5e065 100644
--- a/protobuf/CMakeLists.txt
+++ b/protobuf/CMakeLists.txt
@@ -1,5 +1,5 @@
-add_subdirectory(echo)
add_subdirectory(echo_attributes)
+add_subdirectory(echo)
add_subdirectory(protoc_echo_plugin)
add_subdirectory(protoc_echo_plugin_csharp)
add_subdirectory(protoc_echo_plugin_java)
diff --git a/protobuf/echo/CMakeLists.txt b/protobuf/echo/CMakeLists.txt
index 168b25331..3f459aaeb 100644
--- a/protobuf/echo/CMakeLists.txt
+++ b/protobuf/echo/CMakeLists.txt
@@ -8,6 +8,11 @@ target_link_libraries(protobuf.echo PUBLIC
target_sources(protobuf.echo PRIVATE
Echo.cpp
Echo.hpp
+ Proto.hpp
+ ProtoMessageReceiver.cpp
+ ProtoMessageReceiver.hpp
+ ProtoMessageSender.cpp
+ ProtoMessageSender.hpp
ServiceForwarder.cpp
ServiceForwarder.hpp
TracingEcho.cpp
diff --git a/protobuf/echo/Echo.hpp b/protobuf/echo/Echo.hpp
index 81d04ba97..96a5e6a1d 100644
--- a/protobuf/echo/Echo.hpp
+++ b/protobuf/echo/Echo.hpp
@@ -1,12 +1,11 @@
#ifndef PROTOBUF_ECHO_HPP
#define PROTOBUF_ECHO_HPP
-#include "infra/syntax/ProtoFormatter.hpp"
-#include "infra/syntax/ProtoParser.hpp"
#include "infra/util/BoundedDeque.hpp"
#include "infra/util/Compatibility.hpp"
#include "infra/util/Function.hpp"
#include "infra/util/Optional.hpp"
+#include "protobuf/echo/Proto.hpp"
#include "services/util/MessageCommunication.hpp"
namespace services
@@ -15,121 +14,6 @@ namespace services
class Service;
class ServiceProxy;
- struct ProtoBool
- {};
-
- struct ProtoUInt32
- {};
-
- struct ProtoInt32
- {};
-
- struct ProtoUInt64
- {};
-
- struct ProtoInt64
- {};
-
- struct ProtoFixed32
- {};
-
- struct ProtoFixed64
- {};
-
- struct ProtoSFixed32
- {};
-
- struct ProtoSFixed64
- {};
-
- struct ProtoUnboundedString
- {};
-
- struct ProtoUnboundedBytes
- {};
-
- template
- struct ProtoMessage
- {};
-
- template
- struct ProtoEnum
- {};
-
- template
- struct ProtoBytes
- {};
-
- template
- struct ProtoString
- {};
-
- template
- struct ProtoRepeated
- {};
-
- template
- struct ProtoUnboundedRepeated
- {};
-
- void SerializeField(ProtoBool, infra::ProtoFormatter& formatter, bool value, uint32_t fieldNumber);
- void SerializeField(ProtoUInt32, infra::ProtoFormatter& formatter, uint32_t value, uint32_t fieldNumber);
- void SerializeField(ProtoInt32, infra::ProtoFormatter& formatter, int32_t value, uint32_t fieldNumber);
- void SerializeField(ProtoUInt64, infra::ProtoFormatter& formatter, uint64_t value, uint32_t fieldNumber);
- void SerializeField(ProtoInt64, infra::ProtoFormatter& formatter, int64_t value, uint32_t fieldNumber);
- void SerializeField(ProtoFixed32, infra::ProtoFormatter& formatter, uint32_t value, uint32_t fieldNumber);
- void SerializeField(ProtoFixed64, infra::ProtoFormatter& formatter, uint64_t value, uint32_t fieldNumber);
- void SerializeField(ProtoSFixed32, infra::ProtoFormatter& formatter, int32_t value, uint32_t fieldNumber);
- void SerializeField(ProtoSFixed64, infra::ProtoFormatter& formatter, int64_t value, uint32_t fieldNumber);
- void SerializeField(ProtoUnboundedString, infra::ProtoFormatter& formatter, const std::string& value, uint32_t fieldNumber);
- void SerializeField(ProtoUnboundedBytes, infra::ProtoFormatter& formatter, const std::vector& value, uint32_t fieldNumber);
-
- template
- void SerializeField(ProtoRepeated, infra::ProtoFormatter& formatter, const infra::BoundedVector& value, uint32_t fieldNumber);
- template
- void SerializeField(ProtoUnboundedRepeated, infra::ProtoFormatter& formatter, const std::vector& value, uint32_t fieldNumber);
- template
- void SerializeField(ProtoUnboundedRepeated, infra::ProtoFormatter& formatter, const std::vector& value, uint32_t fieldNumber);
- template
- void SerializeField(ProtoMessage, infra::ProtoFormatter& formatter, const U& value, uint32_t fieldNumber);
- template
- void SerializeField(ProtoEnum, infra::ProtoFormatter& formatter, T value, uint32_t fieldNumber);
- template
- void SerializeField(ProtoBytes, infra::ProtoFormatter& formatter, const infra::BoundedVector& value, uint32_t fieldNumber);
- template
- void SerializeField(ProtoString, infra::ProtoFormatter& formatter, infra::BoundedConstString value, uint32_t fieldNumber);
-
- void DeserializeField(ProtoBool, infra::ProtoParser& parser, infra::ProtoParser::Field& field, bool& value);
- void DeserializeField(ProtoUInt32, infra::ProtoParser& parser, infra::ProtoParser::Field& field, uint32_t& value);
- void DeserializeField(ProtoInt32, infra::ProtoParser& parser, infra::ProtoParser::Field& field, int32_t& value);
- void DeserializeField(ProtoUInt64, infra::ProtoParser& parser, infra::ProtoParser::Field& field, uint64_t& value);
- void DeserializeField(ProtoInt64, infra::ProtoParser& parser, infra::ProtoParser::Field& field, int64_t& value);
- void DeserializeField(ProtoFixed32, infra::ProtoParser& parser, infra::ProtoParser::Field& field, uint32_t& value);
- void DeserializeField(ProtoFixed64, infra::ProtoParser& parser, infra::ProtoParser::Field& field, uint64_t& value);
- void DeserializeField(ProtoSFixed32, infra::ProtoParser& parser, infra::ProtoParser::Field& field, int32_t& value);
- void DeserializeField(ProtoSFixed64, infra::ProtoParser& parser, infra::ProtoParser::Field& field, int64_t& value);
- void DeserializeField(ProtoUnboundedString, infra::ProtoParser& parser, infra::ProtoParser::Field& field, std::string& value);
- void DeserializeField(ProtoUnboundedBytes, infra::ProtoParser& parser, infra::ProtoParser::Field& field, std::vector& value);
-
- template
- void DeserializeField(ProtoRepeated, infra::ProtoParser& parser, infra::ProtoParser::Field& field, infra::BoundedVector& value);
- template
- void DeserializeField(ProtoUnboundedRepeated, infra::ProtoParser& parser, infra::ProtoParser::Field& field, std::vector& value);
- template
- void DeserializeField(ProtoUnboundedRepeated, infra::ProtoParser& parser, infra::ProtoParser::Field& field, std::vector& value);
- template
- void DeserializeField(ProtoMessage, infra::ProtoParser& parser, infra::ProtoParser::Field& field, U& value);
- template
- void DeserializeField(ProtoEnum, infra::ProtoParser& parser, infra::ProtoParser::Field& field, T& value);
- template
- void DeserializeField(ProtoBytes, infra::ProtoParser& parser, infra::ProtoParser::Field& field, infra::BoundedVector& value);
- template
- void DeserializeField(ProtoBytes, infra::ProtoParser& parser, infra::ProtoParser::Field& field, infra::ConstByteRange& value);
- template
- void DeserializeField(ProtoString, infra::ProtoParser& parser, infra::ProtoParser::Field& field, infra::BoundedString& value);
- template
- void DeserializeField(ProtoString, infra::ProtoParser& parser, infra::ProtoParser::Field& field, infra::BoundedConstString& value);
-
class EchoErrorPolicy
{
protected:
@@ -275,261 +159,6 @@ namespace services
//// Implementation ////
- inline void SerializeField(ProtoBool, infra::ProtoFormatter& formatter, bool value, uint32_t fieldNumber)
- {
- formatter.PutVarIntField(value, fieldNumber);
- }
-
- inline void SerializeField(ProtoUInt32, infra::ProtoFormatter& formatter, uint32_t value, uint32_t fieldNumber)
- {
- formatter.PutVarIntField(value, fieldNumber);
- }
-
- inline void SerializeField(ProtoInt32, infra::ProtoFormatter& formatter, int32_t value, uint32_t fieldNumber)
- {
- formatter.PutVarIntField(value, fieldNumber);
- }
-
- inline void SerializeField(ProtoUInt64, infra::ProtoFormatter& formatter, uint64_t value, uint32_t fieldNumber)
- {
- formatter.PutVarIntField(value, fieldNumber);
- }
-
- inline void SerializeField(ProtoInt64, infra::ProtoFormatter& formatter, int64_t value, uint32_t fieldNumber)
- {
- formatter.PutVarIntField(value, fieldNumber);
- }
-
- inline void SerializeField(ProtoFixed32, infra::ProtoFormatter& formatter, uint32_t value, uint32_t fieldNumber)
- {
- formatter.PutFixed32Field(value, fieldNumber);
- }
-
- inline void SerializeField(ProtoFixed64, infra::ProtoFormatter& formatter, uint64_t value, uint32_t fieldNumber)
- {
- formatter.PutFixed64Field(value, fieldNumber);
- }
-
- inline void SerializeField(ProtoSFixed32, infra::ProtoFormatter& formatter, int32_t value, uint32_t fieldNumber)
- {
- formatter.PutFixed32Field(static_cast(value), fieldNumber);
- }
-
- inline void SerializeField(ProtoSFixed64, infra::ProtoFormatter& formatter, int64_t value, uint32_t fieldNumber)
- {
- formatter.PutFixed64Field(static_cast(value), fieldNumber);
- }
-
- inline void SerializeField(ProtoUnboundedString, infra::ProtoFormatter& formatter, const std::string& value, uint32_t fieldNumber)
- {
- formatter.PutStringField(value, fieldNumber);
- }
-
- inline void SerializeField(ProtoUnboundedBytes, infra::ProtoFormatter& formatter, const std::vector& value, uint32_t fieldNumber)
- {
- formatter.PutBytesField(value, fieldNumber);
- }
-
- template
- void SerializeField(ProtoRepeated, infra::ProtoFormatter& formatter, const infra::BoundedVector& value, uint32_t fieldNumber)
- {
- for (auto& v : value)
- SerializeField(T(), formatter, v, fieldNumber);
- }
-
- template
- void SerializeField(ProtoUnboundedRepeated, infra::ProtoFormatter& formatter, const std::vector& value, uint32_t fieldNumber)
- {
- for (auto& v : value)
- SerializeField(T(), formatter, v, fieldNumber);
- }
-
- template
- void SerializeField(ProtoUnboundedRepeated, infra::ProtoFormatter& formatter, const std::vector& value, uint32_t fieldNumber)
- {
- for (auto v : value)
- SerializeField(T(), formatter, v, fieldNumber);
- }
-
- template
- void SerializeField(ProtoMessage, infra::ProtoFormatter& formatter, const U& value, uint32_t fieldNumber)
- {
- infra::ProtoLengthDelimitedFormatter nestedMessage(formatter, fieldNumber);
- value.Serialize(formatter);
- }
-
- template
- void SerializeField(ProtoEnum, infra::ProtoFormatter& formatter, T value, uint32_t fieldNumber)
- {
- formatter.PutVarIntField(static_cast(value), fieldNumber);
- }
-
- template
- void SerializeField(ProtoBytes, infra::ProtoFormatter& formatter, const infra::BoundedVector& value, uint32_t fieldNumber)
- {
- formatter.PutBytesField(infra::MakeRange(value), fieldNumber);
- }
-
- template
- void SerializeField(ProtoString, infra::ProtoFormatter& formatter, infra::BoundedConstString value, uint32_t fieldNumber)
- {
- formatter.PutStringField(value, fieldNumber);
- }
-
- inline void DeserializeField(ProtoBool, infra::ProtoParser& parser, infra::ProtoParser::Field& field, bool& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- value = field.first.Get() != 0;
- }
-
- inline void DeserializeField(ProtoUInt32, infra::ProtoParser& parser, infra::ProtoParser::Field& field, uint32_t& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- value = static_cast(field.first.Get());
- }
-
- inline void DeserializeField(ProtoInt32, infra::ProtoParser& parser, infra::ProtoParser::Field& field, int32_t& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- value = static_cast(field.first.Get());
- }
-
- inline void DeserializeField(ProtoUInt64, infra::ProtoParser& parser, infra::ProtoParser::Field& field, uint64_t& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- value = field.first.Get();
- }
-
- inline void DeserializeField(ProtoInt64, infra::ProtoParser& parser, infra::ProtoParser::Field& field, int64_t& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- value = static_cast(field.first.Get());
- }
-
- inline void DeserializeField(ProtoFixed32, infra::ProtoParser& parser, infra::ProtoParser::Field& field, uint32_t& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- value = field.first.Get();
- }
-
- inline void DeserializeField(ProtoFixed64, infra::ProtoParser& parser, infra::ProtoParser::Field& field, uint64_t& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- value = field.first.Get();
- }
-
- inline void DeserializeField(ProtoSFixed32, infra::ProtoParser& parser, infra::ProtoParser::Field& field, int32_t& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- value = static_cast(field.first.Get());
- }
-
- inline void DeserializeField(ProtoSFixed64, infra::ProtoParser& parser, infra::ProtoParser::Field& field, int64_t& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- value = static_cast(field.first.Get());
- }
-
- inline void DeserializeField(ProtoUnboundedString, infra::ProtoParser& parser, infra::ProtoParser::Field& field, std::string& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- value = field.first.Get().GetStdString();
- }
-
- inline void DeserializeField(ProtoUnboundedBytes, infra::ProtoParser& parser, infra::ProtoParser::Field& field, std::vector& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- value = field.first.Get().GetUnboundedBytes();
- }
-
- template
- void DeserializeField(ProtoRepeated, infra::ProtoParser& parser, infra::ProtoParser::Field& field, infra::BoundedVector& value)
- {
- parser.ReportFormatResult(!value.full());
- if (!value.full())
- {
- value.emplace_back();
- DeserializeField(T(), parser, field, value.back());
- }
- }
-
- template
- void DeserializeField(ProtoUnboundedRepeated, infra::ProtoParser& parser, infra::ProtoParser::Field& field, std::vector& value)
- {
- value.emplace_back();
- DeserializeField(T(), parser, field, value.back());
- }
-
- template
- void DeserializeField(ProtoUnboundedRepeated, infra::ProtoParser& parser, infra::ProtoParser::Field& field, std::vector& value)
- {
- bool result{};
- DeserializeField(T(), parser, field, result);
- value.push_back(result);
- }
-
- template
- void DeserializeField(ProtoMessage, infra::ProtoParser& parser, infra::ProtoParser::Field& field, U& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- {
- infra::ProtoParser nestedParser = field.first.Get().Parser();
- value.Deserialize(nestedParser);
- }
- }
-
- template
- void DeserializeField(ProtoEnum, infra::ProtoParser& parser, infra::ProtoParser::Field& field, T& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- value = static_cast(field.first.Get());
- }
-
- template
- void DeserializeField(ProtoBytes, infra::ProtoParser& parser, infra::ProtoParser::Field& field, infra::BoundedVector& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- field.first.Get().GetBytes(value);
- }
-
- template
- void DeserializeField(ProtoBytes, infra::ProtoParser& parser, infra::ProtoParser::Field& field, infra::ConstByteRange& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- field.first.Get().GetBytesReference(value);
- }
-
- template
- void DeserializeField(ProtoString, infra::ProtoParser& parser, infra::ProtoParser::Field& field, infra::BoundedString& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- field.first.Get().GetString(value);
- }
-
- template
- void DeserializeField(ProtoString, infra::ProtoParser& parser, infra::ProtoParser::Field& field, infra::BoundedConstString& value)
- {
- parser.ReportFormatResult(field.first.Is());
- if (field.first.Is())
- field.first.Get().GetStringReference(value);
- }
-
template
template
ServiceProxyResponseQueue::ServiceProxyResponseQueue(Container& container, Args&&... args)
diff --git a/protobuf/echo/Proto.hpp b/protobuf/echo/Proto.hpp
new file mode 100644
index 000000000..3fb0ae479
--- /dev/null
+++ b/protobuf/echo/Proto.hpp
@@ -0,0 +1,541 @@
+#ifndef PROTOBUF_PROTO_HPP
+#define PROTOBUF_PROTO_HPP
+
+#include "infra/syntax/ProtoFormatter.hpp"
+#include "infra/syntax/ProtoParser.hpp"
+#include
+
+namespace services
+{
+ struct ProtoBool
+ {};
+
+ struct ProtoUInt32
+ {};
+
+ struct ProtoInt32
+ {};
+
+ struct ProtoUInt64
+ {};
+
+ struct ProtoInt64
+ {};
+
+ struct ProtoFixed32
+ {};
+
+ struct ProtoFixed64
+ {};
+
+ struct ProtoSFixed32
+ {};
+
+ struct ProtoSFixed64
+ {};
+
+ struct ProtoUnboundedString
+ {};
+
+ struct ProtoUnboundedBytes
+ {};
+
+ template
+ struct ProtoMessage
+ {};
+
+ template
+ struct ProtoEnum
+ {};
+
+ struct ProtoBytesBase
+ {};
+
+ template
+ struct ProtoBytes
+ : ProtoBytesBase
+ {};
+
+ struct ProtoStringBase
+ {};
+
+ template
+ struct ProtoString
+ : ProtoStringBase
+ {};
+
+ template
+ struct ProtoRepeatedBase
+ {};
+
+ template
+ struct ProtoRepeated
+ : ProtoRepeatedBase
+ {};
+
+ template