diff --git a/.clusterfuzzlite/Dockerfile b/.clusterfuzzlite/Dockerfile
index 4e7d64e7f..692a22c73 100644
--- a/.clusterfuzzlite/Dockerfile
+++ b/.clusterfuzzlite/Dockerfile
@@ -1,4 +1,4 @@
-FROM gcr.io/oss-fuzz-base/base-builder@sha256:e808bf977a4c4bfab17c3c41c6c7e8d131a488c5e844296bd515ae5f90930131
+FROM gcr.io/oss-fuzz-base/base-builder@sha256:6bc204c52f3c00f691125cadc3f13cce24bd663fb0fed41fec4119444f8bfe5b
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/Dockerfile b/.devcontainer/Dockerfile
new file mode 100644
index 000000000..6d2442bad
--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1 @@
+FROM ghcr.io/philips-software/amp-devcontainer:v4.0.2@sha256:2d052e0bcb3840ea45aaa21ea6904f6d84b0e310c97e5690a6d48da522ec384e
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index df9f970f3..cf0d16912 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,18 +1,36 @@
{
// 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",
+ "build": {
+ "context": "..",
+ "dockerfile": "Dockerfile"
+ },
"runArgs": ["--add-host=host.docker.internal:host-gateway"],
"remoteEnv": { "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" },
"mounts": [
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
],
- "extensions": [
- "llvm-vs-code-extensions.vscode-clangd",
- "marus25.cortex-debug",
- "matepek.vscode-catch2-test-adapter",
- "ms-vscode.cmake-tools",
- "SonarSource.sonarlint-vscode"
- ]
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "llvm-vs-code-extensions.vscode-clangd",
+ "marus25.cortex-debug",
+ "matepek.vscode-catch2-test-adapter",
+ "mhutchie.git-graph",
+ "ms-vscode.cmake-tools",
+ "ms-vscode.cpptools",
+ "ms-vsliveshare.vsliveshare",
+ "SonarSource.sonarlint-vscode"
+ ],
+ "settings": {
+ "C_Cpp.autoAddFileAssociations": false,
+ "C_Cpp.intelliSenseEngine": "disabled",
+ "clangd.arguments": ["--query-driver=/**/arm-none-eabi-*"],
+ "cmake.copyCompileCommands": "${workspaceFolder}/build/compile_commands.json",
+ "cmake.statusbar.visibility": "default",
+ "cmake.useProjectStatusView": false,
+ "sonarlint.pathToCompileCommands": "${workspaceFolder}/build/compile_commands.json"
+ }
+ }
+ }
}
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index d7a361356..3c5d27e4d 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -8,5 +8,9 @@ updates:
interval: daily
- package-ecosystem: docker
directory: .clusterfuzzlite
+ schedule:
+ interval: monthly
+ - package-ecosystem: docker
+ directory: .devcontainer
schedule:
interval: daily
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index cb650a5ca..3e5975375 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@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ - 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: lukka/run-cmake@c2b72aff009141774c5a5fabe74ea46c8c04d9c4 # v10.6
+ - uses: seanmiddleditch/gha-setup-ninja@8b297075da4cd2a5f1fd21fe011b499edf06e9d2 # v4
+ - uses: lukka/run-cmake@2ce8982be71b8e9a3c4d5e432135035afd1e76a7 # v10.7
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@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - 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@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ 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,25 +54,25 @@ jobs:
matrix:
os: [macos-latest, windows-latest, windows-2019]
steps:
- - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- uses: hendrikmuhs/ccache-action@6d1841ec156c39a52b1b23a810da917ab98da1f4 # v1.2.10
with:
key: ${{ github.job }}-${{ matrix.os }}
variant: sccache
- - uses: lukka/run-cmake@c2b72aff009141774c5a5fabe74ea46c8c04d9c4 # v10.6
+ - uses: lukka/run-cmake@2ce8982be71b8e9a3c4d5e432135035afd1e76a7 # v10.7
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@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ 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@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ - 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
@@ -97,10 +98,30 @@ jobs:
name: emil
- run: tar -zxvf emil-*.tar.gz
- run: mkdir install && mv emil-*/* install/
- - uses: lukka/run-cmake@c2b72aff009141774c5a5fabe74ea46c8c04d9c4 # v10.6
+ - uses: lukka/run-cmake@2ce8982be71b8e9a3c4d5e432135035afd1e76a7 # v10.7
with:
- configurePreset: "Embedded"
- buildPreset: "Embedded-${{ matrix.configuration }}"
+ configurePreset: "embedded"
+ buildPreset: "embedded-${{ matrix.configuration }}"
+ configurePresetAdditionalArgs: "['-DCMAKE_C_COMPILER_LAUNCHER=ccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=ccache']"
+ embedded_build_without_host_install:
+ name: Embedded Build Without Host Install
+ runs-on: ubuntu-latest
+ steps:
+ - 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@e9cd61b92edb079b14b2d0449b21f8a517121fe8 # v1.8.0
+ with:
+ release: "10.3-2021.10"
+ - run: sudo apt-get update && sudo apt-get install ninja-build
+ - uses: hendrikmuhs/ccache-action@6d1841ec156c39a52b1b23a810da917ab98da1f4 # v1.2.10
+ with:
+ key: ${{ github.job }}
+ - uses: lukka/run-cmake@2ce8982be71b8e9a3c4d5e432135035afd1e76a7 # v10.7
+ with:
+ configurePreset: "embedded"
+ buildPreset: "embedded-RelWithDebInfo"
configurePresetAdditionalArgs: "['-DCMAKE_C_COMPILER_LAUNCHER=ccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=ccache']"
rtos:
name: Embedded Build - RTOS
@@ -110,11 +131,11 @@ jobs:
matrix:
rtos: ["FreeRTOS", "ThreadX"]
steps:
- - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ - 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
+ - name: Install GNU Arm Embedded Toolchain 10.3-2021.10
+ 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
@@ -126,8 +147,8 @@ jobs:
name: emil
- run: tar -zxvf emil-*.tar.gz
- run: mkdir install && mv emil-*/* install/
- - uses: lukka/run-cmake@c2b72aff009141774c5a5fabe74ea46c8c04d9c4 # v10.6
+ - uses: lukka/run-cmake@2ce8982be71b8e9a3c4d5e432135035afd1e76a7 # v10.7
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 dbf3fef7b..5cf6beb79 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@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ - 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@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- - uses: actions/dependency-review-action@f6fff72a3217f580d5afd49a46826795305b63c7 # v3.0.8
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/dependency-review-action@7bbfa034e752445ea40215fff1c3bf9597993d3f # v3.1.3
with:
comment-summary-in-pr: true
diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml
index 58d4a1c7c..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@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0
persist-credentials: false
@@ -28,7 +28,7 @@ jobs:
antora_generator: "antora-site-generator-lunr"
antora_docsearch_enabled: "true"
- name: Store Antora Site
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce
+ uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32
with:
name: antora
path: "${{ github.workspace }}/build/site"
@@ -44,7 +44,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0
persist-credentials: false
@@ -56,7 +56,7 @@ jobs:
antora_generator: "antora-site-generator-lunr"
antora_docsearch_enabled: "true"
- name: Store Antora Site
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: antora-branch
path: "${{ github.workspace }}/build/site"
@@ -69,7 +69,7 @@ jobs:
name: Publish to GitHub Pages
steps:
- name: Checkout
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ 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/fuzzing-batch.yml b/.github/workflows/fuzzing-batch.yml
index 638b80623..e4c4a4604 100644
--- a/.github/workflows/fuzzing-batch.yml
+++ b/.github/workflows/fuzzing-batch.yml
@@ -18,12 +18,12 @@ jobs:
sanitizer: [address, undefined]
steps:
- name: Build Fuzzers (${{ matrix.sanitizer }})
- uses: google/clusterfuzzlite/actions/build_fuzzers@1e163f06cba7820da5154ac9fe1a32d7fe6f73a3
+ uses: google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1
with:
language: c++
sanitizer: ${{ matrix.sanitizer }}
- name: Run Fuzzers (${{ matrix.sanitizer }})
- uses: google/clusterfuzzlite/actions/run_fuzzers@1e163f06cba7820da5154ac9fe1a32d7fe6f73a3
+ uses: google/clusterfuzzlite/actions/run_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fuzz-seconds: 1800
diff --git a/.github/workflows/fuzzing-cron.yml b/.github/workflows/fuzzing-cron.yml
index ca68f1ba6..e640930bc 100644
--- a/.github/workflows/fuzzing-cron.yml
+++ b/.github/workflows/fuzzing-cron.yml
@@ -14,11 +14,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
- uses: google/clusterfuzzlite/actions/build_fuzzers@1e163f06cba7820da5154ac9fe1a32d7fe6f73a3
+ uses: google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1
with:
language: c++
- name: Run Fuzzers
- uses: google/clusterfuzzlite/actions/run_fuzzers@1e163f06cba7820da5154ac9fe1a32d7fe6f73a3
+ uses: google/clusterfuzzlite/actions/run_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fuzz-seconds: 600
@@ -28,12 +28,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
- uses: google/clusterfuzzlite/actions/build_fuzzers@1e163f06cba7820da5154ac9fe1a32d7fe6f73a3
+ uses: google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1
with:
language: c++
sanitizer: coverage
- name: Run Fuzzers
- uses: google/clusterfuzzlite/actions/run_fuzzers@1e163f06cba7820da5154ac9fe1a32d7fe6f73a3
+ uses: google/clusterfuzzlite/actions/run_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fuzz-seconds: 600
diff --git a/.github/workflows/fuzzing-pr.yml b/.github/workflows/fuzzing-pr.yml
index 3815ca3ad..916746b3c 100644
--- a/.github/workflows/fuzzing-pr.yml
+++ b/.github/workflows/fuzzing-pr.yml
@@ -22,14 +22,14 @@ jobs:
sanitizer: [address, undefined]
steps:
- name: Build Fuzzers (${{ matrix.sanitizer }})
- uses: google/clusterfuzzlite/actions/build_fuzzers@1e163f06cba7820da5154ac9fe1a32d7fe6f73a3
+ uses: google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1
with:
language: c++
github-token: ${{ secrets.GITHUB_TOKEN }}
sanitizer: ${{ matrix.sanitizer }}
storage-repo: https://${{ secrets.METRICS_TOKEN }}@github.com/philips-software/amp-embedded-infra-lib-metrics.git
- name: Run Fuzzers (${{ matrix.sanitizer }})
- uses: google/clusterfuzzlite/actions/run_fuzzers@1e163f06cba7820da5154ac9fe1a32d7fe6f73a3
+ uses: google/clusterfuzzlite/actions/run_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fuzz-seconds: 300
diff --git a/.github/workflows/linting-formatting.yml b/.github/workflows/linting-formatting.yml
index 229157d6e..6a15006d6 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@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- uses: DoozyX/clang-format-lint-action@a83a8fb7d371f66da7dd1c4f33a193023899494b # v0.16
@@ -30,7 +30,7 @@ jobs:
inplace: true
extensions: "cpp,hpp"
exclude: "./external"
- - uses: reviewdog/action-suggester@3f60d0e826f0873905e0eeca522d562a6e67afbd # v1.7.1
+ - uses: reviewdog/action-suggester@94877e550e6b522dc1d21231974b645ff2f084ce # v1.8.0
with:
tool_name: clang-format
filter_mode: diff_context
@@ -42,26 +42,26 @@ jobs:
pull-requests: write
security-events: write
steps:
- - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ - 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@6ca1aa8c195c3ca3e77c174fe0356db1bce3b319 # v2.21.1
- if: ${{ success() }} || ${{ failure() }}
+ - uses: github/codeql-action/upload-sarif@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.22.7
+ if: ${{ success() || failure() }}
with:
sarif_file: megalinter-reports/megalinter-report.sarif
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
- if: ${{ success() }} || ${{ failure() }}
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ if: ${{ success() || failure() }}
with:
name: linter
path: |
megalinter-reports
- - uses: reviewdog/action-suggester@3f60d0e826f0873905e0eeca522d562a6e67afbd # v1.7.1
+ - uses: reviewdog/action-suggester@94877e550e6b522dc1d21231974b645ff2f084ce # v1.8.0
with:
tool_name: MegaLinter
filter_mode: diff_context
diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml
index 893c91ccb..487fc0b51 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@db8f2c60ee802b3748b512940dde88eabd7b7e01 # v3.7.13
id: release
with:
command: manifest
@@ -43,17 +43,17 @@ jobs:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
steps:
- - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- uses: hendrikmuhs/ccache-action@6d1841ec156c39a52b1b23a810da917ab98da1f4 # v1.2.10
with:
key: ${{ github.job }}-${{ matrix.os }}
variant: sccache
- - uses: lukka/run-cmake@c2b72aff009141774c5a5fabe74ea46c8c04d9c4 # v10.6
+ - uses: lukka/run-cmake@2ce8982be71b8e9a3c4d5e432135035afd1e76a7 # v10.7
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 58186f616..d8aaeb19f 100644
--- a/.github/workflows/security.yml
+++ b/.github/workflows/security.yml
@@ -21,16 +21,16 @@ jobs:
actions: read
contents: read
steps:
- - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ - 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@6ca1aa8c195c3ca3e77c174fe0356db1bce3b319 # v2.21.1
+ - uses: github/codeql-action/upload-sarif@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.22.7
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 fe911e555..a15240a81 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:v4.0.2@sha256:2d052e0bcb3840ea45aaa21ea6904f6d84b0e310c97e5690a6d48da522ec384e
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@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ - 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@2ce8982be71b8e9a3c4d5e432135035afd1e76a7 # v10.7
+ 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:v4.0.2@sha256:2d052e0bcb3840ea45aaa21ea6904f6d84b0e310c97e5690a6d48da522ec384e
permissions:
security-events: write
steps:
- - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ - 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@6ca1aa8c195c3ca3e77c174fe0356db1bce3b319 # v2.21.1
+ - uses: github/codeql-action/init@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.22.7
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@6ca1aa8c195c3ca3e77c174fe0356db1bce3b319 # v2.21.1
+ - uses: lukka/run-cmake@2ce8982be71b8e9a3c4d5e432135035afd1e76a7 # v10.7
+ with:
+ configurePreset: "host"
+ buildPreset: "host-Debug"
+ configurePresetAdditionalArgs: "['-DCMAKE_C_COMPILER_LAUNCHER=ccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=ccache']"
+ - uses: github/codeql-action/analyze@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.22.7
diff --git a/.github/workflows/validate-pr.yml b/.github/workflows/validate-pr.yml
index c8b2c855c..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@15e783651cfaa0c26ed993b971edf4418f50aba0 # v0.13.0
+ - uses: Namchee/conventional-pr@93f510707dd4ef011c5e8fe7c94c93c59fc86d4c # v0.15.1
with:
access_token: ${{ secrets.GITHUB_TOKEN }}
body: false
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index e6f877563..9d5573ce6 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "4.0.0"
+ ".": "5.0.1"
}
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
deleted file mode 100644
index 0a94675c8..000000000
--- a/.vscode/extensions.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "recommendations": ["ms-vscode-remote.vscode-remote-extensionpack"]
-}
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index dba4ddea6..000000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "cmake.copyCompileCommands": "${workspaceFolder}/build/compile_commands.json",
- "sonarlint.pathToCompileCommands": "${workspaceFolder}/build/compile_commands.json",
- "clangd.arguments": ["--query-driver=/**/arm-none-eabi-*"],
- "cmake.statusbar.visibility": "compact",
- "cmake.useProjectStatusView": false
-}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b9b3070ff..786f4bc16 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,46 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+## [5.0.1](https://github.com/philips-software/amp-embedded-infra-lib/compare/v5.0.0...v5.0.1) (2023-11-15)
+
+
+### Bug Fixes
+
+* Corrected incorrect destructor syntax ([#460](https://github.com/philips-software/amp-embedded-infra-lib/issues/460)) ([e01dd98](https://github.com/philips-software/amp-embedded-infra-lib/commit/e01dd985d0d4699dc859d3e8fc375c72dccf8a89))
+* Various fixes for echo ([#462](https://github.com/philips-software/amp-embedded-infra-lib/issues/462)) ([0062598](https://github.com/philips-software/amp-embedded-infra-lib/commit/006259893b8bd57b7c0796977cd96fc4bfbcc626))
+
+## [5.0.0](https://github.com/philips-software/amp-embedded-infra-lib/compare/v4.0.0...v5.0.0) (2023-11-09)
+
+
+### ⚠ BREAKING CHANGES
+
+* generic pairing/bonding classes updated ([#330](https://github.com/philips-software/amp-embedded-infra-lib/issues/330))
+* ble interface improvements ([#300](https://github.com/philips-software/amp-embedded-infra-lib/issues/300))
+
+### Features
+
+* Add protobuf/echo/ProtoMessageBuilder ([#416](https://github.com/philips-software/amp-embedded-infra-lib/issues/416)) ([f5260dd](https://github.com/philips-software/amp-embedded-infra-lib/commit/f5260dd65ae4adfea14755dfef04a18074441951))
+* Add ServiceProxyResponseQueue ([#338](https://github.com/philips-software/amp-embedded-infra-lib/issues/338)) ([88cb197](https://github.com/philips-software/amp-embedded-infra-lib/commit/88cb197acb2f38d3b6fad00f88983cf15d49c864))
+* Add streaming of little endian mac addresses ([#336](https://github.com/philips-software/amp-embedded-infra-lib/issues/336)) ([e3d7fd8](https://github.com/philips-software/amp-embedded-infra-lib/commit/e3d7fd8f12ad934b98a86a6b27d8f574049f12b3))
+* Added SerialCommunicationLoopback ([#440](https://github.com/philips-software/amp-embedded-infra-lib/issues/440)) ([2c87dfb](https://github.com/philips-software/amp-embedded-infra-lib/commit/2c87dfb5ecd1e76669af69a97f80c29bfab773b9))
+* Ble interface improvements ([#300](https://github.com/philips-software/amp-embedded-infra-lib/issues/300)) ([88a4689](https://github.com/philips-software/amp-embedded-infra-lib/commit/88a4689e8f08e2afe856170aa5b5036f69d1610c))
+* Generic pairing/bonding classes updated ([#330](https://github.com/philips-software/amp-embedded-infra-lib/issues/330)) ([dbda405](https://github.com/philips-software/amp-embedded-infra-lib/commit/dbda405cc2ef2d356fbe707df5389042a49c7959))
+* Removed Dac.hpp ([#439](https://github.com/philips-software/amp-embedded-infra-lib/issues/439)) ([4b52156](https://github.com/philips-software/amp-embedded-infra-lib/commit/4b5215609b9ee2a6ca72d8d660b8c797aa3e31c9))
+* Support payloads bigger than the MaxSendStreamSize ([#331](https://github.com/philips-software/amp-embedded-infra-lib/issues/331)) ([c411f66](https://github.com/philips-software/amp-embedded-infra-lib/commit/c411f66f7ae972786a7fa1134989ab8e4f0631aa))
+* Support streaming echo messages ([#435](https://github.com/philips-software/amp-embedded-infra-lib/issues/435)) ([07756bb](https://github.com/philips-software/amp-embedded-infra-lib/commit/07756bb41f068adbf3a2eb76adb2778fff5491f0))
+
+
+### Bug Fixes
+
+* Add acd sources to lwip ([#400](https://github.com/philips-software/amp-embedded-infra-lib/issues/400)) ([a4f68ef](https://github.com/philips-software/amp-embedded-infra-lib/commit/a4f68efdf19e7b556cb6fe2cba0165908f56be8c))
+* Added workaround mbedtls and clang-cl incomatibility ([#441](https://github.com/philips-software/amp-embedded-infra-lib/issues/441)) ([063b595](https://github.com/philips-software/amp-embedded-infra-lib/commit/063b59508f1d09c2675b338c7b54d64934f7792c))
+* Cpp:S6232 well-defined type-punning method should be used instead of a union-based one ([d809c17](https://github.com/philips-software/amp-embedded-infra-lib/commit/d809c173cacefd3bf2d661718111d5d301a95fc1))
+* Destruction of HttpClientJson while resetting the reader resulted in memory corruption ([#404](https://github.com/philips-software/amp-embedded-infra-lib/issues/404)) ([ed8a8a0](https://github.com/philips-software/amp-embedded-infra-lib/commit/ed8a8a0e5893074fc56fde94cfdb003a870e930c))
+* Detaching HttpClient while in HeaderAvailable resulted in a crash ([#406](https://github.com/philips-software/amp-embedded-infra-lib/issues/406)) ([a905a30](https://github.com/philips-software/amp-embedded-infra-lib/commit/a905a306be194c7cf6380e70cf83b668c8d27425))
+* Enable service scoping of method invocations in services.echo_console ([#325](https://github.com/philips-software/amp-embedded-infra-lib/issues/325)) ([7090a40](https://github.com/philips-software/amp-embedded-infra-lib/commit/7090a407f50d89073c468381e5207f1c0f56b6c1))
+* UpgradePackBuilderFacade setting mbedtls global memory pool on stack ([#324](https://github.com/philips-software/amp-embedded-infra-lib/issues/324)) ([ec567d5](https://github.com/philips-software/amp-embedded-infra-lib/commit/ec567d511f40eb3c0962ac4b6ac3479f64c0a871))
+* UpgradePackBuilderFacade setting mbedtls global memory pool on stack, causing a crash when combined with ConnectionMbedTls ([ec567d5](https://github.com/philips-software/amp-embedded-infra-lib/commit/ec567d511f40eb3c0962ac4b6ac3479f64c0a871))
+
## [4.0.0](https://github.com/philips-software/amp-embedded-infra-lib/compare/v3.2.0...v4.0.0) (2023-06-02)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 546496543..f39f7aa10 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@ if (APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
endif()
-project(emil LANGUAGES C CXX VERSION 4.0.0) # x-release-please-version
+project(emil LANGUAGES C CXX VERSION 5.0.1) # x-release-please-version
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED On)
@@ -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})
option(EMIL_ENABLE_GLOBAL_TRACING "Enable Global Tracing" On)
# Enable or disable optional features.
@@ -149,18 +149,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)
@@ -185,20 +179,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..77fca450a 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,9 @@ 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 -fpass-plugin=/usr/lib/mull-ir-frontend
+ )
add_link_options(-fprofile-instr-generate)
else()
@@ -68,13 +62,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/documents/antora.yml b/documents/antora.yml
index 8cd191ba9..088eb1760 100644
--- a/documents/antora.yml
+++ b/documents/antora.yml
@@ -1,5 +1,5 @@
name: embedded_infrastructure_library
title: Embedded Infrastructure Library documentation
-version: 4.0.0 # x-release-please-version
+version: 5.0.1 # x-release-please-version
nav:
- modules/ROOT/nav.adoc
diff --git a/examples/rpc/Server.cpp b/examples/rpc/Server.cpp
index 6e8f6ac32..c960da908 100644
--- a/examples/rpc/Server.cpp
+++ b/examples/rpc/Server.cpp
@@ -23,8 +23,9 @@ class EchoConnection
: public services::EchoOnConnection
{
public:
- EchoConnection()
- : console(*this)
+ EchoConnection(services::MethodSerializerFactory& serializerFactory)
+ : services::EchoOnConnection(serializerFactory)
+ , console(*this)
{}
private:
@@ -45,12 +46,13 @@ class RpcServer
connection->::services::ConnectionObserver::Subject().AbortAndDestroy();
if (connection.Allocatable())
- createdObserver(connection.Emplace());
+ createdObserver(connection.Emplace(serializerFactory));
}
private:
infra::SharedPtr listener;
infra::SharedOptional connection;
+ services::MethodSerializerFactory::OnHeap serializerFactory;
};
int main(int argc, const char* argv[], const char* env[])
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/external/protoc/CMakeLists.txt b/external/protoc/CMakeLists.txt
index e95241f24..07c71cfd8 100644
--- a/external/protoc/CMakeLists.txt
+++ b/external/protoc/CMakeLists.txt
@@ -106,7 +106,7 @@ function(protocol_buffer_csharp target input)
endfunction()
function(protocol_buffer_java target input)
- protocol_buffer_generator(TARGET ${target} INPUT ${input} GENERATOR java PATH_INFIX "/com/philips/emil/ProtobufEcho/" GENERATED_POSTFIXES Proto.java)
+ protocol_buffer_generator(TARGET ${target} INPUT ${input} GENERATOR java PATH_INFIX "/com/philips/emil/protobufEcho/" GENERATED_POSTFIXES Proto.java)
endfunction()
function(protocol_buffer_all target input)
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..53c32f5ed
--- /dev/null
+++ b/infra/stream/BufferingStreamReader.cpp
@@ -0,0 +1,109 @@
+#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;
+ }
+
+ auto result = input.ExtractContiguousRange(max);
+ index += result.size();
+ return result;
+ }
+
+ 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/CountingOutputStream.cpp b/infra/stream/CountingOutputStream.cpp
index befd5208f..95a46a230 100644
--- a/infra/stream/CountingOutputStream.cpp
+++ b/infra/stream/CountingOutputStream.cpp
@@ -2,6 +2,10 @@
namespace infra
{
+ CountingStreamWriter::CountingStreamWriter(infra::ByteRange saveStateStorage)
+ : saveStateStorage(saveStateStorage)
+ {}
+
std::size_t CountingStreamWriter::Processed() const
{
return processed;
@@ -24,16 +28,18 @@ namespace infra
std::size_t CountingStreamWriter::GetProcessedBytesSince(std::size_t marker) const
{
- return marker - processed;
+ return processed - marker;
}
infra::ByteRange CountingStreamWriter::SaveState(std::size_t marker)
{
- return infra::ByteRange();
+ return saveStateStorage;
}
void CountingStreamWriter::RestoreState(infra::ByteRange range)
- {}
+ {
+ processed += saveStateStorage.size() - range.size();
+ }
infra::ByteRange CountingStreamWriter::Overwrite(std::size_t marker)
{
diff --git a/infra/stream/CountingOutputStream.hpp b/infra/stream/CountingOutputStream.hpp
index 781802eb4..69c09c974 100644
--- a/infra/stream/CountingOutputStream.hpp
+++ b/infra/stream/CountingOutputStream.hpp
@@ -9,6 +9,8 @@ namespace infra
: public StreamWriter
{
public:
+ explicit CountingStreamWriter(infra::ByteRange saveStateStorage = {});
+
std::size_t Processed() const;
void Insert(ConstByteRange range, StreamErrorPolicy& errorPolicy) override;
@@ -20,6 +22,7 @@ namespace infra
infra::ByteRange Overwrite(std::size_t marker) override;
private:
+ infra::ByteRange saveStateStorage;
std::size_t processed = 0;
};
}
diff --git a/infra/stream/LimitedInputStream.cpp b/infra/stream/LimitedInputStream.cpp
index 3fe3bba94..dd0f6cb56 100644
--- a/infra/stream/LimitedInputStream.cpp
+++ b/infra/stream/LimitedInputStream.cpp
@@ -58,7 +58,7 @@ namespace infra
}
LimitedStreamReaderWithRewinding::LimitedStreamReaderWithRewinding(StreamReaderWithRewinding& input, uint32_t length)
- : input(input)
+ : input(&input)
, length(length)
{}
@@ -72,12 +72,22 @@ namespace infra
length = newLength;
}
+ bool LimitedStreamReaderWithRewinding::LimitReached() const
+ {
+ return length == 0;
+ }
+
+ void LimitedStreamReaderWithRewinding::SwitchInput(StreamReaderWithRewinding& newInput)
+ {
+ this->input = &newInput;
+ }
+
void LimitedStreamReaderWithRewinding::Extract(ByteRange range, StreamErrorPolicy& errorPolicy)
{
errorPolicy.ReportResult(length >= range.size());
range.shrink_from_back_to(length);
length -= range.size();
- input.Extract(range, errorPolicy);
+ input->Extract(range, errorPolicy);
}
uint8_t LimitedStreamReaderWithRewinding::Peek(StreamErrorPolicy& errorPolicy)
@@ -85,42 +95,42 @@ namespace infra
errorPolicy.ReportResult(length != 0);
if (length != 0)
- return input.Peek(errorPolicy);
+ return input->Peek(errorPolicy);
else
return 0;
}
ConstByteRange LimitedStreamReaderWithRewinding::ExtractContiguousRange(std::size_t max)
{
- ConstByteRange result = input.ExtractContiguousRange(std::min(length, max));
+ ConstByteRange result = input->ExtractContiguousRange(std::min(length, max));
length -= result.size();
return result;
}
ConstByteRange infra::LimitedStreamReaderWithRewinding::PeekContiguousRange(std::size_t start)
{
- return input.PeekContiguousRange(start);
+ return input->PeekContiguousRange(start);
}
bool LimitedStreamReaderWithRewinding::Empty() const
{
- return length == 0 || input.Empty();
+ return length == 0 || input->Empty();
}
std::size_t LimitedStreamReaderWithRewinding::Available() const
{
- return std::min(length, input.Available());
+ return std::min(length, input->Available());
}
std::size_t LimitedStreamReaderWithRewinding::ConstructSaveMarker() const
{
- return input.ConstructSaveMarker();
+ return input->ConstructSaveMarker();
}
void LimitedStreamReaderWithRewinding::Rewind(std::size_t marker)
{
- auto now = input.ConstructSaveMarker();
- input.Rewind(marker);
+ auto now = input->ConstructSaveMarker();
+ input->Rewind(marker);
length += now - marker;
}
diff --git a/infra/stream/LimitedInputStream.hpp b/infra/stream/LimitedInputStream.hpp
index 2a170b6cf..66e6ecf77 100644
--- a/infra/stream/LimitedInputStream.hpp
+++ b/infra/stream/LimitedInputStream.hpp
@@ -44,6 +44,8 @@ namespace infra
~LimitedStreamReaderWithRewinding() = default;
void ResetLength(uint32_t newLength);
+ bool LimitReached() const;
+ void SwitchInput(StreamReaderWithRewinding& newInput);
public:
void Extract(ByteRange range, StreamErrorPolicy& errorPolicy) override;
@@ -56,7 +58,7 @@ namespace infra
void Rewind(std::size_t marker) override;
private:
- StreamReaderWithRewinding& input;
+ StreamReaderWithRewinding* input;
uint32_t length;
};
diff --git a/infra/stream/OutputStream.hpp b/infra/stream/OutputStream.hpp
index a0fe2702f..ed15456f1 100644
--- a/infra/stream/OutputStream.hpp
+++ b/infra/stream/OutputStream.hpp
@@ -27,6 +27,11 @@ namespace infra
virtual void Insert(ConstByteRange range, StreamErrorPolicy& errorPolicy) = 0;
virtual std::size_t Available() const = 0;
+ bool Empty() const
+ {
+ return Available() == 0;
+ }
+
virtual std::size_t ConstructSaveMarker() const;
virtual std::size_t GetProcessedBytesSince(std::size_t marker) const;
virtual infra::ByteRange SaveState(std::size_t marker);
diff --git a/infra/stream/test/CMakeLists.txt b/infra/stream/test/CMakeLists.txt
index 957be3ce4..5f41d2420 100644
--- a/infra/stream/test/CMakeLists.txt
+++ b/infra/stream/test/CMakeLists.txt
@@ -12,9 +12,12 @@ target_sources(infra.stream_test PRIVATE
StreamMock.hpp
TestBoundedDequeInputStream.cpp
TestBoundedVectorOutputStream.cpp
+ TestBufferingStreamReader.cpp
+ TestBufferingStreamWriter.cpp
TestByteInputStream.cpp
TestByteOutputStream.cpp
TestCountingInputStream.cpp
+ TestCountingOutputStream.cpp
TestFormatter.cpp
TestLimitedInputStream.cpp
TestLimitedOutputStream.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/stream/test/TestCountingOutputStream.cpp b/infra/stream/test/TestCountingOutputStream.cpp
new file mode 100644
index 000000000..b37cfcdbd
--- /dev/null
+++ b/infra/stream/test/TestCountingOutputStream.cpp
@@ -0,0 +1,30 @@
+#include "infra/stream/CountingOutputStream.hpp"
+#include "gmock/gmock.h"
+
+TEST(CountingOutputStreamTest, Insert)
+{
+ infra::CountingStreamWriter writer;
+ infra::StreamErrorPolicy errorPolicy;
+
+ std::array data;
+ writer.Insert(data, errorPolicy);
+ EXPECT_EQ(4, writer.Processed());
+ EXPECT_EQ(std::numeric_limits::max(), writer.Available());
+}
+
+TEST(CountingOutputStreamTest, save_and_restore)
+{
+ std::array saveStateStorage;
+ infra::CountingStreamWriter writer(saveStateStorage);
+ infra::StreamErrorPolicy errorPolicy;
+
+ std::array data;
+ writer.Insert(data, errorPolicy);
+
+ EXPECT_EQ(4, writer.ConstructSaveMarker());
+ EXPECT_EQ(infra::MakeRange(saveStateStorage), writer.SaveState(4));
+ writer.Insert(infra::Head(infra::MakeRange(data), 3), errorPolicy);
+ EXPECT_EQ(3, writer.GetProcessedBytesSince(4));
+ writer.RestoreState(infra::Tail(infra::MakeRange(saveStateStorage), 1)); // Restore 1 out of the 6 bytes
+ EXPECT_EQ(4 + 3 + 5, writer.Processed());
+}
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..445b84466 100644
--- a/infra/syntax/ProtoParser.cpp
+++ b/infra/syntax/ProtoParser.cpp
@@ -90,6 +90,7 @@ namespace infra
uint64_t result = 0;
uint8_t byte = 0;
uint8_t shift = 0;
+ uint8_t index = 0;
do
{
@@ -97,7 +98,11 @@ namespace infra
result += static_cast(byte & 0x7f) << shift;
shift += 7;
- } while (!input.Failed() && (byte & 0x80) != 0);
+ ++index;
+ } while (!input.Failed() && (byte & 0x80) != 0 && index != 10);
+
+ if (!input.Failed() && (byte & 0x80) != 0 && index == 10)
+ formatErrorPolicy.Failed();
return result;
}
@@ -116,7 +121,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 +167,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/BoundedVector.hpp b/infra/util/BoundedVector.hpp
index 109cf119f..1d3f534c0 100644
--- a/infra/util/BoundedVector.hpp
+++ b/infra/util/BoundedVector.hpp
@@ -492,12 +492,7 @@ namespace infra
{
really_assert(size() + n <= max_size());
move_up(position, n);
-
- for (size_type i = 0; i != n; ++i)
- {
- *position = value;
- ++position;
- }
+ std::fill_n(position, n, value);
}
template
@@ -508,13 +503,7 @@ namespace infra
really_assert(size() + n <= max_size());
move_up(position, n);
-
- while (first != last)
- {
- *position = *first;
- ++position;
- ++first;
- }
+ std::copy(first, last, position);
}
template
diff --git a/infra/util/CMakeLists.txt b/infra/util/CMakeLists.txt
index adf3e3df7..8d7a032db 100644
--- a/infra/util/CMakeLists.txt
+++ b/infra/util/CMakeLists.txt
@@ -51,6 +51,7 @@ target_sources(infra.util PRIVATE
IntrusiveSet.hpp
IntrusiveUnorderedSet.hpp
MemoryRange.hpp
+ MultiFunction.hpp
Observer.hpp
Optional.cpp
Optional.hpp
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/Function.hpp b/infra/util/Function.hpp
index 70a008b1c..db8486bd5 100644
--- a/infra/util/Function.hpp
+++ b/infra/util/Function.hpp
@@ -488,7 +488,7 @@ namespace infra
{}
template
- ExecuteOnDestruction::WithExtraSize::~WithExtraSize()
+ ExecuteOnDestruction::WithExtraSize::~WithExtraSize()
{
f();
}
diff --git a/infra/util/MultiFunction.hpp b/infra/util/MultiFunction.hpp
index 59549d22d..64b3937e7 100644
--- a/infra/util/MultiFunction.hpp
+++ b/infra/util/MultiFunction.hpp
@@ -23,7 +23,9 @@ namespace infra
using And = MultiFunctionHelper>;
MultiFunctionHelper() = default;
- MultiFunctionHelper(std::nullptr_t) {}
+
+ MultiFunctionHelper(std::nullptr_t)
+ {}
template
struct IndexOf
@@ -86,12 +88,15 @@ namespace infra
}
template
- bool Invocable(EMIL_MAYBE_UNUSED Args&&...args)
+ bool Invocable(EMIL_MAYBE_UNUSED Args&&... args)
{
return functions.Which() == IndexOf::Value + 1;
}
- explicit operator bool() const { return functions.Which() != 0; }
+ explicit operator bool() const
+ {
+ return functions.Which() != 0;
+ }
bool operator==(const std::nullptr_t) const
{
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/infra/util/test/TestMultiFunction.cpp b/infra/util/test/TestMultiFunction.cpp
index be536d7ff..6076ef4a3 100644
--- a/infra/util/test/TestMultiFunction.cpp
+++ b/infra/util/test/TestMultiFunction.cpp
@@ -1,6 +1,6 @@
-#include "gtest/gtest.h"
#include "infra/util/MultiFunction.hpp"
#include "infra/util/test_helper/MockCallback.hpp"
+#include "gtest/gtest.h"
TEST(MultiFunctionTest, construct_empty)
{
@@ -24,7 +24,10 @@ TEST(MultiFunctionTest, construct_with_function)
{
infra::VerifyingFunctionMock m;
- infra::MultiFunction f([&]() { m.callback(); });
+ infra::MultiFunction f([&]()
+ {
+ m.callback();
+ });
f();
}
@@ -32,7 +35,10 @@ TEST(MultiFunctionTest, multi_function_construct_with_first)
{
infra::VerifyingFunctionMock m;
- infra::MultiFunction::And::And f([&]() { m.callback(); });
+ infra::MultiFunction::And::And f([&]()
+ {
+ m.callback();
+ });
f();
}
@@ -40,7 +46,10 @@ TEST(MultiFunctionTest, multi_function_construct_with_second)
{
infra::VerifyingFunctionMock m(true);
- infra::MultiFunction::And f([&](bool v) { m.callback(v); });
+ infra::MultiFunction::And f([&](bool v)
+ {
+ m.callback(v);
+ });
f(true);
}
@@ -49,7 +58,10 @@ TEST(MultiFunctionTest, reassign_multi_function)
infra::VerifyingFunctionMock m(true);
infra::MultiFunction::And f([]() {});
- f = [&](bool v) { m.callback(v); };
+ f = [&](bool v)
+ {
+ m.callback(v);
+ };
f(true);
}
@@ -65,7 +77,10 @@ TEST(MultiFunctionTest, return_value)
infra::MockCallback m;
EXPECT_CALL(m, callback()).WillOnce(testing::Return(5));
- infra::MultiFunction::And f([&]() { return m.callback(); });
+ infra::MultiFunction::And f([&]()
+ {
+ return m.callback();
+ });
EXPECT_EQ(5, f());
}
@@ -78,7 +93,10 @@ TEST(MultiFunctionTest, multi_function_Invocable)
TEST(MultiFunctionTest, mutable_function)
{
- infra::MultiFunction f([n = 0]() mutable { return ++n; });
+ infra::MultiFunction f([n = 0]() mutable
+ {
+ return ++n;
+ });
EXPECT_EQ(1, f());
EXPECT_EQ(2, f());
EXPECT_EQ(3, f());
diff --git a/lwip/lwip/CMakeLists.txt b/lwip/lwip/CMakeLists.txt
index f2e96a950..9419cc360 100644
--- a/lwip/lwip/CMakeLists.txt
+++ b/lwip/lwip/CMakeLists.txt
@@ -54,6 +54,7 @@ target_sources(lwip.lwip PRIVATE
${lwip_SOURCE_DIR}/src/core/tcp_out.c
${lwip_SOURCE_DIR}/src/core/timeouts.c
${lwip_SOURCE_DIR}/src/core/udp.c
+ ${lwip_SOURCE_DIR}/src/core/ipv4/acd.c
${lwip_SOURCE_DIR}/src/core/ipv4/autoip.c
${lwip_SOURCE_DIR}/src/core/ipv4/dhcp.c
${lwip_SOURCE_DIR}/src/core/ipv4/etharp.c
@@ -71,6 +72,7 @@ target_sources(lwip.lwip PRIVATE
${lwip_SOURCE_DIR}/src/core/ipv6/ip6_frag.c
${lwip_SOURCE_DIR}/src/core/ipv6/mld6.c
${lwip_SOURCE_DIR}/src/core/ipv6/nd6.c
+ ${lwip_SOURCE_DIR}/src/include/lwip/acd.h
${lwip_SOURCE_DIR}/src/include/lwip/altcp.h
${lwip_SOURCE_DIR}/src/include/lwip/altcp_tcp.h
${lwip_SOURCE_DIR}/src/include/lwip/altcp_tls.h
diff --git a/lwip/lwip_cpp/DatagramLwIp.cpp b/lwip/lwip_cpp/DatagramLwIp.cpp
index eae05b7b8..1a23b7d5b 100644
--- a/lwip/lwip_cpp/DatagramLwIp.cpp
+++ b/lwip/lwip_cpp/DatagramLwIp.cpp
@@ -46,6 +46,7 @@ namespace services
control = CreateUdpPcb(versions);
really_assert(control != nullptr);
ip_set_option(control, SOF_BROADCAST);
+ ip_set_option(control, SOF_REUSEADDR);
err_t result = udp_bind(control, IpAddrAny(versions), port);
assert(result == ERR_OK);
diff --git a/osal/freertos_std_thread/stdmutex.hpp b/osal/freertos_std_thread/stdmutex.hpp
index 88fd40a29..f652448c7 100644
--- a/osal/freertos_std_thread/stdmutex.hpp
+++ b/osal/freertos_std_thread/stdmutex.hpp
@@ -56,7 +56,7 @@ namespace std
return xSemaphoreTake(handle, (chrono::duration_cast(duration).count() + adjustForInaccuracies) / portTICK_RATE_MS) == pdTRUE;
}
- template
+ template
bool try_lock_until(const chrono::time_point& timePoint)
{
return try_lock_for(timePoint - Clock::now());
@@ -112,7 +112,7 @@ namespace std
return xSemaphoreTakeRecursive(handle, chrono::duration_cast(duration) + adjustForInaccuracies) == pdTRUE;
}
- template
+ template
bool try_lock_until(const chrono::time_point& timePoint)
{
return try_lock_for(timePoint - Clock::now());
@@ -134,8 +134,8 @@ namespace std
mutex& operator=(const mutex& other) = delete;
~mutex() = default;
- using timed_mutex::native_handle_type;
using timed_mutex::lock;
+ using timed_mutex::native_handle_type;
using timed_mutex::try_lock;
using timed_mutex::unlock;
};
@@ -149,8 +149,8 @@ namespace std
recursive_mutex& operator=(const recursive_mutex&) = delete;
~recursive_mutex() = default;
- using recursive_timed_mutex::native_handle_type;
using recursive_timed_mutex::lock;
+ using recursive_timed_mutex::native_handle_type;
using recursive_timed_mutex::try_lock;
using recursive_timed_mutex::unlock;
};
diff --git a/osal/freertos_std_thread/test/semphr.h b/osal/freertos_std_thread/test/semphr.h
index 8367ca16b..e425c143a 100644
--- a/osal/freertos_std_thread/test/semphr.h
+++ b/osal/freertos_std_thread/test/semphr.h
@@ -1,8 +1,8 @@
#ifndef TEST_FREERTOS_STD_THREAD_SEMPHR_H
#define TEST_FREERTOS_STD_THREAD_SEMPHR_H
-#include
#include "gmock/gmock.h"
+#include
typedef void* xSemaphoreHandle;
typedef std::chrono::system_clock::duration::rep portTickType;
diff --git a/osal/freertos_std_thread/test/test_condition_variable.cpp b/osal/freertos_std_thread/test/test_condition_variable.cpp
index f77ee8f02..7920abeda 100644
--- a/osal/freertos_std_thread/test/test_condition_variable.cpp
+++ b/osal/freertos_std_thread/test/test_condition_variable.cpp
@@ -101,8 +101,9 @@ TEST_F(SemaphoreWaitFixture, WhenWaitingNotifyOneReleasesSemaphore)
EXPECT_CALL(mock, SemaphoreTake(p1, 3000))
.WillOnce(testing::Invoke([this](xSemaphoreHandle, portTickType)
{
- condition_variable.notify_one();
- return true; }));
+ condition_variable.notify_one();
+ return true;
+ }));
EXPECT_CALL(mock, SemaphoreGive(p1));
@@ -116,8 +117,9 @@ TEST_F(SemaphoreWaitFixture, WhenWaitingNotifyAllReleasesSemaphore)
EXPECT_CALL(mock, SemaphoreTake(p1, 3000))
.WillOnce(testing::Invoke([this](xSemaphoreHandle, portTickType)
{
- condition_variable.notify_all();
- return true; }));
+ condition_variable.notify_all();
+ return true;
+ }));
EXPECT_CALL(mock, SemaphoreGive(p1));
@@ -138,9 +140,10 @@ TEST_F(SemaphoreFixture, WhenWaitingTwiceNotifyAllReleasesTwoSemaphores)
EXPECT_CALL(mock, SemaphoreTake(p1, 3000))
.WillOnce(testing::Invoke([this](xSemaphoreHandle, portTickType)
{
- std::unique_lock lock(mutex);
- condition_variable.wait_for(lock, std::chrono::seconds(2));
- return true; }));
+ std::unique_lock lock(mutex);
+ condition_variable.wait_for(lock, std::chrono::seconds(2));
+ return true;
+ }));
EXPECT_CALL(mock, SemaphoreCreateBinary())
.WillOnce(testing::Return(p2));
@@ -150,8 +153,9 @@ TEST_F(SemaphoreFixture, WhenWaitingTwiceNotifyAllReleasesTwoSemaphores)
EXPECT_CALL(mock, SemaphoreTake(p2, 2000))
.WillOnce(testing::Invoke([this](xSemaphoreHandle, portTickType)
{
- condition_variable.notify_all();
- return true; }));
+ condition_variable.notify_all();
+ return true;
+ }));
EXPECT_CALL(mock, SemaphoreGive(p1));
EXPECT_CALL(mock, SemaphoreGive(p2));
@@ -175,9 +179,10 @@ TEST_F(SemaphoreFixture, WhenWaitingTwiceNotifyOneReleasesFirstSemaphore)
EXPECT_CALL(mock, SemaphoreTake(p1, 3000))
.WillOnce(testing::Invoke([this](xSemaphoreHandle, portTickType)
{
- std::unique_lock lock(mutex);
- condition_variable.wait_for(lock, std::chrono::seconds(2));
- return true; }));
+ std::unique_lock lock(mutex);
+ condition_variable.wait_for(lock, std::chrono::seconds(2));
+ return true;
+ }));
EXPECT_CALL(mock, SemaphoreCreateBinary())
.WillOnce(testing::Return(p2));
@@ -187,8 +192,9 @@ TEST_F(SemaphoreFixture, WhenWaitingTwiceNotifyOneReleasesFirstSemaphore)
EXPECT_CALL(mock, SemaphoreTake(p2, 2000))
.WillOnce(testing::Invoke([this](xSemaphoreHandle, portTickType)
{
- condition_variable.notify_one();
- return false; })); // Second semaphore times out
+ condition_variable.notify_one();
+ return false;
+ })); // Second semaphore times out
EXPECT_CALL(mock, SemaphoreGive(p1));
diff --git a/osal/freertos_system_time/TimerServiceFreeRtos.hpp b/osal/freertos_system_time/TimerServiceFreeRtos.hpp
index 0d9136728..d32302a23 100644
--- a/osal/freertos_system_time/TimerServiceFreeRtos.hpp
+++ b/osal/freertos_system_time/TimerServiceFreeRtos.hpp
@@ -1,7 +1,6 @@
#ifndef TIMER_SERVICE_FREE_RTOS_HPP
#define TIMER_SERVICE_FREE_RTOS_HPP
-//#include "hal_st/cortex/InterruptCortex.hpp"
#include "infra/timer/TickOnInterruptTimerService.hpp"
#include "infra/util/InterfaceConnector.hpp"
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..6f345eece 100644
--- a/protobuf/echo/CMakeLists.txt
+++ b/protobuf/echo/CMakeLists.txt
@@ -8,6 +8,15 @@ target_link_libraries(protobuf.echo PUBLIC
target_sources(protobuf.echo PRIVATE
Echo.cpp
Echo.hpp
+ EchoErrorPolicy.cpp
+ EchoErrorPolicy.hpp
+ Proto.hpp
+ ProtoMessageReceiver.cpp
+ ProtoMessageReceiver.hpp
+ ProtoMessageSender.cpp
+ ProtoMessageSender.hpp
+ Serialization.cpp
+ Serialization.hpp
ServiceForwarder.cpp
ServiceForwarder.hpp
TracingEcho.cpp
diff --git a/protobuf/echo/Echo.cpp b/protobuf/echo/Echo.cpp
index 2f357edfe..20cba19e1 100644
--- a/protobuf/echo/Echo.cpp
+++ b/protobuf/echo/Echo.cpp
@@ -1,26 +1,10 @@
#include "protobuf/echo/Echo.hpp"
-#include "infra/event/EventDispatcherWithWeakPtr.hpp"
namespace services
{
- EchoErrorPolicyAbortOnMessageFormatError echoErrorPolicyAbortOnMessageFormatError;
- EchoErrorPolicyAbort echoErrorPolicyAbort;
-
void Service::MethodDone()
{
- inProgress = false;
- Rpc().ServiceDone(*this);
- }
-
- bool Service::InProgress() const
- {
- return inProgress;
- }
-
- void Service::HandleMethod(uint32_t serviceId, uint32_t methodId, infra::ProtoLengthDelimited& contents, EchoErrorPolicy& errorPolicy)
- {
- inProgress = true;
- Handle(serviceId, methodId, contents, errorPolicy);
+ Rpc().ServiceDone();
}
Echo& Service::Rpc()
@@ -50,9 +34,10 @@ namespace services
echo.RequestSend(*this);
}
- void ServiceProxy::GrantSend()
+ infra::SharedPtr ServiceProxy::GrantSend()
{
onGranted();
+ return methodSerializer;
}
uint32_t ServiceProxy::MaxMessageSize() const
@@ -65,124 +50,184 @@ namespace services
return currentRequestedSize;
}
- void EchoErrorPolicyAbortOnMessageFormatError::MessageFormatError()
+ void ServiceProxy::SetSerializer(const infra::SharedPtr& serializer)
{
- std::abort();
+ methodSerializer = serializer;
}
- void EchoErrorPolicyAbortOnMessageFormatError::ServiceNotFound(uint32_t serviceId)
+ EchoOnStreams::EchoOnStreams(services::MethodSerializerFactory& serializerFactory, const EchoErrorPolicy& errorPolicy)
+ : serializerFactory(serializerFactory)
+ , errorPolicy(errorPolicy)
{}
- void EchoErrorPolicyAbortOnMessageFormatError::MethodNotFound(uint32_t serviceId, uint32_t methodId)
- {}
-
- void EchoErrorPolicyAbort::ServiceNotFound(uint32_t serviceId)
+ EchoOnStreams::~EchoOnStreams()
{
- std::abort();
+ readerAccess.SetAction(nullptr);
}
- void EchoErrorPolicyAbort::MethodNotFound(uint32_t serviceId, uint32_t methodId)
+ void EchoOnStreams::RequestSend(ServiceProxy& serviceProxy)
{
- std::abort();
- }
+ sendRequesters.push_back(serviceProxy);
- EchoOnStreams::EchoOnStreams(EchoErrorPolicy& errorPolicy)
- : errorPolicy(errorPolicy)
- {}
+ TryGrantSend();
+ }
- void EchoOnStreams::RequestSend(ServiceProxy& serviceProxy)
+ void EchoOnStreams::ServiceDone()
{
- if (sendRequesters.empty() && streamWriter == nullptr)
- {
- sendRequesters.push_back(serviceProxy);
- RequestSendStream(serviceProxy.CurrentRequestedSize());
- }
- else
- sendRequesters.push_back(serviceProxy);
+ methodDeserializer = nullptr;
+
+ if (readerPtr != nullptr)
+ DataReceived();
}
- infra::StreamWriter& EchoOnStreams::SendStreamWriter()
+ services::MethodSerializerFactory& EchoOnStreams::SerializerFactory()
{
- return *streamWriter;
+ return serializerFactory;
}
- void EchoOnStreams::Send()
+ void EchoOnStreams::DataReceived(infra::SharedPtr&& reader)
{
- streamWriter = nullptr;
+ assert(readerPtr == nullptr);
+ readerPtr = std::move(reader);
+ bufferedReader.Emplace(receiveBuffer, *readerPtr);
+ DataReceived();
+ }
- if (!sendRequesters.empty())
- RequestSendStream(sendRequesters.front().CurrentRequestedSize());
+ void EchoOnStreams::ReleaseReader()
+ {
+ readerAccess.SetAction(nullptr);
+ bufferedReader = infra::none;
+ readerPtr = nullptr;
}
- void EchoOnStreams::ServiceDone(Service& service)
+ void EchoOnStreams::TryGrantSend()
{
- if (serviceBusy && service.AcceptsService(*serviceBusy))
+ if (sendingProxy == nullptr && !sendRequesters.empty())
{
- serviceBusy = infra::none;
- infra::EventDispatcherWithWeakPtr::Instance().Schedule([](infra::SharedPtr echo)
- {
- echo->BusyServiceDone();
- },
- SharedFromThis());
+ sendingProxy = &sendRequesters.front();
+ sendRequesters.pop_front();
+ RequestSendStream(sendingProxy->CurrentRequestedSize() + 2 * infra::MaxVarIntSize(std::numeric_limits::max()));
}
}
- void EchoOnStreams::ExecuteMethod(uint32_t serviceId, uint32_t methodId, infra::ProtoLengthDelimited& contents, infra::StreamReaderWithRewinding& reader)
+ infra::SharedPtr EchoOnStreams::GrantSend(ServiceProxy& proxy)
{
- if (!NotifyObservers([this, serviceId, methodId, &contents](auto& service)
- {
- if (service.AcceptsService(serviceId))
- {
- if (service.InProgress())
- serviceBusy = serviceId;
- else
- service.HandleMethod(serviceId, methodId, contents, errorPolicy);
-
- return true;
- }
+ return proxy.GrantSend();
+ }
- return false;
- }))
- {
- errorPolicy.ServiceNotFound(serviceId);
- contents.SkipEverything();
- }
+ infra::SharedPtr EchoOnStreams::StartingMethod(uint32_t serviceId, uint32_t methodId, uint32_t size, const infra::SharedPtr& deserializer)
+ {
+ return deserializer;
}
- void EchoOnStreams::SetStreamWriter(infra::SharedPtr&& writer)
+ void EchoOnStreams::SendStreamAvailable(infra::SharedPtr&& writer)
{
- streamWriter = std::move(writer);
+ if (methodSerializer == nullptr)
+ methodSerializer = GrantSend(*sendingProxy);
+
+ auto more = methodSerializer->Serialize(std::move(writer));
- ServiceProxy& proxy = sendRequesters.front();
- sendRequesters.pop_front();
- proxy.GrantSend();
+ if (more)
+ RequestSendStream(sendingProxy->CurrentRequestedSize());
+ else
+ {
+ sendingProxy = nullptr;
+ methodSerializer->SerializationDone();
+ methodSerializer = nullptr;
+ TryGrantSend();
+ }
}
- bool EchoOnStreams::ServiceBusy() const
+ void EchoOnStreams::DataReceived()
{
- return serviceBusy != infra::none;
+ while (readerPtr != nullptr && methodDeserializer == nullptr && !readerAccess.Referenced())
+ {
+ if (limitedReader == infra::none)
+ StartReceiveMessage();
+
+ if (limitedReader != infra::none)
+ ContinueReceiveMessage();
+ }
}
- bool EchoOnStreams::ProcessMessage(infra::StreamReaderWithRewinding& reader)
+ void EchoOnStreams::StartReceiveMessage()
{
- infra::DataInputStream::WithErrorPolicy stream(reader, infra::softFail);
+ auto start = bufferedReader->ConstructSaveMarker();
+ infra::DataInputStream::WithErrorPolicy stream(*bufferedReader, infra::softFail);
infra::StreamErrorPolicy formatErrorPolicy(infra::softFail);
infra::ProtoParser parser(stream, formatErrorPolicy);
uint32_t serviceId = static_cast(parser.GetVarInt());
- infra::ProtoParser::Field message = parser.GetField();
- if (stream.Failed())
- return false;
+ auto [contents, methodId] = parser.GetPartialField();
- if (formatErrorPolicy.Failed() || !message.first.Is())
+ if (stream.Failed())
+ {
+ bufferedReader->Rewind(start);
+ bufferedReader = infra::none;
+ readerPtr = nullptr;
+ }
+ else if (formatErrorPolicy.Failed() || !contents.Is())
+ {
errorPolicy.MessageFormatError();
+ AckReceived();
+ }
else
{
- ExecuteMethod(serviceId, message.second, message.first.Get(), reader);
+ limitedReader.Emplace(*bufferedReader, contents.Get().length);
+ StartMethod(serviceId, methodId, contents.Get().length);
- if (stream.Failed() || formatErrorPolicy.Failed())
+ if (formatErrorPolicy.Failed())
errorPolicy.MessageFormatError();
}
+ }
+
+ void EchoOnStreams::ContinueReceiveMessage()
+ {
+ limitedReader->SwitchInput(*bufferedReader);
+ readerAccess.SetAction(infra::emptyFunction);
+ methodDeserializer->MethodContents(readerAccess.MakeShared(*limitedReader));
+
+ if (readerAccess.Referenced())
+ readerAccess.SetAction([this]()
+ {
+ ReaderDone();
+ DataReceived();
+ });
+ else
+ ReaderDone();
+ }
+
+ void EchoOnStreams::StartMethod(uint32_t serviceId, uint32_t methodId, uint32_t size)
+ {
+ if (!NotifyObservers([this, serviceId, methodId, size](auto& service)
+ {
+ if (service.AcceptsService(serviceId))
+ {
+ methodDeserializer = StartingMethod(serviceId, methodId, size, service.StartMethod(serviceId, methodId, size, errorPolicy));
+ return true;
+ }
+
+ return false;
+ }))
+ {
+ errorPolicy.ServiceNotFound(serviceId);
+ methodDeserializer = deserializerDummy.Emplace(*this);
+ }
+ }
- return true;
+ void EchoOnStreams::ReaderDone()
+ {
+ AckReceived();
+
+ if (limitedReader->LimitReached())
+ {
+ limitedReader = infra::none;
+ if (methodDeserializer->Failed())
+ {
+ errorPolicy.MessageFormatError();
+ methodDeserializer = nullptr;
+ }
+ else
+ methodDeserializer->ExecuteMethod();
+ }
}
}
diff --git a/protobuf/echo/Echo.hpp b/protobuf/echo/Echo.hpp
index 81d04ba97..aa4d5b9ac 100644
--- a/protobuf/echo/Echo.hpp
+++ b/protobuf/echo/Echo.hpp
@@ -1,13 +1,15 @@
#ifndef PROTOBUF_ECHO_HPP
#define PROTOBUF_ECHO_HPP
-#include "infra/syntax/ProtoFormatter.hpp"
-#include "infra/syntax/ProtoParser.hpp"
+#include "infra/stream/BufferingStreamReader.hpp"
#include "infra/util/BoundedDeque.hpp"
#include "infra/util/Compatibility.hpp"
#include "infra/util/Function.hpp"
+#include "infra/util/Observer.hpp"
#include "infra/util/Optional.hpp"
-#include "services/util/MessageCommunication.hpp"
+#include "protobuf/echo/EchoErrorPolicy.hpp"
+#include "protobuf/echo/Proto.hpp"
+#include "protobuf/echo/Serialization.hpp"
namespace services
{
@@ -15,152 +17,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:
- ~EchoErrorPolicy() = default;
-
- public:
- virtual void MessageFormatError() = 0;
- virtual void ServiceNotFound(uint32_t serviceId) = 0;
- virtual void MethodNotFound(uint32_t serviceId, uint32_t methodId) = 0;
- };
-
- class EchoErrorPolicyAbortOnMessageFormatError
- : public EchoErrorPolicy
- {
- public:
- void MessageFormatError() override;
- void ServiceNotFound(uint32_t serviceId) override;
- void MethodNotFound(uint32_t serviceId, uint32_t methodId) override;
- };
-
- class EchoErrorPolicyAbort
- : public EchoErrorPolicyAbortOnMessageFormatError
- {
- public:
- void ServiceNotFound(uint32_t serviceId) override;
- void MethodNotFound(uint32_t serviceId, uint32_t methodId) override;
- };
-
- extern EchoErrorPolicyAbortOnMessageFormatError echoErrorPolicyAbortOnMessageFormatError;
- extern EchoErrorPolicyAbort echoErrorPolicyAbort;
-
class Service
: public infra::Observer
{
@@ -170,25 +26,10 @@ namespace services
virtual bool AcceptsService(uint32_t id) const = 0;
void MethodDone();
- bool InProgress() const;
- void HandleMethod(uint32_t serviceId, uint32_t methodId, infra::ProtoLengthDelimited& contents, EchoErrorPolicy& errorPolicy);
+ virtual infra::SharedPtr StartMethod(uint32_t serviceId, uint32_t methodId, uint32_t size, const EchoErrorPolicy& errorPolicy) = 0;
protected:
Echo& Rpc();
- virtual void Handle(uint32_t serviceId, uint32_t methodId, infra::ProtoLengthDelimited& contents, EchoErrorPolicy& errorPolicy) = 0;
-
- private:
- bool inProgress = false;
- };
-
- class Echo
- : public infra::Subject
- {
- public:
- virtual void RequestSend(ServiceProxy& serviceProxy) = 0;
- virtual infra::StreamWriter& SendStreamWriter() = 0;
- virtual void Send() = 0;
- virtual void ServiceDone(Service& service) = 0;
};
class ServiceProxy
@@ -200,46 +41,26 @@ namespace services
Echo& Rpc();
virtual void RequestSend(infra::Function onGranted);
virtual void RequestSend(infra::Function onGranted, uint32_t requestedSize);
- void GrantSend();
+ virtual infra::SharedPtr GrantSend();
uint32_t MaxMessageSize() const;
uint32_t CurrentRequestedSize() const;
+ void SetSerializer(const infra::SharedPtr& serializer);
private:
Echo& echo;
uint32_t maxMessageSize;
infra::Function onGranted;
uint32_t currentRequestedSize = 0;
+ infra::SharedPtr methodSerializer;
};
- template
- class ServiceProxyResponseQueue
- : public ServiceProxyType
+ class Echo
+ : public infra::Subject
{
public:
- struct Request
- {
- infra::Function onRequestGranted;
- uint32_t requestedSize;
- };
-
- using Container = infra::BoundedDeque;
-
- template
- using WithStorage = infra::WithStorage>;
-
- template
- explicit ServiceProxyResponseQueue(Container& container, Args&&... args);
-
- void RequestSend(infra::Function onRequestGranted) override;
- void RequestSend(infra::Function onRequestGranted, uint32_t requestedSize) override;
-
- private:
- void ProcessSendQueue();
-
- private:
- Container& container;
-
- bool responseInProgress{ false };
+ virtual void RequestSend(ServiceProxy& serviceProxy) = 0;
+ virtual void ServiceDone() = 0;
+ virtual services::MethodSerializerFactory& SerializerFactory() = 0;
};
class EchoOnStreams
@@ -247,329 +68,50 @@ namespace services
, public infra::EnableSharedFromThis
{
public:
- explicit EchoOnStreams(EchoErrorPolicy& errorPolicy = echoErrorPolicyAbortOnMessageFormatError);
+ explicit EchoOnStreams(services::MethodSerializerFactory& serializerFactory, const EchoErrorPolicy& errorPolicy = echoErrorPolicyAbortOnMessageFormatError);
+ ~EchoOnStreams() override;
// Implementation of Echo
void RequestSend(ServiceProxy& serviceProxy) override;
- infra::StreamWriter& SendStreamWriter() override;
- void Send() override;
- void ServiceDone(Service& service) override;
+ void ServiceDone() override;
+ services::MethodSerializerFactory& SerializerFactory() override;
protected:
+ virtual infra::SharedPtr GrantSend(ServiceProxy& proxy);
+ virtual infra::SharedPtr StartingMethod(uint32_t serviceId, uint32_t methodId, uint32_t size, const infra::SharedPtr& deserializer);
virtual void RequestSendStream(std::size_t size) = 0;
- virtual void BusyServiceDone() = 0;
+ virtual void AckReceived() = 0;
- virtual void ExecuteMethod(uint32_t serviceId, uint32_t methodId, infra::ProtoLengthDelimited& contents, infra::StreamReaderWithRewinding& reader);
- virtual void SetStreamWriter(infra::SharedPtr&& writer);
- bool ServiceBusy() const;
- bool ProcessMessage(infra::StreamReaderWithRewinding& reader);
-
- protected:
- EchoErrorPolicy& errorPolicy;
+ void SendStreamAvailable(infra::SharedPtr&& writer);
+ void DataReceived(infra::SharedPtr&& reader);
+ void ReleaseReader();
private:
- infra::SharedPtr streamWriter;
- infra::IntrusiveList sendRequesters;
- infra::Optional serviceBusy;
- };
-
- //// Implementation ////
-
- inline void SerializeField(ProtoBool, infra::ProtoFormatter& formatter, bool value, uint32_t fieldNumber)
- {
- formatter.PutVarIntField(value, fieldNumber);
- }
+ void TryGrantSend();
- 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);
- }
+ void DataReceived();
+ void StartReceiveMessage();
+ void ContinueReceiveMessage();
+ void StartMethod(uint32_t serviceId, uint32_t methodId, uint32_t size);
+ void ReaderDone();
- 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