pax_global_header00006660000000000000000000000064144453635310014522gustar00rootroot0000000000000052 comment=fab737efbb4b4d03e7c771393708f75594b121e4 protoc-gen-validate-1.0.2/000077500000000000000000000000001444536353100153665ustar00rootroot00000000000000protoc-gen-validate-1.0.2/.bazelversion000066400000000000000000000000061444536353100200660ustar00rootroot000000000000006.2.0 protoc-gen-validate-1.0.2/.clang-format000077500000000000000000000004311444536353100177420ustar00rootroot00000000000000--- Language: Cpp AccessModifierOffset: -2 ColumnLimit: 100 DerivePointerAlignment: false PointerAlignment: Left SortIncludes: false ... --- Language: Proto ColumnLimit: 100 SpacesInContainerLiterals: false AllowShortFunctionsOnASingleLine: false ReflowComments: false ... protoc-gen-validate-1.0.2/.dockerignore000066400000000000000000000000311444536353100200340ustar00rootroot00000000000000.git/ .idea/ .bin/ dist/ protoc-gen-validate-1.0.2/.github/000077500000000000000000000000001444536353100167265ustar00rootroot00000000000000protoc-gen-validate-1.0.2/.github/CODE_OF_CONDUCT.md000066400000000000000000000125351444536353100215330ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at conduct@buf.build. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations]. [homepage]: https://www.contributor-covenant.org [v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq [translations]: https://www.contributor-covenant.org/translations protoc-gen-validate-1.0.2/.github/actions/000077500000000000000000000000001444536353100203665ustar00rootroot00000000000000protoc-gen-validate-1.0.2/.github/actions/github-tag-action/000077500000000000000000000000001444536353100236745ustar00rootroot00000000000000protoc-gen-validate-1.0.2/.github/actions/github-tag-action/entrypoint.sh000077500000000000000000000143651444536353100264570ustar00rootroot00000000000000#!/bin/bash set -o pipefail # config default_semvar_bump=${DEFAULT_BUMP:-patch} with_v=${WITH_V:-true} release_branches=${RELEASE_BRANCHES:-} custom_tag=${CUSTOM_TAG:-} source=${SOURCE:-.} dryrun=${DRY_RUN:-false} initial_version=${INITIAL_VERSION:-0.0.0} tag_context=${TAG_CONTEXT:-repo} prerelease=${PRERELEASE:-true} suffix=${PRERELEASE_SUFFIX:-SNAPSHOT} verbose=${VERBOSE:-false} major_string_token=${MAJOR_STRING_TOKEN:-#major} minor_string_token=${MINOR_STRING_TOKEN:-#minor} patch_string_token=${PATCH_STRING_TOKEN:-#patch} none_string_token=${NONE_STRING_TOKEN:-#none} # since https://github.blog/2022-04-12-git-security-vulnerability-announced/ runner uses? git config --global --add safe.directory /github/workspace cd "${GITHUB_WORKSPACE}/${source}" || exit 1 echo "*** CONFIGURATION ***" echo -e "\tDEFAULT_BUMP: ${default_semvar_bump}" echo -e "\tWITH_V: ${with_v}" echo -e "\tRELEASE_BRANCHES: ${release_branches}" echo -e "\tCUSTOM_TAG: ${custom_tag}" echo -e "\tSOURCE: ${source}" echo -e "\tDRY_RUN: ${dryrun}" echo -e "\tINITIAL_VERSION: ${initial_version}" echo -e "\tTAG_CONTEXT: ${tag_context}" echo -e "\tPRERELEASE: ${prerelease}" echo -e "\tPRERELEASE_SUFFIX: ${suffix}" echo -e "\tVERBOSE: ${verbose}" echo -e "\tMAJOR_STRING_TOKEN: ${major_string_token}" echo -e "\tMINOR_STRING_TOKEN: ${minor_string_token}" echo -e "\tPATCH_STRING_TOKEN: ${patch_string_token}" echo -e "\tNONE_STRING_TOKEN: ${none_string_token}" # verbose, show everything if $verbose then set -x fi setOutput() { echo "${1}=${2}" >> "${GITHUB_OUTPUT}" } current_branch=$(git rev-parse --abbrev-ref HEAD) pre_release="$prerelease" IFS=',' read -ra branch <<< "$release_branches" for b in "${branch[@]}"; do # check if ${current_branch} is in ${release_branches} | exact branch match if [[ "$current_branch" == "$b" ]] then pre_release="false" fi # verify non specific branch names like .* release/* if wildcard filter then =~ if [ "$b" != "${b//[\[\]|.? +*]/}" ] && [[ "$current_branch" =~ $b ]] then pre_release="false" fi done echo "pre_release = $pre_release" # fetch tags git fetch --tags tagFmt="^v?[0-9]+\.[0-9]+\.[0-9]+$" preTagFmt="^v?[0-9]+\.[0-9]+\.[0-9]+(-$suffix\.[0-9]+)$" # get latest tag that looks like a semver (with or without v) case "$tag_context" in *repo*) tag="$(git for-each-ref --sort=-v:refname --format '%(refname:lstrip=2)' | grep -E "$tagFmt" | head -n 1)" pre_tag="$(git for-each-ref --sort=-v:refname --format '%(refname:lstrip=2)' | grep -E "$preTagFmt" | head -n 1)" ;; *branch*) tag="$(git tag --list --merged HEAD --sort=-v:refname | grep -E "$tagFmt" | head -n 1)" pre_tag="$(git tag --list --merged HEAD --sort=-v:refname | grep -E "$preTagFmt" | head -n 1)" ;; * ) echo "Unrecognised context" exit 1;; esac # if there are none, start tags at INITIAL_VERSION if [ -z "$tag" ] then if $with_v then tag="v$initial_version" else tag="$initial_version" fi if [ -z "$pre_tag" ] && $pre_release then if $with_v then pre_tag="v$initial_version" else pre_tag="$initial_version" fi fi fi # get current commit hash for tag tag_commit=$(git rev-list -n 1 "$tag") # get current commit hash commit=$(git rev-parse HEAD) if [ "$tag_commit" == "$commit" ] then echo "No new commits since previous tag. Skipping..." setOutput "new_tag" "$tag" setOutput "tag" "$tag" exit 0 fi # get the merge commit message looking for #bumps log=$(git show -s --format=%s) echo "Last commit message: $log" case "$log" in *$major_string_token* ) new=$(semver -i major "$tag"); part="major";; *$minor_string_token* ) new=$(semver -i minor "$tag"); part="minor";; *$patch_string_token* ) new=$(semver -i patch "$tag"); part="patch";; *$none_string_token* ) echo "Default bump was set to none. Skipping..." setOutput "new_tag" "$tag" setOutput "tag" "$tag" exit 0;; * ) if [ "$default_semvar_bump" == "none" ] then echo "Default bump was set to none. Skipping..." setOutput "new_tag" "$tag" setOutput "tag" "$tag" exit 0 else new=$(semver -i "${default_semvar_bump}" "$tag") part=$default_semvar_bump fi ;; esac if $pre_release then # already a pre-release available, bump it newPreTagFmt="$new+(-$suffix\.[0-9]+)$" exists="$(git tag --list --merged HEAD --sort=-v:refname | grep -E "$newPreTagFmt" | head -n 1)" if [[ $exists != "" ]] then echo -e "Found parent to ${new} pre-tag ${exists}..." new=$(semver -i prerelease "${exists}" --preid "${suffix}") echo -e "Bumping ${suffix} pre-tag ${exists}. New pre-tag ${new}" elif [[ "$pre_tag" =~ $new ]] && [[ "$pre_tag" =~ $suffix ]] then new=$(semver -i prerelease "${pre_tag}" --preid "${suffix}") echo -e "Bumping ${suffix} pre-tag ${pre_tag}. New pre-tag ${new}" else new="$new-$suffix.0" echo -e "Setting ${suffix} pre-tag ${pre_tag} - With pre-tag ${new}" fi part="pre-$part" else echo -e "Bumping tag ${tag} - New tag ${new}" fi if $with_v then new="v$new" fi # as defined in readme if CUSTOM_TAG is used any semver calculations are irrelevant. if [ -n "$custom_tag" ] then new="$custom_tag" fi # set outputs setOutput "new_tag" "$new" setOutput "part" "$part" setOutput "tag" "$new" # this needs to go in v2 is breaking change setOutput "old_tag" "$tag" # dry run exit without real changes if $dryrun then exit 0 fi # create local git tag git tag "$new" # push new tag ref to github dt=$(date '+%Y-%m-%dT%H:%M:%SZ') full_name=$GITHUB_REPOSITORY git_refs_url=$(jq .repository.git_refs_url "$GITHUB_EVENT_PATH" | tr -d '"' | sed 's/{\/sha}//g') echo "$dt: **pushing tag $new to repo $full_name" git_refs_response=$( curl -s -X POST "$git_refs_url" \ -H "Authorization: token $GITHUB_TOKEN" \ -d @- << EOF { "ref": "refs/tags/$new", "sha": "$commit" } EOF ) git_ref_posted=$( echo "${git_refs_response}" | jq .ref | tr -d '"' ) echo "::debug::${git_refs_response}" if [ "${git_ref_posted}" = "refs/tags/${new}" ] then exit 0 else echo "::error::Tag was not created properly." exit 1 fi protoc-gen-validate-1.0.2/.github/buf-logo.svg000066400000000000000000000011511444536353100211570ustar00rootroot00000000000000 protoc-gen-validate-1.0.2/.github/dependabot.yml000066400000000000000000000005201444536353100215530ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "gomod" directory: "/" schedule: interval: "weekly" - package-ecosystem: "gomod" directory: "/tests" schedule: interval: "weekly" - package-ecosystem: "maven" directory: "/java" schedule: interval: "weekly" open-pull-requests-limit: 40 protoc-gen-validate-1.0.2/.github/stale.yml000066400000000000000000000013521444536353100205620ustar00rootroot00000000000000# Number of days of inactivity before an issue becomes stale daysUntilStale: 30 # Number of days of inactivity before a stale issue is closed daysUntilClose: 7 # Issues with these labels will never be considered stale exemptLabels: - Bug - Bazel - Documentation - Enhancement - Help Wanted - Language Support # Label to use when marking an issue as stale staleLabel: Stale # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. # Comment to post when closing a stale issue. Set to `false` to disable closeComment: falseprotoc-gen-validate-1.0.2/.github/workflows/000077500000000000000000000000001444536353100207635ustar00rootroot00000000000000protoc-gen-validate-1.0.2/.github/workflows/ci.yaml000066400000000000000000000030631444536353100222440ustar00rootroot00000000000000name: ci on: push: branches: - main pull_request: workflow_dispatch: env: # Keep these versions in sync with the Dockerfile BDR_VER: '6.0.1' GO_VER: '1.19.x' PGG_VER: 'v1.30.0' PROTOC_VER: '22.2' PYTHON_VER: '3.8' TEST_TAG: protoc-gen-validate:${{ github.sha }} jobs: ci: runs-on: ubuntu-latest steps: - name: Cache uses: actions/cache@v3 with: path: | ~/.cache/bazelisk ~/.cache/bazel ~/.cache/protoc key: ${{ runner.os }}-build-cache - name: Checkout uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VER }} cache: true - uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VER }} cache: 'pip' - name: Install Dependencies run: | mkdir -p ~/.cache/protoc PROTOC_ZIP="${HOME}/.cache/protoc/${PROTOC_VER}.zip" if [[ ! -f "${PROTOC_ZIP}" ]]; then curl -fsSL -o "${PROTOC_ZIP}" https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VER}/protoc-${PROTOC_VER}-linux-x86_64.zip fi unzip -q ${PROTOC_ZIP} -d ~/protoc echo "${HOME}/protoc/bin" >> $GITHUB_PATH go install google.golang.org/protobuf/cmd/protoc-gen-go@${PGG_VER} go install github.com/bazelbuild/buildtools/buildozer@${BDR_VER} pip install -r requirements.txt - name: Build run: make build - name: Run run: make ci protoc-gen-validate-1.0.2/.github/workflows/emergency-review-bypass.yaml000066400000000000000000000004651444536353100264300ustar00rootroot00000000000000name: Bypass review in case of emergency on: pull_request: types: - labeled permissions: pull-requests: write jobs: approve: if: github.event.label.name == 'Emergency Bypass Review' uses: bufbuild/base-workflows/.github/workflows/emergency-review-bypass.yaml@main secrets: inherit protoc-gen-validate-1.0.2/.github/workflows/goreleaser.yaml000066400000000000000000000015141444536353100240000ustar00rootroot00000000000000# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json name: goreleaser on: push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' permissions: contents: write jobs: goreleaser: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - run: git fetch --force --tags - uses: actions/setup-go@v3 with: go-version: 1.19.x use-latest: true cache: true - uses: goreleaser/goreleaser-action@v2 with: distribution: goreleaser version: latest args: release --rm-dist env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload assets uses: actions/upload-artifact@v3 with: name: protoc-gen-validate path: dist/* protoc-gen-validate-1.0.2/.github/workflows/maven-build.yaml000066400000000000000000000012711444536353100240530ustar00rootroot00000000000000# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created ## For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path name: Maven Verify on: pull_request: jobs: build: runs-on: ubuntu-latest permissions: contents: read steps: - uses: actions/checkout@v3 - name: Set up JDK 17 uses: actions/setup-java@v3 with: java-version: "17" distribution: "temurin" cache: "maven" - name: Verify with Maven working-directory: ${{ github.workspace }}/java run: mvn -B verify protoc-gen-validate-1.0.2/.github/workflows/maven-deploy.yaml000066400000000000000000000057271444536353100242620ustar00rootroot00000000000000# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created ## For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path name: Maven Deploy on: push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' jobs: build: runs-on: ubuntu-latest env: SONATYPE_USER: ${{secrets.BUF_SONATYPE_USER}} SONATYPE_PASSWORD: ${{secrets.BUF_SONATYPE_PASSWORD}} GPG_KEY_NAME: ${{secrets.GPG_KEY_NAME}} GPG_PASSPHRASE: ${{secrets.GPG_PASSPHRASE}} MAVEN_OPTS: "--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.text=ALL-UNNAMED --add-opens=java.desktop/java.awt.font=ALL-UNNAMED" REF_NAME: ${{ github.ref_name }} steps: - uses: actions/checkout@v3 - name: Set VERSION variable from tag run: | VERSION=${{ env.REF_NAME }} echo "VERSION=${VERSION:1}" >> $GITHUB_ENV - name: 'Configure GPG signing' env: GPG_KEY: ${{ secrets.GPG_PRIVATE_KEY }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} run: | # https://github.com/keybase/keybase-issues/issues/2798 export GPG_TTY=$(tty) # Import gpg keys and warm the passphrase to avoid the gpg # passphrase prompt when initating a deploy # `--pinentry-mode=loopback` could be needed to ensure we # suppress the gpg prompt echo $GPG_KEY | base64 --decode > signing-key gpg --passphrase $GPG_PASSPHRASE --batch --import signing-key shred signing-key - name: Configure GIT run: | git config --global user.email "envoy-bot@users.noreply.github.com" git config --global user.name "envoy-bot" - name: Set up JDK uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: '17' cache: 'maven' server-id: sonatype-nexus-snapshots server-username: ${ env.SONATYPE_USER } server-password: ${ env.SONATYPE_PASSWORD } gpg-private-key: ${{ secrets.GPG_SECRET_KEY }} gpg-passphrase: ${ env.GPG_PASSPHRASE } - name: Update version in pom working-directory: ${{ github.workspace }}/java run: mvn -B versions:set -DnewVersion=${{ env.VERSION }} -DgenerateBackupPoms=false - name: Publish to Maven Packages Apache Maven working-directory: ${{ github.workspace }}/java run: | mvn -B -s settings.xml clean deploy \ -Darguments="-s settings.xml" \ -DreleaseVersion=${{ env.VERSION }} \ -DdevelopmentVersion=${{ env.VERSION }}-SNAPSHOT \ -DscmCommentPrefix="java release: " env: MAVEN_USERNAME: ${{ env.SONATYPE_USER }} MAVEN_CENTRAL_TOKEN: ${{ env.SONATYPE_PASSWORD }} MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} protoc-gen-validate-1.0.2/.github/workflows/notify-approval-bypass.yaml000066400000000000000000000004121444536353100262750ustar00rootroot00000000000000name: PR Approval Bypass Notifier on: pull_request: types: - closed branches: - main permissions: pull-requests: read jobs: approval: uses: bufbuild/base-workflows/.github/workflows/notify-approval-bypass.yaml@main secrets: inherit protoc-gen-validate-1.0.2/.github/workflows/pr-title.yaml000066400000000000000000000011441444536353100234070ustar00rootroot00000000000000name: Lint PR Title # Prevent writing to the repository using the CI token. # Ref: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#permissions permissions: pull-requests: read on: pull_request: # By default, a workflow only runs when a pull_request's activity type is opened, # synchronize, or reopened. We explicity override here so that PR titles are # re-linted when the PR text content is edited. types: - opened - edited - reopened - synchronize jobs: lint: uses: bufbuild/base-workflows/.github/workflows/pr-title.yaml@main protoc-gen-validate-1.0.2/.github/workflows/python-package.yaml000066400000000000000000000015471444536353100245700ustar00rootroot00000000000000name: Release Python Package on: push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' env: IMAGE_TAG: protoc-gen-validate:${{ github.sha }} REF_NAME: ${{ github.ref_name }} jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Set up QEMU uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Build and export to Docker uses: docker/build-push-action@v3 with: context: . load: true push: false tags: ${{ env.IMAGE_TAG }} - run: | docker run --rm \ --env PYPI_REPO=pypi \ --env PGV_PYPI_TOKEN="${{ secrets.PGV_PYPI_TOKEN }}" \ ${{ env.IMAGE_TAG }} SETUPTOOLS_SCM_PRETEND_VERSION=${{ env.REF_NAME }} python-release protoc-gen-validate-1.0.2/.github/workflows/version-bump.yaml000066400000000000000000000023251444536353100242770ustar00rootroot00000000000000name: Version Bump on: push: branches: - main workflow_dispatch: inputs: prerelease: type: boolean description: Pre-release? default: true bump: type: choice description: Which version? default: 'minor' options: - minor - patch env: PRERELEASE: ${{github.event.inputs.prerelease}} DEFAULT_BUMP: ${{github.event.inputs.bump}} APP_ID: 257305 jobs: build: runs-on: ubuntu-22.04 steps: - name: Generate token id: generate_token uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92 with: app_id: ${{ env.APP_ID }} private_key: ${{ secrets.TOKEN_EXCHANGE_GH_APP_PRIVATE_KEY }} repository: ${{ github.repository }} permissions: >- {"contents": "write"} - uses: actions/checkout@v3 with: fetch-depth: "0" - uses: actions/setup-node@v3 with: node-version: 16 - run: npm install -g semver - name: Bump version and push tag env: GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} run: .github/actions/github-tag-action/entrypoint.sh protoc-gen-validate-1.0.2/.gitignore000066400000000000000000000024151444536353100173600ustar00rootroot00000000000000bazel-* **/.DS_Store !vendor/* /bin /cmd/protoc-gen-validate-cpp/protoc-gen-validate-cpp /cmd/protoc-gen-validate-go/protoc-gen-validate-go /cmd/protoc-gen-validate-java/protoc-gen-validate-java /dist/ /protoc-gen-validate /python/LICENSE /python/validate.proto /python/dist/ *.egg-info/ __pycache__/ *.py[cod] /tests/harness/cases/go /tests/harness/cases/gogo /tests/harness/cases/other_package/go /tests/harness/cases/other_package/gogo /tests/harness/cases/yet_another_package/go /tests/harness/cases/yet_another_package/gogo /tests/harness/cases/sort/go /tests/harness/cases/sort/gogo /tests/harness/go/harness.pb.go /tests/harness/go/main/go-harness /tests/harness/go/main/go-harness.exe /tests/harness/gogo/harness.pb.go /tests/harness/gogo/main/go-harness /tests/harness/gogo/main/go-harness.exe /tests/harness/cc/cc-harness /tests/harness/cc/cc-harness.exe /validate/__pycache__ /tests/harness/cases/**/*.cc /tests/harness/cases/**/*.h /java/.idea /java/**/.project /java/**/*.iml /java/**/target /java/**/*.class .vscode .project .classpath .settings .idea/ .ijwb/ # Local cache directory. .cache # Local build directory. /build # Generated test cases Go files. /tests/harness/**/*.pb.go /tests/harness/**/*.pb.validate.go # Harness test binary. /tests/harness/**/*-harness protoc-gen-validate-1.0.2/.goreleaser.yaml000066400000000000000000000036251444536353100204660ustar00rootroot00000000000000builds: - main: . id: "protoc-gen-validate" binary: "protoc-gen-validate" - main: ./cmd/protoc-gen-validate-cpp id: "protoc-gen-validate-cpp" binary: "protoc-gen-validate-cpp" - main: ./cmd/protoc-gen-validate-go id: "protoc-gen-validate-go" binary: "protoc-gen-validate-go" - main: ./cmd/protoc-gen-validate-java id: "protoc-gen-validate-java" binary: "protoc-gen-validate-java" release: # If set to true, will not auto-publish the release. # Available only for GitHub and Gitea. # Default is false. draft: true # Whether to remove existing draft releases with the same name before creating a new one. # Only effective if `draft` is set to true. # Available only for GitHub. # # Default: false. # Since: v1.11. replace_existing_draft: true # Useful if you want to delay the creation of the tag in the remote. # You can create the tag locally, but not push it, and run GoReleaser. # It'll then set the `target_commitish` portion of the GitHub release to the value of this field. # Only works on GitHub. # # Default: empty. # Since: v1.11. target_commitish: "{{ .Commit }}" # If set to auto, will mark the release as not ready for production # in case there is an indicator for this in the tag e.g. v1.0.0-rc1 # If set to true, will mark the release as not ready for production. # Default is false. prerelease: auto # What to do with the release notes in case there the release already exists. # # Valid options are: # - `keep-existing`: keep the existing notes # - `append`: append the current release notes to the existing notes # - `prepend`: prepend the current release notes to the existing notes # - `replace`: replace existing notes # # Default is `keep-existing`. mode: keep-existing # You can change the name of the release. # Default is `{{.Tag}}` on OSS and `{{.PrefixedTag}}` on Pro. name_template: "{{.Tag}}" protoc-gen-validate-1.0.2/BUILD.bazel000066400000000000000000000016421444536353100172470ustar00rootroot00000000000000load("@bazel_gazelle//:def.bzl", "gazelle") load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") # gazelle:prefix github.com/envoyproxy/protoc-gen-validate # gazelle:exclude tests # gazelle:exclude example-workspace # gazelle:exclude validate/validate.h # gazelle:go_naming_convention import_alias gazelle(name = "gazelle") go_binary( name = "protoc-gen-validate", embed = [":protoc-gen-validate_lib"], importpath = "github.com/envoyproxy/protoc-gen-validate", visibility = ["//visibility:public"], ) go_library( name = "protoc-gen-validate_lib", srcs = ["main.go"], importpath = "github.com/envoyproxy/protoc-gen-validate", visibility = ["//visibility:private"], deps = [ "//module", "@com_github_lyft_protoc_gen_star_v2//:protoc-gen-star", "@com_github_lyft_protoc_gen_star_v2//lang/go", "@org_golang_google_protobuf//types/pluginpb", ], ) protoc-gen-validate-1.0.2/Dockerfile000066400000000000000000000042521444536353100173630ustar00rootroot00000000000000FROM ubuntu:focal ENV DEBIAN_FRONTEND=noninteractive # apt packages ENV INSTALL_DEPS \ ca-certificates \ git \ make \ zip \ unzip \ g++ \ wget \ maven \ patch \ python3 \ python3-distutils \ python3-setuptools \ apt-transport-https \ curl \ openjdk-8-jdk \ gnupg RUN apt update \ && apt install -y -q --no-install-recommends ${INSTALL_DEPS} \ && apt clean # bazel ENV BAZEL_VER=6.1.1 RUN wget -q -O bazel https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VER}/bazel-${BAZEL_VER}-linux-$([ $(uname -m) = "aarch64" ] && echo "arm64" || echo "x86_64") \ && chmod +x bazel \ && mv bazel usr/local/bin/bazel # protoc ENV PROTOC_VER=22.2 RUN export PROTOC_REL=protoc-${PROTOC_VER}-linux-$([ $(uname -m) = "aarch64" ] && echo "aarch" || echo "x86")_64.zip \ && wget -q https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VER}/${PROTOC_REL} \ && unzip ${PROTOC_REL} -d protoc \ && mv protoc /usr/local \ && ln -s /usr/local/protoc/bin/protoc /usr/local/bin \ && rm ${PROTOC_REL} # go ENV GOROOT /usr/local/go ENV GOPATH /go ENV PATH $GOPATH/bin:$GOROOT/bin:$PATH RUN export GORELEASE=go1.19.7.linux-$([ $(uname -m) = "aarch64" ] && echo "arm64" || echo "amd64").tar.gz \ && wget -q https://dl.google.com/go/$GORELEASE \ && tar -C $(dirname $GOROOT) -xzf $GORELEASE \ && rm $GORELEASE \ && mkdir -p $GOPATH/{src,bin,pkg} # protoc-gen-go ENV PGG_VER=v1.30.0 RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@${PGG_VER} \ && rm -rf $(go env GOCACHE) \ && rm -rf $(go env GOMODCACHE) # buildozer ENV BDR_VER=6.0.1 RUN go install github.com/bazelbuild/buildtools/buildozer@${BDR_VER} \ && rm -rf $(go env GOCACHE) \ && rm -rf $(go env GOMODCACHE) # python must be on PATH for the execution of py_binary bazel targets, but # the distribution we installed doesn't provide this alias RUN ln -s /usr/bin/python3.8 /usr/bin/python WORKDIR ${GOPATH}/src/github.com/envoyproxy/protoc-gen-validate # python tooling for linting and uploading to PyPI COPY requirements.txt . RUN python3.8 -m easy_install pip \ && python3.8 -m pip install -r requirements.txt COPY . . RUN make build ENTRYPOINT ["make"] CMD ["build"] protoc-gen-validate-1.0.2/LICENSE000066400000000000000000000261361444536353100164030ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. protoc-gen-validate-1.0.2/Makefile000066400000000000000000000171631444536353100170360ustar00rootroot00000000000000empty := space := $(empty) $(empty) PACKAGE := github.com/envoyproxy/protoc-gen-validate # protoc-gen-go parameters for properly generating the import path for PGV VALIDATE_IMPORT := Mvalidate/validate.proto=${PACKAGE}/validate GO_IMPORT_SPACES := ${VALIDATE_IMPORT},\ Mgoogle/protobuf/any.proto=google.golang.org/protobuf/types/known/anypb,\ Mgoogle/protobuf/duration.proto=google.golang.org/protobuf/types/known/durationpb,\ Mgoogle/protobuf/struct.proto=google.golang.org/protobuf/types/known/structpb,\ Mgoogle/protobuf/timestamp.proto=google.golang.org/protobuf/types/known/timestamppb,\ Mgoogle/protobuf/wrappers.proto=google.golang.org/protobuf/types/known/wrapperspb,\ Mgoogle/protobuf/descriptor.proto=google.golang.org/protobuf/types/descriptorpb GO_IMPORT:=$(subst $(space),,$(GO_IMPORT_SPACES)) .DEFAULT_GOAL := help .PHONY: help help: Makefile @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' .PHONY: build build: validate/validate.pb.go ## generates the PGV binary and installs it into $$GOPATH/bin go install . .PHONY: bazel bazel: ## generate the PGV plugin with Bazel bazel build //cmd/... //tests/... .PHONY: build_generation_tests build_generation_tests: bazel build //tests/generation/... .PHONY: gazelle gazelle: ## runs gazelle against the codebase to generate Bazel BUILD files bazel run //:gazelle -- update-repos -from_file=go.mod -prune -to_macro=dependencies.bzl%go_third_party bazel run //:gazelle .PHONY: lint lint: bin/golint bin/shadow ## lints the package for common code smells test -z "$(shell gofmt -d -s ./*.go)" || (gofmt -d -s ./*.go && exit 1) # golint -set_exit_status # check for variable shadowing go vet -vettool=$(shell pwd)/bin/shadow ./... # lints the python code for style enforcement flake8 --config=python/setup.cfg python/protoc_gen_validate/validator.py isort --check-only python/protoc_gen_validate/validator.py bin/shadow: GOBIN=$(shell pwd)/bin go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow bin/golint: GOBIN=$(shell pwd)/bin go install golang.org/x/lint/golint bin/protoc-gen-go: GOBIN=$(shell pwd)/bin go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.30.0 bin/harness: cd tests && go build -o ../bin/harness ./harness/executor .PHONY: harness harness: testcases tests/harness/go/harness.pb.go tests/harness/go/main/go-harness tests/harness/cc/cc-harness bin/harness ## runs the test harness, validating a series of test cases in all supported languages ./bin/harness -go -cc .PHONY: bazel-tests bazel-tests: ## runs all tests with Bazel bazel test //tests/... --test_output=errors .PHONY: example-workspace example-workspace: ## run all tests in the example workspace cd example-workspace && bazel test //... --test_output=errors .PHONY: testcases testcases: bin/protoc-gen-go ## generate the test harness case protos rm -r tests/harness/cases/go || true mkdir tests/harness/cases/go rm -r tests/harness/cases/other_package/go || true mkdir tests/harness/cases/other_package/go rm -r tests/harness/cases/yet_another_package/go || true mkdir tests/harness/cases/yet_another_package/go rm -r tests/harness/cases/sort/go || true mkdir tests/harness/cases/sort/go # protoc-gen-go makes us go a package at a time cd tests/harness/cases/other_package && \ protoc \ -I . \ -I ../../../.. \ --go_out="module=${PACKAGE}/tests/harness/cases/other_package/go,${GO_IMPORT}:./go" \ --plugin=protoc-gen-go=$(shell pwd)/bin/protoc-gen-go \ --validate_out="module=${PACKAGE}/tests/harness/cases/other_package/go,lang=go:./go" \ ./*.proto cd tests/harness/cases/yet_another_package && \ protoc \ -I . \ -I ../../../.. \ --go_out="module=${PACKAGE}/tests/harness/cases/yet_another_package/go,${GO_IMPORT}:./go" \ --plugin=protoc-gen-go=$(shell pwd)/bin/protoc-gen-go \ --validate_out="module=${PACKAGE}/tests/harness/cases/yet_another_package/go,lang=go:./go" \ ./*.proto cd tests/harness/cases/sort && \ protoc \ -I . \ -I ../../../.. \ --go_out="module=${PACKAGE}/tests/harness/cases/sort/go,${GO_IMPORT}:./go" \ --plugin=protoc-gen-go=$(shell pwd)/bin/protoc-gen-go \ --validate_out="module=${PACKAGE}/tests/harness/cases/sort/go,lang=go:./go" \ ./*.proto cd tests/harness/cases && \ protoc \ -I . \ -I ../../.. \ --go_out="module=${PACKAGE}/tests/harness/cases/go,Mtests/harness/cases/other_package/embed.proto=${PACKAGE}/tests/harness/cases/other_package/go;other_package,Mtests/harness/cases/yet_another_package/embed.proto=${PACKAGE}/tests/harness/cases/yet_another_package/go,${GO_IMPORT}:./go" \ --plugin=protoc-gen-go=$(shell pwd)/bin/protoc-gen-go \ --validate_out="module=${PACKAGE}/tests/harness/cases/go,lang=go,Mtests/harness/cases/other_package/embed.proto=${PACKAGE}/tests/harness/cases/other_package/go,Mtests/harness/cases/yet_another_package/embed.proto=${PACKAGE}/tests/harness/cases/yet_another_package/go:./go" \ ./*.proto validate/validate.pb.go: bin/protoc-gen-go validate/validate.proto protoc -I . \ --plugin=protoc-gen-go=$(shell pwd)/bin/protoc-gen-go \ --go_opt=paths=source_relative \ --go_out="${GO_IMPORT}:." validate/validate.proto tests/harness/go/harness.pb.go: bin/protoc-gen-go tests/harness/harness.proto # generates the test harness protos cd tests/harness && protoc -I . \ --plugin=protoc-gen-go=$(shell pwd)/bin/protoc-gen-go \ --go_out="module=${PACKAGE}/tests/harness/go,${GO_IMPORT}:./go" harness.proto tests/harness/go/main/go-harness: # generates the go-specific test harness cd tests && go build -o ./harness/go/main/go-harness ./harness/go/main tests/harness/cc/cc-harness: tests/harness/cc/harness.cc # generates the C++-specific test harness # use bazel which knows how to pull in the C++ common proto libraries bazel build //tests/harness/cc:cc-harness cp bazel-bin/tests/harness/cc/cc-harness $@ chmod 0755 $@ tests/harness/java/java-harness: # generates the Java-specific test harness mvn -q -f java/pom.xml clean package -DskipTests .PHONY: prepare-python-release prepare-python-release: cp validate/validate.proto python/ cp LICENSE python/ .PHONY: python-release python-release: prepare-python-release rm -rf python/dist python3.8 -m build --no-isolation --sdist python # the below command should be identical to `python3.8 -m build --wheel` # however that returns mysterious `error: could not create 'build': File exists`. # setuptools copies source and data files to a temporary build directory, # but why there's a collision or why setuptools stopped respecting the `build_lib` flag is unclear. # As a workaround, we build a source distribution and then separately build a wheel from it. python3.8 -m pip wheel --wheel-dir python/dist --no-deps python/dist/* python3.8 -m twine upload --verbose --skip-existing --repository ${PYPI_REPO} --username "__token__" --password ${PGV_PYPI_TOKEN} python/dist/* .PHONY: check-generated check-generated: ## run during CI; this checks that the checked-in generated code matches the generated version. for f in validate/validate.pb.go ; do \ mv $$f $$f.original ; \ make $$f ; \ mv $$f $$f.generated ; \ cp $$f.original $$f ; \ diff $$f.original $$f.generated ; \ done .PHONY: ci ci: lint bazel testcases bazel-tests build_generation_tests example-workspace check-generated .PHONY: clean clean: ## clean up generated files (which bazel && bazel clean) || true rm -f \ bin/protoc-gen-go \ bin/harness \ tests/harness/cc/cc-harness \ tests/harness/go/main/go-harness \ tests/harness/go/harness.pb.go rm -rf \ tests/harness/cases/go \ tests/harness/cases/other_package/go \ tests/harness/cases/yet_another_package/go rm -rf \ python/dist \ python/*.egg-info protoc-gen-validate-1.0.2/Next.mk000066400000000000000000000067621444536353100166500ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License") # Plugin name. name := protoc-gen-validate # Root dir returns absolute path of current directory. It has a trailing "/". root_dir := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) # Local cache directory. cache_dir := $(root_dir).cache # Directory of Go tools. go_tools_dir := $(cache_dir)/tools/go # Directory of prepackaged tools (e.g. protoc). prepackaged_tools_dir := $(cache_dir)/tools/prepackaged # Currently we resolve Go using `which`. But more sophisticated approach is to use infer GOROOT. go := $(shell which go) goarch := $(shell $(go) env GOARCH) goexe := $(shell $(go) env GOEXE) goos := $(shell $(go) env GOOS) # The current binary location for the current runtime (goos, goarch). We install our plugin here. current_binary_path := build/$(name)_$(goos)_$(goarch) current_binary := $(current_binary_path)/$(name)$(goexe) # This makes sure protoc can access the installed plugins. export PATH := $(root_dir)$(current_binary_path):$(go_tools_dir)/bin:$(prepackaged_tools_dir)/bin:$(PATH) # The main generated file. validate_pb_go := validate/validate.pb.go # List of harness test cases. tests_harness_cases := \ /harness \ /harness/cases \ /harness/cases/other_package \ /harness/cases/yet_another_package # Include versions of tools we build on-demand include Tools.mk # This provides the "help" target. include tools/build/Help.mk # This sets some required environment variables. include tools/build/Env.mk # Path to the installed protocol buffer compiler. protoc := $(prepackaged_tools_dir)/bin/protoc # Go based tools. bazel := $(go_tools_dir)/bin/bazelisk protoc-gen-go := $(go_tools_dir)/bin/protoc-gen-go test: $(bazel) $(tests_harness_cases) ## Run tests @$(bazel) test //tests/... --test_output=errors build: $(current_binary) ## Build the plugin clean: ## Clean all build and test artifacts @rm -f $(validate_pb_go) @rm -f $(current_binary) check: ## Verify contents of last commit @# Make sure the check-in is clean @if [ ! -z "`git status -s`" ]; then \ echo "The following differences will fail CI until committed:"; \ git diff --exit-code; \ fi # This provides shortcut to various bazel related targets. sanity: bazel-build bazel-build-tests-generation bazel-test-example-workspace bazel-build: $(bazel) ## Build the plugin using bazel @$(bazel) build //:$(name) @mkdir -p $(current_binary_path) @cp -f bazel-bin/$(name)_/$(name)$(goexe) $(current_binary) bazel-build-tests-generation: $(bazel) ## Build tests generation using bazel @$(bazel) build //tests/generation/... bazel-test-example-workspace: $(bazel) ## Test example workspace using bazel @cd example-workspace && bazel test //... --test_output=errors # Generate validate/validate.pb.go from validate/validate.proto. $(validate_pb_go): $(protoc) $(protoc-gen-go) validate/validate.proto @$(protoc) -I . --go_opt=paths=source_relative --go_out=. $(filter %.proto,$^) # Build target for current binary. build/$(name)_%/$(name)$(goexe): $(validate_pb_go) @GOBIN=$(root_dir)$(current_binary_path) $(go) install . # Generate all required files for harness tests in Go. $(tests_harness_cases): $(current_binary) $(call generate-test-cases-go,tests$@) # Generates a test-case for Go. define generate-test-cases-go @cd $1 && \ mkdir -p go && \ $(protoc) \ -I . \ -I $(root_dir) \ --go_opt=paths=source_relative \ --go_out=go \ --validate_opt=paths=source_relative \ --validate_out=lang=go:go \ *.proto endef include tools/build/Installer.mk protoc-gen-validate-1.0.2/README.md000066400000000000000000001004161444536353100166470ustar00rootroot00000000000000# [![](./.github/buf-logo.svg)][buf] protoc-gen-validate (PGV) ![License](https://img.shields.io/github/license/bufbuild/protoc-gen-validate?color=blue) ![Release](https://img.shields.io/github/v/release/bufbuild/protoc-gen-validate?include_prereleases) ![Slack](https://img.shields.io/badge/slack-buf-%23e01563) **_New: The next generation of PGV, called [`protovalidate`][pv], is now available with a [beta release for Go][pv-go]! We're hard at work on C++, Java, TypeScript, and Python implementations as well. To learn more, check out our [blog post][pv-announce]. We value your input in refining our products, so don't hesitate to share your feedback on [`protovalidate`][pv]._** PGV is a protoc plugin to generate polyglot message validators. While protocol buffers effectively guarantee the types of structured data, they cannot enforce semantic rules for values. This plugin adds support to protoc-generated code to validate such constraints. Developers import the PGV extension and annotate the messages and fields in their proto files with constraint rules: ```protobuf syntax = "proto3"; package examplepb; import "validate/validate.proto"; message Person { uint64 id = 1 [(validate.rules).uint64.gt = 999]; string email = 2 [(validate.rules).string.email = true]; string name = 3 [(validate.rules).string = { pattern: "^[^[0-9]A-Za-z]+( [^[0-9]A-Za-z]+)*$", max_bytes: 256, }]; Location home = 4 [(validate.rules).message.required = true]; message Location { double lat = 1 [(validate.rules).double = {gte: -90, lte: 90}]; double lng = 2 [(validate.rules).double = {gte: -180, lte: 180}]; } } ``` Executing `protoc` with PGV and the target language's default plugin will create `Validate` methods on the generated types: ```go p := new(Person) err := p.Validate() // err: Id must be greater than 999 p.Id = 1000 err = p.Validate() // err: Email must be a valid email address p.Email = "example@bufbuild.com" err = p.Validate() // err: Name must match pattern '^[^\d\s]+( [^\d\s]+)*$' p.Name = "Protocol Buffer" err = p.Validate() // err: Home is required p.Home = &Location{37.7, 999} err = p.Validate() // err: Home.Lng must be within [-180, 180] p.Home.Lng = -122.4 err = p.Validate() // err: nil ``` ## Usage ### Dependencies - `go` toolchain (≥ v1.7) - `protoc` compiler in `$PATH` - `protoc-gen-validate` in `$PATH` - official language-specific plugin for target language(s) - **Only `proto3` syntax is currently supported.** `proto2` syntax support is planned. ### Installation #### Download from GitHub Releases Download assets from [GitHub Releases](https://github.com/bufbuild/protoc-gen-validate/releases) and unarchive them and add plugins into `$PATH`. #### Build from source ```sh # fetches this repo into $GOPATH go get -d github.com/envoyproxy/protoc-gen-validate ``` > #### 💡 Yes, our go module path is `github.com/envoyproxy/protoc-gen-validate` **not** `bufbuild` this is intentional. > Changing the module path is effectively creating a new, independent module. We > would prefer not to break our users. The Go team are working on > better `cmd/go` > support for modules that change paths, but progress is slow. Until then, we > will > continue to use the `envoyproxy` module path. ``` git clone github.com/bufbuild/protoc-gen-validate # installs PGV into $GOPATH/bin cd protoc-gen-validate && make build ``` ### Parameters - **`lang`**: specify the target language to generate. Currently, the only supported options are: - `go` - `cc` for c++ (partially implemented) - `java` - Note: Python works via runtime code generation. There's no compile-time generation. See the Python section for details. ### Examples #### Go Go generation should occur into the same output path as the official plugin. For a proto file `example.proto`, the corresponding validation code is generated into `../generated/example.pb.validate.go`: ```sh protoc \ -I . \ -I path/to/validate/ \ --go_out=":../generated" \ --validate_out="lang=go:../generated" \ example.proto ``` All messages generated include the following methods: - `Validate() error` which returns the first error encountered during validation. - `ValidateAll() error` which returns all errors encountered during validation. PGV requires no additional runtime dependencies from the existing generated code. **Note**: by default **example.pb.validate.go** is nested in a directory structure that matches your `option go_package` name. You can change this using the protoc parameter `paths=source_relative:.`, as like `--validate_out="lang=go,paths=source_relative:../generated"`. Then `--validate_out` will output the file where it is expected. See Google's protobuf documentation or [packages and input paths](https://github.com/golang/protobuf#packages-and-input-paths) or [parameters](https://github.com/golang/protobuf#parameters) for more information. There's also support for the `module=example.com/foo` flag [described here](https://developers.google.com/protocol-buffers/docs/reference/go-generated#invocation) . With newer Buf CLI versions (>v1.9.0), you can use the new plugin key instead of using the `protoc` command directly: ``` # buf.gen.yaml version: v1 plugins: - plugin: buf.build/bufbuild/validate-go out: gen ``` ``` # proto/buf.yaml version: v1 deps: - buf.build/envoyproxy/protoc-gen-validate ``` #### Java Java generation is integrated with the existing protobuf toolchain for java projects. For Maven projects, add the following to your pom.xml or build.gradle. ```xml build.buf.protoc-gen-validate pgv-java-stub ${pgv.version} kr.motd.maven os-maven-plugin 1.4.1.Final org.xolstice.maven.plugins protobuf-maven-plugin 0.6.1 com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier} protoc-java-pgv compile-custom lang=java java-pgv build.buf.protoc-gen-validate:protoc-gen-validate:${pgv.version}:exe:${os.detected.classifier} ``` ```gradle plugins { ... id "com.google.protobuf" version "${protobuf.version}" ... } protobuf { protoc { artifact = "com.google.protobuf:protoc:${protoc.version}" } plugins { javapgv { artifact = "build.buf.protoc-gen-validate:protoc-gen-validate:${pgv.version}" } } generateProtoTasks { all()*.plugins { javapgv { option "lang=java" } } } } ``` ```java // Create a validator index that reflectively loads generated validators ValidatorIndex index = new ReflectiveValidatorIndex(); // Assert that a message is valid index.validatorFor(message.getClass()).assertValid(message); // Create a gRPC client and server interceptor to automatically validate messages (requires pgv-java-grpc module) clientStub = clientStub.withInterceptors(new ValidatingClientInterceptor(index)); serverBuilder.addService(ServerInterceptors.intercept(svc, new ValidatingServerInterceptor(index))); ``` #### Python The python implementation works via JIT code generation. In other words, the `validate(msg)` function is written on-demand and [exec-ed](https://docs.python.org/3/library/functions.html#exec). An LRU-cache improves performance by storing generated functions per descriptor. The python package is available on [PyPI](https://pypi.org/project/protoc-gen-validate). To run `validate()`, do the following: ```python from entities_pb2 import Person from protoc_gen_validate.validator import validate, ValidationFailed p = Person(first_name="Foo", last_name="Bar", age=42) try: validate(p) except ValidationFailed as err: print(err) ``` You can view what code has been generated by using the `print_validate()` function. ## Constraint Rules [The provided constraints](validate/validate.proto) are modeled largerly after those in JSON Schema. PGV rules can be mixed for the same field; the plugin ensures the rules applied to a field cannot contradict before code generation. Check the [constraint rule comparison matrix](rule_comparison.md) for language-specific constraint capabilities. ### Numerics > All numeric types (`float`, `double`, `int32`, `int64`, `uint32`, `uint64` > , `sint32`, `sint64`, `fixed32`, `fixed64`, `sfixed32`, `sfixed64`) share the > same rules. - **const**: the field must be _exactly_ the specified value. ```protobuf // x must equal 1.23 exactly float x = 1 [(validate.rules).float.const = 1.23]; ``` - **lt/lte/gt/gte**: these inequalities (`<`, `<=`, `>`, `>=`, respectively) allow for deriving ranges in which the field must reside. ```protobuf // x must be less than 10 int32 x = 1 [(validate.rules).int32.lt = 10]; // x must be greater than or equal to 20 uint64 x = 1 [(validate.rules).uint64.gte = 20]; // x must be in the range [30, 40) fixed32 x = 1 [(validate.rules).fixed32 = {gte:30, lt: 40}]; ``` Inverting the values of `lt(e)` and `gt(e)` is valid and creates an exclusive range. ```protobuf // x must be outside the range [30, 40) double x = 1 [(validate.rules).double = {lt:30, gte:40}]; ``` - **in/not_in**: these two rules permit specifying allow/denylists for the values of a field. ```protobuf // x must be either 1, 2, or 3 uint32 x = 1 [(validate.rules).uint32 = {in: [1,2,3]}]; // x cannot be 0 nor 0.99 float x = 1 [(validate.rules).float = {not_in: [0, 0.99]}]; ``` - **ignore_empty**: this rule specifies that if field is empty or set to the default value, to ignore any validation rules. These are typically useful where being able to unset a field in an update request, or to skip validation for optional fields where switching to WKTs is not feasible. ```protobuf uint32 x = 1 [(validate.rules).uint32 = {ignore_empty: true, gte: 200}]; ``` ### Bools - **const**: the field must be _exactly_ the specified value. ```protobuf // x must be set to true bool x = 1 [(validate.rules).bool.const = true]; // x cannot be set to true bool x = 1 [(validate.rules).bool.const = false]; ``` ### Strings - **const**: the field must be _exactly_ the specified value. ```protobuf // x must be set to "foo" string x = 1 [(validate.rules).string.const = "foo"]; ``` - **len/min_len/max_len**: these rules constrain the number of characters ( Unicode code points) in the field. Note that the number of characters may differ from the number of bytes in the string. The string is considered as-is, and does not normalize. ```protobuf // x must be exactly 5 characters long string x = 1 [(validate.rules).string.len = 5]; // x must be at least 3 characters long string x = 1 [(validate.rules).string.min_len = 3]; // x must be between 5 and 10 characters, inclusive string x = 1 [(validate.rules).string = {min_len: 5, max_len: 10}]; ``` - **min_bytes/max_bytes**: these rules constrain the number of bytes in the field. ```protobuf // x must be at most 15 bytes long string x = 1 [(validate.rules).string.max_bytes = 15]; // x must be between 128 and 1024 bytes long string x = 1 [(validate.rules).string = {min_bytes: 128, max_bytes: 1024}]; ``` - **pattern**: the field must match the specified [RE2-compliant][re2] regular expression. The included expression should elide any delimiters (ie, `/\d+/` should just be `\d+`). ```protobuf // x must be a non-empty, case-insensitive hexadecimal string string x = 1 [(validate.rules).string.pattern = "(?i)^[0-9a-f]+$"]; ``` - **prefix/suffix/contains/not_contains**: the field must contain the specified substring in an optionally explicit location, or not contain the specified substring. ```protobuf // x must begin with "foo" string x = 1 [(validate.rules).string.prefix = "foo"]; // x must end with "bar" string x = 1 [(validate.rules).string.suffix = "bar"]; // x must contain "baz" anywhere inside it string x = 1 [(validate.rules).string.contains = "baz"]; // x cannot contain "baz" anywhere inside it string x = 1 [(validate.rules).string.not_contains = "baz"]; // x must begin with "fizz" and end with "buzz" string x = 1 [(validate.rules).string = {prefix: "fizz", suffix: "buzz"}]; // x must end with ".proto" and be less than 64 characters string x = 1 [(validate.rules).string = {suffix: ".proto", max_len:64}]; ``` - **in/not_in**: these two rules permit specifying allow/denylists for the values of a field. ```protobuf // x must be either "foo", "bar", or "baz" string x = 1 [(validate.rules).string = {in: ["foo", "bar", "baz"]}]; // x cannot be "fizz" nor "buzz" string x = 1 [(validate.rules).string = {not_in: ["fizz", "buzz"]}]; ``` - **ignore_empty**: this rule specifies that if field is empty or set to the default value, to ignore any validation rules. These are typically useful where being able to unset a field in an update request, or to skip validation for optional fields where switching to WKTs is not feasible. ```protobuf string CountryCode = 1 [(validate.rules).string = {ignore_empty: true, len: 2}]; ``` - **well-known formats**: these rules provide advanced constraints for common string patterns. These constraints will typically be more permissive and performant than equivalent regular expression patterns, while providing more explanatory failure descriptions. ```protobuf // x must be a valid email address (via RFC 5322) string x = 1 [(validate.rules).string.email = true]; // x must be a valid address (IP or Hostname). string x = 1 [(validate.rules).string.address = true]; // x must be a valid hostname (via RFC 1034) string x = 1 [(validate.rules).string.hostname = true]; // x must be a valid IP address (either v4 or v6) string x = 1 [(validate.rules).string.ip = true]; // x must be a valid IPv4 address // eg: "192.168.0.1" string x = 1 [(validate.rules).string.ipv4 = true]; // x must be a valid IPv6 address // eg: "fe80::3" string x = 1 [(validate.rules).string.ipv6 = true]; // x must be a valid absolute URI (via RFC 3986) string x = 1 [(validate.rules).string.uri = true]; // x must be a valid URI reference (either absolute or relative) string x = 1 [(validate.rules).string.uri_ref = true]; // x must be a valid UUID (via RFC 4122) string x = 1 [(validate.rules).string.uuid = true]; // x must conform to a well known regex for HTTP header names (via RFC 7230) string x = 1 [(validate.rules).string.well_known_regex = HTTP_HEADER_NAME] // x must conform to a well known regex for HTTP header values (via RFC 7230) string x = 1 [(validate.rules).string.well_known_regex = HTTP_HEADER_VALUE]; // x must conform to a well known regex for headers, disallowing \r\n\0 characters. string x = 1 [(validate.rules).string {well_known_regex: HTTP_HEADER_VALUE, strict: false}]; ``` ### Bytes > Literal values should be expressed with strings, using escaping where > necessary. - **const**: the field must be _exactly_ the specified value. ```protobuf // x must be set to "foo" ("\x66\x6f\x6f") bytes x = 1 [(validate.rules).bytes.const = "foo"]; // x must be set to "\xf0\x90\x28\xbc" bytes x = 1 [(validate.rules).bytes.const = "\xf0\x90\x28\xbc"]; ``` - **len/min_len/max_len**: these rules constrain the number of bytes in the field. ```protobuf // x must be exactly 3 bytes bytes x = 1 [(validate.rules).bytes.len = 3]; // x must be at least 3 bytes long bytes x = 1 [(validate.rules).bytes.min_len = 3]; // x must be between 5 and 10 bytes, inclusive bytes x = 1 [(validate.rules).bytes = {min_len: 5, max_len: 10}]; ``` - **pattern**: the field must match the specified [RE2-compliant][re2] regular expression. The included expression should elide any delimiters (ie, `/\d+/` should just be `\d+`). ```protobuf // x must be a non-empty, ASCII byte sequence bytes x = 1 [(validate.rules).bytes.pattern = "^[\x00-\x7F]+$"]; ``` - **prefix/suffix/contains**: the field must contain the specified byte sequence in an optionally explicit location. ```protobuf // x must begin with "\x99" bytes x = 1 [(validate.rules).bytes.prefix = "\x99"]; // x must end with "buz\x7a" bytes x = 1 [(validate.rules).bytes.suffix = "buz\x7a"]; // x must contain "baz" anywhere inside it bytes x = 1 [(validate.rules).bytes.contains = "baz"]; ``` - **in/not_in**: these two rules permit specifying allow/denylists for the values of a field. ```protobuf // x must be either "foo", "bar", or "baz" bytes x = 1 [(validate.rules).bytes = {in: ["foo", "bar", "baz"]}]; // x cannot be "fizz" nor "buzz" bytes x = 1 [(validate.rules).bytes = {not_in: ["fizz", "buzz"]}]; ``` - **ignore_empty**: this rule specifies that if field is empty or set to the default value, to ignore any validation rules. These are typically useful where being able to unset a field in an update request, or to skip validation for optional fields where switching to WKTs is not feasible. ```protobuf bytes x = 1 [(validate.rules).bytes = {ignore_empty: true, in: ["foo", "bar", "baz"]}]; ``` - **well-known formats**: these rules provide advanced constraints for common patterns. These constraints will typically be more permissive and performant than equivalent regular expression patterns, while providing more explanatory failure descriptions. ```protobuf // x must be a valid IP address (either v4 or v6) in byte format bytes x = 1 [(validate.rules).bytes.ip = true]; // x must be a valid IPv4 address in byte format // eg: "\xC0\xA8\x00\x01" bytes x = 1 [(validate.rules).bytes.ipv4 = true]; // x must be a valid IPv6 address in byte format // eg: "\x20\x01\x0D\xB8\x85\xA3\x00\x00\x00\x00\x8A\x2E\x03\x70\x73\x34" bytes x = 1 [(validate.rules).bytes.ipv6 = true]; ``` ### Enums > All literal values should use the numeric (int32) value as defined in the enum > descriptor. The following examples use this `State` enum ```protobuf enum State { INACTIVE = 0; PENDING = 1; ACTIVE = 2; } ``` - **const**: the field must be _exactly_ the specified value. ```protobuf // x must be set to ACTIVE (2) State x = 1 [(validate.rules).enum.const = 2]; ``` - **defined_only**: the field must be one of the specified values in the enum descriptor. ```protobuf // x can only be INACTIVE, PENDING, or ACTIVE State x = 1 [(validate.rules).enum.defined_only = true]; ``` - **in/not_in**: these two rules permit specifying allow/denylists for the values of a field. ```protobuf // x must be either INACTIVE (0) or ACTIVE (2) State x = 1 [(validate.rules).enum = {in: [0,2]}]; // x cannot be PENDING (1) State x = 1 [(validate.rules).enum = {not_in: [1]}]; ``` ### Messages > If a field contains a message and the message has been generated with PGV, > validation will be performed recursively. Message's not generated with PGV are > skipped. ```protobuf // if Person was generated with PGV and x is set, // x's fields will be validated. Person x = 1; ``` - **skip**: this rule specifies that the validation rules of this field should not be evaluated. ```protobuf // The fields on Person x will not be validated. Person x = 1 [(validate.rules).message.skip = true]; ``` - **required**: this rule specifies that the field cannot be unset. ```protobuf // x cannot be unset Person x = 1 [(validate.rules).message.required = true]; // x cannot be unset, but the validations on x will not be performed Person x = 1 [(validate.rules).message = {required: true, skip: true}]; ``` ### Repeated - **min_items/max_items**: these rules control how many elements are contained in the field ```protobuf // x must contain at least 3 elements repeated int32 x = 1 [(validate.rules).repeated.min_items = 3]; // x must contain between 5 and 10 Persons, inclusive repeated Person x = 1 [(validate.rules).repeated = {min_items: 5, max_items: 10}]; // x must contain exactly 7 elements repeated double x = 1 [(validate.rules).repeated = {min_items: 7, max_items: 7}]; ``` - **unique**: this rule requires that all elements in the field must be unique. This rule does not support repeated messages. ```protobuf // x must contain unique int64 values repeated int64 x = 1 [(validate.rules).repeated.unique = true]; ``` - **items**: this rule specifies constraints that should be applied to each element in the field. Repeated message fields also have their validation rules applied unless `skip` is specified on this constraint. ```protobuf // x must contain positive float values repeated float x = 1 [(validate.rules).repeated.items.float.gt = 0]; // x must contain Persons but don't validate them repeated Person x = 1 [(validate.rules).repeated.items.message.skip = true]; ``` - **ignore_empty**: this rule specifies that if field is empty or set to the default value, to ignore any validation rules. These are typically useful where being able to unset a field in an update request, or to skip validation for optional fields where switching to WKTs is not feasible. ```protobuf repeated int64 x = 1 [(validate.rules).repeated = {ignore_empty: true, items: {int64: {gt: 200}}}]; ``` ### Maps - **min_pairs/max_pairs**: these rules control how many KV pairs are contained in this field ```protobuf // x must contain at least 3 KV pairs map x = 1 [(validate.rules).map.min_pairs = 3]; // x must contain between 5 and 10 KV pairs map x = 1 [(validate.rules).map = {min_pairs: 5, max_pairs: 10}]; // x must contain exactly 7 KV pairs map x = 1 [(validate.rules).map = {min_pairs: 7, max_pairs: 7}]; ``` - **no_sparse**: for map fields with message values, setting this rule to true disallows keys with unset values. ```protobuf // all values in x must be set map x = 1 [(validate.rules).map.no_sparse = true]; ``` - **keys**: this rule specifies constraints that are applied to the keys in the field. ```protobuf // x's keys must all be negative x = [(validate.rules).map.keys.sint32.lt = 0]; ``` - **values**: this rule specifies constraints that are be applied to each value in the field. Repeated message fields also have their validation rules applied unless `skip` is specified on this constraint. ```protobuf // x must contain strings of at least 3 characters map x = 1 [(validate.rules).map.values.string.min_len = 3]; // x must contain Persons but doesn't validate them map x = 1 [(validate.rules).map.values.message.skip = true]; ``` - **ignore_empty**: this rule specifies that if field is empty or set to the default value, to ignore any validation rules. These are typically useful where being able to unset a field in an update request, or to skip validation for optional fields where switching to WKTs is not feasible. ```protobuf map x = 1 [(validate.rules).map = {ignore_empty: true, values: {string: {min_len: 3}}}]; ``` ### Well-Known Types (WKTs) A set of [WKTs][wkts] are packaged with protoc and common message patterns useful in many domains. #### Scalar Value Wrappers In the `proto3` syntax, there is no way of distinguishing between unset and the zero value of a scalar field. The value WKTs permit this differentiation by wrapping them in a message. PGV permits using the same scalar rules that the wrapper encapsulates. ```protobuf // if it is set, x must be greater than 3 google.protobuf.Int32Value x = 1 [(validate.rules).int32.gt = 3]; ``` Message Rules can also be used with scalar Well-Known Types (WKTs): ```protobuf // Ensures that if a value is not set for age, it would not pass the validation despite its zero value being 0. message X {google.protobuf.Int32Value age = 1 [(validate.rules).int32.gt = -1, (validate.rules).message.required = true];} ``` #### Anys - **required**: this rule specifies that the field must be set ```protobuf // x cannot be unset google.protobuf.Any x = 1 [(validate.rules).any.required = true]; ``` - **in/not_in**: these two rules permit specifying allow/denylists for the `type_url` value in this field. Consider using a `oneof` union instead of `in` if possible. ```protobuf // x must not be the Duration or Timestamp WKT google.protobuf.Any x = 1 [(validate.rules).any = {not_in: [ "type.googleapis.com/google.protobuf.Duration", "type.googleapis.com/google.protobuf.Timestamp" ]}]; ``` #### Durations - **required**: this rule specifies that the field must be set ```protobuf // x cannot be unset google.protobuf.Duration x = 1 [(validate.rules).duration.required = true]; ``` - **const**: the field must be _exactly_ the specified value. ```protobuf // x must equal 1.5s exactly google.protobuf.Duration x = 1 [(validate.rules).duration.const = { seconds: 1, nanos: 500000000 }]; ``` - **lt/lte/gt/gte**: these inequalities (`<`, `<=`, `>`, `>=`, respectively) allow for deriving ranges in which the field must reside. ```protobuf // x must be less than 10s google.protobuf.Duration x = 1 [(validate.rules).duration.lt.seconds = 10]; // x must be greater than or equal to 20ns google.protobuf.Duration x = 1 [(validate.rules).duration.gte.nanos = 20]; // x must be in the range [0s, 1s) google.protobuf.Duration x = 1 [(validate.rules).duration = { gte: {}, lt: {seconds: 1} }]; ``` Inverting the values of `lt(e)` and `gt(e)` is valid and creates an exclusive range. ```protobuf // x must be outside the range [0s, 1s) google.protobuf.Duration x = 1 [(validate.rules).duration = { lt: {}, gte: {seconds: 1} }]; ``` - **in/not_in**: these two rules permit specifying allow/denylists for the values of a field. ```protobuf // x must be either 0s or 1s google.protobuf.Duration x = 1 [(validate.rules).duration = {in: [ {}, {seconds: 1} ]}]; // x cannot be 20s nor 500ns google.protobuf.Duration x = 1 [(validate.rules).duration = {not_in: [ {seconds: 20}, {nanos: 500} ]}]; ``` #### Timestamps - **required**: this rule specifies that the field must be set ```protobuf // x cannot be unset google.protobuf.Timestamp x = 1 [(validate.rules).timestamp.required = true]; ``` - **const**: the field must be _exactly_ the specified value. ```protobuf // x must equal 2009/11/10T23:00:00.500Z exactly google.protobuf.Timestamp x = 1 [(validate.rules).timestamp.const = { seconds: 63393490800, nanos: 500000000 }]; ``` - **lt/lte/gt/gte**: these inequalities (`<`, `<=`, `>`, `>=`, respectively) allow for deriving ranges in which the field must reside. ```protobuf // x must be less than the Unix Epoch google.protobuf.Timestamp x = 1 [(validate.rules).timestamp.lt.seconds = 0]; // x must be greater than or equal to 2009/11/10T23:00:00Z google.protobuf.Timestamp x = 1 [(validate.rules).timestamp.gte.seconds = 63393490800]; // x must be in the range [epoch, 2009/11/10T23:00:00Z) google.protobuf.Timestamp x = 1 [(validate.rules).timestamp = { gte: {}, lt: {seconds: 63393490800} }]; ``` Inverting the values of `lt(e)` and `gt(e)` is valid and creates an exclusive range. ```protobuf // x must be outside the range [epoch, 2009/11/10T23:00:00Z) google.protobuf.Timestamp x = 1 [(validate.rules).timestamp = { lt: {}, gte: {seconds: 63393490800} }]; ``` - **lt_now/gt_now**: these inequalities allow for ranges relative to the current time. These rules cannot be used with the absolute rules above. ```protobuf // x must be less than the current timestamp google.protobuf.Timestamp x = 1 [(validate.rules).timestamp.lt_now = true]; ``` - **within**: this rule specifies that the field's value should be within a duration of the current time. This rule can be used in conjunction with `lt_now` and `gt_now` to control those ranges. ```protobuf // x must be within ±1s of the current time google.protobuf.Timestamp x = 1 [(validate.rules).timestamp.within.seconds = 1]; // x must be within the range (now, now+1h) google.protobuf.Timestamp x = 1 [(validate.rules).timestamp = { gt_now: true, within: {seconds: 3600} }]; ``` ### Message-Global - **disabled**: All validation rules for the fields on a message can be nullified, including any message fields that support validation themselves. ```protobuf message Person { option (validate.disabled) = true; // x will not be required to be greater than 123 uint64 x = 1 [(validate.rules).uint64.gt = 123]; // y's fields will not be validated Person y = 2; } ``` - **ignored**: Don't generate a validate method or any related validation code for this message. ```protobuf message Person { option (validate.ignored) = true; // x will not be required to be greater than 123 uint64 x = 1 [(validate.rules).uint64.gt = 123]; // y's fields will not be validated Person y = 2; } ``` ### OneOfs - **required**: require that one of the fields in a `oneof` must be set. By default, none or one of the unioned fields can be set. Enabling this rules disallows having all of them unset. ```protobuf oneof id { // either x, y, or z must be set. option (validate.required) = true; string x = 1; int32 y = 2; Person z = 3; } ``` ## Development PGV is written in Go on top of the [protoc-gen-star][pg*] framework and compiles to a standalone binary. ### Dependencies All PGV dependencies are currently checked into the project. To test PGV, `protoc` must be installed, either from [source][protoc-source], the provided [releases][protoc-releases], or a package manager. The official protoc plugin for the target language(s) should be installed as well. ### Make Targets - **`make build`**: generates the constraints proto and compiles PGV into `$GOPATH/bin` - **`make lint`**: runs static-analysis rules against the PGV codebase, including `golint`, `go vet`, and `gofmt -s` - **`make testcases`**: generates the proto files in [`/tests/harness/cases`](/tests/harness/cases). These are used by the test harness to verify the validation rules generated for each language. - **`make harness`**: executes the test-cases against each language's test harness. ### Run all tests under Bazel Ensure that your `PATH` is setup to include `protoc-gen-go` and `protoc`, then: ``` bazel test //tests/... ``` ### Docker PGV comes with a [Dockerfile](/Dockerfile) for consistent development tooling and CI. The main entrypoint is `make` with `build` as the default target. ```sh # build the image docker build -t bufbuild/protoc-gen-validate . # executes the default make target: build docker run --rm \ bufbuild/protoc-gen-validate # executes the 'ci' make target docker run --rm \ bufbuild/protoc-gen-validate ci # executes the 'build' & 'testcases' make targets docker run --rm \ bufbuild/protoc-gen-validate build testcases # override the entrypoint and interact with the container directly # this can be useful when wanting to run bazel commands without # bazel installed locally. docker run --rm \ -it --entrypoint=/bin/bash \ bufbuild/protoc-gen-validate ``` [buf]: https://buf.build [protoc-source]: https://github.com/google/protobuf [protoc-releases]: https://github.com/google/protobuf/releases [pg*]: https://github.com/bufbuild/protoc-gen-star [re2]: https://github.com/google/re2/wiki/Syntax [wkts]: https://developers.google.com/protocol-buffers/docs/reference/google.protobuf [pv]: https://github.com/bufbuild/protovalidate [pv-go]: https://github.com/bufbuild/protovalidate-go [pv-announce]: https://buf.build/blog/protoc-gen-validate-v1-and-v2/protoc-gen-validate-1.0.2/Tools.mk000066400000000000000000000004011444536353100170120ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License") bazelisk@v := github.com/bazelbuild/bazelisk@v1.15.0 protoc@v := github.com/protocolbuffers/protobuf@v22.2 protoc-gen-go@v := google.golang.org/protobuf/cmd/protoc-gen-go@v1.30.0 protoc-gen-validate-1.0.2/WORKSPACE000066400000000000000000000005311444536353100166460ustar00rootroot00000000000000workspace(name = "com_envoyproxy_protoc_gen_validate") load("//bazel:repositories.bzl", "pgv_dependencies") pgv_dependencies() load("//bazel:dependency_imports.bzl", "pgv_dependency_imports") pgv_dependency_imports() load("//:dependencies.bzl", "go_third_party") # gazelle:repository_macro dependencies.bzl%go_third_party go_third_party() protoc-gen-validate-1.0.2/bazel/000077500000000000000000000000001444536353100164635ustar00rootroot00000000000000protoc-gen-validate-1.0.2/bazel/BUILD000066400000000000000000000004671444536353100172540ustar00rootroot00000000000000load("@bazel_skylib//rules:common_settings.bzl", "string_flag") config_setting( name = "windows_x86_64", values = {"cpu": "x64_windows"}, visibility = ["//visibility:public"], ) string_flag( name = "template-flavor", build_setting_default = "", visibility = ["//visibility:public"], ) protoc-gen-validate-1.0.2/bazel/dependency_imports.bzl000066400000000000000000000022431444536353100230700ustar00rootroot00000000000000load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") load("@rules_python//python:pip.bzl", "pip_install") def _pgv_pip_dependencies(): # This rule translates the specified requirements.in (which must be same as install_requires from setup.cfg) # into @pgv_pip_deps//:requirements.bzl. pip_install( name = "pgv_pip_deps", requirements = "@com_envoyproxy_protoc_gen_validate//python:requirements.in", ) def _pgv_go_dependencies(): go_rules_dependencies() go_register_toolchains( version = "1.19.7", ) gazelle_dependencies() def pgv_dependency_imports(): # Import @com_google_protobuf's dependencies. protobuf_deps() # Import @pgv_pip_deps defined by python/requirements.in. _pgv_pip_dependencies() # Import rules for the Go compiler. _pgv_go_dependencies() # Setup rules_proto. rules_proto_dependencies() rules_proto_toolchains() protoc-gen-validate-1.0.2/bazel/go/000077500000000000000000000000001444536353100170705ustar00rootroot00000000000000protoc-gen-validate-1.0.2/bazel/go/BUILD000066400000000000000000000015571444536353100176620ustar00rootroot00000000000000"""Define our protoc plugin in a rule that can be provided to go_proto_library#compilers This is in a separate BUILD file from /bazel/BUILD to avoid a dependency on rules_go for all users who load from it. If you use Gazelle, you can use a directive so that the pgv_plugin_go is automatically added to generated go_proto_library rules. See https://github.com/bazelbuild/bazel-gazelle#directives For example, in some/BUILD.bazel: # gazelle:go_grpc_compilers @com_envoyproxy_protoc_gen_validate//bazel/go:pgv_plugin_go, @io_bazel_rules_go//proto:go_grpc """ load("@io_bazel_rules_go//proto:compiler.bzl", "go_proto_compiler") go_proto_compiler( name = "pgv_plugin_go", suffix = ".pb.validate.go", valid_archive = False, plugin = "@com_envoyproxy_protoc_gen_validate//:protoc-gen-validate", options = ["lang=go"], visibility = ["//visibility:public"], ) protoc-gen-validate-1.0.2/bazel/pgv_proto_library.bzl000066400000000000000000000040571444536353100227450ustar00rootroot00000000000000load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") load("@rules_cc//cc:defs.bzl", "cc_library") load(":protobuf.bzl", "cc_proto_gen_validate", "java_proto_gen_validate") _DEFAULT_GO_PROTOC = ["@io_bazel_rules_go//proto:go_proto"] def pgv_go_proto_library(name, compilers = _DEFAULT_GO_PROTOC, proto = None, deps = [], **kwargs): go_proto_library( name = name, proto = proto, deps = ["@com_envoyproxy_protoc_gen_validate//validate:validate"] + deps, compilers = compilers + [ "@com_envoyproxy_protoc_gen_validate//bazel/go:pgv_plugin_go", ], visibility = ["//visibility:public"], **kwargs ) def pgv_cc_proto_library( name, deps = [], cc_deps = [], copts = [], **kargs): """Bazel rule to create a C++ protobuf validation library from proto source files Args: name: the name of the pgv_cc_proto_library. deps: proto_library rules that contains the necessary .proto files. cc_deps: C++ dependencies of the protos being compiled. Likely cc_proto_library or pgv_cc_proto_library **kargs: other keyword arguments that are passed to cc_library. """ native.cc_proto_library( name = name + "_cc_proto", deps = deps, ) cc_proto_gen_validate( name = name + "_validate", deps = deps, ) cc_library( name = name, hdrs = [":" + name + "_validate"], srcs = [":" + name + "_validate"], deps = cc_deps + [ ":" + name + "_cc_proto", "@com_envoyproxy_protoc_gen_validate//validate:cc_validate", "@com_envoyproxy_protoc_gen_validate//validate:validate_cc", "@com_google_protobuf//:protobuf", "@com_googlesource_code_re2//:re2", ], copts = copts + select({ "@com_envoyproxy_protoc_gen_validate//bazel:windows_x86_64": ["-DWIN32"], "//conditions:default": [], }), alwayslink = 1, **kargs ) pgv_java_proto_library = java_proto_gen_validate protoc-gen-validate-1.0.2/bazel/protobuf.bzl000066400000000000000000000210741444536353100210400ustar00rootroot00000000000000load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") load("@bazel_tools//tools/jdk:toolchain_utils.bzl", "find_java_runtime_toolchain", "find_java_toolchain") load("@rules_proto//proto:defs.bzl", "ProtoInfo") # Borrowed from https://github.com/grpc/grpc-java/blob/v1.28.0/java_grpc_library.bzl#L59 # "repository" here is for Bazel builds that span multiple WORKSPACES. def _path_ignoring_repository(f): # Bazel creates a _virtual_imports directory in case the .proto source files # need to be accessed at a path that's different from their source path: # https://github.com/bazelbuild/bazel/blob/0.27.1/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCommon.java#L289 # # In that case, the import path of the .proto file is the path relative to # the virtual imports directory of the rule in question. virtual_imports = "/_virtual_imports/" if virtual_imports in f.path: return f.path.split(virtual_imports)[1].split("/", 1)[1] elif len(f.owner.workspace_root) == 0: # |f| is in the main repository return f.short_path else: # If |f| is a generated file, it will have "bazel-out/*/genfiles" prefix # before "external/workspace", so we need to add the starting index of "external/workspace" return f.path[f.path.find(f.owner.workspace_root) + len(f.owner.workspace_root) + 1:] def _protoc_cc_output_file(ctx, proto_file): file_path = proto_file.basename if proto_file.basename.endswith(".proto"): file_path = file_path[:-len(".proto")] return (file_path + ".pb.validate.h", file_path + ".pb.validate.cc") def _proto_sources(ctx): protos = [] for dep in ctx.attr.deps: protos += [f for f in dep[ProtoInfo].direct_sources] return protos def _output_dir(ctx): dir_out = ctx.genfiles_dir.path if ctx.label.workspace_root: dir_out += "/" + ctx.label.workspace_root return dir_out def _protoc_gen_validate_cc_impl(ctx): """Generate C++ protos using protoc-gen-validate plugin""" flavor = ctx.attr._flavor[BuildSettingInfo].value or "" protos = _proto_sources(ctx) out_files = [] for f in protos: for out in _protoc_cc_output_file(ctx, f): out_files.append(ctx.actions.declare_file(out, sibling = f)) dir_out = _output_dir(ctx) args = [ "--validate_out=lang=cc" + flavor + ":" + dir_out, ] return _protoc_gen_validate_impl( ctx = ctx, lang = "cc", protos = protos, out_files = out_files, protoc_args = args, package_command = "true", ) def _protoc_gen_validate_impl(ctx, lang, protos, out_files, protoc_args, package_command): protoc_args.append("--plugin=protoc-gen-validate=" + ctx.executable._plugin.path) dir_out = ctx.genfiles_dir.path if ctx.label.workspace_root: dir_out += "/" + ctx.label.workspace_root tds = depset([], transitive = [dep[ProtoInfo].transitive_descriptor_sets for dep in ctx.attr.deps]) descriptor_args = [ds.path for ds in tds.to_list()] if len(descriptor_args) != 0: protoc_args.append("--descriptor_set_in=%s" % ctx.configuration.host_path_separator.join(descriptor_args)) package_command = package_command.format(dir_out = dir_out) ctx.actions.run_shell( outputs = out_files, inputs = protos + tds.to_list(), tools = [ctx.executable._plugin, ctx.executable._protoc], command = " && ".join([ ctx.executable._protoc.path + " $@", package_command, ]), arguments = protoc_args + [_path_ignoring_repository(proto) for proto in protos], mnemonic = "ProtoGenValidate" + lang.capitalize() + "Generate", use_default_shell_env = True, ) return struct( files = depset(out_files), ) cc_proto_gen_validate = rule( attrs = { "deps": attr.label_list( mandatory = True, providers = [ProtoInfo], ), "_validate_deps": attr.label_list( default = [Label("@com_googlesource_code_re2//:re2")], ), "_protoc": attr.label( cfg = "host", default = Label("@com_google_protobuf//:protoc"), executable = True, allow_single_file = True, ), "_plugin": attr.label( cfg = "host", default = Label("@com_envoyproxy_protoc_gen_validate//:protoc-gen-validate"), allow_files = True, executable = True, ), "_flavor": attr.label(default = ":template-flavor"), }, output_to_genfiles = True, implementation = _protoc_gen_validate_cc_impl, ) _ProtoValidateSourceInfo = provider( fields = { "sources": "Depset of sources created by protoc with protoc-gen-validate plugin", }, ) def _create_include_path(include): return "--proto_path={0}={1}".format(_path_ignoring_repository(include), include.path) def _java_proto_gen_validate_aspect_impl(target, ctx): proto_info = target[ProtoInfo] includes = proto_info.transitive_imports srcs = proto_info.direct_sources options = ",".join(["lang=java"]) srcjar = ctx.actions.declare_file("%s-validate-gensrc.jar" % ctx.label.name) args = ctx.actions.args() args.add(ctx.executable._plugin.path, format = "--plugin=protoc-gen-validate=%s") args.add("--validate_out={0}:{1}".format(options, srcjar.path)) args.add_all(includes, map_each = _create_include_path) args.add_all(srcs, map_each = _path_ignoring_repository) ctx.actions.run( inputs = depset(transitive = [proto_info.transitive_imports]), outputs = [srcjar], executable = ctx.executable._protoc, arguments = [args], tools = [ctx.executable._plugin], progress_message = "Generating %s" % srcjar.path, ) return [_ProtoValidateSourceInfo( sources = depset( [srcjar], transitive = [dep[_ProtoValidateSourceInfo].sources for dep in ctx.rule.attr.deps], ), )] _java_proto_gen_validate_aspect = aspect( _java_proto_gen_validate_aspect_impl, provides = [_ProtoValidateSourceInfo], attr_aspects = ["deps"], attrs = { "_protoc": attr.label( cfg = "host", default = Label("@com_google_protobuf//:protoc"), executable = True, allow_single_file = True, ), "_plugin": attr.label( cfg = "host", default = Label("@com_envoyproxy_protoc_gen_validate//:protoc-gen-validate"), allow_files = True, executable = True, ), }, ) def _java_proto_gen_validate_impl(ctx): source_jars = [source_jar for dep in ctx.attr.deps for source_jar in dep[_ProtoValidateSourceInfo].sources.to_list()] deps = [java_common.make_non_strict(dep[JavaInfo]) for dep in ctx.attr.java_deps] deps += [dep[JavaInfo] for dep in ctx.attr._validate_deps] java_info = java_common.compile( ctx, source_jars = source_jars, deps = deps, output_source_jar = ctx.outputs.srcjar, output = ctx.outputs.jar, java_toolchain = find_java_toolchain(ctx, ctx.attr._java_toolchain), ) return [java_info] """Bazel rule to create a Java protobuf validation library from proto sources files. Args: deps: proto_library rules that contain the necessary .proto files java_deps: the java_proto_library of the protos being compiled. """ java_proto_gen_validate = rule( attrs = { "deps": attr.label_list( providers = [ProtoInfo], aspects = [_java_proto_gen_validate_aspect], mandatory = True, ), "java_deps": attr.label_list( providers = [JavaInfo], mandatory = True, ), "_validate_deps": attr.label_list( default = [ Label("@com_envoyproxy_protoc_gen_validate//validate:validate_java"), Label("@com_google_re2j//jar"), Label("@com_google_protobuf//:protobuf_java"), Label("@com_google_protobuf//:protobuf_java_util"), Label("@com_envoyproxy_protoc_gen_validate//java/pgv-java-stub/src/main/java/io/envoyproxy/pgv"), Label("@com_envoyproxy_protoc_gen_validate//java/pgv-java-validation/src/main/java/io/envoyproxy/pgv"), ], ), "_java_toolchain": attr.label(default = Label("@bazel_tools//tools/jdk:current_java_toolchain")), }, fragments = ["java"], provides = [JavaInfo], outputs = { "jar": "lib%{name}.jar", "srcjar": "lib%{name}-src.jar", }, implementation = _java_proto_gen_validate_impl, ) protoc-gen-validate-1.0.2/bazel/repositories.bzl000066400000000000000000000141171444536353100217270ustar00rootroot00000000000000load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:jvm.bzl", "jvm_maven_import_external") _DEFAULT_REPOSITORIES = ["https://repo.maven.apache.org/maven2"] def pgv_dependencies(maven_repos = _DEFAULT_REPOSITORIES): if not native.existing_rule("io_bazel_rules_go"): http_archive( name = "io_bazel_rules_go", sha256 = "dd926a88a564a9246713a9c00b35315f54cbd46b31a26d5d8fb264c07045f05d", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.38.1/rules_go-v0.38.1.zip", "https://github.com/bazelbuild/rules_go/releases/download/v0.38.1/rules_go-v0.38.1.zip", ], ) if not native.existing_rule("bazel_gazelle"): http_archive( name = "bazel_gazelle", sha256 = "ecba0f04f96b4960a5b250c8e8eeec42281035970aa8852dda73098274d14a1d", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz", "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz", ], ) if not native.existing_rule("com_google_protobuf"): http_archive( name = "com_google_protobuf", url = "https://github.com/protocolbuffers/protobuf/archive/v3.15.3.tar.gz", sha256 = "b10bf4e2d1a7586f54e64a5d9e7837e5188fc75ae69e36f215eb01def4f9721b", strip_prefix = "protobuf-3.15.3", ) # TODO(akonradi): This shouldn't be necessary since the same http_archive block is imported by # protobuf_deps from @com_google_protobuf. Investigate why. if not native.existing_rule("zlib"): http_archive( name = "zlib", build_file = "@com_google_protobuf//:third_party/zlib.BUILD", sha256 = "b3a24de97a8fdbc835b9833169501030b8977031bcb54b3b3ac13740f846ab30", strip_prefix = "zlib-1.2.13", urls = ["https://zlib.net/zlib-1.2.13.tar.gz"], ) if not native.existing_rule("bazel_skylib"): http_archive( name = "bazel_skylib", sha256 = "66ffd9315665bfaafc96b52278f57c7e2dd09f5ede279ea6d39b2be471e7e3aa", urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.2/bazel-skylib-1.4.2.tar.gz"], ) if not native.existing_rule("six"): http_archive( name = "six", build_file = "@com_google_protobuf//:third_party/six.BUILD", sha256 = "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73", urls = ["https://pypi.python.org/packages/source/s/six/six-1.12.0.tar.gz"], ) if not native.existing_rule("com_google_re2j"): jvm_maven_import_external( name = "com_google_re2j", artifact = "com.google.re2j:re2j:1.2", artifact_sha256 = "e9dc705fd4c570344b54a7146b2e3a819cdc271a29793f4acc1a93b56a388e59", server_urls = maven_repos, ) if not native.existing_rule("com_googlesource_code_re2"): http_archive( name = "com_googlesource_code_re2", sha256 = "2e9489a31ae007c81e90e8ec8a15d62d58a9c18d4fd1603f6441ef248556b41f", strip_prefix = "re2-2020-07-06", urls = ["https://github.com/google/re2/archive/2020-07-06.tar.gz"], ) if not native.existing_rule("com_google_guava"): jvm_maven_import_external( name = "com_google_guava", artifact = "com.google.guava:guava:27.0-jre", artifact_sha256 = "63b09db6861011e7fb2481be7790c7fd4b03f0bb884b3de2ecba8823ad19bf3f", server_urls = maven_repos, ) if not native.existing_rule("guava"): native.bind( name = "guava", actual = "@com_google_guava//jar", ) if not native.existing_rule("com_google_gson"): jvm_maven_import_external( name = "com_google_gson", artifact = "com.google.code.gson:gson:2.8.5", artifact_sha256 = "233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81", server_urls = maven_repos, ) if not native.existing_rule("gson"): native.bind( name = "gson", actual = "@com_google_gson//jar", ) if not native.existing_rule("error_prone_annotations_maven"): jvm_maven_import_external( name = "error_prone_annotations_maven", artifact = "com.google.errorprone:error_prone_annotations:2.3.2", artifact_sha256 = "357cd6cfb067c969226c442451502aee13800a24e950fdfde77bcdb4565a668d", server_urls = maven_repos, ) if not native.existing_rule("error_prone_annotations"): native.bind( name = "error_prone_annotations", actual = "@error_prone_annotations_maven//jar", ) if not native.existing_rule("org_apache_commons_validator"): jvm_maven_import_external( name = "org_apache_commons_validator", artifact = "commons-validator:commons-validator:1.6", artifact_sha256 = "bd62795d7068a69cbea333f6dbf9c9c1a6ad7521443fb57202a44874f240ba25", server_urls = maven_repos, ) if not native.existing_rule("rules_python"): http_archive( name = "rules_python", sha256 = "b593d13bb43c94ce94b483c2858e53a9b811f6f10e1e0eedc61073bd90e58d9c", strip_prefix = "rules_python-0.12.0", url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.12.0.tar.gz", ) if not native.existing_rule("rules_proto"): http_archive( name = "rules_proto", sha256 = "2490dca4f249b8a9a3ab07bd1ba6eca085aaf8e45a734af92aad0c42d9dc7aaf", strip_prefix = "rules_proto-218ffa7dfa5408492dc86c01ee637614f8695c45", urls = ["https://github.com/bazelbuild/rules_proto/archive/218ffa7dfa5408492dc86c01ee637614f8695c45.tar.gz"], ) protoc-gen-validate-1.0.2/cmd/000077500000000000000000000000001444536353100161315ustar00rootroot00000000000000protoc-gen-validate-1.0.2/cmd/protoc-gen-validate-cpp/000077500000000000000000000000001444536353100225555ustar00rootroot00000000000000protoc-gen-validate-1.0.2/cmd/protoc-gen-validate-cpp/BUILD000066400000000000000000000017461444536353100233470ustar00rootroot00000000000000load("@bazel_gazelle//:def.bzl", "gazelle") load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") # gazelle:prefix github.com/envoyproxy/protoc-gen-validate # gazelle:exclude tests # gazelle:exclude example-workspace # gazelle:exclude validate/validate.h # gazelle:go_naming_convention import_alias gazelle(name = "gazelle") go_binary( name = "protoc-gen-validate-cpp", embed = [":protoc-gen-validate-cpp_lib"], importpath = "github.com/envoyproxy/protoc-gen-validate/cmd/protoc-gen-validate-cpp", visibility = ["//visibility:public"], ) go_library( name = "protoc-gen-validate-cpp_lib", srcs = ["main.go"], importpath = "github.com/envoyproxy/protoc-gen-validate/cmd/protoc-gen-validate-cpp", visibility = ["//visibility:private"], deps = [ "//module", "@com_github_lyft_protoc_gen_star_v2//:protoc-gen-star", "@com_github_lyft_protoc_gen_star_v2//lang/go", "@org_golang_google_protobuf//types/pluginpb", ], ) protoc-gen-validate-1.0.2/cmd/protoc-gen-validate-cpp/main.go000066400000000000000000000006141444536353100240310ustar00rootroot00000000000000package main import ( "github.com/envoyproxy/protoc-gen-validate/module" pgs "github.com/lyft/protoc-gen-star/v2" "google.golang.org/protobuf/types/pluginpb" ) func main() { optional := uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) pgs. Init(pgs.DebugEnv("DEBUG_PGV"), pgs.SupportedFeatures(&optional)). RegisterModule(module.ValidatorForLanguage("cc")). Render() } protoc-gen-validate-1.0.2/cmd/protoc-gen-validate-go/000077500000000000000000000000001444536353100224005ustar00rootroot00000000000000protoc-gen-validate-1.0.2/cmd/protoc-gen-validate-go/BUILD000066400000000000000000000017411444536353100231650ustar00rootroot00000000000000load("@bazel_gazelle//:def.bzl", "gazelle") load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") # gazelle:prefix github.com/envoyproxy/protoc-gen-validate # gazelle:exclude tests # gazelle:exclude example-workspace # gazelle:exclude validate/validate.h # gazelle:go_naming_convention import_alias gazelle(name = "gazelle") go_binary( name = "protoc-gen-validate-go", embed = [":protoc-gen-validate-go_lib"], importpath = "github.com/envoyproxy/protoc-gen-validate/cmd/protoc-gen-validate-go", visibility = ["//visibility:public"], ) go_library( name = "protoc-gen-validate-go_lib", srcs = ["main.go"], importpath = "github.com/envoyproxy/protoc-gen-validate/cmd/protoc-gen-validate-go", visibility = ["//visibility:private"], deps = [ "//module", "@com_github_lyft_protoc_gen_star_v2//:protoc-gen-star", "@com_github_lyft_protoc_gen_star_v2//lang/go", "@org_golang_google_protobuf//types/pluginpb", ], ) protoc-gen-validate-1.0.2/cmd/protoc-gen-validate-go/main.go000066400000000000000000000007501444536353100236550ustar00rootroot00000000000000package main import ( "github.com/envoyproxy/protoc-gen-validate/module" pgs "github.com/lyft/protoc-gen-star/v2" pgsgo "github.com/lyft/protoc-gen-star/v2/lang/go" "google.golang.org/protobuf/types/pluginpb" ) func main() { optional := uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) pgs. Init(pgs.DebugEnv("DEBUG_PGV"), pgs.SupportedFeatures(&optional)). RegisterModule(module.ValidatorForLanguage("go")). RegisterPostProcessor(pgsgo.GoFmt()). Render() } protoc-gen-validate-1.0.2/cmd/protoc-gen-validate-java/000077500000000000000000000000001444536353100227145ustar00rootroot00000000000000protoc-gen-validate-1.0.2/cmd/protoc-gen-validate-java/BUILD000066400000000000000000000017531444536353100235040ustar00rootroot00000000000000load("@bazel_gazelle//:def.bzl", "gazelle") load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") # gazelle:prefix github.com/envoyproxy/protoc-gen-validate # gazelle:exclude tests # gazelle:exclude example-workspace # gazelle:exclude validate/validate.h # gazelle:go_naming_convention import_alias gazelle(name = "gazelle") go_binary( name = "protoc-gen-validate-java", embed = [":protoc-gen-validate-java_lib"], importpath = "github.com/envoyproxy/protoc-gen-validate/cmd/protoc-gen-validate-java", visibility = ["//visibility:public"], ) go_library( name = "protoc-gen-validate-java_lib", srcs = ["main.go"], importpath = "github.com/envoyproxy/protoc-gen-validate/cmd/protoc-gen-validate-java", visibility = ["//visibility:private"], deps = [ "//module", "@com_github_lyft_protoc_gen_star_v2//:protoc-gen-star", "@com_github_lyft_protoc_gen_star_v2//lang/go", "@org_golang_google_protobuf//types/pluginpb", ], ) protoc-gen-validate-1.0.2/cmd/protoc-gen-validate-java/main.go000066400000000000000000000006161444536353100241720ustar00rootroot00000000000000package main import ( "github.com/envoyproxy/protoc-gen-validate/module" pgs "github.com/lyft/protoc-gen-star/v2" "google.golang.org/protobuf/types/pluginpb" ) func main() { optional := uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) pgs. Init(pgs.DebugEnv("DEBUG_PGV"), pgs.SupportedFeatures(&optional)). RegisterModule(module.ValidatorForLanguage("java")). Render() } protoc-gen-validate-1.0.2/dependencies.bzl000066400000000000000000000421231444536353100205270ustar00rootroot00000000000000load("@bazel_gazelle//:deps.bzl", "go_repository") def go_third_party(): go_repository( name = "co_honnef_go_tools", importpath = "honnef.co/go/tools", sum = "h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8=", version = "v0.0.1-2020.1.4", ) go_repository( name = "com_github_burntsushi_toml", importpath = "github.com/BurntSushi/toml", sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=", version = "v0.3.1", ) go_repository( name = "com_github_burntsushi_xgb", importpath = "github.com/BurntSushi/xgb", sum = "h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=", version = "v0.0.0-20160522181843-27f122750802", ) go_repository( name = "com_github_census_instrumentation_opencensus_proto", importpath = "github.com/census-instrumentation/opencensus-proto", sum = "h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=", version = "v0.2.1", ) go_repository( name = "com_github_chzyer_logex", importpath = "github.com/chzyer/logex", sum = "h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=", version = "v1.1.10", ) go_repository( name = "com_github_chzyer_readline", importpath = "github.com/chzyer/readline", sum = "h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=", version = "v0.0.0-20180603132655-2972be24d48e", ) go_repository( name = "com_github_chzyer_test", importpath = "github.com/chzyer/test", sum = "h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=", version = "v0.0.0-20180213035817-a1ea475d72b1", ) go_repository( name = "com_github_client9_misspell", importpath = "github.com/client9/misspell", sum = "h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=", version = "v0.3.4", ) go_repository( name = "com_github_cncf_udpa_go", importpath = "github.com/cncf/udpa/go", sum = "h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M=", version = "v0.0.0-20201120205902-5459f2c99403", ) go_repository( name = "com_github_davecgh_go_spew", importpath = "github.com/davecgh/go-spew", sum = "h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=", version = "v1.1.0", ) go_repository( name = "com_github_envoyproxy_go_control_plane", importpath = "github.com/envoyproxy/go-control-plane", sum = "h1:EmNYJhPYy0pOFjCx2PrgtaBXmee0iUX9hLlxE1xHOJE=", version = "v0.9.9-0.20201210154907-fd9021fe5dad", ) go_repository( name = "com_github_go_gl_glfw", importpath = "github.com/go-gl/glfw", sum = "h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=", version = "v0.0.0-20190409004039-e6da0acd62b1", ) go_repository( name = "com_github_go_gl_glfw_v3_3_glfw", importpath = "github.com/go-gl/glfw/v3.3/glfw", sum = "h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I=", version = "v0.0.0-20200222043503-6f7a984d4dc4", ) go_repository( name = "com_github_golang_glog", importpath = "github.com/golang/glog", sum = "h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=", version = "v0.0.0-20160126235308-23def4e6c14b", ) go_repository( name = "com_github_golang_groupcache", importpath = "github.com/golang/groupcache", sum = "h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=", version = "v0.0.0-20200121045136-8c9f03a8e57e", ) go_repository( name = "com_github_golang_mock", importpath = "github.com/golang/mock", sum = "h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=", version = "v1.4.4", ) go_repository( name = "com_github_golang_protobuf", importpath = "github.com/golang/protobuf", sum = "h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=", version = "v1.5.2", ) go_repository( name = "com_github_google_btree", importpath = "github.com/google/btree", sum = "h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=", version = "v1.0.0", ) go_repository( name = "com_github_google_go_cmp", importpath = "github.com/google/go-cmp", sum = "h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=", version = "v0.5.5", ) go_repository( name = "com_github_google_martian", importpath = "github.com/google/martian", sum = "h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=", version = "v2.1.0+incompatible", ) go_repository( name = "com_github_google_martian_v3", importpath = "github.com/google/martian/v3", sum = "h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60=", version = "v3.1.0", ) go_repository( name = "com_github_google_pprof", importpath = "github.com/google/pprof", sum = "h1:LR89qFljJ48s990kEKGsk213yIJDPI4205OKOzbURK8=", version = "v0.0.0-20201218002935-b9804c9f04c2", ) go_repository( name = "com_github_google_renameio", importpath = "github.com/google/renameio", sum = "h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=", version = "v0.1.0", ) go_repository( name = "com_github_google_uuid", importpath = "github.com/google/uuid", sum = "h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=", version = "v1.1.2", ) go_repository( name = "com_github_googleapis_gax_go_v2", importpath = "github.com/googleapis/gax-go/v2", sum = "h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=", version = "v2.0.5", ) go_repository( name = "com_github_googleapis_google_cloud_go_testing", importpath = "github.com/googleapis/google-cloud-go-testing", sum = "h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4=", version = "v0.0.0-20200911160855-bcd43fbb19e8", ) go_repository( name = "com_github_hashicorp_golang_lru", importpath = "github.com/hashicorp/golang-lru", sum = "h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=", version = "v0.5.1", ) go_repository( name = "com_github_iancoleman_strcase", importpath = "github.com/iancoleman/strcase", sum = "h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=", version = "v0.2.0", ) go_repository( name = "com_github_ianlancetaylor_demangle", importpath = "github.com/ianlancetaylor/demangle", sum = "h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI=", version = "v0.0.0-20200824232613-28f6c0f3b639", ) go_repository( name = "com_github_jstemmer_go_junit_report", importpath = "github.com/jstemmer/go-junit-report", sum = "h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=", version = "v0.9.1", ) go_repository( name = "com_github_kisielk_gotool", importpath = "github.com/kisielk/gotool", sum = "h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=", version = "v1.0.0", ) go_repository( name = "com_github_kr_fs", importpath = "github.com/kr/fs", sum = "h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=", version = "v0.1.0", ) go_repository( name = "com_github_kr_pretty", importpath = "github.com/kr/pretty", sum = "h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=", version = "v0.1.0", ) go_repository( name = "com_github_kr_pty", importpath = "github.com/kr/pty", sum = "h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=", version = "v1.1.1", ) go_repository( name = "com_github_kr_text", importpath = "github.com/kr/text", sum = "h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=", version = "v0.1.0", ) go_repository( name = "com_github_lyft_protoc_gen_star_v2", importpath = "github.com/lyft/protoc-gen-star/v2", sum = "h1:keaAo8hRuAT0O3DfJ/wM3rufbAjGeJ1lAtWZHDjKGB0=", version = "v2.0.1", ) go_repository( name = "com_github_pkg_errors", importpath = "github.com/pkg/errors", sum = "h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=", version = "v0.9.1", ) go_repository( name = "com_github_pkg_sftp", importpath = "github.com/pkg/sftp", sum = "h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs=", version = "v1.13.1", ) go_repository( name = "com_github_pmezard_go_difflib", importpath = "github.com/pmezard/go-difflib", sum = "h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=", version = "v1.0.0", ) go_repository( name = "com_github_prometheus_client_model", importpath = "github.com/prometheus/client_model", sum = "h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=", version = "v0.0.0-20190812154241-14fe0d1b01d4", ) go_repository( name = "com_github_rogpeppe_go_internal", importpath = "github.com/rogpeppe/go-internal", sum = "h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=", version = "v1.3.0", ) go_repository( name = "com_github_spf13_afero", importpath = "github.com/spf13/afero", sum = "h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=", version = "v1.9.2", ) go_repository( name = "com_github_stretchr_objx", importpath = "github.com/stretchr/objx", sum = "h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=", version = "v0.1.0", ) go_repository( name = "com_github_stretchr_testify", importpath = "github.com/stretchr/testify", sum = "h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=", version = "v1.7.0", ) go_repository( name = "com_github_yuin_goldmark", importpath = "github.com/yuin/goldmark", sum = "h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=", version = "v1.4.13", ) go_repository( name = "com_google_cloud_go", importpath = "cloud.google.com/go", sum = "h1:XgtDnVJRCPEUG21gjFiRPz4zI1Mjg16R+NYQjfmU4XY=", version = "v0.75.0", ) go_repository( name = "com_google_cloud_go_bigquery", importpath = "cloud.google.com/go/bigquery", sum = "h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA=", version = "v1.8.0", ) go_repository( name = "com_google_cloud_go_datastore", importpath = "cloud.google.com/go/datastore", sum = "h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ=", version = "v1.1.0", ) go_repository( name = "com_google_cloud_go_pubsub", importpath = "cloud.google.com/go/pubsub", sum = "h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU=", version = "v1.3.1", ) go_repository( name = "com_google_cloud_go_storage", importpath = "cloud.google.com/go/storage", sum = "h1:6RRlFMv1omScs6iq2hfE3IvgE+l6RfJPampq8UZc5TU=", version = "v1.14.0", ) go_repository( name = "com_shuralyov_dmitri_gpu_mtl", importpath = "dmitri.shuralyov.com/gpu/mtl", sum = "h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY=", version = "v0.0.0-20190408044501-666a987793e9", ) go_repository( name = "in_gopkg_check_v1", importpath = "gopkg.in/check.v1", sum = "h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=", version = "v1.0.0-20180628173108-788fd7840127", ) go_repository( name = "in_gopkg_errgo_v2", importpath = "gopkg.in/errgo.v2", sum = "h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=", version = "v2.1.0", ) go_repository( name = "in_gopkg_yaml_v2", importpath = "gopkg.in/yaml.v2", sum = "h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=", version = "v2.2.2", ) go_repository( name = "in_gopkg_yaml_v3", importpath = "gopkg.in/yaml.v3", sum = "h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=", version = "v3.0.0-20200313102051-9f266ea9e77c", ) go_repository( name = "io_opencensus_go", importpath = "go.opencensus.io", sum = "h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0=", version = "v0.22.5", ) go_repository( name = "io_rsc_binaryregexp", importpath = "rsc.io/binaryregexp", sum = "h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE=", version = "v0.2.0", ) go_repository( name = "io_rsc_quote_v3", importpath = "rsc.io/quote/v3", sum = "h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=", version = "v3.1.0", ) go_repository( name = "io_rsc_sampler", importpath = "rsc.io/sampler", sum = "h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=", version = "v1.3.0", ) go_repository( name = "org_golang_google_api", importpath = "google.golang.org/api", sum = "h1:uWrpz12dpVPn7cojP82mk02XDgTJLDPc2KbVTxrWb4A=", version = "v0.40.0", ) go_repository( name = "org_golang_google_appengine", importpath = "google.golang.org/appengine", sum = "h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=", version = "v1.6.7", ) go_repository( name = "org_golang_google_genproto", importpath = "google.golang.org/genproto", sum = "h1:PYBmACG+YEv8uQPW0r1kJj8tR+gkF0UWq7iFdUezwEw=", version = "v0.0.0-20210226172003-ab064af71705", ) go_repository( name = "org_golang_google_grpc", importpath = "google.golang.org/grpc", sum = "h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8=", version = "v1.35.0", ) go_repository( name = "org_golang_google_protobuf", importpath = "google.golang.org/protobuf", sum = "h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=", version = "v1.30.0", ) go_repository( name = "org_golang_x_crypto", importpath = "golang.org/x/crypto", sum = "h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4=", version = "v0.0.0-20211108221036-ceb1ce70b4fa", ) go_repository( name = "org_golang_x_exp", importpath = "golang.org/x/exp", sum = "h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y=", version = "v0.0.0-20200224162631-6cc2880d07d6", ) go_repository( name = "org_golang_x_image", importpath = "golang.org/x/image", sum = "h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=", version = "v0.0.0-20190802002840-cff245a6509b", ) go_repository( name = "org_golang_x_lint", importpath = "golang.org/x/lint", sum = "h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=", version = "v0.0.0-20210508222113-6edffad5e616", ) go_repository( name = "org_golang_x_mobile", importpath = "golang.org/x/mobile", sum = "h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs=", version = "v0.0.0-20190719004257-d2bd2a29d028", ) go_repository( name = "org_golang_x_mod", importpath = "golang.org/x/mod", sum = "h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=", version = "v0.6.0-dev.0.20220419223038-86c51ed26bb4", ) go_repository( name = "org_golang_x_net", importpath = "golang.org/x/net", sum = "h1:1WGATo9HAhkWMbfyuVU0tEFP88OIkUvwaHFveQPvzCQ=", version = "v0.0.0-20220907135653-1e95f45603a7", ) go_repository( name = "org_golang_x_oauth2", importpath = "golang.org/x/oauth2", sum = "h1:5vD4XjIc0X5+kHZjx4UecYdjA6mJo+XXNoaW0EjU5Os=", version = "v0.0.0-20210218202405-ba52d332ba99", ) go_repository( name = "org_golang_x_sync", importpath = "golang.org/x/sync", sum = "h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=", version = "v0.0.0-20220722155255-886fb9371eb4", ) go_repository( name = "org_golang_x_sys", importpath = "golang.org/x/sys", sum = "h1:RoyzQTK76Rktm3p4xyZslc8T8I1tBz4UEjZCzeh57mM=", version = "v0.0.0-20220908150016-7ac13a9a928d", ) go_repository( name = "org_golang_x_term", importpath = "golang.org/x/term", sum = "h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=", version = "v0.0.0-20210927222741-03fcf44c2211", ) go_repository( name = "org_golang_x_text", importpath = "golang.org/x/text", sum = "h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=", version = "v0.3.7", ) go_repository( name = "org_golang_x_time", importpath = "golang.org/x/time", sum = "h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=", version = "v0.0.0-20191024005414-555d28b269f0", ) go_repository( name = "org_golang_x_tools", importpath = "golang.org/x/tools", sum = "h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=", version = "v0.1.12", ) go_repository( name = "org_golang_x_xerrors", importpath = "golang.org/x/xerrors", sum = "h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=", version = "v0.0.0-20220907171357-04be3eba64a2", ) protoc-gen-validate-1.0.2/example-workspace/000077500000000000000000000000001444536353100210155ustar00rootroot00000000000000protoc-gen-validate-1.0.2/example-workspace/.bazelrc000066400000000000000000000000641444536353100224400ustar00rootroot00000000000000build --incompatible_use_cc_configure_from_rules_cc protoc-gen-validate-1.0.2/example-workspace/BUILD000066400000000000000000000035441444536353100216050ustar00rootroot00000000000000# Example C++ binary that uses the generated validation code. # # This binary attempts to read files named on the command line as binary protos. # To try it out, first use Bazel to build this binary: # # bazel build //:example_cc # # Now run it on some files. From the repository root directory: # # bazel run //:example_cc -- $(pwd)/example.cc # # The binary will fail because example.cc is not a valid textproto. Luckily # this directory contains two textprotos already: valid.textproto and # invalid.textproto. From the root directory: # # bazel run //:example_cc -- $(pwd)/valid.textproto # # which succeeds, or # # bazel run //:example_cc -- $(pwd)/invalid.textproto # # which fails. cc_binary( name = "example_cc", srcs = ["example.cc"], deps = ["//foo:bar_cc_proto"], ) # Example python binary that uses the dynamic python validation code. # # Exactly as example_cc above except different label. Example: # # bazel run //:example_py -- $(pwd)/valid.textproto py_binary( name = "example_py", srcs = ["example.py"], main = "example.py", srcs_version = "PY3", deps = [ "@com_google_protobuf//:protobuf_python", "@com_envoyproxy_protoc_gen_validate//python:validator_py", "//foo:bar_py_proto", ], ) # Test that the example textproto inputs evoke the right responses. [ sh_test( name = "example_{lang}_test_{which}".format(lang=lang, which=which), srcs = ["example_test.sh"], args = [ "$(location :example_{lang})".format(lang=lang), str(code), "$(location :{which})".format(which=which), ], data = [ which, ":example_{lang}".format(lang=lang), ], ) for lang in ( "cc", "py", ) for (which, code) in ( ("valid.textproto", 0), ("invalid.textproto", 1), ) ] protoc-gen-validate-1.0.2/example-workspace/WORKSPACE000066400000000000000000000017511444536353100223020ustar00rootroot00000000000000# Initialize this as a self-contained Bazel workspace. workspace(name = "pgv_example") # Declare the protoc-gen-validate repository as an external dependency. # This uses a local_repository declaration because this workspace is part of # the same Git repository. External repositories should declare PGV as a # dependency using http_repository pointed at the PGV GitHub repository. local_repository( name = "com_envoyproxy_protoc_gen_validate", path = "../", ) # Load the dependencies of PGV. This is required for the next step to work. load("@com_envoyproxy_protoc_gen_validate//bazel:repositories.bzl", "pgv_dependencies") pgv_dependencies() # Perform any necessary actions to initialize dependencies. load("@com_envoyproxy_protoc_gen_validate//bazel:dependency_imports.bzl", "pgv_dependency_imports") pgv_dependency_imports() load("@com_envoyproxy_protoc_gen_validate//:dependencies.bzl", "go_third_party") # gazelle:repository_macro dependencies.bzl%go_third_party go_third_party() protoc-gen-validate-1.0.2/example-workspace/dependencies.bzl000066400000000000000000000421231444536353100241560ustar00rootroot00000000000000load("@bazel_gazelle//:deps.bzl", "go_repository") def go_third_party(): go_repository( name = "co_honnef_go_tools", importpath = "honnef.co/go/tools", sum = "h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8=", version = "v0.0.1-2020.1.4", ) go_repository( name = "com_github_burntsushi_toml", importpath = "github.com/BurntSushi/toml", sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=", version = "v0.3.1", ) go_repository( name = "com_github_burntsushi_xgb", importpath = "github.com/BurntSushi/xgb", sum = "h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=", version = "v0.0.0-20160522181843-27f122750802", ) go_repository( name = "com_github_census_instrumentation_opencensus_proto", importpath = "github.com/census-instrumentation/opencensus-proto", sum = "h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=", version = "v0.2.1", ) go_repository( name = "com_github_chzyer_logex", importpath = "github.com/chzyer/logex", sum = "h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=", version = "v1.1.10", ) go_repository( name = "com_github_chzyer_readline", importpath = "github.com/chzyer/readline", sum = "h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=", version = "v0.0.0-20180603132655-2972be24d48e", ) go_repository( name = "com_github_chzyer_test", importpath = "github.com/chzyer/test", sum = "h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=", version = "v0.0.0-20180213035817-a1ea475d72b1", ) go_repository( name = "com_github_client9_misspell", importpath = "github.com/client9/misspell", sum = "h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=", version = "v0.3.4", ) go_repository( name = "com_github_cncf_udpa_go", importpath = "github.com/cncf/udpa/go", sum = "h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M=", version = "v0.0.0-20201120205902-5459f2c99403", ) go_repository( name = "com_github_davecgh_go_spew", importpath = "github.com/davecgh/go-spew", sum = "h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=", version = "v1.1.0", ) go_repository( name = "com_github_envoyproxy_go_control_plane", importpath = "github.com/envoyproxy/go-control-plane", sum = "h1:EmNYJhPYy0pOFjCx2PrgtaBXmee0iUX9hLlxE1xHOJE=", version = "v0.9.9-0.20201210154907-fd9021fe5dad", ) go_repository( name = "com_github_go_gl_glfw", importpath = "github.com/go-gl/glfw", sum = "h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=", version = "v0.0.0-20190409004039-e6da0acd62b1", ) go_repository( name = "com_github_go_gl_glfw_v3_3_glfw", importpath = "github.com/go-gl/glfw/v3.3/glfw", sum = "h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I=", version = "v0.0.0-20200222043503-6f7a984d4dc4", ) go_repository( name = "com_github_golang_glog", importpath = "github.com/golang/glog", sum = "h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=", version = "v0.0.0-20160126235308-23def4e6c14b", ) go_repository( name = "com_github_golang_groupcache", importpath = "github.com/golang/groupcache", sum = "h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=", version = "v0.0.0-20200121045136-8c9f03a8e57e", ) go_repository( name = "com_github_golang_mock", importpath = "github.com/golang/mock", sum = "h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=", version = "v1.4.4", ) go_repository( name = "com_github_golang_protobuf", importpath = "github.com/golang/protobuf", sum = "h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=", version = "v1.5.2", ) go_repository( name = "com_github_google_btree", importpath = "github.com/google/btree", sum = "h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=", version = "v1.0.0", ) go_repository( name = "com_github_google_go_cmp", importpath = "github.com/google/go-cmp", sum = "h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=", version = "v0.5.5", ) go_repository( name = "com_github_google_martian", importpath = "github.com/google/martian", sum = "h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=", version = "v2.1.0+incompatible", ) go_repository( name = "com_github_google_martian_v3", importpath = "github.com/google/martian/v3", sum = "h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60=", version = "v3.1.0", ) go_repository( name = "com_github_google_pprof", importpath = "github.com/google/pprof", sum = "h1:LR89qFljJ48s990kEKGsk213yIJDPI4205OKOzbURK8=", version = "v0.0.0-20201218002935-b9804c9f04c2", ) go_repository( name = "com_github_google_renameio", importpath = "github.com/google/renameio", sum = "h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=", version = "v0.1.0", ) go_repository( name = "com_github_google_uuid", importpath = "github.com/google/uuid", sum = "h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=", version = "v1.1.2", ) go_repository( name = "com_github_googleapis_gax_go_v2", importpath = "github.com/googleapis/gax-go/v2", sum = "h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=", version = "v2.0.5", ) go_repository( name = "com_github_googleapis_google_cloud_go_testing", importpath = "github.com/googleapis/google-cloud-go-testing", sum = "h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4=", version = "v0.0.0-20200911160855-bcd43fbb19e8", ) go_repository( name = "com_github_hashicorp_golang_lru", importpath = "github.com/hashicorp/golang-lru", sum = "h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=", version = "v0.5.1", ) go_repository( name = "com_github_iancoleman_strcase", importpath = "github.com/iancoleman/strcase", sum = "h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=", version = "v0.2.0", ) go_repository( name = "com_github_ianlancetaylor_demangle", importpath = "github.com/ianlancetaylor/demangle", sum = "h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI=", version = "v0.0.0-20200824232613-28f6c0f3b639", ) go_repository( name = "com_github_jstemmer_go_junit_report", importpath = "github.com/jstemmer/go-junit-report", sum = "h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=", version = "v0.9.1", ) go_repository( name = "com_github_kisielk_gotool", importpath = "github.com/kisielk/gotool", sum = "h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=", version = "v1.0.0", ) go_repository( name = "com_github_kr_fs", importpath = "github.com/kr/fs", sum = "h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=", version = "v0.1.0", ) go_repository( name = "com_github_kr_pretty", importpath = "github.com/kr/pretty", sum = "h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=", version = "v0.1.0", ) go_repository( name = "com_github_kr_pty", importpath = "github.com/kr/pty", sum = "h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=", version = "v1.1.1", ) go_repository( name = "com_github_kr_text", importpath = "github.com/kr/text", sum = "h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=", version = "v0.1.0", ) go_repository( name = "com_github_lyft_protoc_gen_star_v2", importpath = "github.com/lyft/protoc-gen-star/v2", sum = "h1:erE0rdztuaDq3bpGifD95wfoPrSZc95nGA6tbiNYh6M=", version = "v0.6.1", ) go_repository( name = "com_github_pkg_errors", importpath = "github.com/pkg/errors", sum = "h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=", version = "v0.9.1", ) go_repository( name = "com_github_pkg_sftp", importpath = "github.com/pkg/sftp", sum = "h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs=", version = "v1.13.1", ) go_repository( name = "com_github_pmezard_go_difflib", importpath = "github.com/pmezard/go-difflib", sum = "h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=", version = "v1.0.0", ) go_repository( name = "com_github_prometheus_client_model", importpath = "github.com/prometheus/client_model", sum = "h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=", version = "v0.0.0-20190812154241-14fe0d1b01d4", ) go_repository( name = "com_github_rogpeppe_go_internal", importpath = "github.com/rogpeppe/go-internal", sum = "h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=", version = "v1.3.0", ) go_repository( name = "com_github_spf13_afero", importpath = "github.com/spf13/afero", sum = "h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=", version = "v1.9.2", ) go_repository( name = "com_github_stretchr_objx", importpath = "github.com/stretchr/objx", sum = "h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=", version = "v0.1.0", ) go_repository( name = "com_github_stretchr_testify", importpath = "github.com/stretchr/testify", sum = "h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=", version = "v1.7.0", ) go_repository( name = "com_github_yuin_goldmark", importpath = "github.com/yuin/goldmark", sum = "h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=", version = "v1.4.13", ) go_repository( name = "com_google_cloud_go", importpath = "cloud.google.com/go", sum = "h1:XgtDnVJRCPEUG21gjFiRPz4zI1Mjg16R+NYQjfmU4XY=", version = "v0.75.0", ) go_repository( name = "com_google_cloud_go_bigquery", importpath = "cloud.google.com/go/bigquery", sum = "h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA=", version = "v1.8.0", ) go_repository( name = "com_google_cloud_go_datastore", importpath = "cloud.google.com/go/datastore", sum = "h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ=", version = "v1.1.0", ) go_repository( name = "com_google_cloud_go_pubsub", importpath = "cloud.google.com/go/pubsub", sum = "h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU=", version = "v1.3.1", ) go_repository( name = "com_google_cloud_go_storage", importpath = "cloud.google.com/go/storage", sum = "h1:6RRlFMv1omScs6iq2hfE3IvgE+l6RfJPampq8UZc5TU=", version = "v1.14.0", ) go_repository( name = "com_shuralyov_dmitri_gpu_mtl", importpath = "dmitri.shuralyov.com/gpu/mtl", sum = "h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY=", version = "v0.0.0-20190408044501-666a987793e9", ) go_repository( name = "in_gopkg_check_v1", importpath = "gopkg.in/check.v1", sum = "h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=", version = "v1.0.0-20180628173108-788fd7840127", ) go_repository( name = "in_gopkg_errgo_v2", importpath = "gopkg.in/errgo.v2", sum = "h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=", version = "v2.1.0", ) go_repository( name = "in_gopkg_yaml_v2", importpath = "gopkg.in/yaml.v2", sum = "h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=", version = "v2.2.2", ) go_repository( name = "in_gopkg_yaml_v3", importpath = "gopkg.in/yaml.v3", sum = "h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=", version = "v3.0.0-20200313102051-9f266ea9e77c", ) go_repository( name = "io_opencensus_go", importpath = "go.opencensus.io", sum = "h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0=", version = "v0.22.5", ) go_repository( name = "io_rsc_binaryregexp", importpath = "rsc.io/binaryregexp", sum = "h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE=", version = "v0.2.0", ) go_repository( name = "io_rsc_quote_v3", importpath = "rsc.io/quote/v3", sum = "h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=", version = "v3.1.0", ) go_repository( name = "io_rsc_sampler", importpath = "rsc.io/sampler", sum = "h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=", version = "v1.3.0", ) go_repository( name = "org_golang_google_api", importpath = "google.golang.org/api", sum = "h1:uWrpz12dpVPn7cojP82mk02XDgTJLDPc2KbVTxrWb4A=", version = "v0.40.0", ) go_repository( name = "org_golang_google_appengine", importpath = "google.golang.org/appengine", sum = "h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=", version = "v1.6.7", ) go_repository( name = "org_golang_google_genproto", importpath = "google.golang.org/genproto", sum = "h1:PYBmACG+YEv8uQPW0r1kJj8tR+gkF0UWq7iFdUezwEw=", version = "v0.0.0-20210226172003-ab064af71705", ) go_repository( name = "org_golang_google_grpc", importpath = "google.golang.org/grpc", sum = "h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8=", version = "v1.35.0", ) go_repository( name = "org_golang_google_protobuf", importpath = "google.golang.org/protobuf", sum = "h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=", version = "v1.30.0", ) go_repository( name = "org_golang_x_crypto", importpath = "golang.org/x/crypto", sum = "h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4=", version = "v0.0.0-20211108221036-ceb1ce70b4fa", ) go_repository( name = "org_golang_x_exp", importpath = "golang.org/x/exp", sum = "h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y=", version = "v0.0.0-20200224162631-6cc2880d07d6", ) go_repository( name = "org_golang_x_image", importpath = "golang.org/x/image", sum = "h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=", version = "v0.0.0-20190802002840-cff245a6509b", ) go_repository( name = "org_golang_x_lint", importpath = "golang.org/x/lint", sum = "h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=", version = "v0.0.0-20210508222113-6edffad5e616", ) go_repository( name = "org_golang_x_mobile", importpath = "golang.org/x/mobile", sum = "h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs=", version = "v0.0.0-20190719004257-d2bd2a29d028", ) go_repository( name = "org_golang_x_mod", importpath = "golang.org/x/mod", sum = "h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=", version = "v0.6.0-dev.0.20220419223038-86c51ed26bb4", ) go_repository( name = "org_golang_x_net", importpath = "golang.org/x/net", sum = "h1:1WGATo9HAhkWMbfyuVU0tEFP88OIkUvwaHFveQPvzCQ=", version = "v0.0.0-20220907135653-1e95f45603a7", ) go_repository( name = "org_golang_x_oauth2", importpath = "golang.org/x/oauth2", sum = "h1:5vD4XjIc0X5+kHZjx4UecYdjA6mJo+XXNoaW0EjU5Os=", version = "v0.0.0-20210218202405-ba52d332ba99", ) go_repository( name = "org_golang_x_sync", importpath = "golang.org/x/sync", sum = "h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=", version = "v0.0.0-20220722155255-886fb9371eb4", ) go_repository( name = "org_golang_x_sys", importpath = "golang.org/x/sys", sum = "h1:RoyzQTK76Rktm3p4xyZslc8T8I1tBz4UEjZCzeh57mM=", version = "v0.0.0-20220908150016-7ac13a9a928d", ) go_repository( name = "org_golang_x_term", importpath = "golang.org/x/term", sum = "h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=", version = "v0.0.0-20210927222741-03fcf44c2211", ) go_repository( name = "org_golang_x_text", importpath = "golang.org/x/text", sum = "h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=", version = "v0.3.7", ) go_repository( name = "org_golang_x_time", importpath = "golang.org/x/time", sum = "h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=", version = "v0.0.0-20191024005414-555d28b269f0", ) go_repository( name = "org_golang_x_tools", importpath = "golang.org/x/tools", sum = "h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=", version = "v0.1.12", ) go_repository( name = "org_golang_x_xerrors", importpath = "golang.org/x/xerrors", sum = "h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=", version = "v0.0.0-20220907171357-04be3eba64a2", ) protoc-gen-validate-1.0.2/example-workspace/example.cc000066400000000000000000000033721444536353100227640ustar00rootroot00000000000000#include #include #include #include #include "google/protobuf/io/zero_copy_stream_impl.h" #include "google/protobuf/text_format.h" #include "foo/bar.pb.h" #include "foo/bar.pb.validate.h" int main(const int nargs, const char** const args) { if (nargs <= 1) { std::cout << "No inputs provided; exiting" << std::endl; return EXIT_SUCCESS; } int success_count = 0; for (int i = 1; i < nargs; ++i) { pgv::example::foo::Bars bars; const auto filename = args[i]; const auto fd = ::open(filename, O_RDONLY); if (fd < 0) { std::cerr << "Failed to open file '" << filename << "'" << std::endl; continue; } google::protobuf::io::FileInputStream input(fd); input.SetCloseOnDelete(true); if (!google::protobuf::TextFormat::Parse(&input, &bars)) { std::cerr << "Failed to parse file '" << filename << "' as a " << bars.GetDescriptor()->full_name() << " textproto" << std::endl; return EXIT_FAILURE; } pgv::ValidationMsg error_message; if (Validate(bars, &error_message)) { std::cout << "Successfully validated file '" << filename << "' as a " << bars.GetDescriptor()->full_name() << " textproto" << std::endl; ++success_count; } else { std::cerr << "Failed to validate file '" << filename << "' as a " << bars.GetDescriptor()->full_name() << " textproto: " << error_message << std::endl; } } const int failure_count = nargs - 1 - success_count; if (failure_count != 0) { std::cerr << "Failed to validate " << failure_count << " file" << (failure_count == 1 ? "" : "s") << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; } protoc-gen-validate-1.0.2/example-workspace/example.py000066400000000000000000000031201444536353100230160ustar00rootroot00000000000000import sys from google.protobuf import text_format from foo import bar_pb2 from com_envoyproxy_protoc_gen_validate.python.protoc_gen_validate import validator from typing import List def main(filenames: List[str]) -> None: if not filenames: print("No inputs provided; exiting") success_count = 0 for filename in filenames: bars = bar_pb2.Bars() fullname = bars.DESCRIPTOR.name try: with open(filename, 'r') as fh: text_format.Parse(fh.read(), bars) except IOError as error: msg = f"Failed to open file '{filename}': {error}" raise RuntimeError(msg) from error except text_format.ParseError as error: msg = f"Failed to parse file '{filename}' as a {fullname} textproto: {error}" raise RuntimeError(msg) from error try: validator.validate(bars) except validator.ValidationFailed as error: print( f"Failed to validate file '{filename}' as a {fullname} textproto: {error}", file=sys.stderr, ) else: print(f"Successfully validated file '{filename}' as a {fullname} textproto") success_count += 1 failure_count = len(filenames) - success_count if failure_count: s = "s" if failure_count > 1 else "" msg = f"Failed to validate {failure_count} file{s}" raise RuntimeError(msg) if __name__ == "__main__": try: main(sys.argv[1:]) except RuntimeError as error: print(error, file=sys.stderr) sys.exit(1) protoc-gen-validate-1.0.2/example-workspace/example_test.sh000077500000000000000000000001711444536353100240450ustar00rootroot00000000000000#!/bin/bash # BINARY=$1 EXPECTED_EXIT_CODE=$2 FILENAME=$3 "${BINARY}" "${FILENAME}" test $? -eq ${EXPECTED_EXIT_CODE} protoc-gen-validate-1.0.2/example-workspace/foo/000077500000000000000000000000001444536353100216005ustar00rootroot00000000000000protoc-gen-validate-1.0.2/example-workspace/foo/BUILD000066400000000000000000000017561444536353100223730ustar00rootroot00000000000000load("@com_envoyproxy_protoc_gen_validate//bazel:pgv_proto_library.bzl", "pgv_cc_proto_library") load("@com_google_protobuf//:protobuf.bzl", "py_proto_library") package( default_visibility = ["//visibility:public"], ) proto_library( name = "bar_proto", srcs = ["bar.proto"], deps = ["@com_envoyproxy_protoc_gen_validate//validate:validate_proto"], ) pgv_cc_proto_library( name = "bar_cc_proto", deps = [":bar_proto"], ) proto_library( name = "baz_proto", srcs = ["subdir_without_package/baz.proto"], deps = ["@com_envoyproxy_protoc_gen_validate//validate:validate_proto"], ) pgv_cc_proto_library( name = "baz_cc_proto", deps = [":baz_proto"], ) cc_test( name = "baz_cc_test", srcs = ["baz_cc_test.cc"], deps = [":baz_cc_proto"], ) py_proto_library( name = "bar_py_proto", srcs = ["bar.proto"], deps = [ "@com_envoyproxy_protoc_gen_validate//validate:validate_py", "@com_google_protobuf//:protobuf_python", ], ) protoc-gen-validate-1.0.2/example-workspace/foo/bar.proto000066400000000000000000000004101444536353100234240ustar00rootroot00000000000000syntax = "proto3"; package pgv.example.foo; import "validate/validate.proto"; message BarNone { int32 value = 1; } message BarOne { int32 value = 1 [(validate.rules).int32 = { not_in: 1 }]; } message Bars { BarNone bar_none = 1; BarOne bar_one = 2; } protoc-gen-validate-1.0.2/example-workspace/foo/baz_cc_test.cc000066400000000000000000000006421444536353100243710ustar00rootroot00000000000000#include #include #include #include #include "foo/subdir_without_package/baz.pb.h" #include "foo/subdir_without_package/baz.pb.validate.h" #include "google/protobuf/io/zero_copy_stream_impl.h" #include "google/protobuf/text_format.h" int main(int nargs, char** args) { pgv::example::foo::Baz baz; pgv::ValidationMsg msg; Validate(baz, &msg); return EXIT_SUCCESS; } protoc-gen-validate-1.0.2/example-workspace/foo/subdir_without_package/000077500000000000000000000000001444536353100263265ustar00rootroot00000000000000protoc-gen-validate-1.0.2/example-workspace/foo/subdir_without_package/baz.proto000066400000000000000000000002371444536353100301710ustar00rootroot00000000000000syntax = "proto3"; package pgv.example.foo; import "validate/validate.proto"; message Baz { int32 not_two = 1 [(validate.rules).int32 = { not_in: 2 }]; } protoc-gen-validate-1.0.2/example-workspace/invalid.textproto000066400000000000000000000001671444536353100244410ustar00rootroot00000000000000# proto-file: src/foo/bar.proto # proto-message: pgv.example.foo.Bars bar_one { value: 1 } bar_none { value: 5 } protoc-gen-validate-1.0.2/example-workspace/valid.textproto000066400000000000000000000001661444536353100241110ustar00rootroot00000000000000# proto-file: src/foo/bar.proto # proto-message: pgv.example.foo.Bars bar_none { value: 5 } bar_one { value: 3 } protoc-gen-validate-1.0.2/go.mod000066400000000000000000000010071444536353100164720ustar00rootroot00000000000000module github.com/envoyproxy/protoc-gen-validate go 1.19 require ( github.com/iancoleman/strcase v0.2.0 github.com/lyft/protoc-gen-star/v2 v2.0.3 golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 golang.org/x/net v0.11.0 golang.org/x/tools v0.10.0 google.golang.org/protobuf v1.30.0 ) require ( github.com/spf13/afero v1.3.3 // indirect golang.org/x/mod v0.11.0 // indirect golang.org/x/sys v0.9.0 // indirect golang.org/x/text v0.10.0 // indirect ) retract [v0.6.9, v0.6.12] // Published accidentally protoc-gen-validate-1.0.2/go.sum000066400000000000000000000117721444536353100165310ustar00rootroot00000000000000github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/lyft/protoc-gen-star/v2 v2.0.3 h1:/3+/2sWyXeMLzKd1bX+ixWKgEMsULrIivpDsuaF441o= github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/spf13/afero v1.3.3 h1:p5gZEKLYoL7wh8VrJesMaYeNxdEd1v3cb4irOk9zB54= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= protoc-gen-validate-1.0.2/java/000077500000000000000000000000001444536353100163075ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/RELEASING.md000066400000000000000000000026321444536353100201450ustar00rootroot00000000000000# Releasing PGV Java components These steps are for releasing the Java components of PGV: - pgv-java-stub - pgv-java-grpc - pgv-artifacts ## Releasing using CI Releasing from main is fully automated by CI: Releasing from versioned tags is similar. To release version `vX.Y.Z`, first create a Git tag called `vX.Y.Z` (preferably through the GitHub release flow), then run the following to kick off a release build: The [`Maven Deploy`](../.github/workflows/maven-publish.yaml) CI flow will use the version number from the tag to deploy to the Maven repository. ## Manually releasing from git history Manually releasing from git history is a more involved process, but allows you to release from any point in the history. 1. Create a new `release/x.y.z` branch at the point you want to release. 1. Copy `java/settings.xml` to a scratch location. 1. Fill out the parameters in `settings.xml`. You will need a published GPG key for code signing and the EnvoyReleaseBot sonatype username and password. 1. Execute the release command, substituting the path to `settings.xml`, the `releaseVersion`, and the next `developmentVersion` (-SNAPSHOT). 1. Merge the release branch back into master. ```shell mvn -B -s /path/to/settings.xml clean release:prepare release:perform \ -Darguments="-s /path/to/settings.xml" \ -DreleaseVersion=x.y.z \ -DdevelopmentVersion=x.y.z-SNAPSHOT \ -DscmCommentPrefix="java release: " ``` protoc-gen-validate-1.0.2/java/pgv-artifacts/000077500000000000000000000000001444536353100210615ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-artifacts/pom.xml000066400000000000000000000254411444536353100224040ustar00rootroot00000000000000 pgv-java build.buf.protoc-gen-validate VERSION 4.0.0 protoc-gen-validate pom PGV-Java Protoc Plugins org.codehaus.mojo exec-maven-plugin 3.1.0 osx-x86_64 exec compile go build -o ${project.build.directory}/protoc-gen-validate-${project.version}-osx-x86_64.exe ../.. darwin amd64 osx-aarch_64 exec compile go build -o ${project.build.directory}/protoc-gen-validate-${project.version}-osx-aarch_64.exe ../.. darwin arm64 linux_x86_32 exec compile go build -o ${project.build.directory}/protoc-gen-validate-${project.version}-linux-x86_32.exe ../.. linux 386 linux_x86_64 exec compile go build -o ${project.build.directory}/protoc-gen-validate-${project.version}-linux-x86_64.exe ../.. linux amd64 windows_x86_32 exec compile go build -o ${project.build.directory}/protoc-gen-validate-${project.version}-windows-x86_32.exe ../.. windows 386 windows_x86_64 exec compile go build -o ${project.build.directory}/protoc-gen-validate-${project.version}-windows-x86_64.exe ../.. windows amd64 linux-aarch_64 exec compile go build -o ${project.build.directory}/protoc-gen-validate-${project.version}-linux-aarch_64.exe ../.. linux arm64 org.codehaus.mojo build-helper-maven-plugin 3.4.0 attach-artifacts attach-artifact ${project.build.directory}/protoc-gen-validate-${project.version}-osx-x86_64.exe exe osx-x86_64 ${project.build.directory}/protoc-gen-validate-${project.version}-osx-aarch_64.exe exe osx-aarch_64 ${project.build.directory}/protoc-gen-validate-${project.version}-linux-aarch_64.exe exe linux-aarch_64 ${project.build.directory}/protoc-gen-validate-${project.version}-linux-x86_32.exe exe linux-x86_32 ${project.build.directory}/protoc-gen-validate-${project.version}-linux-x86_64.exe exe linux-x86_64 ${project.build.directory}/protoc-gen-validate-${project.version}-windows-x86_32.exe exe windows-x86_32 ${project.build.directory}/protoc-gen-validate-${project.version}-windows-x86_64.exe exe windows-x86_64 protoc-gen-validate-1.0.2/java/pgv-java-grpc/000077500000000000000000000000001444536353100207535ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/pom.xml000066400000000000000000000117261444536353100222770ustar00rootroot00000000000000 pgv-java build.buf.protoc-gen-validate VERSION 4.0.0 pgv-java-grpc PGV-Java gRPC Interceptors io.grpc grpc-bom ${grpc.version} pom import com.google.api.grpc proto-google-common-protos ${proto-google-common-protos.version} io.grpc grpc-core io.grpc grpc-testing test io.grpc grpc-protobuf io.grpc grpc-stub test javax.annotation javax.annotation-api 1.3.2 test build.buf.protoc-gen-validate protoc-gen-validate ${project.version} pom test build.buf.protoc-gen-validate pgv-java-stub ${project.version} kr.motd.maven os-maven-plugin 1.7.1 org.xolstice.maven.plugins protobuf-maven-plugin ${protobuf.maven.plugin.version} com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier} grpc-java io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} test-compile test-compile-custom protoc-java-pgv test-compile-custom lang=java java-pgv build.buf.protoc-gen-validate:protoc-gen-validate:${project.version}:exe:${os.detected.classifier} org.jacoco jacoco-maven-plugin 0.8.10 prepare-agent report prepare-package report protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/000077500000000000000000000000001444536353100215425ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/000077500000000000000000000000001444536353100224665ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/000077500000000000000000000000001444536353100234075ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/000077500000000000000000000000001444536353100240165ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/envoyproxy/000077500000000000000000000000001444536353100262605ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/envoyproxy/pgv/000077500000000000000000000000001444536353100270545ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/envoyproxy/pgv/grpc/000077500000000000000000000000001444536353100300075ustar00rootroot00000000000000ValidatingClientInterceptor.java000066400000000000000000000023431444536353100362350ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/envoyproxy/pgv/grpcpackage io.envoyproxy.pgv.grpc; import io.envoyproxy.pgv.ValidationException; import io.envoyproxy.pgv.ValidatorIndex; import io.grpc.*; /** * {@code ValidatingClientInterceptor} is a gRPC {@code ClientInterceptor} that validates outbound gRPC messages before * transmission. Non-compliant messages result in an {@code INVALID_ARGUMENT} status exception. */ public class ValidatingClientInterceptor implements ClientInterceptor { private final ValidatorIndex index; public ValidatingClientInterceptor(ValidatorIndex index) { this.index = index; } @Override public ClientCall interceptCall(MethodDescriptor method, CallOptions callOptions, Channel next) { return new ForwardingClientCall.SimpleForwardingClientCall(next.newCall(method, callOptions)) { @Override public void sendMessage(ReqT message) { try { index.validatorFor(message.getClass()).assertValid(message); super.sendMessage(message); } catch (ValidationException ex) { throw ValidationExceptions.asStatusRuntimeException(ex); } } }; } } ValidatingServerInterceptor.java000066400000000000000000000033331444536353100362650ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/envoyproxy/pgv/grpcpackage io.envoyproxy.pgv.grpc; import io.envoyproxy.pgv.ValidationException; import io.envoyproxy.pgv.ValidatorIndex; import io.grpc.*; /** * {@code ValidatingServerInterceptor} is a gRPC {@code ServerInterceptor} that validates inbound gRPC messages before * processing. Non-compliant messages result in an {@code INVALID_ARGUMENT} status response. */ public class ValidatingServerInterceptor implements ServerInterceptor { private final ValidatorIndex index; public ValidatingServerInterceptor(ValidatorIndex index) { this.index = index; } @Override public ServerCall.Listener interceptCall(ServerCall call, Metadata headers, ServerCallHandler next) { return new ForwardingServerCallListener.SimpleForwardingServerCallListener(next.startCall(call, headers)) { // Implementations are free to block for extended periods of time. Implementations are not // required to be thread-safe. private boolean aborted = false; @Override public void onMessage(ReqT message) { try { index.validatorFor(message.getClass()).assertValid(message); super.onMessage(message); } catch (ValidationException ex) { StatusRuntimeException status = ValidationExceptions.asStatusRuntimeException(ex); aborted = true; call.close(status.getStatus(), status.getTrailers()); } } @Override public void onHalfClose() { if (!aborted) { super.onHalfClose(); } } }; } } ValidationExceptions.java000066400000000000000000000030011444536353100347210ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/envoyproxy/pgv/grpcpackage io.envoyproxy.pgv.grpc; import com.google.protobuf.Any; import com.google.rpc.BadRequest; import com.google.rpc.Code; import com.google.rpc.Status; import io.envoyproxy.pgv.ValidationException; import io.grpc.StatusRuntimeException; import io.grpc.protobuf.StatusProto; /** * {@code ValidationExceptions} provides utilities for converting {@link ValidationException} objects into gRPC * {@code StatusRuntimeException} objects. */ public final class ValidationExceptions { private ValidationExceptions() { } /** * Convert a {@link ValidationException} into a gRPC {@code StatusRuntimeException} * with status code {@code Code.INVALID_ARGUMENT}, * the {@link ValidationException} exception message, * and {@link Any} error details containing {@link BadRequest} with field violation details. * * @param ex the {@code ValidationException} to convert. * @return a gRPC {@code StatusRuntimeException} */ public static StatusRuntimeException asStatusRuntimeException(ValidationException ex) { BadRequest badRequestElement = BadRequest.newBuilder() .addFieldViolations(BadRequest.FieldViolation.newBuilder().setField(ex.getField()).setDescription(ex.getReason()).build()) .build(); return StatusProto.toStatusRuntimeException(Status.newBuilder() .setCode(Code.INVALID_ARGUMENT.getNumber()) .setMessage(ex.getMessage()) .addDetails(Any.pack(badRequestElement)).build()); } } protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/000077500000000000000000000000001444536353100225215ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/000077500000000000000000000000001444536353100234425ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/io/000077500000000000000000000000001444536353100240515ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/io/envoyproxy/000077500000000000000000000000001444536353100263135ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/io/envoyproxy/pgv/000077500000000000000000000000001444536353100271075ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/io/envoyproxy/pgv/grpc/000077500000000000000000000000001444536353100300425ustar00rootroot00000000000000ValidatingClientInterceptorTest.java000066400000000000000000000140021444536353100371230ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/io/envoyproxy/pgv/grpcpackage io.envoyproxy.pgv.grpc; import com.google.protobuf.Any; import com.google.protobuf.InvalidProtocolBufferException; import com.google.rpc.BadRequest; import com.google.rpc.Status; import io.envoyproxy.pgv.ReflectiveValidatorIndex; import io.envoyproxy.pgv.ValidationException; import io.envoyproxy.pgv.Validator; import io.envoyproxy.pgv.ValidatorIndex; import io.envoyproxy.pgv.grpc.asubpackage.GreeterGrpc; import io.envoyproxy.pgv.grpc.asubpackage.HelloJKRequest; import io.envoyproxy.pgv.grpc.asubpackage.HelloResponse; import io.grpc.BindableService; import io.grpc.StatusRuntimeException; import io.grpc.protobuf.StatusProto; import io.grpc.stub.StreamObserver; import io.grpc.testing.GrpcServerRule; import org.assertj.core.api.Condition; import org.junit.Rule; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class ValidatingClientInterceptorTest { @Rule public GrpcServerRule serverRule = new GrpcServerRule(); private BindableService svc = new GreeterGrpc.GreeterImplBase() { @Override public void sayHello(HelloJKRequest request, StreamObserver responseObserver) { responseObserver.onNext(HelloResponse.newBuilder().setMessage("Hello " + request.getName()).build()); responseObserver.onCompleted(); } }; @Test public void InterceptorPassesValidMessages() { serverRule.getServiceRegistry().addService(svc); ValidatingClientInterceptor interceptor = new ValidatingClientInterceptor(ValidatorIndex.ALWAYS_VALID); GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(serverRule.getChannel()).withInterceptors(interceptor); stub.sayHello(HelloJKRequest.newBuilder().setName("World").build()); } @Test public void InterceptorPassesValidMessagesGenerated() { serverRule.getServiceRegistry().addService(svc); ValidatingClientInterceptor interceptor = new ValidatingClientInterceptor(new ReflectiveValidatorIndex()); GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(serverRule.getChannel()).withInterceptors(interceptor); stub.sayHello(HelloJKRequest.newBuilder().setName("World").build()); } @Test public void InterceptorRejectsInvalidMessages() { // Don't set up server, so it will error if the call goes through ValidatingClientInterceptor interceptor = new ValidatingClientInterceptor(new ValidatorIndex() { @Override public Validator validatorFor(Class clazz) { return proto -> { throw new ValidationException("one", "", "is invalid"); }; } }); GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(serverRule.getChannel()).withInterceptors(interceptor); assertThatThrownBy(() -> stub.sayHello(HelloJKRequest.newBuilder().setName("Foo").build())) .isInstanceOf(StatusRuntimeException.class) .hasMessage("INVALID_ARGUMENT: one: is invalid - Got "); } @Test public void InterceptorRejectsInvalidMessagesGenerated() { // Don't set up server, so it will error if the call goes through ValidatingClientInterceptor interceptor = new ValidatingClientInterceptor(new ReflectiveValidatorIndex()); GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(serverRule.getChannel()).withInterceptors(interceptor); assertThatExceptionOfType(StatusRuntimeException.class).isThrownBy(() -> stub.sayHello(HelloJKRequest.newBuilder().setName("Foo").build())) .withMessageStartingWith("INVALID_ARGUMENT: .io.envoyproxy.pgv.grpc.HelloJKRequest.name: must equal World") .has(new Condition<>(e -> { try { Status status = StatusProto.fromThrowable(e); Any any = status.getDetailsList().get(0); BadRequest badRequest = any.unpack(BadRequest.class); return badRequest.getFieldViolationsCount() == 1 && badRequest.getFieldViolations(0).getField().equals(".io.envoyproxy.pgv.grpc.HelloJKRequest.name") && badRequest.getFieldViolations(0).getDescription().equals("must equal World"); } catch (InvalidProtocolBufferException ex) { return false; } }, "BadRequest details")); } // Also testing compilation of proto files with strings of uppercase characters in their filename. @Test public void InterceptorRejectsInvalidMessagesGenerated2() { // Don't set up server, so it will error if the call goes through ValidatingClientInterceptor interceptor = new ValidatingClientInterceptor(new ReflectiveValidatorIndex()); DismisserGrpc.DismisserBlockingStub stub = DismisserGrpc.newBlockingStub(serverRule.getChannel()).withInterceptors(interceptor); assertThatExceptionOfType(StatusRuntimeException.class).isThrownBy(() -> stub.sayGoodbye(GooDBYe.GoodbyeJKRequest.newBuilder().setName("Foo").build())) .withMessageStartingWith("INVALID_ARGUMENT: .io.envoyproxy.pgv.grpc.GoodbyeJKRequest.name: must equal World") .has(new Condition<>(e -> { try { Status status = StatusProto.fromThrowable(e); Any any = status.getDetailsList().get(0); BadRequest badRequest = any.unpack(BadRequest.class); return badRequest.getFieldViolationsCount() == 1 && badRequest.getFieldViolations(0).getField().equals(".io.envoyproxy.pgv.grpc.GoodbyeJKRequest.name") && badRequest.getFieldViolations(0).getDescription().equals("must equal World"); } catch (InvalidProtocolBufferException ex) { return false; } }, "BadRequest details")); } } ValidatingServerInterceptorTest.java000066400000000000000000000122411444536353100371560ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/io/envoyproxy/pgv/grpcpackage io.envoyproxy.pgv.grpc; import com.google.protobuf.Any; import com.google.protobuf.InvalidProtocolBufferException; import com.google.rpc.BadRequest; import com.google.rpc.Status; import io.envoyproxy.pgv.ReflectiveValidatorIndex; import io.envoyproxy.pgv.ValidationException; import io.envoyproxy.pgv.Validator; import io.envoyproxy.pgv.ValidatorIndex; import io.envoyproxy.pgv.grpc.asubpackage.GreeterGrpc; import io.envoyproxy.pgv.grpc.asubpackage.HelloJKRequest; import io.envoyproxy.pgv.grpc.asubpackage.HelloResponse; import io.grpc.BindableService; import io.grpc.ServerInterceptors; import io.grpc.StatusRuntimeException; import io.grpc.protobuf.StatusProto; import io.grpc.stub.StreamObserver; import io.grpc.testing.GrpcServerRule; import org.assertj.core.api.Condition; import org.junit.Rule; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; public class ValidatingServerInterceptorTest { @Rule public GrpcServerRule serverRule = new GrpcServerRule(); private BindableService svc = new GreeterGrpc.GreeterImplBase() { @Override public void sayHello(HelloJKRequest request, StreamObserver responseObserver) { responseObserver.onNext(HelloResponse.newBuilder().setMessage("Hello " + request.getName()).build()); responseObserver.onCompleted(); } }; @Test public void InterceptorPassesValidMessages() { ValidatingServerInterceptor interceptor = new ValidatingServerInterceptor(ValidatorIndex.ALWAYS_VALID); serverRule.getServiceRegistry().addService(ServerInterceptors.intercept(svc, interceptor)); GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(serverRule.getChannel()); stub.sayHello(HelloJKRequest.newBuilder().setName("World").build()); } @Test public void InterceptorPassesValidMessagesGenerated() { ValidatingServerInterceptor interceptor = new ValidatingServerInterceptor(new ReflectiveValidatorIndex()); serverRule.getServiceRegistry().addService(ServerInterceptors.intercept(svc, interceptor)); GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(serverRule.getChannel()); stub.sayHello(HelloJKRequest.newBuilder().setName("World").build()); } @Test public void InterceptorRejectsInvalidMessages() { ValidatingServerInterceptor interceptor = new ValidatingServerInterceptor(new ValidatorIndex() { @Override public Validator validatorFor(Class clazz) { return proto -> { throw new ValidationException("one", "", "is invalid"); }; } }); serverRule.getServiceRegistry().addService(ServerInterceptors.intercept(svc, interceptor)); GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(serverRule.getChannel()); assertThatExceptionOfType(StatusRuntimeException.class).isThrownBy(() -> stub.sayHello(HelloJKRequest.newBuilder().setName("World").build())) .withMessage("INVALID_ARGUMENT: one: is invalid - Got ") .has(new Condition<>(e -> { try { Status status = StatusProto.fromThrowable(e); Any any = status.getDetailsList().get(0); BadRequest badRequest = any.unpack(BadRequest.class); return badRequest.getFieldViolationsCount() == 1 && badRequest.getFieldViolations(0).getField().equals("one") && badRequest.getFieldViolations(0).getDescription().equals("is invalid"); } catch (InvalidProtocolBufferException ex) { return false; } }, "BadRequest details")); } @Test public void InterceptorRejectsInvalidMessagesGenerated() { ValidatingServerInterceptor interceptor = new ValidatingServerInterceptor(new ReflectiveValidatorIndex()); serverRule.getServiceRegistry().addService(ServerInterceptors.intercept(svc, interceptor)); GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(serverRule.getChannel()); assertThatExceptionOfType(StatusRuntimeException.class).isThrownBy(() -> stub.sayHello(HelloJKRequest.newBuilder().setName("Bananas").build())) .withMessageStartingWith("INVALID_ARGUMENT: .io.envoyproxy.pgv.grpc.HelloJKRequest.name: must equal World") .has(new Condition<>(e -> { try { Status status = StatusProto.fromThrowable(e); Any any = status.getDetailsList().get(0); BadRequest badRequest = any.unpack(BadRequest.class); return badRequest.getFieldViolationsCount() == 1 && badRequest.getFieldViolations(0).getField().equals(".io.envoyproxy.pgv.grpc.HelloJKRequest.name") && badRequest.getFieldViolations(0).getDescription().equals("must equal World"); } catch (InvalidProtocolBufferException ex) { return false; } }, "BadRequest details")); } } protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/proto/000077500000000000000000000000001444536353100236645ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/proto/BUILD.bazel000066400000000000000000000023001444536353100255350ustar00rootroot00000000000000load("@io_bazel_rules_go//go:def.bzl", "go_library") load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") load("@rules_proto//proto:defs.bzl", "proto_library") proto_library( name = "io_envoyproxy_pgv_grpc_proto", srcs = [ "GooDBYe.proto", "hello.proto", ], visibility = ["//visibility:public"], deps = ["//validate:validate_proto"], ) go_proto_library( name = "io_envoyproxy_pgv_grpc_go_proto", compilers = ["@io_bazel_rules_go//proto:go_grpc"], importpath = "github.com/envoyproxy/protoc-gen-validate/java/pgv-java-grpc/src/test/proto", proto = ":io_envoyproxy_pgv_grpc_proto", visibility = ["//visibility:public"], deps = ["//validate:validate_go"], ) go_library( name = "proto", embed = [":io_envoyproxy_pgv_grpc_go_proto"], importpath = "github.com/envoyproxy/protoc-gen-validate/java/pgv-java-grpc/src/test/proto", visibility = ["//visibility:public"], ) alias( name = "go_default_library", actual = ":proto", deprecation = "Use :proto instead of :go_default_library. Details about the new naming convention: https://github.com/bazelbuild/bazel-gazelle/pull/863", visibility = ["//visibility:public"], ) protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/proto/GooDBYe.proto000066400000000000000000000005501444536353100262010ustar00rootroot00000000000000syntax = "proto3"; package io.envoyproxy.pgv.grpc; option java_multiple_files = false; import "validate/validate.proto"; service Dismisser { rpc SayGoodbye (GoodbyeJKRequest) returns (GoodbyeResponse) {} } message GoodbyeJKRequest { string name = 1 [(validate.rules).string.const = "World"]; } message GoodbyeResponse { string message = 1; } protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/proto/hello.proto000066400000000000000000000007031444536353100260540ustar00rootroot00000000000000syntax = "proto3"; package io.envoyproxy.pgv.grpc; option java_multiple_files = true; option java_package = "io.envoyproxy.pgv.grpc.asubpackage"; option java_outer_classname = "Ponycopter"; import "validate/validate.proto"; service Greeter { rpc SayHello (HelloJKRequest) returns (HelloResponse) {} } message HelloJKRequest { string name = 1 [(validate.rules).string.const = "World"]; } message HelloResponse { string message = 1; } protoc-gen-validate-1.0.2/java/pgv-java-stub/000077500000000000000000000000001444536353100207755ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/pom.xml000066400000000000000000000124511444536353100223150ustar00rootroot00000000000000 pgv-java build.buf.protoc-gen-validate VERSION 4.0.0 pgv-java-stub PGV-Java Stubs com.google.re2j re2j ${re2j.version} commons-validator commons-validator ${commons.validator.version} * * com.google.protobuf protobuf-java ${google.protobuf.version} com.google.protobuf protobuf-java-util ${google.protobuf.version} build.buf.protoc-gen-validate protoc-gen-validate ${project.version} pom test ../.. validate/validate.proto kr.motd.maven os-maven-plugin 1.7.1 org.xolstice.maven.plugins protobuf-maven-plugin ${protobuf.maven.plugin.version} com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier} protoc-java-pgv compile ../../ validate/*.proto protoc-java test-compile test-protoc-java-pgv test-compile-custom lang=java java-pgv build.buf.protoc-gen-validate:protoc-gen-validate:${project.version}:exe:${os.detected.classifier} org.jacoco jacoco-maven-plugin 0.8.10 prepare-agent report prepare-package report protoc-gen-validate-1.0.2/java/pgv-java-stub/src/000077500000000000000000000000001444536353100215645ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/000077500000000000000000000000001444536353100225105ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/000077500000000000000000000000001444536353100234315ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/000077500000000000000000000000001444536353100240405ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/000077500000000000000000000000001444536353100263025ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/000077500000000000000000000000001444536353100270765ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/BUILD000066400000000000000000000006011444536353100276550ustar00rootroot00000000000000load("@rules_java//java:defs.bzl", "java_library") java_library( name = "pgv", srcs = glob(["*.java"]), visibility = ["//visibility:public"], deps = [ "//external:guava", "@com_google_protobuf//:protobuf_java", "@com_google_protobuf//:protobuf_java_util", "@com_google_re2j//jar", "@org_apache_commons_validator//jar", ], ) protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/BytesValidation.java000066400000000000000000000064141444536353100330470ustar00rootroot00000000000000package io.envoyproxy.pgv; import com.google.common.primitives.Bytes; import com.google.protobuf.ByteString; import com.google.re2j.Pattern; import java.util.Arrays; /** * {@code BytesValidation} implements PGV validators for protobuf {@code Byte} fields. */ public final class BytesValidation { private BytesValidation() { } public static void length(String field, ByteString value, int expected) throws ValidationException { if (value.size() != expected) { throw new ValidationException(field, Arrays.toString(value.toByteArray()), "length must be " + expected); } } public static void minLength(String field, ByteString value, int expected) throws ValidationException { if (value.size() < expected) { throw new ValidationException(field, Arrays.toString(value.toByteArray()), "length must be at least " + expected); } } public static void maxLength(String field, ByteString value, int expected) throws ValidationException { if (value.size() > expected) { throw new ValidationException(field, Arrays.toString(value.toByteArray()), "length must be at most " + expected); } } public static void prefix(String field, ByteString value, byte[] prefix) throws ValidationException { if (!value.startsWith(ByteString.copyFrom(prefix))) { throw new ValidationException(field, Arrays.toString(value.toByteArray()), "should start with " + Arrays.toString(prefix)); } } public static void contains(String field, ByteString value, byte[] contains) throws ValidationException { if (Bytes.indexOf(value.toByteArray(), contains) == -1) { throw new ValidationException(field, Arrays.toString(value.toByteArray()), "should contain " + Arrays.toString(contains)); } } public static void suffix(String field, ByteString value, byte[] suffix) throws ValidationException { if (!value.endsWith(ByteString.copyFrom(suffix))) { throw new ValidationException(field, Arrays.toString(value.toByteArray()), "should end with " + Arrays.toString(suffix)); } } public static void pattern(String field, ByteString value, Pattern p) throws ValidationException { if (!p.matches(value.toStringUtf8())) { throw new ValidationException(field, Arrays.toString(value.toByteArray()), "must match pattern " + p.pattern()); } } public static void ip(String field, ByteString value) throws ValidationException { if (value.toByteArray().length != 4 && value.toByteArray().length != 16) { throw new ValidationException(field, Arrays.toString(value.toByteArray()), "should be valid ip address " + value); } } public static void ipv4(String field, ByteString value) throws ValidationException { if (value.toByteArray().length != 4) { throw new ValidationException(field, Arrays.toString(value.toByteArray()), "should be valid ipv4 address " + value); } } public static void ipv6(String field, ByteString value) throws ValidationException { if (value.toByteArray().length != 16) { throw new ValidationException(field, Arrays.toString(value.toByteArray()), "should be valid ipv6 address " + value); } } } CollectiveValidation.java000066400000000000000000000015221444536353100337660ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import java.util.Arrays; /** * {@code CollectiveValidation} implements PGV validators for the collective {@code in} and {@code notIn} rules. */ public final class CollectiveValidation { private CollectiveValidation() { } public static void in(String field, T value, T[] set) throws ValidationException { for (T i : set) { if (value.equals(i)) { return; } } throw new ValidationException(field, value, "must be in " + Arrays.toString(set)); } public static void notIn(String field, T value, T[] set) throws ValidationException { for (T i : set) { if (value.equals(i)) { throw new ValidationException(field, value, "must not be in " + Arrays.toString(set)); } } } } ComparativeValidation.java000066400000000000000000000100531444536353100341460ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import java.util.Comparator; /** * {@code ComparativeValidation} implements PGV validation rules for ordering relationships. */ public final class ComparativeValidation { private ComparativeValidation() { } public static void lessThan(String field, T value, T limit, Comparator comparator) throws ValidationException { if (!lt(comparator.compare(value, limit))) { throw new ValidationException(field, value, "must be less than " + limit.toString()); } } public static void lessThanOrEqual(String field, T value, T limit, Comparator comparator) throws ValidationException { if (!lte(comparator.compare(value, limit))) { throw new ValidationException(field, value, "must be less than or equal to " + limit.toString()); } } public static void greaterThan(String field, T value, T limit, Comparator comparator) throws ValidationException { if (!gt(comparator.compare(value, limit))) { throw new ValidationException(field, value, "must be greater than " + limit.toString()); } } public static void greaterThanOrEqual(String field, T value, T limit, Comparator comparator) throws ValidationException { if (!gte(comparator.compare(value, limit))) { throw new ValidationException(field, value, "must be greater than or equal to " + limit.toString()); } } public static void range(String field, T value, T lt, T lte, T gt, T gte, Comparator comparator) throws ValidationException { T ltx = first(lt, lte); boolean ltxInc = lte != null; T gtx = first(gt, gte); boolean gtxInc = gte != null; // Inverting the values of lt(e) and gt(e) is valid and creates an exclusive range. // {gte:30, lt: 40} => x must be in the range [30, 40) // {lt:30, gte:40} => x must be outside the range [30, 40) if (lte(comparator.compare(gtx, ltx))) { between(field, value, gtx, gtxInc, ltx, ltxInc, comparator); } else { outside(field, value, ltx, !ltxInc, gtx, !gtxInc, comparator); } } public static void between(String field, T value, T lower, boolean lowerInclusive, T upper, boolean upperInclusive, Comparator comparator) throws ValidationException { if (!between(value, lower, lowerInclusive, upper, upperInclusive, comparator)) { throw new ValidationException(field, value, "must be in the range " + range(lower, lowerInclusive, upper, upperInclusive)); } } public static void outside(String field, T value, T lower, boolean lowerInclusive, T upper, boolean upperInclusive, Comparator comparator) throws ValidationException { if (between(value, lower, lowerInclusive, upper, upperInclusive, comparator)) { throw new ValidationException(field, value, "must be outside the range " + range(lower, lowerInclusive, upper, upperInclusive)); } } private static boolean between(T value, T lower, boolean lowerInclusive, T upper, boolean upperInclusive, Comparator comparator) { return (lowerInclusive ? gte(comparator.compare(value, lower)) : gt(comparator.compare(value, lower))) && (upperInclusive ? lte(comparator.compare(value, upper)) : lt(comparator.compare(value, upper))); } private static String range(T lower, boolean lowerInclusive, T upper, boolean upperInclusive) { return (lowerInclusive ? "[" : "(") + lower.toString() + ", " + upper.toString() + (upperInclusive ? "]" : ")"); } private static boolean lt(int comparatorResult) { return comparatorResult < 0; } private static boolean lte(int comparatorResult) { return comparatorResult <= 0; } private static boolean gt(int comparatorResult) { return comparatorResult > 0; } private static boolean gte(int comparatorResult) { return comparatorResult >= 0; } private static T first(T lhs, T rhs) { return lhs != null ? lhs : rhs; } } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/ConstantValidation.java000066400000000000000000000006761444536353100335560ustar00rootroot00000000000000package io.envoyproxy.pgv; /** * {@code ConstantValidation} implements PVG validators for constant values. */ public final class ConstantValidation { private ConstantValidation() { } public static void constant(String field, T value, T expected) throws ValidationException { if (!value.equals(expected)) { throw new ValidationException(field, value, "must equal " + expected.toString()); } } } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/EnumValidation.java000066400000000000000000000010131444536353100326530ustar00rootroot00000000000000package io.envoyproxy.pgv; import com.google.protobuf.ProtocolMessageEnum; /** * {@code EnumValidation} implements PGV validation for protobuf enumerated types. */ public final class EnumValidation { private EnumValidation() { } public static void definedOnly(String field, ProtocolMessageEnum value) throws ValidationException { if (value.toString().equals("UNRECOGNIZED")) { throw new ValidationException(field, value, "value is not a defined Enum value " + value); } } } ExplicitValidatorIndex.java000066400000000000000000000027501444536353100343050ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import java.util.concurrent.ConcurrentHashMap; /** * {@code ExplicitValidatorIndex} is an explicit registry of {@link Validator} instances. If no validator is registered * for {@code type}, a fallback validator will be used (default ALWAYS_VALID). */ public final class ExplicitValidatorIndex implements ValidatorIndex { private final ConcurrentHashMap VALIDATOR_IMPL_INDEX = new ConcurrentHashMap<>(); private final ConcurrentHashMap VALIDATOR_INDEX = new ConcurrentHashMap<>(); private final ValidatorIndex fallbackIndex; public ExplicitValidatorIndex() { this(ValidatorIndex.ALWAYS_VALID); } public ExplicitValidatorIndex(ValidatorIndex fallbackIndex) { this.fallbackIndex = fallbackIndex; } /** * Adds a {@link Validator} to the set of known validators. * @param forType the type to validate * @param validator the validator to apply * @return this */ public ExplicitValidatorIndex add(Class forType, ValidatorImpl validator) { VALIDATOR_IMPL_INDEX.put(forType, validator); return this; } @SuppressWarnings("unchecked") public Validator validatorFor(Class clazz) { return VALIDATOR_INDEX.computeIfAbsent(clazz, c -> proto -> VALIDATOR_IMPL_INDEX.getOrDefault(c, (p, i) -> fallbackIndex.validatorFor(c)) .assertValid(proto, ExplicitValidatorIndex.this)); } } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/MapValidation.java000066400000000000000000000025061444536353100324740ustar00rootroot00000000000000package io.envoyproxy.pgv; import java.util.Collection; import java.util.Map; /** * {@code MapValidation} implements PGV validation for protobuf {@code Map} fields. */ public final class MapValidation { private MapValidation() { } public static void min(String field, Map value, int expected) throws ValidationException { if (Math.min(value.size(), expected) != expected) { throw new ValidationException(field, value, "value size must be at least " + expected); } } public static void max(String field, Map value, int expected) throws ValidationException { if (Math.max(value.size(), expected) != expected) { throw new ValidationException(field, value, "value size must not exceed " + expected); } } public static void noSparse(String field, Map value) throws ValidationException { throw new UnimplementedException(field, "no_sparse validation is not implemented for Java because protobuf maps cannot be sparse in Java"); } @FunctionalInterface public interface MapValidator { void accept(T val) throws ValidationException; } public static void validateParts(Collection vals, MapValidator validator) throws ValidationException { for (T val : vals) { validator.accept(val); } } } ReflectiveValidatorIndex.java000066400000000000000000000040431444536353100346110ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import java.sql.Ref; import java.util.concurrent.ConcurrentHashMap; /** * {@code ReflectiveValidatorIndex} uses reflection to discover {@link Validator} implementations lazily the first * time a type is validated. If no validator can be found for {@code type}, a fallback validator * will be used (default ALWAYS_VALID). */ public final class ReflectiveValidatorIndex implements ValidatorIndex { private final ConcurrentHashMap VALIDATOR_INDEX = new ConcurrentHashMap<>(); private final ValidatorIndex fallbackIndex; public ReflectiveValidatorIndex() { this(ValidatorIndex.ALWAYS_VALID); } /** * @param fallbackIndex a {@link ValidatorIndex} implementation to use if reflective validator discovery fails. */ public ReflectiveValidatorIndex(ValidatorIndex fallbackIndex) { this.fallbackIndex = fallbackIndex; } /** * Returns the validator for {@code }, or {@code ALWAYS_VALID} if not found. */ @Override @SuppressWarnings("unchecked") public Validator validatorFor(Class clazz) { return VALIDATOR_INDEX.computeIfAbsent(clazz, c -> { try { return reflectiveValidatorFor(c); } catch (ReflectiveOperationException ex) { return fallbackIndex.validatorFor(clazz); } }); } @SuppressWarnings("unchecked") private Validator reflectiveValidatorFor(Class clazz) throws ReflectiveOperationException { Class enclosingClass = clazz; while (enclosingClass.getEnclosingClass() != null) { enclosingClass = enclosingClass.getEnclosingClass(); } String validatorClassName = enclosingClass.getName() + "Validator"; Class validatorClass = clazz.getClassLoader().loadClass(validatorClassName); ValidatorImpl impl = (ValidatorImpl) validatorClass.getDeclaredMethod("validatorFor", Class.class).invoke(null, clazz); return proto -> impl.assertValid(proto, ReflectiveValidatorIndex.this); } } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/RepeatedValidation.java000066400000000000000000000027671444536353100335210ustar00rootroot00000000000000package io.envoyproxy.pgv; import java.util.HashSet; import java.util.List; import java.util.Set; /** * {@code RepeatedValidation} implements PGV validators for collection-type validators. */ public final class RepeatedValidation { private RepeatedValidation() { } public static void minItems(String field, List values, int expected) throws ValidationException { if (values.size() < expected) { throw new ValidationException(field, values, "must have at least " + expected + " items"); } } public static void maxItems(String field, List values, int expected) throws ValidationException { if (values.size() > expected) { throw new ValidationException(field, values, "must have at most " + expected + " items"); } } public static void unique(String field, List values) throws ValidationException { Set seen = new HashSet<>(); for (T value : values) { // Abort at the first sign of a duplicate if (!seen.add(value)) { throw new ValidationException(field, values, "must have all unique values"); } } } @FunctionalInterface public interface ValidationConsumer { void accept(T value) throws ValidationException; } public static void forEach(List values, ValidationConsumer consumer) throws ValidationException { for (T value : values) { consumer.accept(value); } } } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/RequiredValidation.java000066400000000000000000000007201444536353100335330ustar00rootroot00000000000000package io.envoyproxy.pgv; import com.google.protobuf.GeneratedMessageV3; /** * {@code RequiredValidation} implements PGV validation for required fields. */ public final class RequiredValidation { private RequiredValidation() { } public static void required(String field, GeneratedMessageV3 value) throws ValidationException { if (value == null) { throw new ValidationException(field, "null", "is required"); } } } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/StringValidation.java000066400000000000000000000263731444536353100332350ustar00rootroot00000000000000package io.envoyproxy.pgv; import com.google.re2j.Pattern; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.Arrays; import org.apache.commons.validator.routines.DomainValidator; import org.apache.commons.validator.routines.EmailValidator; import org.apache.commons.validator.routines.InetAddressValidator; /** * {@code StringValidation} implements PGV validation for protobuf {@code String} fields. */ @SuppressWarnings("WeakerAccess") public final class StringValidation { private StringValidation() { // Intentionally left blank. } // Defers initialization until needed and from there on we keep an object // reference and avoid future calls; it is safe to assume that we require // the instance again after initialization. private static class Lazy { static final EmailValidator EMAIL_VALIDATOR = EmailValidator.getInstance(true, true); } public static void length(final String field, final String value, final int expected) throws ValidationException { final int actual = value.codePointCount(0, value.length()); if (actual != expected) { throw new ValidationException(field, enquote(value), "length must be " + expected + " but got: " + actual); } } public static void minLength(final String field, final String value, final int expected) throws ValidationException { final int actual = value.codePointCount(0, value.length()); if (actual < expected) { throw new ValidationException(field, enquote(value), "length must be at least " + expected + " but got: " + actual); } } public static void maxLength(final String field, final String value, final int expected) throws ValidationException { final int actual = value.codePointCount(0, value.length()); if (actual > expected) { throw new ValidationException(field, enquote(value), "length must be at most " + expected + " but got: " + actual); } } public static void lenBytes(String field, String value, int expected) throws ValidationException { if (value.getBytes(StandardCharsets.UTF_8).length != expected) { throw new ValidationException(field, enquote(value), "bytes length must be " + expected); } } public static void minBytes(String field, String value, int expected) throws ValidationException { if (value.getBytes(StandardCharsets.UTF_8).length < expected) { throw new ValidationException(field, enquote(value), "bytes length must be at least " + expected); } } public static void maxBytes(String field, String value, int expected) throws ValidationException { if (value.getBytes(StandardCharsets.UTF_8).length > expected) { throw new ValidationException(field, enquote(value), "bytes length must be at most " + expected); } } public static void pattern(String field, String value, Pattern p) throws ValidationException { if (!p.matches(value)) { throw new ValidationException(field, enquote(value), "must match pattern " + p.pattern()); } } public static void prefix(String field, String value, String prefix) throws ValidationException { if (!value.startsWith(prefix)) { throw new ValidationException(field, enquote(value), "should start with " + prefix); } } public static void contains(String field, String value, String contains) throws ValidationException { if (!value.contains(contains)) { throw new ValidationException(field, enquote(value), "should contain " + contains); } } public static void notContains(String field, String value, String contains) throws ValidationException { if (value.contains(contains)) { throw new ValidationException(field, enquote(value), "should not contain " + contains); } } public static void suffix(String field, String value, String suffix) throws ValidationException { if (!value.endsWith(suffix)) { throw new ValidationException(field, enquote(value), "should end with " + suffix); } } public static void email(final String field, String value) throws ValidationException { if (!value.isEmpty() && value.charAt(value.length() - 1) == '>') { final char[] chars = value.toCharArray(); final StringBuilder sb = new StringBuilder(); boolean insideQuotes = false; for (int i = chars.length - 2; i >= 0; i--) { final char c = chars[i]; if (c == '<') { if (!insideQuotes) break; } else if (c == '"') { insideQuotes = !insideQuotes; } sb.append(c); } value = sb.reverse().toString(); } if (!Lazy.EMAIL_VALIDATOR.isValid(value)) { throw new ValidationException(field, enquote(value), "should be a valid email"); } } public static void address(String field, String value) throws ValidationException { boolean validHost = isAscii(value) && DomainValidator.getInstance(true).isValid(value); boolean validIp = InetAddressValidator.getInstance().isValid(value); if (!validHost && !validIp) { throw new ValidationException(field, enquote(value), "should be a valid host, or an ip address."); } } public static void hostName(String field, String value) throws ValidationException { if (!isAscii(value)) { throw new ValidationException(field, enquote(value), "should be a valid host containing only ascii characters"); } DomainValidator domainValidator = DomainValidator.getInstance(true); if (!domainValidator.isValid(value)) { throw new ValidationException(field, enquote(value), "should be a valid host"); } } public static void ip(String field, String value) throws ValidationException { InetAddressValidator ipValidator = InetAddressValidator.getInstance(); if (!ipValidator.isValid(value)) { throw new ValidationException(field, enquote(value), "should be a valid ip address"); } } public static void ipv4(String field, String value) throws ValidationException { InetAddressValidator ipValidator = InetAddressValidator.getInstance(); if (!ipValidator.isValidInet4Address(value)) { throw new ValidationException(field, enquote(value), "should be a valid ipv4 address"); } } public static void ipv6(String field, String value) throws ValidationException { InetAddressValidator ipValidator = InetAddressValidator.getInstance(); if (!ipValidator.isValidInet6Address(value)) { throw new ValidationException(field, enquote(value), "should be a valid ipv6 address"); } } public static void uri(String field, String value) throws ValidationException { try { URI uri = new URI(value); if (!uri.isAbsolute()) { throw new ValidationException(field, enquote(value), "should be a valid absolute uri"); } } catch (URISyntaxException ex) { throw new ValidationException(field, enquote(value), "should be a valid absolute uri"); } } public static void uriRef(String field, String value) throws ValidationException { try { new URI(value); } catch (URISyntaxException ex) { throw new ValidationException(field, enquote(value), "should be a valid absolute uri"); } } /** * Validates if the given value is a UUID or GUID in RFC 4122 hyphenated * ({@code 00000000-0000-0000-0000-000000000000}) form; both lower and upper * hex digits are accepted. *

* The implementation is the same Java uses for UUID parsing since Java 15, * but without the alternate path that accepts invalid UUIDs, and without * actually constructing a UUID. * * @see JDK-8196334 * @see OpenJDK Commit */ public static void uuid(final String field, final String value) throws ValidationException { if (value.length() == 36) { final char dash1 = value.charAt(8); final char dash2 = value.charAt(13); final char dash3 = value.charAt(18); final char dash4 = value.charAt(23); if (dash1 == '-' && dash2 == '-' && dash3 == '-' && dash4 == '-') { final byte[] nibbles = UuidHolder.NIBBLES; final long msb1 = uuidParse4Nibbles(nibbles, value, 0); final long msb2 = uuidParse4Nibbles(nibbles, value, 4); final long msb3 = uuidParse4Nibbles(nibbles, value, 9); final long msb4 = uuidParse4Nibbles(nibbles, value, 14); final long lsb1 = uuidParse4Nibbles(nibbles, value, 19); final long lsb2 = uuidParse4Nibbles(nibbles, value, 24); final long lsb3 = uuidParse4Nibbles(nibbles, value, 28); final long lsb4 = uuidParse4Nibbles(nibbles, value, 32); if ((msb1 | msb2 | msb3 | msb4 | lsb1 | lsb2 | lsb3 | lsb4) >= 0) { return; } } } throw new ValidationException(field, enquote(value), "invalid UUID string"); } private static long uuidParse4Nibbles(final byte[] nibbles, final String value, final int i) { final char c1 = value.charAt(i); final char c2 = value.charAt(i + 1); final char c3 = value.charAt(i + 2); final char c4 = value.charAt(i + 3); return (c1 | c2 | c3 | c4) > 0xff ? -1 : nibbles[c1] << 12 | nibbles[c2] << 8 | nibbles[c3] << 4 | nibbles[c4]; } private static String enquote(String value) { return "\"" + value + "\""; } private static boolean isAscii(final String value) { for (char c : value.toCharArray()) { if (c > 127) { return false; } } return true; } /** * This class implements the static holder singleton pattern for the * additional data required in the {@link #uuid(String, String) uuid} * validation method. With it, we can postpone the allocation of the * {@link #NIBBLES} array until we really need it, in a thread safe manner. */ private static class UuidHolder { private static final byte[] NIBBLES; static { final byte[] ns = new byte[256]; Arrays.fill(ns, (byte) -1); ns['0'] = 0; ns['1'] = 1; ns['2'] = 2; ns['3'] = 3; ns['4'] = 4; ns['5'] = 5; ns['6'] = 6; ns['7'] = 7; ns['8'] = 8; ns['9'] = 9; ns['A'] = 10; ns['B'] = 11; ns['C'] = 12; ns['D'] = 13; ns['E'] = 14; ns['F'] = 15; ns['a'] = 10; ns['b'] = 11; ns['c'] = 12; ns['d'] = 13; ns['e'] = 14; ns['f'] = 15; NIBBLES = ns; } } } TimestampValidation.java000066400000000000000000000030511444536353100336370ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import com.google.protobuf.Duration; import com.google.protobuf.Timestamp; import com.google.protobuf.util.Durations; import com.google.protobuf.util.Timestamps; /** * {@code TimestampValidation} implements PGV validation for protobuf {@code Timestamp} fields. */ public final class TimestampValidation { private TimestampValidation() { } public static void within(String field, Timestamp value, Duration duration, Timestamp when) throws ValidationException { Duration between = Timestamps.between(when, value); if (Long.compare(Math.abs(Durations.toNanos(between)), Math.abs(Durations.toNanos(duration))) == 1) { throw new ValidationException(field, value, "value must be within " + Durations.toString(duration) + " of " + Timestamps.toString(when)); } } /** * Converts {@code seconds} and {@code nanos} to a protobuf {@code Timestamp}. */ public static Timestamp toTimestamp(long seconds, int nanos) { return Timestamp.newBuilder() .setSeconds(seconds) .setNanos(nanos) .build(); } /** * Converts {@code seconds} and {@code nanos} to a protobuf {@code Duration}. */ public static Duration toDuration(long seconds, long nanos) { return Duration.newBuilder() .setSeconds(seconds) .setNanos((int) nanos) .build(); } public static Timestamp currentTimestamp() { return Timestamps.fromMillis(System.currentTimeMillis()); } } UnimplementedException.java000066400000000000000000000004661444536353100343550ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; /** * {@code UnimplementedException} indicates a PGV validation is unimplemented for Java. */ public class UnimplementedException extends ValidationException { public UnimplementedException(String field, String reason) { super(field, "UNIMPLEMENTED", reason); } } ValidationException.java000066400000000000000000000011721444536353100336340ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; /** * Base class for failed field validations. */ public class ValidationException extends Exception { private String field; private Object value; private String reason; public ValidationException(String field, Object value, String reason) { super(field + ": " + reason + " - Got " + value.toString()); this.field = field; this.value = value; this.reason = reason; } public String getField() { return field; } public Object getValue() { return value; } public String getReason() { return reason; } } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/Validator.java000066400000000000000000000021141444536353100316640ustar00rootroot00000000000000package io.envoyproxy.pgv; /** * {@code Validator} asserts the validity of a protobuf object. * @param The type to validate */ @FunctionalInterface public interface Validator { /** * Asserts validation rules on a protobuf object. * * @param proto the protobuf object to validate. * @throws ValidationException with the first validation error encountered. */ void assertValid(T proto) throws ValidationException; /** * Checks validation rules on a protobuf object. * * @param proto the protobuf object to validate. * @return {@code true} if all rules are valid, {@code false} if not. */ default boolean isValid(T proto) { try { assertValid(proto); return true; } catch (io.envoyproxy.pgv.ValidationException ex) { return false; } } Validator ALWAYS_VALID = (proto) -> { // Do nothing. Always valid. }; Validator ALWAYS_INVALID = (proto) -> { throw new ValidationException("UNKNOWN", new Object(), "Explicitly invalid"); }; } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/ValidatorImpl.java000066400000000000000000000011231444536353100325050ustar00rootroot00000000000000package io.envoyproxy.pgv; /** * {@code Validator} is the base interface for all generated PGV validators. * @param The type to validate */ @FunctionalInterface public interface ValidatorImpl { /** * Asserts validation rules on a protobuf object. * * @param proto the protobuf object to validate. * @throws ValidationException with the first validation error encountered. */ void assertValid(T proto, ValidatorIndex index) throws ValidationException; ValidatorImpl ALWAYS_VALID = (proto, index) -> { // Do nothing. Always valid. }; } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/ValidatorIndex.java000066400000000000000000000021201444536353100326510ustar00rootroot00000000000000package io.envoyproxy.pgv; /** * {@code ValidatorIndex} defines the entry point for finding {@link Validator} instances for a given type. */ @FunctionalInterface public interface ValidatorIndex { /** * Returns the validator for {@code clazz}, or {@code ALWAYS_VALID} if not found. */ Validator validatorFor(Class clazz); /** * Returns the validator for {@code }, or {@code ALWAYS_VALID} if not found. */ @SuppressWarnings("unchecked") default Validator validatorFor(Object instance) { return validatorFor(instance == null ? null : instance.getClass()); } ValidatorIndex ALWAYS_VALID = new ValidatorIndex() { @Override @SuppressWarnings("unchecked") public Validator validatorFor(Class clazz) { return Validator.ALWAYS_VALID; } }; ValidatorIndex ALWAYS_INVALID = new ValidatorIndex() { @Override @SuppressWarnings("unchecked") public Validator validatorFor(Class clazz) { return Validator.ALWAYS_INVALID; } }; } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/000077500000000000000000000000001444536353100225435ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/000077500000000000000000000000001444536353100234645ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/000077500000000000000000000000001444536353100240735ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/000077500000000000000000000000001444536353100263355ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv/000077500000000000000000000000001444536353100271315ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv/AnyValidationTest.java000066400000000000000000000022511444536353100333760ustar00rootroot00000000000000package io.envoyproxy.pgv; import com.google.protobuf.Any; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class AnyValidationTest { @Test public void inWorks() throws ValidationException { String[] set = new String[]{"type.googleapis.com/google.protobuf.Duration"}; // In CollectiveValidation.in("x", Any.newBuilder().setTypeUrl("type.googleapis.com/google.protobuf.Duration").build().getTypeUrl(), set); // Not In assertThatThrownBy(() -> CollectiveValidation.in("x", Any.newBuilder().setTypeUrl("junk").build().getTypeUrl(), set)).isInstanceOf(ValidationException.class); } @Test public void notInWorks() throws ValidationException { String[] set = new String[]{"type.googleapis.com/google.protobuf.Duration"}; // In assertThatThrownBy(() -> CollectiveValidation.notIn("x", Any.newBuilder().setTypeUrl("type.googleapis.com/google.protobuf.Duration").build().getTypeUrl(), set)).isInstanceOf(ValidationException.class); // Not In CollectiveValidation.notIn("x", Any.newBuilder().setTypeUrl("junk").build().getTypeUrl(), set); } } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv/Assertions.java000066400000000000000000000006411444536353100321270ustar00rootroot00000000000000package io.envoyproxy.pgv; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import static org.assertj.core.api.Assertions.assertThatThrownBy; public final class Assertions { private Assertions() { // Intentionally left blank. } public static void assertValidationException(final ThrowingCallable f) { assertThatThrownBy(f).isInstanceOf(ValidationException.class); } } BytesValidationTest.java000066400000000000000000000130061444536353100336560ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import com.google.protobuf.ByteString; import com.google.re2j.Pattern; import org.junit.Test; import java.net.InetAddress; import java.net.UnknownHostException; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class BytesValidationTest { @Test public void lengthWorks() throws ValidationException { // Short assertThatThrownBy(() -> BytesValidation.length("x", ByteString.copyFromUtf8("ñįö"), 8)).isInstanceOf(ValidationException.class); // Same BytesValidation.length("x", ByteString.copyFromUtf8("ñįöxx"), 8); // Long assertThatThrownBy(() -> BytesValidation.length("x", ByteString.copyFromUtf8("ñįöxxxx"), 8)).isInstanceOf(ValidationException.class); } @Test public void minLengthWorks() throws ValidationException { // Short assertThatThrownBy(() -> BytesValidation.minLength("x", ByteString.copyFromUtf8("ñįö"), 8)).isInstanceOf(ValidationException.class); // Same BytesValidation.minLength("x", ByteString.copyFromUtf8("ñįöxx"), 8); // Long BytesValidation.minLength("x", ByteString.copyFromUtf8("ñįöxxxx"), 8); } @Test public void maxLengthWorks() throws ValidationException { // Short BytesValidation.maxLength("x", ByteString.copyFromUtf8("ñįö"), 8); // Same BytesValidation.maxLength("x", ByteString.copyFromUtf8("ñįöxx"), 8); // Long assertThatThrownBy(() -> BytesValidation.maxLength("x", ByteString.copyFromUtf8("ñįöxxxx"), 8)).isInstanceOf(ValidationException.class); } @Test public void patternWorks() throws ValidationException { Pattern p = Pattern.compile("^[\\x00-\\x7F]+$"); // Match BytesValidation.pattern("x", ByteString.copyFromUtf8("aaabbb"), p); // non-empty, ASCII byte sequence // No Match assertThatThrownBy(() -> BytesValidation.pattern("x", ByteString.copyFromUtf8("aaañbbb"), p)).isInstanceOf(ValidationException.class); } @Test public void prefixWorks() throws ValidationException { // Match BytesValidation.prefix("x", ByteString.copyFromUtf8("Hello World"), "Hello".getBytes()); // No Match assertThatThrownBy(() -> BytesValidation.prefix("x", ByteString.copyFromUtf8("Hello World"), "Bananas".getBytes())).isInstanceOf(ValidationException.class); } @Test public void containsWorks() throws ValidationException { // Match BytesValidation.contains("x", ByteString.copyFromUtf8("Hello World"), "o W".getBytes()); // No Match assertThatThrownBy(() -> BytesValidation.contains("x", ByteString.copyFromUtf8("Hello World"), "Bananas".getBytes())).isInstanceOf(ValidationException.class); } @Test public void suffixWorks() throws ValidationException { // Match BytesValidation.suffix("x", ByteString.copyFromUtf8("Hello World"), "World".getBytes()); // No Match assertThatThrownBy(() -> BytesValidation.suffix("x", ByteString.copyFromUtf8("Hello World"), "Bananas".getBytes())).isInstanceOf(ValidationException.class); } @Test public void ipWorks() throws ValidationException, UnknownHostException { // Match BytesValidation.ip("x", ByteString.copyFrom(InetAddress.getByName("192.168.0.1").getAddress())); BytesValidation.ip("x", ByteString.copyFrom(InetAddress.getByName("fe80::3").getAddress())); // No Match assertThatThrownBy(() -> BytesValidation.ip("x", ByteString.copyFromUtf8("BANANAS!"))).isInstanceOf(ValidationException.class); } @Test public void ipV4Works() throws ValidationException, UnknownHostException { // Match BytesValidation.ipv4("x", ByteString.copyFrom(InetAddress.getByName("192.168.0.1").getAddress())); // No Match assertThatThrownBy(() -> BytesValidation.ipv4("x", ByteString.copyFrom(InetAddress.getByName("fe80::3").getAddress()))).isInstanceOf(ValidationException.class); assertThatThrownBy(() -> BytesValidation.ipv4("x", ByteString.copyFromUtf8("BANANAS!"))).isInstanceOf(ValidationException.class); } @Test public void ipV6Works() throws ValidationException, UnknownHostException { // Match BytesValidation.ipv6("x", ByteString.copyFrom(InetAddress.getByName("fe80::3").getAddress())); // No Match assertThatThrownBy(() -> BytesValidation.ipv6("x", ByteString.copyFrom(InetAddress.getByName("192.168.0.1").getAddress()))).isInstanceOf(ValidationException.class); assertThatThrownBy(() -> BytesValidation.ipv6("x", ByteString.copyFromUtf8("BANANAS!"))).isInstanceOf(ValidationException.class); } @Test public void inWorks() throws ValidationException { ByteString[] set = new ByteString[]{ByteString.copyFromUtf8("foo"), ByteString.copyFromUtf8("bar")}; // In CollectiveValidation.in("x", ByteString.copyFromUtf8("foo"), set); // Not In assertThatThrownBy(() -> CollectiveValidation.in("x", ByteString.copyFromUtf8("baz"), set)).isInstanceOf(ValidationException.class); } @Test public void notInWorks() throws ValidationException { ByteString[] set = new ByteString[]{ByteString.copyFromUtf8("foo"), ByteString.copyFromUtf8("bar")}; // In assertThatThrownBy(() -> CollectiveValidation.notIn("x", ByteString.copyFromUtf8("foo"), set)).isInstanceOf(ValidationException.class); // Not In CollectiveValidation.notIn("x", ByteString.copyFromUtf8("baz"), set); } } CollectiveValidationTest.java000066400000000000000000000014531444536353100346640ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class CollectiveValidationTest { @Test public void inWorks() throws ValidationException { String[] set = new String[]{"foo", "bar"}; // In CollectiveValidation.in("x", "foo", set); // Not In assertThatThrownBy(() -> CollectiveValidation.in("x", "baz", set)).isInstanceOf(ValidationException.class); } @Test public void notInWorks() throws ValidationException { String[] set = new String[]{"foo", "bar"}; // In assertThatThrownBy(() -> CollectiveValidation.notIn("x", "foo", set)).isInstanceOf(ValidationException.class); // Not In CollectiveValidation.notIn("x", "baz", set); } } ComparativeValidationTest.java000066400000000000000000000140421444536353100350430ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import org.junit.Test; import java.util.Comparator; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class ComparativeValidationTest { @Test public void lessThanWorks() throws ValidationException { // Less than ComparativeValidation.lessThan("x", 10, 20, Comparator.naturalOrder()); // Equal to assertThatThrownBy(() -> ComparativeValidation.lessThan("x", 10, 10, Comparator.naturalOrder())); // Greater than assertThatThrownBy(() -> ComparativeValidation.lessThan("x", 20, 10, Comparator.naturalOrder())); } @Test public void lessThanOrEqualWorks() throws ValidationException { // Less than ComparativeValidation.lessThanOrEqual("x", 10, 20, Comparator.naturalOrder()); // Equal to ComparativeValidation.lessThanOrEqual("x", 10, 10, Comparator.naturalOrder()); // Greater than assertThatThrownBy(() -> ComparativeValidation.lessThanOrEqual("x", 20, 10, Comparator.naturalOrder())); } @Test public void greaterThanWorks() throws ValidationException { // Less than assertThatThrownBy(() -> ComparativeValidation.greaterThan("x", 10, 20, Comparator.naturalOrder())); // Equal to assertThatThrownBy(() -> ComparativeValidation.greaterThan("x", 10, 10, Comparator.naturalOrder())); // Greater than ComparativeValidation.greaterThan("x", 20, 10, Comparator.naturalOrder()); } @Test public void greaterThanOrEqualWorks() throws ValidationException { // Less than assertThatThrownBy(() -> ComparativeValidation.greaterThanOrEqual("x", 10, 20, Comparator.naturalOrder())); // Equal to ComparativeValidation.greaterThanOrEqual("x", 10, 10, Comparator.naturalOrder()); // Greater than ComparativeValidation.greaterThanOrEqual("x", 20, 10, Comparator.naturalOrder()); } @Test public void betweenInclusiveWorks() throws ValidationException { // Lower outside assertThatThrownBy(() -> ComparativeValidation.between("x", 5, 10, true, 20, true, Comparator.naturalOrder())).isInstanceOf(ValidationException.class); // Lower bound ComparativeValidation.between("x", 10, 10, true, 20, true, Comparator.naturalOrder()); // Inside ComparativeValidation.between("x", 15, 10, true, 20, true, Comparator.naturalOrder()); // Upper bound ComparativeValidation.between("x", 20, 10, true, 20, true, Comparator.naturalOrder()); // Upper outside assertThatThrownBy(() -> ComparativeValidation.between("x", 25, 10, true, 20, true, Comparator.naturalOrder())).isInstanceOf(ValidationException.class); } @Test public void betweenExclusiveWorks() throws ValidationException { // Lower outside assertThatThrownBy(() -> ComparativeValidation.between("x", 5, 10, false, 20, false, Comparator.naturalOrder())).isInstanceOf(ValidationException.class); // Lower bound assertThatThrownBy(() -> ComparativeValidation.between("x", 10, 10, false, 20, false, Comparator.naturalOrder())).isInstanceOf(ValidationException.class); // Inside ComparativeValidation.between("x", 15, 10, false, 20, false, Comparator.naturalOrder()); // Upper bound assertThatThrownBy(() -> ComparativeValidation.between("x", 20, 10, false, 20, false, Comparator.naturalOrder())).isInstanceOf(ValidationException.class); // Upper outside assertThatThrownBy(() -> ComparativeValidation.between("x", 25, 10, false, 20, false, Comparator.naturalOrder())).isInstanceOf(ValidationException.class); } @Test public void outsideInclusiveWorks() throws ValidationException { // Lower outside ComparativeValidation.outside("x", 5, 10, true, 20, true, Comparator.naturalOrder()); // Lower bound assertThatThrownBy(() -> ComparativeValidation.outside("x", 10, 10, true, 20, true, Comparator.naturalOrder())).isInstanceOf(ValidationException.class); // Inside assertThatThrownBy(() -> ComparativeValidation.outside("x", 15, 10, true, 20, true, Comparator.naturalOrder())).isInstanceOf(ValidationException.class); // Upper bound assertThatThrownBy(() -> ComparativeValidation.outside("x", 20, 10, true, 20, true, Comparator.naturalOrder())).isInstanceOf(ValidationException.class); // Upper outside ComparativeValidation.outside("x", 25, 10, true, 20, true, Comparator.naturalOrder()); } @Test public void outsideExclusiveWorks() throws ValidationException { // Lower outside ComparativeValidation.outside("x", 5, 10, false, 20, false, Comparator.naturalOrder()); // Lower bound ComparativeValidation.outside("x", 10, 10, false, 20, false, Comparator.naturalOrder()); // Inside assertThatThrownBy(() -> ComparativeValidation.outside("x", 15, 10, false, 20, false, Comparator.naturalOrder())).isInstanceOf(ValidationException.class); // Upper bound ComparativeValidation.outside("x", 20, 10, false, 20, false, Comparator.naturalOrder()); // Upper outside ComparativeValidation.outside("x", 25, 10, false, 20, false, Comparator.naturalOrder()); } @Test public void rangeChoosesCorrectly() throws ValidationException { // {gte:30, lt: 40} => x must be in the range [30, 40) // In between range ComparativeValidation.range("x", 35, 40, null, null, 30, Comparator.naturalOrder()); // Outside between range assertThatThrownBy(() -> ComparativeValidation.range("x", 10, 40, null, null, 30, Comparator.naturalOrder())).isInstanceOf(ValidationException.class); // {lt:30, gte:40} => x must be outside the range [30, 40) // In outside range assertThatThrownBy(() -> ComparativeValidation.range("x", 35, 30, null, null, 40, Comparator.naturalOrder())).isInstanceOf(ValidationException.class); // Outside outside range ComparativeValidation.range("x", 10, 30, null, null, 40, Comparator.naturalOrder()); } } ConstantValidationTest.java000066400000000000000000000012471444536353100343650ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class ConstantValidationTest { @Test public void constantBooleanWorks() throws ValidationException { ConstantValidation.constant("x", true, true); assertThatThrownBy(() -> ConstantValidation.constant("x", true, false)).isInstanceOf(ValidationException.class); } @Test public void constantFloatWorks() throws ValidationException { ConstantValidation.constant("x", 1.23F, 1.23F); assertThatThrownBy(() -> ConstantValidation.constant("x", 1.23F, 3.21F)).isInstanceOf(ValidationException.class); } } DurationValidationTest.java000066400000000000000000000070431444536353100343610ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import com.google.protobuf.Duration; import com.google.protobuf.util.Durations; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class DurationValidationTest { @Test public void lessThanWorks() throws ValidationException { // Less ComparativeValidation.lessThan("x", Durations.fromSeconds(10), Durations.fromSeconds(20), Durations.comparator()); // Equal assertThatThrownBy(() -> ComparativeValidation.lessThan("x", Durations.fromSeconds(10), Durations.fromSeconds(10), Durations.comparator())).isInstanceOf(ValidationException.class); // Greater assertThatThrownBy(() -> ComparativeValidation.lessThan("x", Durations.fromSeconds(20), Durations.fromSeconds(10), Durations.comparator())).isInstanceOf(ValidationException.class); } @Test public void lessThanOrEqualsWorks() throws ValidationException { // Less ComparativeValidation.lessThanOrEqual("x", Durations.fromSeconds(10), Durations.fromSeconds(20), Durations.comparator()); // Equal ComparativeValidation.lessThanOrEqual("x", Durations.fromSeconds(10), Durations.fromSeconds(10), Durations.comparator()); // Greater assertThatThrownBy(() -> ComparativeValidation.lessThanOrEqual("x", Durations.fromSeconds(20), Durations.fromSeconds(10), Durations.comparator())).isInstanceOf(ValidationException.class); } @Test public void greaterThanWorks() throws ValidationException { // Less assertThatThrownBy(() -> ComparativeValidation.greaterThan("x", Durations.fromSeconds(10), Durations.fromSeconds(20), Durations.comparator())).isInstanceOf(ValidationException.class); // Equal assertThatThrownBy(() -> ComparativeValidation.greaterThan("x", Durations.fromSeconds(10), Durations.fromSeconds(10), Durations.comparator())).isInstanceOf(ValidationException.class); // Greater ComparativeValidation.greaterThan("x", Durations.fromSeconds(20), Durations.fromSeconds(10), Durations.comparator()); } @Test public void greaterThanOrEqualsWorks() throws ValidationException { // Less assertThatThrownBy(() -> ComparativeValidation.greaterThanOrEqual("x", Durations.fromSeconds(10), Durations.fromSeconds(20), Durations.comparator())).isInstanceOf(ValidationException.class); // Equal ComparativeValidation.greaterThanOrEqual("x", Durations.fromSeconds(10), Durations.fromSeconds(10), Durations.comparator()); // Greater ComparativeValidation.greaterThanOrEqual("x", Durations.fromSeconds(20), Durations.fromSeconds(10), Durations.comparator()); } @Test public void inWorks() throws ValidationException { Duration[] set = new Duration[]{TimestampValidation.toDuration(1, 0), TimestampValidation.toDuration(2, 0)}; // In CollectiveValidation.in("x", TimestampValidation.toDuration(1, 0), set); // Not In assertThatThrownBy(() -> CollectiveValidation.in("x", TimestampValidation.toDuration(3, 0), set)).isInstanceOf(ValidationException.class); } @Test public void notInWorks() throws ValidationException { Duration[] set = new Duration[]{TimestampValidation.toDuration(1, 0), TimestampValidation.toDuration(2, 0)}; // In assertThatThrownBy(() -> CollectiveValidation.notIn("x", TimestampValidation.toDuration(1, 0), set)).isInstanceOf(ValidationException.class); // Not In CollectiveValidation.notIn("x", TimestampValidation.toDuration(3, 0), set); } } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv/EnumValidationTest.java000066400000000000000000000025761444536353100335650ustar00rootroot00000000000000package io.envoyproxy.pgv; import io.envoyproxy.pvg.cases.Enum; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class EnumValidationTest { @Test public void definedOnlyWorks() throws ValidationException { // Defined EnumValidation.definedOnly("x", Enum.TestEnum.ONE); // Not Defined assertThatThrownBy(() -> EnumValidation.definedOnly("x", Enum.TestEnum.UNRECOGNIZED)).isInstanceOf(ValidationException.class); } @Test public void inWorks() throws ValidationException { Enum.TestEnum[] set = new Enum.TestEnum[]{ Enum.TestEnum.forNumber(0), Enum.TestEnum.forNumber(2), }; // In CollectiveValidation.in("x", Enum.TestEnum.TWO, set); // Not In assertThatThrownBy(() -> CollectiveValidation.in("x", Enum.TestEnum.ONE, set)).isInstanceOf(ValidationException.class); } @Test public void notInWorks() throws ValidationException { Enum.TestEnum[] set = new Enum.TestEnum[]{ Enum.TestEnum.forNumber(0), Enum.TestEnum.forNumber(2), }; // In assertThatThrownBy(() -> CollectiveValidation.notIn("x", Enum.TestEnum.TWO, set)).isInstanceOf(ValidationException.class); // Not In CollectiveValidation.notIn("x", Enum.TestEnum.ONE, set); } } ExplicitValidatorIndexTest.java000066400000000000000000000031001444536353100351660ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import org.junit.Test; import java.util.concurrent.atomic.AtomicBoolean; import static org.assertj.core.api.Assertions.assertThat; @SuppressWarnings("unchecked") public class ExplicitValidatorIndexTest { class Thing {} @Test public void indexFindsValidator() throws ValidationException { AtomicBoolean called = new AtomicBoolean(); ValidatorImpl validatorImpl = (ValidatorImpl) (proto, index) -> called.set(true); ExplicitValidatorIndex index = new ExplicitValidatorIndex(); index.add(Thing.class, validatorImpl); Thing thing = new Thing(); Validator validator = index.validatorFor(thing); assertThat(validator).isNotEqualTo(ValidatorImpl.ALWAYS_VALID); validator.assertValid(thing); assertThat(called).isTrue(); } @Test public void indexFallsBack() throws ValidationException { AtomicBoolean called = new AtomicBoolean(); ValidatorIndex fallback = new ValidatorIndex() { @Override @SuppressWarnings("unchecked") public Validator validatorFor(Class clazz) { called.set(true); return Validator.ALWAYS_VALID; } }; ExplicitValidatorIndex index = new ExplicitValidatorIndex(fallback); Thing thing = new Thing(); Validator validator = index.validatorFor(thing); assertThat(validator).isNotEqualTo(ValidatorImpl.ALWAYS_VALID); validator.assertValid(thing); assertThat(called).isTrue(); } } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv/MapValidationTest.java000066400000000000000000000023461444536353100333710ustar00rootroot00000000000000package io.envoyproxy.pgv; import org.junit.Test; import java.util.Map; import java.util.HashMap; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class MapValidationTest { @Test public void minWorks() throws ValidationException { Map map = new HashMap<>(); map.put("1", "ONE"); map.put("2", "TWO"); // Equals MapValidation.min("x", map, 2); // Not Equals assertThatThrownBy(() -> MapValidation.min("x", map, 3)).isInstanceOf(ValidationException.class); } @Test public void maxWorks() throws ValidationException { Map map = new HashMap<>(); map.put("1", "ONE"); map.put("2", "TWO"); // Equals MapValidation.max("x", map, 2); // Not Equals assertThatThrownBy(() -> MapValidation.max("x", map, 1)).isInstanceOf(ValidationException.class); } @Test public void noSparseWorks() throws ValidationException { Map map = new HashMap<>(); map.put("1", "ONE"); map.put("2", null); // Sparse Map assertThatThrownBy(() -> MapValidation.noSparse("x", map)).isInstanceOf(ValidationException.class); } } ReflectiveValidatorIndexTest.java000066400000000000000000000050121444536353100355010ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import io.envoyproxy.pvg.cases.TokenUse; import org.assertj.core.api.AtomicBooleanAssert; import org.junit.Test; import java.util.concurrent.atomic.AtomicBoolean; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.in; public class ReflectiveValidatorIndexTest { @Test public void indexFindsOuterMessage() throws ValidationException { TokenUse token = TokenUse.newBuilder().setPayload(TokenUse.Payload.newBuilder().setToken(TokenUse.Payload.Token.newBuilder().setValue("FOO"))).build(); ReflectiveValidatorIndex index = new ReflectiveValidatorIndex(); Validator validator = index.validatorFor(TokenUse.class); assertThat(validator).withFailMessage("Unexpected Validator.ALWAYS_VALID").isNotEqualTo(Validator.ALWAYS_VALID); validator.assertValid(token); } @Test public void indexFindsEmbeddedMessage() throws ValidationException { TokenUse.Payload payload = TokenUse.Payload.newBuilder().setToken(TokenUse.Payload.Token.newBuilder().setValue("FOO")).build(); ReflectiveValidatorIndex index = new ReflectiveValidatorIndex(); Validator validator = index.validatorFor(TokenUse.Payload.class); assertThat(validator).withFailMessage("Unexpected Validator.ALWAYS_VALID").isNotEqualTo(Validator.ALWAYS_VALID); validator.assertValid(payload); } @Test public void indexFindsDoubleEmbeddedMessage() throws ValidationException { TokenUse.Payload.Token token = TokenUse.Payload.Token.newBuilder().setValue("FOO").build(); ReflectiveValidatorIndex index = new ReflectiveValidatorIndex(); Validator validator = index.validatorFor(TokenUse.Payload.Token.class); assertThat(validator).withFailMessage("Unexpected Validator.ALWAYS_VALID").isNotEqualTo(Validator.ALWAYS_VALID); validator.assertValid(token); } @Test public void indexFallsBack() throws ValidationException { AtomicBoolean called = new AtomicBoolean(); ValidatorIndex fallback = new ValidatorIndex() { @Override @SuppressWarnings("unchecked") public Validator validatorFor(Class clazz) { called.set(true); return Validator.ALWAYS_VALID; } }; ReflectiveValidatorIndex index = new ReflectiveValidatorIndex(fallback); index.validatorFor(fallback); assertThat(called).isTrue(); } } RepeatedValidationTest.java000066400000000000000000000024371444536353100343270ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import org.junit.Test; import java.util.Arrays; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class RepeatedValidationTest { @Test public void minItemsWorks() throws ValidationException { // More RepeatedValidation.minItems("x", Arrays.asList(10, 20, 30), 2); // Equal RepeatedValidation.minItems("x", Arrays.asList(10, 20), 2); // Fewer assertThatThrownBy(() -> RepeatedValidation.minItems("x", Arrays.asList(10), 2)).isInstanceOf(ValidationException.class); } @Test public void maxItemsWorks() throws ValidationException { // More assertThatThrownBy(() -> RepeatedValidation.maxItems("x", Arrays.asList(10, 20, 30), 2)).isInstanceOf(ValidationException.class); // Equal RepeatedValidation.maxItems("x", Arrays.asList(10, 20), 2); // Fewer RepeatedValidation.maxItems("x", Arrays.asList(10), 2); } @Test public void uniqueWorks() throws ValidationException { // Unique RepeatedValidation.unique("x", Arrays.asList(10, 20, 30, 40)); // Duplicate assertThatThrownBy(() -> RepeatedValidation.unique("x", Arrays.asList(10, 20, 20, 30, 30, 40))).isInstanceOf(ValidationException.class); } } RequiredValidationTest.java000066400000000000000000000007631444536353100343560ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import io.envoyproxy.pvg.cases.Enum; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class RequiredValidationTest { @Test public void requiredWorks() throws ValidationException { // Present RequiredValidation.required("x", Enum.Outer.getDefaultInstance()); // Absent assertThatThrownBy(() -> RequiredValidation.required("x", null)).isInstanceOf(ValidationException.class); } } StringValidationTest.java000066400000000000000000000260271444536353100340450ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import com.google.re2j.Pattern; import org.junit.Test; import static io.envoyproxy.pgv.Assertions.assertValidationException; import static io.envoyproxy.pgv.StringValidation.uuid; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class StringValidationTest { private static String repeat(final char c, final int n) { return new String(new char[n]).replace('\0', c); } @Test public void inWorks() throws ValidationException { String[] set = new String[]{"foo", "bar", "🙈"}; // In CollectiveValidation.in("x", "🙈", set); // Not In assertThatThrownBy(() -> CollectiveValidation.in("x", "baz", set)).isInstanceOf(ValidationException.class); } @Test public void notInWorks() throws ValidationException { String[] set = new String[]{"foo", "bar", "🙈"}; // In assertThatThrownBy(() -> CollectiveValidation.notIn("x", "🙈", set)).isInstanceOf(ValidationException.class); // Not In CollectiveValidation.notIn("x", "baz", set); } @Test public void lengthWorks() throws ValidationException { // Short assertThatThrownBy(() -> StringValidation.length("x", "🙈", 2)).isInstanceOf(ValidationException.class); // Same StringValidation.length("x", "🙈🙉", 2); // Long assertThatThrownBy(() -> StringValidation.length("x", "🙈🙉🙊", 2)).isInstanceOf(ValidationException.class); } @Test public void minLengthWorks() throws ValidationException { // Short assertThatThrownBy(() -> StringValidation.minLength("x", "🙈", 2)).isInstanceOf(ValidationException.class); // Same StringValidation.minLength("x", "🙈🙉", 2); // Long StringValidation.minLength("x", "🙈🙉🙊", 2); } @Test public void maxLengthWorks() throws ValidationException { // Short StringValidation.maxLength("x", "🙈", 2); // Same StringValidation.maxLength("x", "🙈🙉", 2); // Long assertThatThrownBy(() -> StringValidation.maxLength("x", "🙈🙉🙊", 2)).isInstanceOf(ValidationException.class); } @Test public void lengthBytesWorks() throws ValidationException { // Short assertThatThrownBy(() -> StringValidation.lenBytes("x", "ñįö", 8)).isInstanceOf(ValidationException.class); assertThatThrownBy(() -> StringValidation.lenBytes("x", "ñįö", 8)).isInstanceOf(ValidationException.class); // Same StringValidation.lenBytes("x", "ñįöxx", 8); // Long assertThatThrownBy(() -> StringValidation.lenBytes("x", "ñįöxxxx", 8)).isInstanceOf(ValidationException.class); } @Test public void minBytesWorks() throws ValidationException { // Short assertThatThrownBy(() -> StringValidation.minBytes("x", "ñįö", 8)).isInstanceOf(ValidationException.class); // Same StringValidation.minBytes("x", "ñįöxx", 8); StringValidation.minBytes("x", "你好", 4); // Long StringValidation.minBytes("x", "ñįöxxxx", 8); } @Test public void maxBytesWorks() throws ValidationException { // Short StringValidation.maxBytes("x", "ñįö", 8); // Same StringValidation.maxBytes("x", "ñįöxx", 8); // Long assertThatThrownBy(() -> StringValidation.maxBytes("x", "ñįöxxxx", 8)).isInstanceOf(ValidationException.class); } @Test public void patternWorks() throws ValidationException { Pattern p = Pattern.compile("a*b*"); // Match StringValidation.pattern("x", "aaabbb", p); // No Match assertThatThrownBy(() -> StringValidation.pattern("x", "aaabbbccc", p)).isInstanceOf(ValidationException.class); } @Test public void patternWorks2() throws ValidationException { Pattern p = Pattern.compile("\\* \\\\ \\w"); // Match StringValidation.pattern("x", "* \\ x", p); } @Test public void prefixWorks() throws ValidationException { // Match StringValidation.prefix("x", "Hello World", "Hello"); // No Match assertThatThrownBy(() -> StringValidation.prefix("x", "Hello World", "Bananas")).isInstanceOf(ValidationException.class); } @Test public void containsWorks() throws ValidationException { // Match StringValidation.contains("x", "Hello World", "o W"); // No Match assertThatThrownBy(() -> StringValidation.contains("x", "Hello World", "Bananas")).isInstanceOf(ValidationException.class); } @Test public void notContainsWorks() throws ValidationException { // Match StringValidation.notContains("x", "Hello World", "Bananas"); // No Match assertThatThrownBy(() -> StringValidation.notContains("x", "Hello World", "o W")).isInstanceOf(ValidationException.class); } @Test public void suffixWorks() throws ValidationException { // Match StringValidation.suffix("x", "Hello World", "World"); // No Match assertThatThrownBy(() -> StringValidation.suffix("x", "Hello World", "Bananas")).isInstanceOf(ValidationException.class); } @Test public void emailWorks() throws ValidationException { // Match StringValidation.email("x", "foo@bar.com"); StringValidation.email("x", "John Smith "); StringValidation.email("x", "John Doe r>do\".doe@example.com>"); StringValidation.email("x", "john@foo.africa"); // No Match assertThatThrownBy(() -> StringValidation.email("x", "bar.bar.bar")).isInstanceOf(ValidationException.class); assertThatThrownBy(() -> StringValidation.email("x", "John Doe StringValidation.email("x", "John Doe ")).isInstanceOf(ValidationException.class); } @Test public void hostNameWorks() throws ValidationException { // Match StringValidation.hostName("x", "google.com"); // No Match assertThatThrownBy(() -> StringValidation.hostName("x", "bananas.bananas")).isInstanceOf(ValidationException.class); assertThatThrownBy(() -> StringValidation.hostName("x", "你好.com")).isInstanceOf(ValidationException.class); } @Test public void addressWorks() throws ValidationException { // Match Hostname StringValidation.address("x", "google.com"); StringValidation.address("x", "images.google.com"); // Match IP StringValidation.address("x", "127.0.0.1"); StringValidation.address("x", "fe80::3"); // No Match assertThatThrownBy(() -> StringValidation.address("x", "bananas.bananas")).isInstanceOf(ValidationException.class); assertThatThrownBy(() -> StringValidation.address("x", "你好.com")).isInstanceOf(ValidationException.class); assertThatThrownBy(() -> StringValidation.address("x", "ff::fff::0b")).isInstanceOf(ValidationException.class); } @Test public void ipWorks() throws ValidationException { // Match StringValidation.ip("x", "192.168.0.1"); StringValidation.ip("x", "fe80::3"); // No Match assertThatThrownBy(() -> StringValidation.ip("x", "999.999.999.999")).isInstanceOf(ValidationException.class); } @Test public void ipV4Works() throws ValidationException { // Match StringValidation.ipv4("x", "192.168.0.1"); // No Match assertThatThrownBy(() -> StringValidation.ipv4("x", "fe80::3")).isInstanceOf(ValidationException.class); assertThatThrownBy(() -> StringValidation.ipv4("x", "999.999.999.999")).isInstanceOf(ValidationException.class); } @Test public void ipV6Works() throws ValidationException { // Match StringValidation.ipv6("x", "fe80::3"); // No Match assertThatThrownBy(() -> StringValidation.ipv6("x", "192.168.0.1")).isInstanceOf(ValidationException.class); assertThatThrownBy(() -> StringValidation.ipv6("x", "999.999.999.999")).isInstanceOf(ValidationException.class); } @Test public void uriWorks() throws ValidationException { // Match StringValidation.uri("x", "ftp://ftp.is.co.za/rfc/rfc1808.txt"); StringValidation.uri("x", "http://www.ietf.org/rfc/rfc2396.txt"); StringValidation.uri("x", "ldap://[2001:db8::7]/c=GB?objectClass?one"); StringValidation.uri("x", "mailto:John.Doe@example.com"); StringValidation.uri("x", "news:comp.infosystems.www.servers.unix"); StringValidation.uri("x", "telnet://192.0.2.16:80/"); StringValidation.uri("x", "urn:oasis:names:specification:docbook:dtd:xml:4.1.2"); StringValidation.uri("x", "tel:+1-816-555-1212"); // No Match assertThatThrownBy(() -> StringValidation.uri("x", "server/resource")).isInstanceOf(ValidationException.class); assertThatThrownBy(() -> StringValidation.uri("x", "this is not a uri")).isInstanceOf(ValidationException.class); } @Test public void uriRefWorks() throws ValidationException { // Match StringValidation.uriRef("x", "server/resource"); // No Match assertThatThrownBy(() -> StringValidation.uri("x", "this is not a uri")).isInstanceOf(ValidationException.class); } @Test public void uuidWorks() throws ValidationException { // We use this to generate UUIDs for all valid hex digits, so: // 00000000-0000…, 11111111-1111…, …, FFFFFFFF-FFFF… char[] chars = "0123456789abcdefABCDEF".toCharArray(); // Match for (char c : chars) { final String s4 = repeat(c, 4); uuid(String.valueOf(c), repeat(c, 8) + '-' + s4 + '-' + s4 + '-' + s4 + '-' + repeat(c, 12)); } // No Match assertValidationException(() -> uuid("g", "00000000-0000-0000-0000-00000000000g")); assertValidationException(() -> uuid("underscore", "00000000-0000_0000-0000-000000000000")); assertValidationException(() -> uuid("short", "00000000-000000000-0000-00000000000")); assertValidationException(() -> uuid("long", "00000000-000000000-0000-0000000000000")); assertValidationException(() -> uuid("1_dash_at_07", "0000000-00000-0000-0000-000000000000")); assertValidationException(() -> uuid("1_dash_at_09", "000000000-000-0000-0000-000000000000")); assertValidationException(() -> uuid("2_dash_at_12", "00000000-000-00000-0000-000000000000")); assertValidationException(() -> uuid("2_dash_at_14", "00000000-00000-000-0000-000000000000")); assertValidationException(() -> uuid("3_dash_at_17", "00000000-0000-000-00000-000000000000")); assertValidationException(() -> uuid("3_dash_at_19", "00000000-0000-00000-000-000000000000")); assertValidationException(() -> uuid("4_dash_at_22", "00000000-0000-0000-000-0000000000000")); assertValidationException(() -> uuid("4_dash_at_24", "00000000-0000-0000-00000-00000000000")); } } TimestampValidationTest.java000066400000000000000000000073241444536353100345410ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgvpackage io.envoyproxy.pgv; import com.google.protobuf.Duration; import com.google.protobuf.Timestamp; import com.google.protobuf.util.Durations; import com.google.protobuf.util.Timestamps; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class TimestampValidationTest { @Test public void lessThanWorks() throws ValidationException { // Less ComparativeValidation.lessThan("x", Timestamps.fromSeconds(10), Timestamps.fromSeconds(20), Timestamps.comparator()); // Equal assertThatThrownBy(() -> ComparativeValidation.lessThan("x", Timestamps.fromSeconds(10), Timestamps.fromSeconds(10), Timestamps.comparator())).isInstanceOf(ValidationException.class); // Greater assertThatThrownBy(() -> ComparativeValidation.lessThan("x", Timestamps.fromSeconds(20), Timestamps.fromSeconds(10), Timestamps.comparator())).isInstanceOf(ValidationException.class); } @Test public void lessThanOrEqualsWorks() throws ValidationException { // Less ComparativeValidation.lessThanOrEqual("x", Timestamps.fromSeconds(10), Timestamps.fromSeconds(20), Timestamps.comparator()); // Equal ComparativeValidation.lessThanOrEqual("x", Timestamps.fromSeconds(10), Timestamps.fromSeconds(10), Timestamps.comparator()); // Greater assertThatThrownBy(() -> ComparativeValidation.lessThanOrEqual("x", Timestamps.fromSeconds(20), Timestamps.fromSeconds(10), Timestamps.comparator())).isInstanceOf(ValidationException.class); } @Test public void greaterThanWorks() throws ValidationException { // Less assertThatThrownBy(() -> ComparativeValidation.greaterThan("x", Timestamps.fromSeconds(10), Timestamps.fromSeconds(20), Timestamps.comparator())).isInstanceOf(ValidationException.class); // Equal assertThatThrownBy(() -> ComparativeValidation.greaterThan("x", Timestamps.fromSeconds(10), Timestamps.fromSeconds(10), Timestamps.comparator())).isInstanceOf(ValidationException.class); // Greater ComparativeValidation.greaterThan("x", Timestamps.fromSeconds(20), Timestamps.fromSeconds(10), Timestamps.comparator()); } @Test public void greaterThanOrEqualsWorks() throws ValidationException { // Less assertThatThrownBy(() -> ComparativeValidation.greaterThanOrEqual("x", Timestamps.fromSeconds(10), Timestamps.fromSeconds(20), Timestamps.comparator())).isInstanceOf(ValidationException.class); // Equal ComparativeValidation.greaterThanOrEqual("x", Timestamps.fromSeconds(10), Timestamps.fromSeconds(10), Timestamps.comparator()); // Greater ComparativeValidation.greaterThanOrEqual("x", Timestamps.fromSeconds(20), Timestamps.fromSeconds(10), Timestamps.comparator()); } @Test public void withinWorks() throws ValidationException { Timestamp when = Timestamps.fromSeconds(20); Duration duration = Durations.fromSeconds(5); // Less TimestampValidation.within("x", Timestamps.fromSeconds(18), duration, when); TimestampValidation.within("x", Timestamps.fromSeconds(20), duration, when); TimestampValidation.within("x", Timestamps.fromSeconds(22), duration, when); // Equal TimestampValidation.within("x", Timestamps.fromSeconds(15), duration, when); TimestampValidation.within("x", Timestamps.fromSeconds(25), duration, when); // Greater assertThatThrownBy(() -> TimestampValidation.within("x", Timestamps.fromSeconds(10), duration, when)).isInstanceOf(ValidationException.class); assertThatThrownBy(() -> TimestampValidation.within("x", Timestamps.fromSeconds(30), duration, when)).isInstanceOf(ValidationException.class); } } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/proto/000077500000000000000000000000001444536353100237065ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/proto/BUILD.bazel000066400000000000000000000011121444536353100255570ustar00rootroot00000000000000load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") load("@rules_proto//proto:defs.bzl", "proto_library") proto_library( name = "io_envoyproxy_pvg_cases_proto", srcs = [ "embedded.proto", "enum.proto", ], visibility = ["//visibility:public"], deps = ["//validate:validate_proto"], ) go_proto_library( name = "io_envoyproxy_pvg_cases_go_proto", importpath = "java/pgv-java-stub/src/test/proto", proto = ":io_envoyproxy_pvg_cases_proto", visibility = ["//visibility:public"], deps = ["//validate:go_default_library"], ) protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/proto/embedded.proto000066400000000000000000000004401444536353100265220ustar00rootroot00000000000000syntax = "proto3"; package io.envoyproxy.pvg.cases; option java_multiple_files = true; import "validate/validate.proto"; message TokenUse { message Payload { message Token { string value = 1; } Token token = 1; } Payload payload = 1; } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/proto/enum.proto000066400000000000000000000002311444536353100257330ustar00rootroot00000000000000syntax = "proto3"; package io.envoyproxy.pvg.cases; enum TestEnum { ZERO = 0; ONE = 1; TWO = 2; } message Outer { string val = 1; } protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/proto/underscoreName.proto000066400000000000000000000007271444536353100277530ustar00rootroot00000000000000syntax = "proto3"; package io.envoyproxy.pgv.grpc; option java_multiple_files = true; option java_package = "io.envoyproxy.pgv.validate"; import "validate/validate.proto"; message MessageNameWith_Underscore { string v = 1 [(validate.rules).string.min_len = 2]; } message AnotherMessageNameWith_Underscore { string v = 1 [(validate.rules).string.min_len = 2]; } message MessageNameWith_Two_Underscore { string v = 1 [(validate.rules).string.min_len = 2]; }protoc-gen-validate-1.0.2/java/pgv-java-validation/000077500000000000000000000000001444536353100221525ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/pom.xml000066400000000000000000000135731444536353100235000ustar00rootroot00000000000000 pgv-java build.buf.protoc-gen-validate VERSION 4.0.0 pgv-java-validation PGV-Java Validation Harness true build.buf.protoc-gen-validate pgv-java-stub ${project.version} com.google.protobuf protobuf-java ${google.protobuf.version} build.buf.protoc-gen-validate protoc-gen-validate ${project.version} pom kr.motd.maven os-maven-plugin 1.7.1 org.xolstice.maven.plugins protobuf-maven-plugin ${protobuf.maven.plugin.version} com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier} protoc-java compile ../../ tests/harness/harness.proto tests/harness/cases/*.proto tests/harness/cases/other_package/*.proto tests/harness/cases/yet_another_package/*.proto tests/harness/cases/sort/*.proto protoc-java-pgv compile-custom ../../ lang=java tests/harness/cases/*.proto tests/harness/cases/other_package/*.proto tests/harness/cases/yet_another_package/*.proto java-pgv build.buf.protoc-gen-validate:protoc-gen-validate:${project.version}:exe:${os.detected.classifier} org.apache.maven.plugins maven-shade-plugin 3.5.0 package shade java-harness io.envoyproxy.pgv.validation.JavaHarness org.jacoco jacoco-maven-plugin 0.8.10 prepare-agent report prepare-package report protoc-gen-validate-1.0.2/java/pgv-java-validation/src/000077500000000000000000000000001444536353100227415ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/000077500000000000000000000000001444536353100236655ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/000077500000000000000000000000001444536353100246065ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/000077500000000000000000000000001444536353100252155ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/envoyproxy/000077500000000000000000000000001444536353100274575ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/envoyproxy/pgv/000077500000000000000000000000001444536353100302535ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/envoyproxy/pgv/BUILD000066400000000000000000000003341444536353100310350ustar00rootroot00000000000000load("@rules_java//java:defs.bzl", "java_library") java_library( name = "pgv", visibility = ["//visibility:public"], runtime_deps = [ "//java/pgv-java-stub/src/main/java/io/envoyproxy/pgv", ], ) protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/envoyproxy/pgv/validation/000077500000000000000000000000001444536353100324055ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/envoyproxy/pgv/validation/BUILD000066400000000000000000000016351444536353100331740ustar00rootroot00000000000000load("@rules_java//java:defs.bzl", "java_library") java_library( name = "java_harness", srcs = glob(["*.java"]), visibility = ["//tests/harness:__subpackages__"], deps = [ "//java/pgv-java-stub/src/main/java/io/envoyproxy/pgv", "//java/pgv-java-validation/src/main/java/io/envoyproxy/pgv", "//tests/harness:harness_java_proto", "//tests/harness/cases:cases_java_proto", "//tests/harness/cases:java", "//tests/harness/cases/other_package:embed_java_proto", "//tests/harness/cases/other_package:java", "//tests/harness/cases/yet_another_package:embed_java_proto", "//tests/harness/cases/yet_another_package:java", "//tests/harness/cases/sort:sort_java_proto", "//tests/harness/cases/sort:java", "//validate:validate_java", "@com_google_guava//jar", "@com_google_protobuf//:protobuf_java", ], ) JavaHarness.java000066400000000000000000000066331444536353100354060ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/envoyproxy/pgv/validationpackage io.envoyproxy.pgv.validation; import com.google.common.base.Throwables; import com.google.protobuf.ExtensionRegistry; import com.google.protobuf.Message; import io.envoyproxy.pgv.ReflectiveValidatorIndex; import io.envoyproxy.pgv.UnimplementedException; import io.envoyproxy.pgv.ValidationException; import io.envoyproxy.pgv.ValidatorIndex; import tests.harness.Harness; import tests.harness.cases.*; import tests.harness.cases.other_package.EmbedOuterClass; import io.envoyproxy.pgv.validate.Validate; import java.io.IOException; import java.util.Arrays; @SuppressWarnings("unchecked") public class JavaHarness { public static void main(String[] args) { Message message = null; try { ProtoTypeMap typeMap = ProtoTypeMap.of(Arrays.asList( Bool.getDescriptor().toProto(), Bytes.getDescriptor().toProto(), Enums.getDescriptor().toProto(), KitchenSink.getDescriptor().toProto(), Maps.getDescriptor().toProto(), Messages.getDescriptor().toProto(), Numbers.getDescriptor().toProto(), Oneofs.getDescriptor().toProto(), Repeated.getDescriptor().toProto(), Strings.getDescriptor().toProto(), WktAny.getDescriptor().toProto(), WktDuration.getDescriptor().toProto(), WktNested.getDescriptor().toProto(), WktTimestamp.getDescriptor().toProto(), WktWrappers.getDescriptor().toProto(), EmbedOuterClass.getDescriptor().toProto() )); ExtensionRegistry registry = ExtensionRegistry.newInstance(); Validate.registerAllExtensions(registry); Harness.TestCase testCase = Harness.TestCase.parseFrom(System.in, registry); message = typeMap.unpackAny(testCase.getMessage()); ValidatorIndex validatorIndex = new ReflectiveValidatorIndex(); validatorIndex.validatorFor(message).assertValid(message); writeResult(Harness.TestResult.newBuilder().setValid(true).build()); } catch (UnimplementedException ex) { writeResult(Harness.TestResult.newBuilder().setValid(false).setAllowFailure(true).addReasons(ex.getMessage()).build()); } catch (ValidationException ex) { writeResult(Harness.TestResult.newBuilder().setValid(false).addReasons(ex.getMessage()).build()); } catch (NullPointerException ex) { if (message.getDescriptorForType().getOptions().getExtension(Validate.ignored)) { writeResult(Harness.TestResult.newBuilder().setValid(false).setAllowFailure(true).addReasons("validation not generated due to ignore option").build()); } else { writeResult(Harness.TestResult.newBuilder().setValid(false).setError(true).addReasons(Throwables.getStackTraceAsString(ex)).build()); } } catch (Throwable ex) { writeResult(Harness.TestResult.newBuilder().setValid(false).setError(true).addReasons(Throwables.getStackTraceAsString(ex)).build()); } System.out.flush(); System.exit(0); } private static void writeResult(Harness.TestResult result) { try { result.writeTo(System.out); } catch (IOException ex) { ex.printStackTrace(); } } } ProtoTypeMap.java000066400000000000000000000206231444536353100355770ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/envoyproxy/pgv/validationpackage io.envoyproxy.pgv.validation; import com.google.common.base.*; import com.google.common.collect.ImmutableMap; import com.google.protobuf.Any; import com.google.protobuf.DescriptorProtos; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; import java.util.Collection; /** * {@code ProtoTypeMap} maintains a dictionary for looking up Java type names when given proto types. */ public final class ProtoTypeMap { private final ImmutableMap types; private ProtoTypeMap(ImmutableMap types) { Preconditions.checkNotNull(types, "types"); this.types = types; } /** * Returns an instance of {@link ProtoTypeMap} based on the given FileDescriptorProto instances. * * @param fileDescriptorProtos the full collection of files descriptors from the code generator request */ public static ProtoTypeMap of(Collection fileDescriptorProtos) { Preconditions.checkNotNull(fileDescriptorProtos, "fileDescriptorProtos"); Preconditions.checkArgument(!fileDescriptorProtos.isEmpty(), "fileDescriptorProtos.isEmpty()"); final ImmutableMap.Builder types = ImmutableMap.builder(); for (final DescriptorProtos.FileDescriptorProto fileDescriptor : fileDescriptorProtos) { final DescriptorProtos.FileOptions fileOptions = fileDescriptor.getOptions(); final String protoPackage = fileDescriptor.hasPackage() ? "." + fileDescriptor.getPackage() : ""; final String javaPackage = Strings.emptyToNull( fileOptions.hasJavaPackage() ? fileOptions.getJavaPackage() : fileDescriptor.getPackage()); final String enclosingClassName = fileOptions.getJavaMultipleFiles() ? null : getJavaOuterClassname(fileDescriptor, fileOptions); // Identify top-level enums fileDescriptor.getEnumTypeList().forEach( e -> types.put( protoPackage + "." + e.getName(), toJavaTypeName(e.getName(), enclosingClassName, javaPackage))); // Identify top-level messages, and nested types fileDescriptor.getMessageTypeList().forEach( m -> recursivelyAddTypes(types, m, protoPackage, enclosingClassName, javaPackage) ); } return new ProtoTypeMap(types.build()); } private static void recursivelyAddTypes(ImmutableMap.Builder types, DescriptorProtos.DescriptorProto m, String protoPackage, String enclosingClassName, String javaPackage) { // Identify current type types.put( protoPackage + "." + m.getName(), toJavaTypeName(m.getName(), enclosingClassName, javaPackage)); // Identify any nested Enums m.getEnumTypeList().forEach( e -> types.put( protoPackage + "." + e.getName(), toJavaTypeName(e.getName(), enclosingClassName, javaPackage))); // Recursively identify any nested types m.getNestedTypeList().forEach( n -> recursivelyAddTypes( types, n, protoPackage + "." + m.getName(), enclosingClassName + "$" + m.getName(), javaPackage)); } /** * Returns the full Java type name for the given proto type. * * @param protoTypeName the proto type to be converted to a Java type */ public String toJavaTypeName(String protoTypeName) { Preconditions.checkNotNull(protoTypeName, "protoTypeName"); return types.get(protoTypeName); } /** * Returns the full Java type name based on the given protobuf type parameters. * * @param className the protobuf type name * @param enclosingClassName the optional enclosing class for the given type * @param javaPackage the proto file's configured java package name */ private static String toJavaTypeName( String className, String enclosingClassName, String javaPackage) { Preconditions.checkNotNull(className, "className"); Joiner dotJoiner = Joiner.on('.').skipNulls(); Joiner dollarJoiner = Joiner.on('$').skipNulls(); return dotJoiner.join(javaPackage, dollarJoiner.join(enclosingClassName, className)); } private static String getJavaOuterClassname( DescriptorProtos.FileDescriptorProto fileDescriptor, DescriptorProtos.FileOptions fileOptions) { if (fileOptions.hasJavaOuterClassname()) { return fileOptions.getJavaOuterClassname(); } // If the outer class name is not explicitly defined, then we take the proto filename, strip its extension, // and convert it from snake case to camel case. String filename = fileDescriptor.getName().substring(0, fileDescriptor.getName().length() - ".proto".length()); // Protos in subdirectories without java_outer_classname have their path prepended to the filename. Remove // if present. if (filename.contains("/")) { filename = filename.substring(filename.lastIndexOf('/') + 1); } filename = makeInvalidCharactersUnderscores(filename); filename = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, filename); filename = upcaseAfterNumber(filename); filename = appendOuterClassSuffix(filename, fileDescriptor); return filename; } /** * In the event of a name conflict between the outer and inner type names, protoc adds an OuterClass suffix to the * outer type's name. */ private static String appendOuterClassSuffix(final String enclosingClassName, DescriptorProtos.FileDescriptorProto fd) { if (fd.getEnumTypeList().stream().anyMatch(enumProto -> enumProto.getName().equals(enclosingClassName)) || fd.getMessageTypeList().stream().anyMatch(messageProto -> messageProto.getName().equals(enclosingClassName)) || fd.getServiceList().stream().anyMatch(serviceProto -> serviceProto.getName().equals(enclosingClassName))) { return enclosingClassName + "OuterClass"; } else { return enclosingClassName; } } /** * Replace invalid proto identifier characters with an underscore, so they will be dropped and camel cases below. * https://developers.google.com/protocol-buffers/docs/reference/proto3-spec */ private static String makeInvalidCharactersUnderscores(String filename) { char[] filechars = filename.toCharArray(); for (int i = 0; i < filechars.length; i++) { char c = filechars[i]; if (!CharMatcher.inRange('0', '9').or(CharMatcher.inRange('A', 'Z')).or(CharMatcher.inRange('a', 'z')).matches(c)) { filechars[i] = '_'; } } return new String(filechars); } /** * Upper case characters after numbers, like {@code Weyland9Yutani}. */ private static String upcaseAfterNumber(String filename) { char[] filechars = filename.toCharArray(); for (int i = 1; i < filechars.length; i++) { if (CharMatcher.inRange('0', '9').matches(filechars[i - 1])) { filechars[i] = Character.toUpperCase(filechars[i]); } } return new String(filechars); } @SuppressWarnings("unchecked") public Message unpackAny(Any any) throws ClassNotFoundException, InvalidProtocolBufferException { String typeUrl = any.getTypeUrl(); if (typeUrl.startsWith("type.googleapis.com/")){ String protoTypeName = any.getTypeUrl().substring(20); String className = toJavaTypeName("." + protoTypeName); if (className == null) { throw new IllegalArgumentException(protoTypeName + " does not map to a Java type name"); } Class clazz = (Class) Class.forName(className); return any.unpack(clazz); } else { throw new IllegalArgumentException("Any typeUrl does not start with type.googleapis.com - " + typeUrl); } } } protoc-gen-validate-1.0.2/java/pgv-java-validation/src/test/000077500000000000000000000000001444536353100237205ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/test/java/000077500000000000000000000000001444536353100246415ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/test/java/io/000077500000000000000000000000001444536353100252505ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/test/java/io/envoyproxy/000077500000000000000000000000001444536353100275125ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/test/java/io/envoyproxy/pgv/000077500000000000000000000000001444536353100303065ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/test/java/io/envoyproxy/pgv/validation/000077500000000000000000000000001444536353100324405ustar00rootroot00000000000000ProtoTypeMapTest.java000066400000000000000000000027641444536353100365000ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-java-validation/src/test/java/io/envoyproxy/pgv/validationpackage io.envoyproxy.pgv.validation; import com.google.protobuf.Any; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; import org.junit.Test; import tests.harness.Harness; import tests.harness.cases.Messages; import tests.harness.cases.Numbers; import java.util.Collections; import static org.assertj.core.api.Assertions.assertThat; public class ProtoTypeMapTest { @Test public void unpackAnyWorks() throws InvalidProtocolBufferException, ClassNotFoundException { Harness.TestCase testCase = Harness.TestCase.newBuilder() .setMessage(Any.pack(Numbers.UInt64GTLT.newBuilder().setVal(12345L).build())) .build(); ProtoTypeMap typeMap = ProtoTypeMap.of(Collections.singletonList(Numbers.getDescriptor().toProto())); Message message = typeMap.unpackAny(testCase.getMessage()); assertThat(message).isInstanceOf(Numbers.UInt64GTLT.class); } @Test public void unpackAnyNestedWorks() throws InvalidProtocolBufferException, ClassNotFoundException { Harness.TestCase testCase = Harness.TestCase.newBuilder() .setMessage(Any.pack(Messages.MessageNone.NoneMsg.newBuilder().build())) .build(); ProtoTypeMap typeMap = ProtoTypeMap.of(Collections.singletonList(Messages.getDescriptor().toProto())); Message message = typeMap.unpackAny(testCase.getMessage()); assertThat(message).isInstanceOf(Messages.MessageNone.NoneMsg.class); } } protoc-gen-validate-1.0.2/java/pgv-test-coverage-report/000077500000000000000000000000001444536353100231625ustar00rootroot00000000000000protoc-gen-validate-1.0.2/java/pgv-test-coverage-report/pom.xml000066400000000000000000000043361444536353100245050ustar00rootroot00000000000000 pgv-java build.buf.protoc-gen-validate VERSION 4.0.0 pgv-test-coverage-report PGV-Java Code Coverage Report build.buf.protoc-gen-validate protoc-gen-validate ${project.version} pom test build.buf.protoc-gen-validate pgv-java-stub ${project.version} build.buf.protoc-gen-validate pgv-java-grpc ${project.version} build.buf.protoc-gen-validate pgv-java-validation ${project.version} org.jacoco jacoco-maven-plugin 0.8.10 prepare-agent report prepare-package report-aggregate protoc-gen-validate-1.0.2/java/pom.xml000066400000000000000000000202121444536353100176210ustar00rootroot00000000000000 4.0.0 build.buf.protoc-gen-validate pgv-java VERSION pgv-java-stub pgv-java-validation pgv-java-grpc pgv-artifacts pgv-test-coverage-report pom PGV-Java Parent Protoc plugin to generate protobuf message validators. https://github.com/envoyproxy/protoc-gen-validate The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo elliotmjackson Elliot Jackson ejackson@buf.build UTF-8 3.22.2 3.23.3 0.6.1 1.7 1.7 1.56.0 4.13.2 3.24.2 8 1.8 2.21.0 junit junit ${junit.version} test org.assertj assertj-core ${assertj.version} test org.apache.maven.plugins maven-compiler-plugin 3.11.0 ${java.release} ${java.version} ${java.version} -Xlint:unchecked org.apache.maven.plugins maven-surefire-plugin 3.1.2 false org.apache.maven.plugins maven-javadoc-plugin 3.5.0 false true accessibility,html,reference,syntax true false 8 attach-javadocs jar org.apache.maven.plugins maven-source-plugin 3.3.0 attach-sources jar ci org.apache.maven.plugins maven-release-plugin 3.0.1 true v@{project.version}-java java release: java/pom.xml org.codehaus.mojo versions-maven-plugin 2.16.0 org.sonatype.plugins nexus-staging-maven-plugin 1.6.13 true sonatype-nexus-staging https://s01.oss.sonatype.org/ true signing org.apache.maven.plugins maven-gpg-plugin 3.1.0 sign-artifacts verify sign --pinentry-mode loopback https://github.com/bufbuild/protoc-gen-validate scm:git:git@github.com:bufbuild/protoc-gen-validate.git scm:git:git@github.com:bufbuild/protoc-gen-validate.git HEAD sonatype-nexus-snapshots https://s01.oss.sonatype.org/content/repositories/snapshots protoc-gen-validate-1.0.2/java/settings.xml000066400000000000000000000035401444536353100206730ustar00rootroot00000000000000 sonatype-nexus-snapshots ${env.SONATYPE_USER} ${env.SONATYPE_PASSWORD} sonatype-nexus-staging ${env.SONATYPE_USER} ${env.SONATYPE_PASSWORD} github ${env.GITHUB_ACTOR} ${env.GITHUB_TOKEN} gpg.passphrase ${env.GPG_PASSPHRASE} ci sonatype-staging https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ default true signing gpg ${env.GPG_KEY_NAME} ${env.GPG_PASSPHRASE} ci signing protoc-gen-validate-1.0.2/main.go000066400000000000000000000007311444536353100166420ustar00rootroot00000000000000package main import ( "github.com/envoyproxy/protoc-gen-validate/module" pgs "github.com/lyft/protoc-gen-star/v2" pgsgo "github.com/lyft/protoc-gen-star/v2/lang/go" "google.golang.org/protobuf/types/pluginpb" ) func main() { optional := uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) pgs. Init(pgs.DebugEnv("DEBUG_PGV"), pgs.SupportedFeatures(&optional)). RegisterModule(module.Validator()). RegisterPostProcessor(pgsgo.GoFmt()). Render() } protoc-gen-validate-1.0.2/module/000077500000000000000000000000001444536353100166535ustar00rootroot00000000000000protoc-gen-validate-1.0.2/module/BUILD000066400000000000000000000016451444536353100174430ustar00rootroot00000000000000load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "module", srcs = [ "checker.go", "validate.go", ], importpath = "github.com/envoyproxy/protoc-gen-validate/module", visibility = ["//visibility:public"], deps = [ "//templates", "//templates/java", "//validate:validate_go", "@com_github_lyft_protoc_gen_star_v2//:protoc-gen-star", "@com_github_lyft_protoc_gen_star_v2//lang/go", "@org_golang_google_protobuf//proto", "@org_golang_google_protobuf//types/known/durationpb", "@org_golang_google_protobuf//types/known/timestamppb", ], ) alias( name = "go_default_library", actual = ":module", deprecation = "Use :module instead of :go_default_library. Details about the new naming convention: https://github.com/bazelbuild/bazel-gazelle/pull/863", visibility = ["//visibility:public"], ) protoc-gen-validate-1.0.2/module/checker.go000066400000000000000000000335171444536353100206170ustar00rootroot00000000000000package module import ( "reflect" "regexp" "time" "unicode/utf8" "github.com/envoyproxy/protoc-gen-validate/validate" pgs "github.com/lyft/protoc-gen-star/v2" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/timestamppb" ) var unknown = "" var httpHeaderName = "^:?[0-9a-zA-Z!#$%&'*+-.^_|~\x60]+$" var httpHeaderValue = "^[^\u0000-\u0008\u000A-\u001F\u007F]*$" var headerString = "^[^\u0000\u000A\u000D]*$" // For non-strict validation. // Map from well known regex to regex pattern. var regex_map = map[string]*string{ "UNKNOWN": &unknown, "HTTP_HEADER_NAME": &httpHeaderName, "HTTP_HEADER_VALUE": &httpHeaderValue, "HEADER_STRING": &headerString, } type FieldType interface { ProtoType() pgs.ProtoType Embed() pgs.Message } type Repeatable interface { IsRepeated() bool } func (m *Module) CheckRules(msg pgs.Message) { m.Push("msg: " + msg.Name().String()) defer m.Pop() var disabled bool _, err := msg.Extension(validate.E_Disabled, &disabled) m.CheckErr(err, "unable to read validation extension from message") if disabled { m.Debug("validation disabled, skipping checks") return } for _, f := range msg.Fields() { m.Push(f.Name().String()) var rules validate.FieldRules _, err = f.Extension(validate.E_Rules, &rules) m.CheckErr(err, "unable to read validation rules from field") if rules.GetMessage() != nil { m.MustType(f.Type(), pgs.MessageT, pgs.UnknownWKT) m.CheckMessage(f, &rules) } m.CheckFieldRules(f.Type(), &rules) m.Pop() } } func (m *Module) CheckFieldRules(typ FieldType, rules *validate.FieldRules) { if rules == nil { return } switch r := rules.Type.(type) { case *validate.FieldRules_Float: m.MustType(typ, pgs.FloatT, pgs.FloatValueWKT) m.CheckFloat(r.Float) case *validate.FieldRules_Double: m.MustType(typ, pgs.DoubleT, pgs.DoubleValueWKT) m.CheckDouble(r.Double) case *validate.FieldRules_Int32: m.MustType(typ, pgs.Int32T, pgs.Int32ValueWKT) m.CheckInt32(r.Int32) case *validate.FieldRules_Int64: m.MustType(typ, pgs.Int64T, pgs.Int64ValueWKT) m.CheckInt64(r.Int64) case *validate.FieldRules_Uint32: m.MustType(typ, pgs.UInt32T, pgs.UInt32ValueWKT) m.CheckUInt32(r.Uint32) case *validate.FieldRules_Uint64: m.MustType(typ, pgs.UInt64T, pgs.UInt64ValueWKT) m.CheckUInt64(r.Uint64) case *validate.FieldRules_Sint32: m.MustType(typ, pgs.SInt32, pgs.UnknownWKT) m.CheckSInt32(r.Sint32) case *validate.FieldRules_Sint64: m.MustType(typ, pgs.SInt64, pgs.UnknownWKT) m.CheckSInt64(r.Sint64) case *validate.FieldRules_Fixed32: m.MustType(typ, pgs.Fixed32T, pgs.UnknownWKT) m.CheckFixed32(r.Fixed32) case *validate.FieldRules_Fixed64: m.MustType(typ, pgs.Fixed64T, pgs.UnknownWKT) m.CheckFixed64(r.Fixed64) case *validate.FieldRules_Sfixed32: m.MustType(typ, pgs.SFixed32, pgs.UnknownWKT) m.CheckSFixed32(r.Sfixed32) case *validate.FieldRules_Sfixed64: m.MustType(typ, pgs.SFixed64, pgs.UnknownWKT) m.CheckSFixed64(r.Sfixed64) case *validate.FieldRules_Bool: m.MustType(typ, pgs.BoolT, pgs.BoolValueWKT) case *validate.FieldRules_String_: m.MustType(typ, pgs.StringT, pgs.StringValueWKT) m.CheckString(r.String_) case *validate.FieldRules_Bytes: m.MustType(typ, pgs.BytesT, pgs.BytesValueWKT) m.CheckBytes(r.Bytes) case *validate.FieldRules_Enum: m.MustType(typ, pgs.EnumT, pgs.UnknownWKT) m.CheckEnum(typ, r.Enum) case *validate.FieldRules_Repeated: m.CheckRepeated(typ, r.Repeated) case *validate.FieldRules_Map: m.CheckMap(typ, r.Map) case *validate.FieldRules_Any: m.CheckAny(typ, r.Any) case *validate.FieldRules_Duration: m.CheckDuration(typ, r.Duration) case *validate.FieldRules_Timestamp: m.CheckTimestamp(typ, r.Timestamp) case nil: // noop default: m.Failf("unknown rule type (%T)", rules.Type) } } func (m *Module) MustType(typ FieldType, pt pgs.ProtoType, wrapper pgs.WellKnownType) { if emb := typ.Embed(); emb != nil && emb.IsWellKnown() && emb.WellKnownType() == wrapper { m.MustType(emb.Fields()[0].Type(), pt, pgs.UnknownWKT) return } if typ, ok := typ.(Repeatable); ok { m.Assert(!typ.IsRepeated(), "repeated rule should be used for repeated fields") } m.Assert(typ.ProtoType() == pt, " expected rules for ", typ.ProtoType().Proto(), " but got ", pt.Proto(), ) } func (m *Module) CheckFloat(r *validate.FloatRules) { m.checkNums(len(r.In), len(r.NotIn), r.Const, r.Lt, r.Lte, r.Gt, r.Gte) } func (m *Module) CheckDouble(r *validate.DoubleRules) { m.checkNums(len(r.In), len(r.NotIn), r.Const, r.Lt, r.Lte, r.Gt, r.Gte) } func (m *Module) CheckInt32(r *validate.Int32Rules) { m.checkNums(len(r.In), len(r.NotIn), r.Const, r.Lt, r.Lte, r.Gt, r.Gte) } func (m *Module) CheckInt64(r *validate.Int64Rules) { m.checkNums(len(r.In), len(r.NotIn), r.Const, r.Lt, r.Lte, r.Gt, r.Gte) } func (m *Module) CheckUInt32(r *validate.UInt32Rules) { m.checkNums(len(r.In), len(r.NotIn), r.Const, r.Lt, r.Lte, r.Gt, r.Gte) } func (m *Module) CheckUInt64(r *validate.UInt64Rules) { m.checkNums(len(r.In), len(r.NotIn), r.Const, r.Lt, r.Lte, r.Gt, r.Gte) } func (m *Module) CheckSInt32(r *validate.SInt32Rules) { m.checkNums(len(r.In), len(r.NotIn), r.Const, r.Lt, r.Lte, r.Gt, r.Gte) } func (m *Module) CheckSInt64(r *validate.SInt64Rules) { m.checkNums(len(r.In), len(r.NotIn), r.Const, r.Lt, r.Lte, r.Gt, r.Gte) } func (m *Module) CheckFixed32(r *validate.Fixed32Rules) { m.checkNums(len(r.In), len(r.NotIn), r.Const, r.Lt, r.Lte, r.Gt, r.Gte) } func (m *Module) CheckFixed64(r *validate.Fixed64Rules) { m.checkNums(len(r.In), len(r.NotIn), r.Const, r.Lt, r.Lte, r.Gt, r.Gte) } func (m *Module) CheckSFixed32(r *validate.SFixed32Rules) { m.checkNums(len(r.In), len(r.NotIn), r.Const, r.Lt, r.Lte, r.Gt, r.Gte) } func (m *Module) CheckSFixed64(r *validate.SFixed64Rules) { m.checkNums(len(r.In), len(r.NotIn), r.Const, r.Lt, r.Lte, r.Gt, r.Gte) } func (m *Module) CheckString(r *validate.StringRules) { m.checkLen(r.Len, r.MinLen, r.MaxLen) m.checkLen(r.LenBytes, r.MinBytes, r.MaxBytes) m.checkMinMax(r.MinLen, r.MaxLen) m.checkMinMax(r.MinBytes, r.MaxBytes) m.checkIns(len(r.In), len(r.NotIn)) m.checkWellKnownRegex(r.GetWellKnownRegex(), r) m.checkPattern(r.Pattern, len(r.In)) if r.MaxLen != nil { max := int(r.GetMaxLen()) m.Assert(utf8.RuneCountInString(r.GetPrefix()) <= max, "`prefix` length exceeds the `max_len`") m.Assert(utf8.RuneCountInString(r.GetSuffix()) <= max, "`suffix` length exceeds the `max_len`") m.Assert(utf8.RuneCountInString(r.GetContains()) <= max, "`contains` length exceeds the `max_len`") m.Assert( r.MaxBytes == nil || r.GetMaxBytes() >= r.GetMaxLen(), "`max_len` cannot exceed `max_bytes`") } if r.MaxBytes != nil { max := int(r.GetMaxBytes()) m.Assert(len(r.GetPrefix()) <= max, "`prefix` length exceeds the `max_bytes`") m.Assert(len(r.GetSuffix()) <= max, "`suffix` length exceeds the `max_bytes`") m.Assert(len(r.GetContains()) <= max, "`contains` length exceeds the `max_bytes`") } } func (m *Module) CheckBytes(r *validate.BytesRules) { m.checkMinMax(r.MinLen, r.MaxLen) m.checkIns(len(r.In), len(r.NotIn)) m.checkPattern(r.Pattern, len(r.In)) if r.MaxLen != nil { max := int(r.GetMaxLen()) m.Assert(len(r.GetPrefix()) <= max, "`prefix` length exceeds the `max_len`") m.Assert(len(r.GetSuffix()) <= max, "`suffix` length exceeds the `max_len`") m.Assert(len(r.GetContains()) <= max, "`contains` length exceeds the `max_len`") } } func (m *Module) CheckEnum(ft FieldType, r *validate.EnumRules) { m.checkIns(len(r.In), len(r.NotIn)) if r.GetDefinedOnly() && len(r.In) > 0 { typ, ok := ft.(interface { Enum() pgs.Enum }) if !ok { m.Failf("unexpected field type (%T)", ft) } defined := typ.Enum().Values() vals := make(map[int32]struct{}, len(defined)) for _, val := range defined { vals[val.Value()] = struct{}{} } for _, in := range r.In { if _, ok = vals[in]; !ok { m.Failf("undefined `in` value (%d) conflicts with `defined_only` rule") } } } } func (m *Module) CheckMessage(f pgs.Field, rules *validate.FieldRules) { m.Assert(f.Type().IsEmbed(), "field is not embedded but got message rules") emb := f.Type().Embed() if emb != nil && emb.IsWellKnown() { switch emb.WellKnownType() { case pgs.AnyWKT: m.Failf("Any rules should be used for Any fields") case pgs.DurationWKT: m.Failf("Duration rules should be used for Duration fields") case pgs.TimestampWKT: m.Failf("Timestamp rules should be used for Timestamp fields") } } if rules.Type != nil && rules.GetMessage().GetSkip() { m.Failf("Skip should not be used with WKT scalar rules") } } func (m *Module) CheckRepeated(ft FieldType, r *validate.RepeatedRules) { typ := m.mustFieldType(ft) m.Assert(typ.IsRepeated(), "field is not repeated but got repeated rules") m.checkMinMax(r.MinItems, r.MaxItems) if r.GetUnique() { m.Assert( !typ.Element().IsEmbed(), "unique rule is only applicable for scalar types") } m.Push("items") m.CheckFieldRules(typ.Element(), r.Items) m.Pop() } func (m *Module) CheckMap(ft FieldType, r *validate.MapRules) { typ := m.mustFieldType(ft) m.Assert(typ.IsMap(), "field is not a map but got map rules") m.checkMinMax(r.MinPairs, r.MaxPairs) if r.GetNoSparse() { m.Assert( typ.Element().IsEmbed(), "no_sparse rule is only applicable for embedded message types", ) } m.Push("keys") m.CheckFieldRules(typ.Key(), r.Keys) m.Pop() m.Push("values") m.CheckFieldRules(typ.Element(), r.Values) m.Pop() } func (m *Module) CheckAny(ft FieldType, r *validate.AnyRules) { m.checkIns(len(r.In), len(r.NotIn)) } func (m *Module) CheckDuration(ft FieldType, r *validate.DurationRules) { m.checkNums( len(r.GetIn()), len(r.GetNotIn()), m.checkDur(r.GetConst()), m.checkDur(r.GetLt()), m.checkDur(r.GetLte()), m.checkDur(r.GetGt()), m.checkDur(r.GetGte())) for _, v := range r.GetIn() { m.Assert(v != nil, "cannot have nil values in `in`") m.checkDur(v) } for _, v := range r.GetNotIn() { m.Assert(v != nil, "cannot have nil values in `not_in`") m.checkDur(v) } } func (m *Module) CheckTimestamp(ft FieldType, r *validate.TimestampRules) { m.checkNums(0, 0, m.checkTS(r.GetConst()), m.checkTS(r.GetLt()), m.checkTS(r.GetLte()), m.checkTS(r.GetGt()), m.checkTS(r.GetGte())) m.Assert( (r.LtNow == nil && r.GtNow == nil) || (r.Lt == nil && r.Lte == nil && r.Gt == nil && r.Gte == nil), "`now` rules cannot be mixed with absolute `lt/gt` rules") m.Assert( r.Within == nil || (r.Lt == nil && r.Lte == nil && r.Gt == nil && r.Gte == nil), "`within` rule cannot be used with absolute `lt/gt` rules") m.Assert( r.LtNow == nil || r.GtNow == nil, "both `now` rules cannot be used together") dur := m.checkDur(r.Within) m.Assert( dur == nil || *dur > 0, "`within` rule must be positive and non-zero") } func (m *Module) mustFieldType(ft FieldType) pgs.FieldType { typ, ok := ft.(pgs.FieldType) if !ok { m.Failf("unexpected field type (%T)", ft) } return typ } func (m *Module) checkNums(in, notIn int, ci, lti, ltei, gti, gtei interface{}) { m.checkIns(in, notIn) c := reflect.ValueOf(ci) lt, lte := reflect.ValueOf(lti), reflect.ValueOf(ltei) gt, gte := reflect.ValueOf(gti), reflect.ValueOf(gtei) m.Assert( c.IsNil() || in == 0 && notIn == 0 && lt.IsNil() && lte.IsNil() && gt.IsNil() && gte.IsNil(), "`const` can be the only rule on a field", ) m.Assert( in == 0 || lt.IsNil() && lte.IsNil() && gt.IsNil() && gte.IsNil(), "cannot have both `in` and range constraint rules on the same field", ) m.Assert( lt.IsNil() || lte.IsNil(), "cannot have both `lt` and `lte` rules on the same field", ) m.Assert( gt.IsNil() || gte.IsNil(), "cannot have both `gt` and `gte` rules on the same field", ) if !lt.IsNil() { m.Assert(gt.IsNil() || !reflect.DeepEqual(lti, gti), "cannot have equal `gt` and `lt` rules on the same field") m.Assert(gte.IsNil() || !reflect.DeepEqual(lti, gtei), "cannot have equal `gte` and `lt` rules on the same field") } else if !lte.IsNil() { m.Assert(gt.IsNil() || !reflect.DeepEqual(ltei, gti), "cannot have equal `gt` and `lte` rules on the same field") m.Assert(gte.IsNil() || !reflect.DeepEqual(ltei, gtei), "use `const` instead of equal `lte` and `gte` rules") } } func (m *Module) checkIns(in, notIn int) { m.Assert( in == 0 || notIn == 0, "cannot have both `in` and `not_in` rules on the same field") } func (m *Module) checkMinMax(min, max *uint64) { if min == nil || max == nil { return } m.Assert( *min <= *max, "`min` value is greater than `max` value") } func (m *Module) checkLen(len, min, max *uint64) { if len == nil { return } m.Assert( min == nil, "cannot have both `len` and `min_len` rules on the same field") m.Assert( max == nil, "cannot have both `len` and `max_len` rules on the same field") } func (m *Module) checkWellKnownRegex(wk validate.KnownRegex, r *validate.StringRules) { if wk != 0 { m.Assert(r.Pattern == nil, "regex `well_known_regex` and regex `pattern` are incompatible") var non_strict = r.Strict != nil && !*r.Strict if (wk.String() == "HTTP_HEADER_NAME" || wk.String() == "HTTP_HEADER_VALUE") && non_strict { // Use non-strict header validation. r.Pattern = regex_map["HEADER_STRING"] } else { r.Pattern = regex_map[wk.String()] } } } func (m *Module) checkPattern(p *string, in int) { if p != nil { m.Assert(in == 0, "regex `pattern` and `in` rules are incompatible") _, err := regexp.Compile(*p) m.CheckErr(err, "unable to parse regex `pattern`") } } func (m *Module) checkDur(d *durationpb.Duration) *time.Duration { if d == nil { return nil } dur, err := d.AsDuration(), d.CheckValid() m.CheckErr(err, "could not resolve duration") return &dur } func (m *Module) checkTS(ts *timestamppb.Timestamp) *int64 { if ts == nil { return nil } t, err := ts.AsTime(), ts.CheckValid() m.CheckErr(err, "could not resolve timestamp") return proto.Int64(t.UnixNano()) } protoc-gen-validate-1.0.2/module/validate.go000066400000000000000000000051041444536353100207730ustar00rootroot00000000000000package module import ( "path/filepath" "strings" "github.com/envoyproxy/protoc-gen-validate/templates" "github.com/envoyproxy/protoc-gen-validate/templates/java" pgs "github.com/lyft/protoc-gen-star/v2" pgsgo "github.com/lyft/protoc-gen-star/v2/lang/go" ) const ( validatorName = "validator" langParam = "lang" moduleParam = "module" ) type Module struct { *pgs.ModuleBase ctx pgsgo.Context // lang contains the selected language (one of 'cc', 'go', 'java'). // It is initialized in ValidatorForLanguage. // If unset, it will be parsed as the 'lang' parameter. lang string } func Validator() pgs.Module { return &Module{ModuleBase: &pgs.ModuleBase{}} } func ValidatorForLanguage(lang string) pgs.Module { return &Module{lang: lang, ModuleBase: &pgs.ModuleBase{}} } func (m *Module) InitContext(ctx pgs.BuildContext) { m.ModuleBase.InitContext(ctx) m.ctx = pgsgo.InitContext(ctx.Parameters()) } func (m *Module) Name() string { return validatorName } func (m *Module) Execute(targets map[string]pgs.File, pkgs map[string]pgs.Package) []pgs.Artifact { lang := m.lang langParamValue := m.Parameters().Str(langParam) if lang == "" { lang = langParamValue m.Assert(lang != "", "`lang` parameter must be set") } else if langParamValue != "" { m.Fail("unknown `lang` parameter") } module := m.Parameters().Str(moduleParam) // Process file-level templates tpls := templates.Template(m.Parameters())[lang] m.Assert(tpls != nil, "could not find templates for `lang`: ", lang) for _, f := range targets { m.Push(f.Name().String()) for _, msg := range f.AllMessages() { m.CheckRules(msg) } for _, tpl := range tpls { out := templates.FilePathFor(tpl)(f, m.ctx, tpl) // A nil path means no output should be generated for this file - as controlled by // implementation-specific FilePathFor implementations. // Ex: Don't generate Java validators for files that don't reference PGV. if out != nil { outPath := strings.TrimLeft(strings.ReplaceAll(filepath.ToSlash(out.String()), module, ""), "/") if opts := f.Descriptor().GetOptions(); opts != nil && opts.GetJavaMultipleFiles() && lang == "java" { // TODO: Only Java supports multiple file generation. If more languages add multiple file generation // support, the implementation should be made more inderect. for _, msg := range f.Messages() { m.AddGeneratorTemplateFile(java.JavaMultiFilePath(f, msg).String(), tpl, msg) } } else { m.AddGeneratorTemplateFile(outPath, tpl, f) } } } m.Pop() } return m.Artifacts() } var _ pgs.Module = (*Module)(nil) protoc-gen-validate-1.0.2/python/000077500000000000000000000000001444536353100167075ustar00rootroot00000000000000protoc-gen-validate-1.0.2/python/BUILD000066400000000000000000000004751444536353100174770ustar00rootroot00000000000000load("@rules_python//python:defs.bzl", "py_library") load("@pgv_pip_deps//:requirements.bzl", "all_requirements") exports_files([ "requirements.in", "setup.cfg", ]) py_library( name = "validator_py", srcs = glob(["**/*.py"]), visibility = ["//visibility:public"], deps = all_requirements, ) protoc-gen-validate-1.0.2/python/README.md000066400000000000000000000022221444536353100201640ustar00rootroot00000000000000# Protoc-gen-validate (PGV) While protocol buffers effectively guarantee the types of structured data, they cannot enforce semantic rules for values. This package is a python implementation of [protoc-gen-validate][pgv-home], which allows for runtime validation of various semantic assertions expressed as annotations on the protobuf schema. The syntax for all available annotations is in `validate.proto`. Implemented Python annotations are listed in the [rules comparison][rules-comparison]. ### Example ```python3 from entities_pb2 import Person from protoc_gen_validate.validator import validate, ValidationFailed, validate_all p = Person(name="Foo") try: validate(p) except ValidationFailed as err: print(err) # p.id is not greater than 999 try: validate_all(p) except ValidationFailed as err: print(err) # p.id is not greater than 999 # p.email is not a valid email # p.name pattern does not match ^[^[0-9]A-Za-z]+( [^[0-9]A-Za-z]+)*$ # home is required. ``` [pgv-home]: https://github.com/envoyproxy/protoc-gen-validate [rules-comparison]: https://github.com/envoyproxy/protoc-gen-validate/blob/main/rule_comparison.mdprotoc-gen-validate-1.0.2/python/protoc_gen_validate/000077500000000000000000000000001444536353100227175ustar00rootroot00000000000000protoc-gen-validate-1.0.2/python/protoc_gen_validate/__init__.py000066400000000000000000000000001444536353100250160ustar00rootroot00000000000000protoc-gen-validate-1.0.2/python/protoc_gen_validate/validator.py000066400000000000000000001421571444536353100252700ustar00rootroot00000000000000import ast import re import struct import sys import time import uuid from functools import lru_cache from ipaddress import IPv4Address, IPv6Address, ip_address from urllib import parse as urlparse from google.protobuf.message import Message from jinja2 import Template from validate_email import validate_email if sys.version_info > (3, 9): unparse = ast.unparse else: import astunparse unparse = astunparse.unparse printer = "" # Well known regex mapping. regex_map = { "UNKNOWN": "", "HTTP_HEADER_NAME": r'^:?[0-9a-zA-Z!#$%&\'*+-.^_|~\x60]+$', "HTTP_HEADER_VALUE": r'^[^\u0000-\u0008\u000A-\u001F\u007F]*$', "HEADER_STRING": r'^[^\u0000\u000A\u000D]*$' } class ValidationFailed(Exception): pass class ValidatingMessage(object): """Wrap a proto message to cache validate functions with the message class name. A validate function is defined per message class in protoc-gen-validate, so we can reuse an already generated function for the same message class. """ def __init__(self, proto_message): self.DESCRIPTOR = proto_message.DESCRIPTOR def __hash__(self): return hash(self.DESCRIPTOR.full_name) def __eq__(self, other): if isinstance(other, ValidatingMessage): return self.DESCRIPTOR.full_name == other.DESCRIPTOR.full_name else: return False def validate(proto_message: Message): return _validate_inner(ValidatingMessage(proto_message))(proto_message) # Cache generated functions with the message descriptor's full_name as the cache key @lru_cache() def _validate_inner(proto_message: Message): func = file_template(proto_message) global printer printer += func + "\n" exec(func) try: return generate_validate except NameError: return locals()['generate_validate'] class ChangeFuncName(ast.NodeTransformer): def visit_FunctionDef(self, node: ast.FunctionDef): node.name = node.name + "_all" # add a suffix to the function name return node class InitErr(ast.NodeTransformer): def visit_FunctionDef(self, node: ast.FunctionDef): node.body.insert(0, ast.parse("err = []").body[0]) return node class ReturnErr(ast.NodeTransformer): def visit_Return(self, node: ast.Return): # Change the return value of the function from None to err if hasattr(node.value, "value") and getattr(node.value, "value") is None: return ast.parse("return err").body[0] return node class ChangeInnerCall(ast.NodeTransformer): def visit_Call(self, node: ast.Call): """Changed the validation function of nested messages from `validate` to `_validate_all`""" if isinstance(node.func, ast.Name) and node.func.id == "validate": node.func.id = "_validate_all" return node class ChangeRaise(ast.NodeTransformer): def visit_Raise(self, node: ast.Raise): """ before: raise ValidationFailed(reason) after: err.append(reason) """ # According to the content in the template, the exception object of all `raise` # statements is `ValidationFailed`. if not isinstance(node.exc, ast.Call): return node return ast.Expr( value=ast.Call( args=node.exc.args, keywords=node.exc.keywords, func=ast.Attribute( attr="append", ctx=ast.Load(), value=ast.Name(id="err", ctx=ast.Load()) ), ) ) class ChangeEmbedded(ast.NodeTransformer): """For embedded messages, there is a special structure in the template as follows: if _has_field(p, \"{{ name.split('.')[-1] }}\"): embedded = validate(p.{{ name }}) if embedded is not None: return embedded We need to convert this code into the following form: if _has_field(p, \"{{ name.split('.')[-1] }}\"): err += _validate_all(p.{{ name }} """ @staticmethod def _is_embedded_node(node: ast.Assign): """Check if substructures match pattern: embedded = validate(p.{{ name }}) """ if not isinstance(node, ast.Assign): return False if len(node.targets) != 1: return False target = node.targets[0] value = node.value if not (isinstance(target, ast.Name) and isinstance(value, ast.Call)): return False if not target.id == "embedded": return False return True def visit_If(self, node: ast.If): self.generic_visit(node) for child in ast.iter_child_nodes(node): if self._is_embedded_node(child): new_node = ast.AugAssign( target=ast.Name(id="err", ctx=ast.Store()), op=ast.Add(), value=child.value ) # err += _validate_all(p.{{ name }} node.body = [new_node] return node return node class ChangeExpr(ast.NodeTransformer): """If there is a pure `_validate_all` function call in the template function, its return value needs to be recorded in err before: _validate_all(item) after: err += _validate_all(item} """ def visit_Expr(self, node: ast.Expr): if not isinstance(node.value, ast.Call): return node call_node = node.value if not isinstance(call_node.func, ast.Name): return node if not call_node.func.id == "_validate_all": return node return ast.AugAssign( target=ast.Name(id="err", ctx=ast.Store()), op=ast.Add(), value=call_node ) # err += _validate_all(item} # Cache generated functions with the message descriptor's full_name as the cache key @lru_cache() def _validate_all_inner(proto_message: Message): func = file_template(ValidatingMessage(proto_message)) comment = func.split("\n")[1] func_ast = ast.parse(rf"{func}") for transformer in [ ChangeFuncName, InitErr, ReturnErr, ChangeInnerCall, ChangeRaise, ChangeEmbedded, ChangeExpr, ]: # order is important! func_ast = ast.fix_missing_locations(transformer().visit(func_ast)) func_ast = ast.fix_missing_locations(func_ast) func = unparse(func_ast) func = comment + " All" + "\n" + func global printer printer += func + "\n" exec(func) try: return generate_validate_all except NameError: return locals()['generate_validate_all'] def _validate_all(proto_message: Message) -> str: return _validate_all_inner(ValidatingMessage(proto_message))(proto_message) # raise ValidationFailed if err def validate_all(proto_message: Message): err = _validate_all(proto_message) if err: raise ValidationFailed('\n'.join(err)) def print_validate(): return "".join([s for s in printer.splitlines(True) if s.strip()]) def has_validate(field): if field.GetOptions() is None: return False for option_descriptor, option_value in field.GetOptions().ListFields(): if option_descriptor.full_name == "validate.rules": return True return False def byte_len(s): try: return len(s.encode('utf-8')) except: # noqa return len(s) def _validateHostName(host): if not host: return False if len(host) > 253: return False if host[-1] == '.': host = host[:-1] for part in host.split("."): if len(part) == 0 or len(part) > 63: return False # Host names cannot begin or end with hyphens if part[0] == "-" or part[-1] == '-': return False for r in part: if (r < 'A' or r > 'Z') and (r < 'a' or r > 'z') and (r < '0' or r > '9') and r != '-': return False return True def _validateEmail(addr): if '<' in addr and '>' in addr: addr = addr.split("<")[1].split(">")[0] if not validate_email(addr): return False if len(addr) > 254: return False parts = addr.split("@") if len(parts[0]) > 64: return False return _validateHostName(parts[1]) def _has_field(message_pb, property_name): # NOTE: As of proto3, HasField() only works for message fields, not for # singular (non-message) fields. First try to use HasField and # if it fails (with a ValueError) we manually consult the fields. try: return message_pb.HasField(property_name) except: # noqa all_fields = set([field.name for field in message_pb.DESCRIPTOR.fields]) return property_name in all_fields def const_template(option_value, name): const_tmpl = """{%- if str(o.string) and o.string.HasField('const') -%} if {{ name }} != \"{{ o.string['const'] }}\": raise ValidationFailed(\"{{ name }} not equal to {{ o.string['const'] }}\") {%- elif str(o.bool) and o.bool['const'] != "" -%} if {{ name }} != {{ o.bool['const'] }}: raise ValidationFailed(\"{{ name }} not equal to {{ o.bool['const'] }}\") {%- elif str(o.bytes) and o.bytes.HasField('const') -%} {% if sys.version_info[0] >= 3 %} if {{ name }} != {{ o.bytes['const'] }}: raise ValidationFailed(\"{{ name }} not equal to {{ o.bytes['const'] }}\") {% else %} if {{ name }} != b\"{{ o.bytes['const'].encode('string_escape') }}\": raise ValidationFailed(\"{{ name }} not equal to {{ o.bytes['const'].encode('string_escape') }}\") {% endif %} {%- endif -%} """ return Template(const_tmpl).render(sys=sys, o=option_value, name=name, str=str) def in_template(value, name): in_tmpl = """ {%- if value['in'] %} if {{ name }} not in {{ value['in'] }}: raise ValidationFailed(\"{{ name }} not in {{ value['in'] }}\") {%- endif -%} {%- if value['not_in'] %} if {{ name }} in {{ value['not_in'] }}: raise ValidationFailed(\"{{ name }} in {{ value['not_in'] }}\") {%- endif -%} """ return Template(in_tmpl).render(value=value, name=name) def string_template(option_value, name): if option_value.string.well_known_regex: known_regex_type = option_value.string.DESCRIPTOR.fields_by_name['well_known_regex'].enum_type regex_value = option_value.string.well_known_regex regex_name = known_regex_type.values_by_number[regex_value].name if regex_name in ["HTTP_HEADER_NAME", "HTTP_HEADER_VALUE"] and not option_value.string.strict: option_value.string.pattern = regex_map["HEADER_STRING"] else: option_value.string.pattern = regex_map[regex_name] str_templ = """ {%- set s = o.string -%} {% set i = 0 %} {%- if s['ignore_empty'] %} if {{ name }}: {% set i = 4 %} {%- endif -%} {% filter indent(i,True) %} {{ const_template(o, name) -}} {{ in_template(o.string, name) -}} {%- if s['len'] %} if len({{ name }}) != {{ s['len'] }}: raise ValidationFailed(\"{{ name }} length does not equal {{ s['len'] }}\") {%- endif -%} {%- if s['min_len'] %} if len({{ name }}) < {{ s['min_len'] }}: raise ValidationFailed(\"{{ name }} length is less than {{ s['min_len'] }}\") {%- endif -%} {%- if s['max_len'] %} if len({{ name }}) > {{ s['max_len'] }}: raise ValidationFailed(\"{{ name }} length is more than {{ s['max_len'] }}\") {%- endif -%} {%- if s['len_bytes'] %} if byte_len({{ name }}) != {{ s['len_bytes'] }}: raise ValidationFailed(\"{{ name }} length does not equal {{ s['len_bytes'] }}\") {%- endif -%} {%- if s['min_bytes'] %} if byte_len({{ name }}) < {{ s['min_bytes'] }}: raise ValidationFailed(\"{{ name }} length is less than {{ s['min_bytes'] }}\") {%- endif -%} {%- if s['max_bytes'] %} if byte_len({{ name }}) > {{ s['max_bytes'] }}: raise ValidationFailed(\"{{ name }} length is greater than {{ s['max_bytes'] }}\") {%- endif -%} {%- if s['pattern'] %} if re.search(r\'{{ s['pattern'] }}\', {{ name }}) is None: raise ValidationFailed(\"{{ name }} pattern does not match {{ s['pattern'] }}\") {%- endif -%} {%- if s['prefix'] %} if not {{ name }}.startswith(\"{{ s['prefix'] }}\"): raise ValidationFailed(\"{{ name }} does not start with prefix {{ s['prefix'] }}\") {%- endif -%} {%- if s['suffix'] %} if not {{ name }}.endswith(\"{{ s['suffix'] }}\"): raise ValidationFailed(\"{{ name }} does not end with suffix {{ s['suffix'] }}\") {%- endif -%} {%- if s['contains'] %} if not \"{{ s['contains'] }}\" in {{ name }}: raise ValidationFailed(\"{{ name }} does not contain {{ s['contains'] }}\") {%- endif -%} {%- if s['not_contains'] %} if \"{{ s['not_contains'] }}\" in {{ name }}: raise ValidationFailed(\"{{ name }} contains {{ s['not_contains'] }}\") {%- endif -%} {%- if s['email'] %} if not _validateEmail({{ name }}): raise ValidationFailed(\"{{ name }} is not a valid email\") {%- endif -%} {%- if s['hostname'] %} if not _validateHostName({{ name }}): raise ValidationFailed(\"{{ name }} is not a valid email\") {%- endif -%} {%- if s['address'] %} try: ip_address({{ name }}) except ValueError: if not _validateHostName({{ name }}): raise ValidationFailed(\"{{ name }} is not a valid address\") {%- endif -%} {%- if s['ip'] %} try: ip_address({{ name }}) except ValueError: raise ValidationFailed(\"{{ name }} is not a valid ip\") {%- endif -%} {%- if s['ipv4'] %} try: IPv4Address({{ name }}) except ValueError: raise ValidationFailed(\"{{ name }} is not a valid ipv4\") {%- endif -%} {%- if s['ipv6'] %} try: IPv6Address({{ name }}) except ValueError: raise ValidationFailed(\"{{ name }} is not a valid ipv6\") {%- endif %} {%- if s['uri'] %} url = urlparse.urlparse({{ name }}) if not all([url.scheme, url.netloc, url.path]): raise ValidationFailed(\"{{ name }} is not a valid uri\") {%- endif %} {%- if s['uri_ref'] %} url = urlparse.urlparse({{ name }}) if not all([url.scheme, url.path]) and url.fragment: raise ValidationFailed(\"{{ name }} is not a valid uri ref\") {%- endif -%} {%- if s['uuid'] %} try: uuid.UUID({{ name }}) except ValueError: raise ValidationFailed(\"{{ name }} is not a valid UUID\") {%- endif -%} {% endfilter %} """ return Template(str_templ).render(o=option_value, name=name, const_template=const_template, in_template=in_template) def required_template(value, name): req_tmpl = """{%- if value['required'] %} if not _has_field(p, \"{{ name.split('.')[-1] }}\"): raise ValidationFailed(\"{{ name }} is required.\") {%- endif -%} """ return Template(req_tmpl).render(value=value, name=name) def message_template(option_value, name, repeated=False): message_tmpl = """{%- if m.message %} {{- required_template(m.message, name) }} {%- endif -%} {%- if m.message and m.message['skip'] %} # Skipping validation for {{ name }} {%- else %} {% if repeated %} if {{ name }}: {% else %} if _has_field(p, \"{{ name.split('.')[-1] }}\"): {% endif %} embedded = validate(p.{{ name }}) if embedded is not None: return embedded {%- endif -%} """ return Template(message_tmpl).render( m=option_value, name=name, required_template=required_template, repeated=repeated) def bool_template(option_value, name): bool_tmpl = """ {{ const_template(o, name) -}} """ return Template(bool_tmpl).render(o=option_value, name=name, const_template=const_template) def num_template(option_value, name, num): num_tmpl = """ {% set i = 0 %} {%- if num.HasField('ignore_empty') %} if {{ name }}: {% set i = 4 %} {%- endif -%} {% filter indent(i,True) %} {%- if num.HasField('const') and str(o.float) == "" -%} if {{ name }} != {{ num['const'] }}: raise ValidationFailed(\"{{ name }} not equal to {{ num['const'] }}\") {%- endif -%} {%- if num.HasField('const') and str(o.float) != "" %} if {{ name }} != struct.unpack(\"f\", struct.pack(\"f\", ({{ num['const'] }})))[0]: raise ValidationFailed(\"{{ name }} not equal to {{ num['const'] }}\") {%- endif -%} {{ in_template(num, name) }} {%- if num.HasField('lt') %} {%- if num.HasField('gt') %} {%- if num['lt'] > num['gt'] %} if {{ name }} <= {{ num['gt'] }} or {{ name }} >= {{ num ['lt'] }}: raise ValidationFailed(\"{{ name }} is not in range {{ num['lt'], num['gt'] }}\") {%- else %} if {{ name }} >= {{ num['lt'] }} and {{ name }} <= {{ num['gt'] }}: raise ValidationFailed(\"{{ name }} is not in range {{ num['gt'], num['lt'] }}\") {%- endif -%} {%- elif num.HasField('gte') %} {%- if num['lt'] > num['gte'] %} if {{ name }} < {{ num['gte'] }} or {{ name }} >= {{ num ['lt'] }}: raise ValidationFailed(\"{{ name }} is not in range {{ num['lt'], num['gte'] }}\") {%- else %} if {{ name }} >= {{ num['lt'] }} and {{ name }} < {{ num['gte'] }}: raise ValidationFailed(\"{{ name }} is not in range {{ num['gte'], num['lt'] }}\") {%- endif -%} {%- else %} if {{ name }} >= {{ num['lt'] }}: raise ValidationFailed(\"{{ name }} is not lesser than {{ num['lt'] }}\") {%- endif -%} {%- elif num.HasField('lte') %} {%- if num.HasField('gt') %} {%- if num['lte'] > num['gt'] %} if {{ name }} <= {{ num['gt'] }} or {{ name }} > {{ num ['lte'] }}: raise ValidationFailed(\"{{ name }} is not in range {{ num['lte'], num['gt'] }}\") {%- else %} if {{ name }} > {{ num['lte'] }} and {{ name }} <= {{ num['gt'] }}: raise ValidationFailed(\"{{ name }} is not in range {{ num['gt'], num['lte'] }}\") {%- endif -%} {%- elif num.HasField('gte') %} {%- if num['lte'] > num['gte'] %} if {{ name }} < {{ num['gte'] }} or {{ name }} > {{ num ['lte'] }}: raise ValidationFailed(\"{{ name }} is not in range {{ num['lte'], num['gte'] }}\") {%- else %} if {{ name }} > {{ num['lte'] }} and {{ name }} < {{ num['gte'] }}: raise ValidationFailed(\"{{ name }} is not in range {{ num['gte'], num['lte'] }}\") {%- endif -%} {%- else %} if {{ name }} > {{ num['lte'] }}: raise ValidationFailed(\"{{ name }} is not lesser than or equal to {{ num['lte'] }}\") {%- endif -%} {%- elif num.HasField('gt') %} if {{ name }} <= {{ num['gt'] }}: raise ValidationFailed(\"{{ name }} is not greater than {{ num['gt'] }}\") {%- elif num.HasField('gte') %} if {{ name }} < {{ num['gte'] }}: raise ValidationFailed(\"{{ name }} is not greater than or equal to {{ num['gte'] }}\") {%- endif -%} {% endfilter %} """ return Template(num_tmpl).render(o=option_value, name=name, num=num, in_template=in_template, str=str) def dur_arr(dur): value = 0 arr = [] for val in dur: value += val.seconds value += (10**-9 * val.nanos) arr.append(value) value = 0 return arr def dur_lit(dur): value = dur.seconds + (10**-9 * dur.nanos) return value def duration_template(option_value, name, repeated=False): dur_tmpl = """ {{- required_template(o.duration, name) }} {% if repeated %} if {{ name }}: {% else %} if _has_field(p, \"{{ name.split('.')[-1] }}\"): {% endif %} dur = {{ name }}.seconds + round((10**-9 * {{ name }}.nanos), 9) {%- set dur = o.duration -%} {%- if dur.HasField('lt') %} lt = {{ dur_lit(dur['lt']) }} {% endif %} {%- if dur.HasField('lte') %} lte = {{ dur_lit(dur['lte']) }} {% endif %} {%- if dur.HasField('gt') %} gt = {{ dur_lit(dur['gt']) }} {% endif %} {%- if dur.HasField('gte') %} gte = {{ dur_lit(dur['gte']) }} {% endif %} {%- if dur.HasField('const') %} if dur != {{ dur_lit(dur['const']) }}: raise ValidationFailed(\"{{ name }} is not equal to {{ dur_lit(dur['const']) }}\") {%- endif -%} {%- if dur['in'] %} if dur not in {{ dur_arr(dur['in']) }}: raise ValidationFailed(\"{{ name }} is not in {{ dur_arr(dur['in']) }}\") {%- endif -%} {%- if dur['not_in'] %} if dur in {{ dur_arr(dur['not_in']) }}: raise ValidationFailed(\"{{ name }} is not in {{ dur_arr(dur['not_in']) }}\") {%- endif -%} {%- if dur.HasField('lt') %} {%- if dur.HasField('gt') %} {%- if dur_lit(dur['lt']) > dur_lit(dur['gt']) %} if dur <= gt or dur >= lt: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(dur['lt']), dur_lit(dur['gt']) }}\") {%- else -%} if dur >= lt and dur <= gt: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(dur['gt']), dur_lit(dur['lt']) }}\") {%- endif -%} {%- elif dur.HasField('gte') %} {%- if dur_lit(dur['lt']) > dur_lit(dur['gte']) %} if dur < gte or dur >= lt: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(dur['lt']), dur_lit(dur['gte']) }}\") {%- else -%} if dur >= lt and dur < gte: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(dur['gte']), dur_lit(dur['lt']) }}\") {%- endif -%} {%- else -%} if dur >= lt: raise ValidationFailed(\"{{ name }} is not lesser than {{ dur_lit(dur['lt']) }}\") {%- endif -%} {%- elif dur.HasField('lte') %} {%- if dur.HasField('gt') %} {%- if dur_lit(dur['lte']) > dur_lit(dur['gt']) %} if dur <= gt or dur > lte: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(dur['lte']), dur_lit(dur['gt']) }}\") {%- else -%} if dur > lte and dur <= gt: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(dur['gt']), dur_lit(dur['lte']) }}\") {%- endif -%} {%- elif dur.HasField('gte') %} {%- if dur_lit(dur['lte']) > dur_lit(dur['gte']) %} if dur < gte or dur > lte: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(dur['lte']), dur_lit(dur['gte']) }}\") {%- else -%} if dur > lte and dur < gte: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(dur['gte']), dur_lit(dur['lte']) }}\") {%- endif -%} {%- else -%} if dur > lte: raise ValidationFailed(\"{{ name }} is not lesser than or equal to {{ dur_lit(dur['lte']) }}\") {%- endif -%} {%- elif dur.HasField('gt') %} if dur <= gt: raise ValidationFailed(\"{{ name }} is not greater than {{ dur_lit(dur['gt']) }}\") {%- elif dur.HasField('gte') %} if dur < gte: raise ValidationFailed(\"{{ name }} is not greater than or equal to {{ dur_lit(dur['gte']) }}\") {%- endif -%} """ return Template(dur_tmpl).render(o=option_value, name=name, required_template=required_template, dur_lit=dur_lit, dur_arr=dur_arr, repeated=repeated) def timestamp_template(option_value, name, repeated=False): timestamp_tmpl = """ {{- required_template(o.timestamp, name) }} {% if repeated %} if {{ name }}: {% else %} if _has_field(p, \"{{ name.split('.')[-1] }}\"): {% endif %} ts = {{ name }}.seconds + round((10**-9 * {{ name }}.nanos), 9) {%- set ts = o.timestamp -%} {%- if ts.HasField('lt') %} lt = {{ dur_lit(ts['lt']) }} {% endif -%} {%- if ts.HasField('lte') %} lte = {{ dur_lit(ts['lte']) }} {% endif -%} {%- if ts.HasField('gt') %} gt = {{ dur_lit(ts['gt']) }} {% endif -%} {%- if ts.HasField('gte') %} gte = {{ dur_lit(ts['gte']) }} {% endif -%} {%- if ts.HasField('const') %} if ts != {{ dur_lit(ts['const']) }}: raise ValidationFailed(\"{{ name }} is not equal to {{ dur_lit(ts['const']) }}\") {% endif %} {%- if ts['in'] %} if ts not in {{ dur_arr(ts['in']) }}: raise ValidationFailed(\"{{ name }} is not in {{ dur_arr(ts['in']) }}\") {%- endif %} {%- if ts['not_in'] %} if ts in {{ dur_arr(ts['not_in']) }}: raise ValidationFailed(\"{{ name }} is not in {{ dur_arr(ts['not_in']) }}\") {%- endif %} {%- if ts.HasField('lt') %} {%- if ts.HasField('gt') %} {%- if dur_lit(ts['lt']) > dur_lit(ts['gt']) %} if ts <= gt or ts >= lt: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(ts['lt']), dur_lit(ts['gt']) }}\") {%- else -%} if ts >= lt and ts <= gt: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(ts['gt']), dur_lit(ts['lt']) }}\") {%- endif -%} {%- elif ts.HasField('gte') %} {%- if dur_lit(ts['lt']) > dur_lit(ts['gte']) %} if ts < gte or ts >= lt: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(ts['lt']), dur_lit(ts['gte']) }}\") {%- else -%} if ts >= lt and ts < gte: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(ts['gte']), dur_lit(ts['lt']) }}\") {%- endif -%} {%- else -%} if ts >= lt: raise ValidationFailed(\"{{ name }} is not lesser than {{ dur_lit(ts['lt']) }}\") {%- endif -%} {%- elif ts.HasField('lte') %} {%- if ts.HasField('gt') %} {%- if dur_lit(ts['lte']) > dur_lit(ts['gt']) %} if ts <= gt or ts > lte: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(ts['lte']), dur_lit(ts['gt']) }}\") {%- else -%} if ts > lte and ts <= gt: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(ts['gt']), dur_lit(ts['lte']) }}\") {%- endif -%} {%- elif ts.HasField('gte') %} {%- if dur_lit(ts['lte']) > dur_lit(ts['gte']) %} if ts < gte or ts > lte: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(ts['lte']), dur_lit(ts['gte']) }}\") {%- else -%} if ts > lte and ts < gte: raise ValidationFailed(\"{{ name }} is not in range {{ dur_lit(ts['gte']), dur_lit(ts['lte']) }}\") {%- endif -%} {%- else -%} if ts > lte: raise ValidationFailed(\"{{ name }} is not lesser than or equal to {{ dur_lit(ts['lte']) }}\") {%- endif -%} {%- elif ts.HasField('gt') %} if ts <= gt: raise ValidationFailed(\"{{ name }} is not greater than {{ dur_lit(ts['gt']) }}\") {%- elif ts.HasField('gte') %} if ts < gte: raise ValidationFailed(\"{{ name }} is not greater than or equal to {{ dur_lit(ts['gte']) }}\") {%- elif ts.HasField('lt_now') %} now = time.time() {%- if ts.HasField('within') %} within = {{ dur_lit(ts['within']) }} if ts >= now or ts <= now - within: raise ValidationFailed(\"{{ name }} is not within range {{ dur_lit(ts['within']) }}\") {%- else %} if ts >= now: raise ValidationFailed(\"{{ name }} is not lesser than now\") {%- endif -%} {%- elif ts.HasField('gt_now') %} now = time.time() {%- if ts.HasField('within') %} within = {{ dur_lit(ts['within']) }} if ts <= now or ts >= now + within: raise ValidationFailed(\"{{ name }} is not within range {{ dur_lit(ts['within']) }}\") {%- else %} if ts <= now: raise ValidationFailed(\"{{ name }} is not greater than now\") {%- endif -%} {%- elif ts.HasField('within') %} now = time.time() within = {{ dur_lit(ts['within']) }} if ts >= now + within or ts <= now - within: raise ValidationFailed(\"{{ name }} is not within range {{ dur_lit(ts['within']) }}\") {%- endif -%} """ return Template(timestamp_tmpl).render(o=option_value, name=name, required_template=required_template, dur_lit=dur_lit, dur_arr=dur_arr, repeated=repeated) def wrapper_template(option_value, name, repeated=False): wrapper_tmpl = """ {% if repeated %} if {{ name }}: {% else %} if p.HasField(\"{{ name[2:] }}\"): {% endif %} {%- if str(option_value.float) %} {{- num_template(option_value, name + ".value", option_value.float)|indent(4,True) -}} {% endif -%} {%- if str(option_value.double) %} {{- num_template(option_value, name + ".value", option_value.double)|indent(4,True) -}} {% endif -%} {%- if str(option_value.int32) %} {{- num_template(option_value, name + ".value", option_value.int32)|indent(4,True) -}} {% endif -%} {%- if str(option_value.int64) %} {{- num_template(option_value, name + ".value", option_value.int64)|indent(4,True) -}} {% endif -%} {%- if str(option_value.uint32) %} {{- num_template(option_value, name + ".value", option_value.uint32)|indent(4,True) -}} {% endif -%} {%- if str(option_value.uint64) %} {{- num_template(option_value, name + ".value", option_value.uint64)|indent(4,True) -}} {% endif -%} {%- if str(option_value.bool) %} {{- bool_template(option_value, name + ".value")|indent(4,True) -}} {% endif -%} {%- if str(option_value.string) %} {{- string_template(option_value, name + ".value")|indent(4,True) -}} {% endif -%} {%- if str(option_value.bytes) %} {{- bytes_template(option_value, name + ".value")|indent(4,True) -}} {% endif -%} {%- if str(option_value.message) and option_value.message['required'] %} else: raise ValidationFailed(\"{{ name }} is required.\") {%- endif %} """ return Template(wrapper_tmpl).render(option_value=option_value, name=name, str=str, num_template=num_template, bool_template=bool_template, string_template=string_template, bytes_template=bytes_template, repeated=repeated) def enum_values(field): return [x.number for x in field.enum_type.values] def enum_name(field, number): for x in field.enum_type.values: if x.number == number: return x.name return "" def enum_names(field, numbers): m = {x.number: x.name for x in field.enum_type.values} return "[" + "".join([m[n] for n in numbers]) + "]" def enum_const_template(value, name, field): const_tmpl = """{%- if str(value) and value['const'] -%} if {{ name }} != {{ value['const'] }}: raise ValidationFailed(\"{{ name }} not equal to {{ enum_name(field, value['const']) }}\") {%- endif -%} """ return Template(const_tmpl).render(value=value, name=name, field=field, enum_name=enum_name, str=str) def enum_in_template(value, name, field): in_tmpl = """ {%- if value['in'] %} if {{ name }} not in {{ value['in'] }}: raise ValidationFailed(\"{{ name }} not in {{ enum_names(field, value['in']) }}\") {%- endif -%} {%- if value['not_in'] %} if {{ name }} in {{ value['not_in'] }}: raise ValidationFailed(\"{{ name }} in {{ enum_names(field, value['not_in']) }}\") {%- endif -%} """ return Template(in_tmpl).render(value=value, name=name, field=field, enum_names=enum_names) def enum_template(option_value, name, field): enum_tmpl = """ {{ enum_const_template(option_value.enum, name, field) -}} {{ enum_in_template(option_value.enum, name, field) -}} {% if option_value.enum['defined_only'] %} if {{ name }} not in {{ enum_values(field) }}: raise ValidationFailed(\"{{ name }} is not defined\") {% endif %} """ return Template(enum_tmpl).render(option_value=option_value, name=name, enum_const_template=enum_const_template, enum_in_template=enum_in_template, field=field, enum_values=enum_values) def any_template(option_value, name, repeated=False): any_tmpl = """ {{- required_template(o, name) }} {%- if o['in'] %} {% if repeated %} if {{ name }}: {% else %} if _has_field(p, \"{{ name.split('.')[-1] }}\"): {% endif %} if {{ name }}.type_url not in {{ o['in'] }}: raise ValidationFailed(\"{{ name }} not in {{ o['in'] }}\") {%- endif %} {%- if o['not_in'] %} {% if repeated %} if {{ name }}: {% else %} if _has_field(p, \"{{ name.split('.')[-1] }}\"): {% endif %} if {{ name }}.type_url in {{ o['not_in'] }}: raise ValidationFailed(\"{{ name }} in {{ o['not_in'] }}\") {%- endif %} """ return Template(any_tmpl).render( o=option_value.any, name=name, required_template=required_template, repeated=repeated) def bytes_template(option_value, name): bytes_tmpl = """ {% set i = 0 %} {%- if b['ignore_empty'] %} if {{ name }}: {% set i = 4 %} {%- endif -%} {% filter indent(i,True) %} {{ const_template(o, name) -}} {{ in_template(o.bytes, name) -}} {%- if b['len'] %} if len({{ name }}) != {{ b['len'] }}: raise ValidationFailed(\"{{ name }} length does not equal {{ b['len'] }}\") {%- endif -%} {%- if b['min_len'] %} if len({{ name }}) < {{ b['min_len'] }}: raise ValidationFailed(\"{{ name }} length is less than {{ b['min_len'] }}\") {%- endif -%} {%- if b['max_len'] %} if len({{ name }}) > {{ b['max_len'] }}: raise ValidationFailed(\"{{ name }} length is more than {{ b['max_len'] }}\") {%- endif -%} {%- if b['ip'] %} try: ip_address({{ name }}) except ValueError: raise ValidationFailed(\"{{ name }} is not a valid ip\") {%- endif -%} {%- if b['ipv4'] %} try: IPv4Address({{ name }}) except ValueError: raise ValidationFailed(\"{{ name }} is not a valid ipv4\") {%- endif -%} {%- if b['ipv6'] %} try: IPv6Address({{ name }}) except ValueError: raise ValidationFailed(\"{{ name }} is not a valid ipv6\") {%- endif -%} {% if b['pattern'] %} {% if sys.version_info[0] >= 3%} if re.search({{ b['pattern'].encode('unicode-escape') }}, {{ name }}) is None: raise ValidationFailed(\"{{ name }} pattern does not match b['pattern'].encode('unicode-escape')\") {% else %} if re.search(b\"{{ b['pattern'].encode('unicode-escape') }}\", {{ name }}) is None: raise ValidationFailed(\"{{ name }} pattern does not match \") {% endif %} {% endif %} {% if b['contains'] %} {% if sys.version_info[0] >= 3 %} if not {{ b['contains'] }} in {{ name }}: raise ValidationFailed(\"{{ name }} does not contain {{ b['contains'] }}\") {% else %} if not b\"{{ b['contains'].encode('string_escape') }}\" in {{ name }}: raise ValidationFailed(\"{{ name }} does not contain \") {% endif %} {% endif %} {% if b['prefix'] %} {% if sys.version_info[0] >= 3 %} if not {{ name }}.startswith({{ b['prefix'] }}): raise ValidationFailed(\"{{ name }} does not start with prefix {{ b['prefix'] }}\") {% else %} if not {{name}}.startswith(b\"{{ b['prefix'].encode('string_escape') }}\"): raise ValidationFailed(\"{{ name }} does not start with prefix {{ b['prefix'].encode('string_escape') }}\") {% endif %} {% endif %} {% if b['suffix'] %} {% if sys.version_info[0] >= 3 %} if not {{ name }}.endswith({{ b['suffix'] }}): raise ValidationFailed(\"{{ name }} does not end with suffix {{ b['suffix'] }}\") {% else %} if not {{name}}.endswith(b\"{{ b['suffix'].encode('string_escape') }}\"): raise ValidationFailed(\"{{ name }} does not end with suffix {{ b['suffix'] }}\") {% endif %} {% endif %} {% endfilter %} """ return Template(bytes_tmpl).render(sys=sys, o=option_value, name=name, const_template=const_template, in_template=in_template, b=option_value.bytes) def switcher_template(accessor, name, field, map=False): switcher_tmpl = """ {%- if str(accessor.float) %} {{- num_template(accessor, name, accessor.float)|indent(4,True) -}} {%- elif str(accessor.double) %} {{- num_template(accessor, name, accessor.double)|indent(4,True) -}} {%- elif str(accessor.int32) %} {{- num_template(accessor, name, accessor.int32)|indent(4,True) -}} {%- elif str(accessor.int64) %} {{- num_template(accessor, name, accessor.int64)|indent(4,True) -}} {%- elif str(accessor.uint32) %} {{- num_template(accessor, name, accessor.uint32)|indent(4,True) -}} {%- elif str(accessor.uint64) %} {{- num_template(accessor, name, accessor.uint64)|indent(4,True) -}} {%- elif str(accessor.sint32) %} {{- num_template(accessor, name, accessor.sint32)|indent(4,True) -}} {%- elif str(accessor.sint64) %} {{- num_template(accessor, name, accessor.sint64)|indent(4,True) -}} {%- elif str(accessor.fixed32) %} {{- num_template(accessor, name, accessor.fixed32)|indent(4,True) -}} {%- elif str(accessor.fixed64) %} {{- num_template(accessor, name, accessor.fixed64)|indent(4,True) -}} {%- elif str(accessor.sfixed32) %} {{- num_template(accessor, name, accessor.sfixed32)|indent(4,True) -}} {%- elif str(accessor.sfixed64) %} {{- num_template(accessor, name, accessor.sfixed64)|indent(4,True) -}} {%- elif str(accessor.bool) %} {{- bool_template(accessor, name)|indent(4,True) -}} {%- elif str(accessor.string) %} {{- string_template(accessor, name)|indent(4,True) -}} {%- elif str(accessor.enum) and map %} {{- enum_template(accessor, name, field.message_type.fields[1])|indent(4,True) -}} {%- elif str(accessor.enum) and not map %} {{- enum_template(accessor, name, field)|indent(4,True) -}} {%- elif str(accessor.duration) %} {{- duration_template(accessor, name, True)|indent(4,True) -}} {%- elif str(accessor.timestamp) %} {{- timestamp_template(accessor, name, True)|indent(4,True) -}} {%- elif str(accessor.message) %} {{- message_template(accessor, name, True)|indent(4,True) -}} {%- elif str(accessor.any) %} {{- any_template(accessor, name, True)|indent(4,True) -}} {%- elif str(accessor.message) %} {{- message_template(accessor, name, True)|indent(4,True) -}} {%- endif %} """ return Template(switcher_tmpl).render(accessor=accessor, name=name, str=str, num_template=num_template, bool_template=bool_template, string_template=string_template, enum_template=enum_template, duration_template=duration_template, timestamp_template=timestamp_template, any_template=any_template, message_template=message_template, field=field, map=map) def repeated_template(option_value, name, field): rep_tmpl = """ {% set i = 0 %} {%- if o and o.repeated['ignore_empty'] %} if {{ name }}: {% set i = 4 %} {%- endif -%} {% filter indent(i,True) %} {%- if o and o.repeated['min_items'] %} if len({{ name }}) < {{ o.repeated['min_items'] }}: raise ValidationFailed(\"{{ name }} needs to contain at least {{ o.repeated['min_items'] }} items\") {%- endif %} {%- if o and o.repeated['max_items'] %} if len({{ name }}) > {{ o.repeated['max_items'] }}: raise ValidationFailed(\"{{ name }} needs to contain at most {{ o.repeated['max_items'] }} items\") {%- endif %} {%- if o and o.repeated['unique'] %} seen = set() for item in {{ name }}: if item in seen: raise ValidationFailed(\"{{ name }} must contain unique items. %s has been repeated.\" %item) else: seen.add(item) {%- endif %} {%- if message_type %} for item in {{ name }}: {%- if o and o.repeated and o.repeated.items.message.skip %} pass {% else %} validate(item) {% endif %} {%- endif %} {%- if o and str(o.repeated['items']) %} for item in {{ name }}: {%- set accessor = o.repeated['items'] -%} {{ switcher_template(accessor, 'item', field) }} pass {%- endif %} {% endfilter %} """ return Template(rep_tmpl).render(o=option_value, name=name, message_type=field.message_type, str=str, field=field, switcher_template=switcher_template) def is_map(field): return field.label == 3 and field.message_type and len(field.message_type.fields) == 2 and \ field.message_type.fields[0].name == "key" and field.message_type.fields[1].name == "value" def map_template(option_value, name, field): map_tmpl = """ {% set i = 0 %} {%- if o and o.map['ignore_empty'] %} if {{ name }}: {% set i = 4 %} {%- endif -%} {% filter indent(i,True) %} {%- if o and o.map['min_pairs'] %} if len({{ name }}) < {{ o.map['min_pairs'] }}: raise ValidationFailed(\"{{ name }} needs to contain at least {{ o.map['min_pairs'] }} items\") {%- endif %} {%- if o and o.map['max_pairs'] %} if len({{ name }}) > {{ o.map['max_pairs'] }}: raise ValidationFailed(\"{{ name }} can contain at most {{ o.map['max_pairs'] }} items\") {%- endif %} {%- if o and (str(o.map['keys']) or str(o.map['values']))%} for key in {{ name }}: {%- set keys = o.map['keys'] -%} {%- set values = o.map['values'] -%} {%- if str(keys.double) %} {{- num_template(keys, 'key', keys.double)|indent(4,True) -}} {%- elif str(keys.int32) %} {{- num_template(keys, 'key', keys.int32)|indent(4,True) -}} {%- elif str(keys.int64) %} {{- num_template(keys, 'key', keys.int64)|indent(4,True) -}} {%- elif str(keys.uint32) %} {{- num_template(keys, 'key', keys.uint32)|indent(4,True) -}} {%- elif str(keys.uint64) %} {{- num_template(keys, 'key', keys.uint64)|indent(4,True) -}} {%- elif str(keys.sint32) %} {{- num_template(keys, 'key', keys.sint32)|indent(4,True) -}} {%- elif str(keys.sint64) %} {{- num_template(keys, 'key', keys.sint64)|indent(4,True) -}} {%- elif str(keys.fixed32) %} {{- num_template(keys, 'key', keys.fixed32)|indent(4,True) -}} {%- elif str(keys.fixed64) %} {{- num_template(keys, 'key', keys.fixed64)|indent(4,True) -}} {%- elif str(keys.sfixed32) %} {{- num_template(keys, 'key', keys.sfixed32)|indent(4,True) -}} {%- elif str(keys.sfixed64) %} {{- num_template(keys, 'key', keys.sfixed64)|indent(4,True) -}} {%- elif str(keys.bool) %} {{- bool_template(keys, 'key')|indent(4,True) -}} {%- elif str(keys.string) %} {{- string_template(keys, 'key')|indent(4,True) -}} {%- endif %} {%- set values = o.map['values'] -%} {{ switcher_template(values, name +'[key]', field, True) }} pass {%- elif field.message_type.fields[1].message_type %} for key in {{ name }}: validate({{ name }}[key]) {%- endif %} {% endfilter %} """ return Template(map_tmpl).render(o=option_value, name=name, message_type=field.message_type, str=str, field=field, switcher_template=switcher_template, num_template=num_template, string_template=string_template, bool_template=bool_template) def rule_type(field): name = "p." + field.name if has_validate(field) and field.message_type is None: for option_descriptor, option_value in field.GetOptions().ListFields(): if option_descriptor.full_name == "validate.rules": if str(option_value.string): return string_template(option_value, name) elif str(option_value.message): return message_template(option_value, field.name) elif str(option_value.bool): return bool_template(option_value, name) elif str(option_value.float): return num_template(option_value, name, option_value.float) elif str(option_value.double): return num_template(option_value, name, option_value.double) elif str(option_value.int32): return num_template(option_value, name, option_value.int32) elif str(option_value.int64): return num_template(option_value, name, option_value.int64) elif str(option_value.uint32): return num_template(option_value, name, option_value.uint32) elif str(option_value.uint64): return num_template(option_value, name, option_value.uint64) elif str(option_value.sint32): return num_template(option_value, name, option_value.sint32) elif str(option_value.sint64): return num_template(option_value, name, option_value.sint64) elif str(option_value.fixed32): return num_template(option_value, name, option_value.fixed32) elif str(option_value.fixed64): return num_template(option_value, name, option_value.fixed64) elif str(option_value.sfixed32): return num_template(option_value, name, option_value.sfixed32) elif str(option_value.sfixed64): return num_template(option_value, name, option_value.sfixed64) elif str(option_value.enum): return enum_template(option_value, name, field) elif str(option_value.bytes): return bytes_template(option_value, name) elif str(option_value.repeated): return repeated_template(option_value, name, field) elif str(option_value.map): return map_template(option_value, name, field) elif str(option_value.required): return required_template(option_value, name) if field.message_type: for option_descriptor, option_value in field.GetOptions().ListFields(): if option_descriptor.full_name == "validate.rules": if str(option_value.duration): return duration_template(option_value, name) elif str(option_value.timestamp): return timestamp_template(option_value, name) elif str(option_value.float) or str(option_value.int32) or str(option_value.int64) or \ str(option_value.double) or str(option_value.uint32) or str(option_value.uint64) or \ str(option_value.bool) or str(option_value.string) or str(option_value.bytes): return wrapper_template(option_value, name) elif str(option_value.message) != "": return message_template(option_value, field.name) elif str(option_value.any): return any_template(option_value, name) elif str(option_value.repeated): return repeated_template(option_value, name, field) elif str(option_value.map): return map_template(option_value, name, field) elif str(option_value.required): return required_template(option_value, name) if field.message_type.full_name.startswith("google.protobuf"): return "" elif is_map(field): return map_template(None, name, field) elif field.label == 3: return repeated_template(None, name, field) else: return message_template(None, field.name) return "" def file_template(proto_message): file_tmp = """ # Validates {{ p.DESCRIPTOR.name }} def generate_validate(p): {%- for option_descriptor, option_value in p.DESCRIPTOR.GetOptions().ListFields() %} {%- if option_descriptor.full_name == "validate.disabled" and option_value %} return None {%- elif option_descriptor.full_name == "validate.ignored" and option_value %} return None {%- endif -%} {%- endfor -%} {%- for oneof in p.DESCRIPTOR.oneofs %} present = False {%- for field in oneof.fields %} if _has_field(p, \"{{ field.name }}\"): present = True {{ rule_type(field)|indent(4,True) }} {%- endfor %} {% for option in oneof.GetOptions().ListFields() %} {% if option[0].name == 'required' and option[1] %} if not present: raise ValidationFailed(\"Oneof {{ oneof.name }} is required\") {% endif %} {% endfor %} {%- endfor %} {%- for field in p.DESCRIPTOR.fields -%} {%- if not field.containing_oneof %} {{ rule_type(field) -}} {%- endif %} {%- endfor %} return None""" return Template(file_tmp).render(rule_type=rule_type, p=proto_message) protoc-gen-validate-1.0.2/python/pyproject.toml000066400000000000000000000002471444536353100216260ustar00rootroot00000000000000[build-system] requires = [ "setuptools>=45", "setuptools_scm[toml]>=6.2", "wheel>=0.38.1" ] build-backend = "setuptools.build_meta" [tool.setuptools_scm] protoc-gen-validate-1.0.2/python/requirements.in000066400000000000000000000003521444536353100217620ustar00rootroot00000000000000# These must be the same as the requirements listed in # install_requires section of setup.cfg. A test checks for this. # See requirements_test.py for more context. validate-email>=1.3 Jinja2>=2.11.1 protobuf>=3.6.1 astunparse>=1.6.3 protoc-gen-validate-1.0.2/python/setup.cfg000066400000000000000000000015131444536353100205300ustar00rootroot00000000000000[metadata] name = protoc-gen-validate version = env: SETUPTOOLS_SCM_PRETEND_VERSION author = Buf author_email = dev@buf.build description = PGV for python via just-in-time code generation long_description = file: README.md long_description_content_type = text/markdown url = https://github.com/bufbuild/protoc-gen-validate license_files = LICENSE classifiers = Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 [options] packages = find: install_requires = validate-email>=1.3 Jinja2>=2.11.1 protobuf>=3.6.1 astunparse>=1.6.3 python_requires = >=3.6 [options.data_files] data = validate.proto [flake8] max-line-length = 120 ignore = F401 # unused imports protoc-gen-validate-1.0.2/requirements.txt000066400000000000000000000004641444536353100206560ustar00rootroot00000000000000# Requirements for linting, building, and uploading the PGV python package to PyPI. # The package's own requirements are in python/setup.cfg (and also in python/requirements.in). flake8==3.8.4 isort==5.7.0 build==0.3.0 twine==3.3.0 wheel==0.38.1 setuptools==65.5.1 protobuf==3.20.2 setuptools_scm[toml]>=6.2 protoc-gen-validate-1.0.2/rule_comparison.md000066400000000000000000000101671444536353100211160ustar00rootroot00000000000000# Constraint Rule Comparison ## Global | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | disabled |✅|✅|✅|✅|✅| ## Numerics | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | const |✅|✅|✅|✅|✅| | lt/lte/gt/gte |✅|✅|✅|✅|✅| | in/not_in |✅|✅|✅|✅|✅| ## Bools | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | const |✅|✅|✅|✅|✅| ## Strings | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | const |✅|✅|✅|✅|✅| | len/min\_len/max_len |✅|✅|✅|✅|✅| | min\_bytes/max\_bytes |✅|✅|✅|✅|✅| | pattern |✅|✅|✅|✅|✅| | prefix/suffix/contains |✅|✅|✅|✅|✅| | contains/not_contains |✅|✅|✅|✅|✅| | in/not_in |✅|✅|✅|✅|✅| | email |✅|✅|❌|✅|✅| | hostname |✅|✅|✅|✅|✅| | address |✅|✅|✅|✅|✅| | ip |✅|✅|✅|✅|✅| | ipv4 |✅|✅|✅|✅|✅| | ipv6 |✅|✅|✅|✅|✅| | uri |✅|✅|❌|✅|✅| | uri_ref |✅|✅|❌|✅|✅| | uuid |✅|✅|✅|✅|✅| | well_known_regex |✅|✅|✅|✅|✅| ## Bytes | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | const |✅|✅|✅|✅|✅| | len/min\_len/max_len |✅|✅|✅|✅|✅| | pattern |✅|✅|✅|✅|✅| | prefix/suffix/contains |✅|✅|✅|✅|✅| | in/not_in |✅|✅|✅|✅|✅| | ip |✅|✅|❌|✅|✅| | ipv4 |✅|✅|❌|✅|✅| | ipv6 |✅|✅|❌|✅|✅| ## Enums | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | const |✅|✅|✅|✅|✅| | defined_only |✅|✅|✅|✅|✅| | in/not_in |✅|✅|✅|✅|✅| ## Messages | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | skip |✅|✅|✅|✅|✅| | required |✅|✅|✅|✅|✅| ## Repeated | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | min\_items/max_items |✅|✅|✅|✅|✅| | unique |✅|✅|✅|✅|✅| | items |✅|✅|❌|✅|✅| ## Maps | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | min\_pairs/max_pairs |✅|✅|✅|✅|✅| | no_sparse |✅|✅|❌|❌|❌| | keys |✅|✅|❌|✅|✅| | values |✅|✅|❌|✅|✅| ## OneOf | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | required |✅|✅|✅|✅|✅| ## WKT Scalar Value Wrappers | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | wrapper validation |✅|✅|✅|✅|✅| ## WKT Any | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | required |✅|✅|✅|✅|✅| | in/not_in |✅|✅|✅|✅|✅| ## WKT Duration | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | required |✅|✅|✅|✅|✅| | const |✅|✅|✅|✅|✅| | lt/lte/gt/gte |✅|✅|✅|✅|✅| | in/not_in |✅|✅|✅|✅|✅| ## WKT Timestamp | Constraint Rule | Go | GoGo | C++ | Java | Python | | ---| :---: | :---: | :---: | :---: | :---: | | required |✅|✅|❌|✅|✅| | const |✅|✅|❌|✅|✅| | lt/lte/gt/gte |✅|✅|❌|✅|✅| | lt_now/gt_now |✅|✅|❌|✅|✅| | within |✅|✅|❌|✅|✅| protoc-gen-validate-1.0.2/templates/000077500000000000000000000000001444536353100173645ustar00rootroot00000000000000protoc-gen-validate-1.0.2/templates/BUILD.bazel000066400000000000000000000014201444536353100212370ustar00rootroot00000000000000load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "templates", srcs = ["pkg.go"], importpath = "github.com/envoyproxy/protoc-gen-validate/templates", visibility = ["//visibility:public"], deps = [ "//templates/cc", "//templates/ccnop", "//templates/go", "//templates/java", "//templates/shared", "@com_github_lyft_protoc_gen_star_v2//:protoc-gen-star", "@com_github_lyft_protoc_gen_star_v2//lang/go", ], ) alias( name = "go_default_library", actual = ":templates", deprecation = "Use :templates instead of :go_default_library. Details about the new naming convention: https://github.com/bazelbuild/bazel-gazelle/pull/863", visibility = ["//visibility:public"], ) protoc-gen-validate-1.0.2/templates/cc/000077500000000000000000000000001444536353100177515ustar00rootroot00000000000000protoc-gen-validate-1.0.2/templates/cc/BUILD.bazel000066400000000000000000000023001444536353100216220ustar00rootroot00000000000000load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "cc", srcs = [ "any.go", "bytes.go", "const.go", "duration.go", "enum.go", "file.go", "in.go", "known.go", "ltgt.go", "map.go", "message.go", "msg.go", "none.go", "num.go", "register.go", "repeated.go", "string.go", "timestamp.go", "wrapper.go", ], importpath = "github.com/envoyproxy/protoc-gen-validate/templates/cc", visibility = ["//visibility:public"], deps = [ "//templates/shared", "@com_github_iancoleman_strcase//:strcase", "@com_github_lyft_protoc_gen_star_v2//:protoc-gen-star", "@com_github_lyft_protoc_gen_star_v2//lang/go", "@org_golang_google_protobuf//types/known/durationpb", "@org_golang_google_protobuf//types/known/timestamppb", ], ) alias( name = "go_default_library", actual = ":cc", deprecation = "Use :cc instead of :go_default_library. Details about the new naming convention: https://github.com/bazelbuild/bazel-gazelle/pull/863", visibility = ["//visibility:public"], ) protoc-gen-validate-1.0.2/templates/cc/any.go000066400000000000000000000010401444536353100210620ustar00rootroot00000000000000package cc const anyTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{ template "required" . }} {{ if $r.In }} {{ $table := lookup $f "InLookup" }} if ({{ hasAccessor . }} && {{ $table }}.find({{ accessor . }}.type_url()) == {{ $table }}.end()) { {{ err . "type URL must be in list " $r.In }} } {{ else if $r.NotIn }} {{ $table := lookup $f "NotInLookup" }} if ({{ hasAccessor . }} && {{ $table }}.find({{ accessor . }}.type_url()) != {{ $table }}.end()) { {{ err . "type URL must not be in list " $r.NotIn }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/cc/bytes.go000066400000000000000000000055671444536353100214430ustar00rootroot00000000000000package cc const bytesTpl = ` {{ $f := .Field }}{{ $r := .Rules }} {{ if $r.GetIgnoreEmpty }} if ({{ accessor . }}.size() > 0) { {{ end }} {{ template "const" . }} {{ template "in" . }} {{ if or $r.Len (and $r.MinLen $r.MaxLen (eq $r.GetMinLen $r.GetMaxLen)) }} { const auto length = {{ accessor . }}.size(); {{ if $r.Len }} if (length != {{ $r.GetLen }}) { {{ err . "value length must be " $r.GetLen " bytes" }} } {{ else }} if (length != {{ $r.GetMinLen }}) { {{ err . "value length must be " $r.GetMinLen " bytes" }} } {{ end }} } {{ else if $r.MinLen }} { const auto length = {{ accessor . }}.size(); {{ if $r.MaxLen }} if (length < {{ $r.GetMinLen }} || length > {{ $r.GetMaxLen }}) { {{ err . "value length must be between " $r.GetMinLen " and " $r.GetMaxLen " bytes, inclusive" }} } {{ else }} if (length < {{ $r.GetMinLen }}) { {{ err . "value length must be at least " $r.GetMinLen " bytes" }} } {{ end }} } {{ else if $r.MaxLen }} if ({{ accessor . }}.size() > {{ $r.GetMaxLen }}) { {{ err . "value length must be at most " $r.GetMaxLen " bytes" }} } {{ end }} {{ if $r.Prefix }} { const std::string prefix = {{ lit $r.GetPrefix }}; if (!pgv::IsPrefix(prefix, {{ accessor . }})) { {{ err . "value does not have prefix " (lit $r.GetPrefix) }} } } {{ end }} {{ if $r.Suffix }} { const std::string suffix = {{ lit $r.GetSuffix }}; if (!pgv::IsSuffix(suffix, {{ accessor .}})) { {{ err . "value does not have suffix " (lit $r.GetSuffix) }} } } {{ end }} {{ if $r.Contains }} { if (!pgv::Contains({{ accessor . }}, {{ lit $r.GetContains }})) { {{ err . "value does not contain substring " (lit $r.GetContains) }} } } {{ end }} {{ if $r.Pattern }} { if (!RE2::FullMatch(re2::StringPiece({{ accessor . }}.c_str(), {{ accessor . }}.size()), {{ lookup $f "Pattern" }})) { {{ err . "value does not match regex pattern " (lit $r.GetPattern) }} } } {{ end }} {{ if $r.GetIp }} {{ unimplemented "C++ ip address validation is not implemented" }} {{/* TODO(akonradi) implement all of this if ip := net.IP({{ accessor . }}); ip.To16() == nil { return {{ err . "value must be a valid IP address" }} } */}} {{ else if $r.GetIpv4 }} {{ unimplemented "C++ ip address validation is not implemented" }} {{/* TODO(akonradi) implement all of this if ip := net.IP({{ accessor . }}); ip.To4() == nil { return {{ err . "value must be a valid IPv4 address" }} } */}} {{ else if $r.GetIpv6 }} {{ unimplemented "C++ ip address validation is not implemented" }} {{/* TODO(akonradi) implement all of this if ip := net.IP({{ accessor . }}); ip.To16() == nil || ip.To4() != nil { return {{ err . "value must be a valid IPv6 address" }} } */}} {{ end }} {{ if $r.GetIgnoreEmpty }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/cc/const.go000066400000000000000000000004771444536353100214360ustar00rootroot00000000000000package cc const constTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{ if $r.Const }} if ({{ accessor . }} != {{ lit $r.GetConst }}) { {{- if isEnum $f }} {{ err . "value must equal " (enumVal $f $r.GetConst) }} {{- else }} {{ err . "value must equal " (lit $r.GetConst) }} {{- end }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/cc/duration.go000066400000000000000000000064101444536353100221260ustar00rootroot00000000000000package cc const durationTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{ template "required" . }} {{ if or $r.In $r.NotIn $r.Lt $r.Lte $r.Gt $r.Gte $r.Const }} { if ({{ hasAccessor . }}) { const pgv::protobuf_wkt::Duration& dur = {{ accessor . }}; if (dur.nanos() > 999999999 || dur.nanos() < -999999999 || dur.seconds() > pgv::protobuf::util::TimeUtil::kDurationMaxSeconds || dur.seconds() < pgv::protobuf::util::TimeUtil::kDurationMinSeconds) {{ errCause . "err" "value is not a valid duration" }} {{ if $r.Const }} if (dur != {{ durLit $r.Const }}) {{ err . "value must equal " (durStr $r.Const) }} {{ end }} {{ if $r.Lt }} const pgv::protobuf_wkt::Duration lt = {{ durLit $r.Lt }}; {{ end }} {{- if $r.Lte }} const pgv::protobuf_wkt::Duration lte = {{ durLit $r.Lte }}; {{ end }} {{- if $r.Gt }} const pgv::protobuf_wkt::Duration gt = {{ durLit $r.Gt }}; {{ end }} {{- if $r.Gte }} const pgv::protobuf_wkt::Duration gte = {{ durLit $r.Gte }}; {{ end }} {{ if $r.Lt }} {{ if $r.Gt }} {{ if durGt $r.GetLt $r.GetGt }} if (dur <= gt || dur >= lt) {{ err . "value must be inside range (" (durStr $r.GetGt) ", " (durStr $r.GetLt) ")" }} {{ else }} if (dur >= lt && dur <= gt) {{ err . "value must be outside range [" (durStr $r.GetLt) ", " (durStr $r.GetGt) "]" }} {{ end }} {{ else if $r.Gte }} {{ if durGt $r.GetLt $r.GetGte }} if (dur < gte || dur >= lt) {{ err . "value must be inside range [" (durStr $r.GetGte) ", " (durStr $r.GetLt) ")" }} {{ else }} if (dur >= lt && dur < gte) {{ err . "value must be outside range [" (durStr $r.GetLt) ", " (durStr $r.GetGte) ")" }} {{ end }} {{ else }} if (dur >= lt) {{ err . "value must be less than " (durStr $r.GetLt) }} {{ end }} {{ else if $r.Lte }} {{ if $r.Gt }} {{ if durGt $r.GetLte $r.GetGt }} if (dur <= gt || dur > lte) {{ err . "value must be inside range (" (durStr $r.GetGt) ", " (durStr $r.GetLte) "]" }} {{ else }} if (dur > lte && dur <= gt) {{ err . "value must be outside range (" (durStr $r.GetLte) ", " (durStr $r.GetGt) "]" }} {{ end }} {{ else if $r.Gte }} {{ if durGt $r.GetLte $r.GetGte }} if (dur < gte || dur > lte) {{ err . "value must be inside range [" (durStr $r.GetGte) ", " (durStr $r.GetLte) "]" }} {{ else }} if (dur > lte && dur < gte) {{ err . "value must be outside range (" (durStr $r.GetLte) ", " (durStr $r.GetGte) ")" }} {{ end }} {{ else }} if (dur > lte) {{ err . "value must be less than or equal to " (durStr $r.GetLte) }} {{ end }} {{ else if $r.Gt }} if (dur <= gt) {{ err . "value must be greater than " (durStr $r.GetGt) }} {{ else if $r.Gte }} if (dur < gte) {{ err . "value must be greater than or equal to " (durStr $r.GetGte) }} {{ end }} {{ if $r.In }} if ({{ lookup $f "InLookup" }}.find(dur) == {{ lookup $f "InLookup" }}.end()) {{ err . "value must be in list " $r.In }} {{ else if $r.NotIn }} if ({{ lookup $f "NotInLookup" }}.find(dur) != {{ lookup $f "NotInLookup" }}.end()) {{ err . "value must not be in list " $r.NotIn }} {{ end }} } } {{ end }} ` protoc-gen-validate-1.0.2/templates/cc/enum.go000066400000000000000000000006711444536353100212500ustar00rootroot00000000000000package cc const enumTpl = ` {{ $f := .Field }}{{ $r := .Rules }} {{ template "const" . }} {{ template "in" . }} {{ if $r.GetDefinedOnly }} {{ if or $f.Type.IsRepeated $f.Type.IsMap }} if (!{{ class $f.Type.Element.Enum }}_IsValid({{ accessor . }})) { {{ else }} if (!{{ class $f.Type.Enum }}_IsValid({{ accessor . }})) { {{ end }} {{ err . "value must be one of the defined enum values" }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/cc/file.go000066400000000000000000000033671444536353100212300ustar00rootroot00000000000000package cc const moduleFileTpl = `// Code generated by protoc-gen-validate // source: {{ .InputPath }} // DO NOT EDIT!!! #include "{{ output .File ".validate.h" }}" #include #include #include "re2/re2.h" namespace pgv { namespace protobuf = google::protobuf; namespace protobuf_wkt = google::protobuf; namespace validate { using std::string; // define the regex for a UUID once up-front const re2::RE2 _uuidPattern("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"); {{ range .AllMessages }} {{- if not (ignored .) -}} {{- if not (disabled .) -}} pgv::Validator<{{ class . }}> {{ staticVarName . }}(static_cast({{ package .}}::Validate)); {{- end -}} {{ end }} {{ end }} } // namespace validate } // namespace pgv {{ range .Package.ProtoName.Split }} namespace {{ . }} { {{- end }} {{ range .AllMessages }} {{- template "msg" . }} {{ end }} {{ range .Package.ProtoName.Split -}} } // namespace {{ end }} ` const headerFileTpl = `// Code generated by protoc-gen-validate // source: {{ .InputPath }} // DO NOT EDIT!!! #pragma once #include #include #include #include #include #include "validate/validate.h" #include "{{ output .File ".h" }}" {{ range .Package.ProtoName.Split }} namespace {{ . }} { {{- end }} using std::string; {{ range .AllMessages }} {{- template "decl" . }} {{ end }} {{ range .Package.ProtoName.Split -}} } // namespace {{ end }} #define X_{{ .Package.ProtoName.ScreamingSnakeCase }}_{{ .File.InputPath.BaseName | screaming_snake_case }}(X) \ {{ range .AllMessages -}} {{- if not (ignored .) -}} X({{class . }}) \ {{ end -}} {{ end }} ` protoc-gen-validate-1.0.2/templates/cc/in.go000066400000000000000000000014151444536353100207070ustar00rootroot00000000000000package cc const inTpl = `{{ $f := .Field -}}{{ $r := .Rules -}} {{- if $r.In }} if ({{ lookup $f "InLookup" }}.find(static_cast({{ accessor . }})) == {{ lookup $f "InLookup" }}.end()) { {{- if isEnum $f }} {{ err . "value must be in list " (enumList $f $r.In) }} {{- else }} {{ err . "value must be in list " $r.In }} {{- end }} } {{- else if $r.NotIn }} if ({{ lookup $f "NotInLookup" }}.find(static_cast({{ accessor . }})) != {{ lookup $f "NotInLookup" }}.end()) { {{- if isEnum $f }} {{ err . "value must not be in list " (enumList $f $r.NotIn) }} {{- else }} {{ err . "value must not be in list " $r.NotIn }} {{- end }} } {{- end }} ` protoc-gen-validate-1.0.2/templates/cc/known.go000066400000000000000000000031421444536353100214340ustar00rootroot00000000000000package cc const hostTpl = ` func (m {{ .TypeName.Pointer }}) _validateHostname(host string) error { s := strings.TrimSuffix(host, ".") if len(host) > 253 { return errors.New("hostname cannot exceed 253 characters") } for _, part := range strings.Split(s, ".") { if l := len(part); l == 0 || l > 63 { return errors.New("hostname part must be non-empty and cannot exceed 63 characters") } if s[0] == '-' { return errors.New("hostname parts cannot begin with hyphens") } if s[len(s)-1] == '-' { return errors.New("hostname parts cannot end with hyphens") } for _, r := range s { if (r < 'A' || r > 'Z') && (r < 'a' || r > 'z') && (r < '0' || r > '9') && r != '-' { return errors.New("hostname parts can only contain alphanumeric characters or hyphens") } } } return nil } ` const emailTpl = ` func (m {{ .TypeName.Pointer }}) _validateEmail(addr string) error { if len(addr) > 254 { return errors.New("email addresses cannot exceed 254 characters") } a, err := mail.ParseAddress(addr) if err != nil { return err } addr = a.Address parts := strings.SplitN(addr, "@", 2) if len(parts[0]) > 64 { return errors.New("email address local phrase cannot exceed 64 characters") } return m._validateHostname(parts[1]) } ` const uuidTpl = ` func (m {{ .TypeName.Pointer }}) _validateUuid(uuid string) error { if matched := _{{ .File.InputPath.BaseName }}_uuidPattern.MatchString(uuid); !matched { return errors.New("invalid uuid format") } return nil } ` protoc-gen-validate-1.0.2/templates/cc/ltgt.go000066400000000000000000000041331444536353100212530ustar00rootroot00000000000000package cc const ltgtTpl = `{{ $f := .Field }}{{ $r := .Rules }}{{ $v := (accessor .) }} {{ if $r.Lt }} {{ if $r.Gt }} {{ if gt $r.GetLt $r.GetGt }} if ({{ $v }} <= {{ $r.Gt }} || {{ $v }} >= {{ $r.Lt }}) { {{ err . "value must be inside range (" $r.GetGt ", " $r.GetLt ")" }} } {{ else }} if ({{ $v }} >= {{ $r.Lt }} && {{ $v }} <= {{ $r.Gt }}) { {{ err . "value must be outside range [" $r.GetLt ", " $r.GetGt "]" }} } {{ end }} {{ else if $r.Gte }} {{ if gt $r.GetLt $r.GetGte }} if ({{ $v }} < {{ $r.Gte }} || {{ $v }} >= {{ $r.Lt }}) { {{ err . "value must be inside range [" $r.GetGte ", " $r.GetLt ")" }} } {{ else }} if ({{ $v }} >= {{ $r.Lt }} && {{ $v }} < {{ $r.Gte }}) { {{ err . "value must be outside range [" $r.GetLt ", " $r.GetGte ")" }} } {{ end }} {{ else }} if ({{ accessor . }} >= {{ $r.Lt }}) { {{ err . "value must be less than " $r.GetLt }} } {{ end }} {{ else if $r.Lte }} {{ if $r.Gt }} {{ if gt $r.GetLte $r.GetGt }} if ({{ $v }} <= {{ $r.Gt }} || {{ $v }} > {{ $r.Lte }}) { {{ err . "value must be inside range (" $r.GetGt ", " $r.GetLte "]" }} } {{ else }} if ({{ $v }} > {{ $r.Lte }} && {{ $v }} <= {{ $r.Gt }}) { {{ err . "value must be outside range (" $r.GetLte ", " $r.GetGt "]" }} } {{ end }} {{ else if $r.Gte }} {{ if gt $r.GetLte $r.GetGte }} if ({{ $v }} < {{ $r.Gte }} || {{ $v }} > {{ $r.Lte }}) { {{ err . "value must be inside range [" $r.GetGte ", " $r.GetLte "]" }} } {{ else }} if ({{ $v }} > {{ $r.Lte }} && {{ $v }} < {{ $r.Gte }}) { {{ err . "value must be outside range (" $r.GetLte ", " $r.GetGte ")" }} } {{ end }} {{ else }} if ({{ accessor . }} > {{ $r.Lte }}) { {{ err . "value must be less than or equal to " $r.GetLte }} } {{ end }} {{ else if $r.Gt }} if ({{ accessor . }} <= {{ $r.Gt }}) { {{ err . "value must be greater than " $r.GetGt }} } {{ else if $r.Gte }} if ({{ accessor . }} < {{ $r.Gte }}) { {{ err . "value must be greater than or equal to " $r.GetGte }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/cc/map.go000066400000000000000000000026511444536353100210610ustar00rootroot00000000000000package cc const mapTpl = ` {{ $f := .Field }}{{ $r := .Rules }} {{ if $r.GetIgnoreEmpty }} if ({{ accessor . }}.size() > 0) { {{ end }} {{ if $r.GetMinPairs }} { const auto size = {{ accessor . }}.size(); {{ if eq $r.GetMinPairs $r.GetMaxPairs }} if (size != {{ $r.GetMinPairs }}) { {{ err . "value must contain exactly " $r.GetMinPairs " pair(s)" }} } {{ else if $r.MaxPairs }} if (size < {{ $r.GetMinPairs }} || size > {{ $r.GetMaxPairs }}) { {{ err . "value must contain between " $r.GetMinPairs " and " $r.GetMaxPairs " pairs, inclusive" }} } {{ else }} if (size < {{ $r.GetMinPairs }}) { {{ err . "value must contain at least " $r.GetMinPairs " pair(s)" }} } {{ end }} } {{ else if $r.MaxPairs }} { const auto size = {{ accessor . }}.size(); if (size > {{ $r.GetMaxPairs }}) { {{ err . "value must contain no more than " $r.GetMaxPairs " pair(s)" }} } } {{ end }} {{ if or $r.GetNoSparse (ne (.Elem "" "").Typ "none") (ne (.Key "" "").Typ "none") }} for (const auto& kv : {{ accessor . }}) { const auto& key = kv.first; const auto& val = kv.second; (void)key; (void)val; {{ render (.Key "key" "key") }} {{ render (.Elem "val" "key") }} } {{ if $r.GetNoSparse }} {{ unimplemented "no_sparse validation is not implemented for C++ because protobuf maps cannot be sparse in C++" }} {{ end }} {{ end }} {{ if $r.GetIgnoreEmpty }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/cc/message.go000066400000000000000000000010441444536353100217230ustar00rootroot00000000000000package cc const messageTpl = ` {{ $f := .Field }}{{ $r := .Rules }} {{ template "required" . }} {{ if .MessageRules.GetSkip }} // skipping validation for {{ $f.Name }} {{ else }} { pgv::ValidationMsg inner_err; if ({{ hasAccessor .}} && !pgv::BaseValidator::AbstractCheckMessage({{ accessor . }}, &inner_err)) { {{ errCause . "inner_err" "embedded message failed validation" }} } } {{ end }} ` const requiredTpl = ` {{ if .Rules.GetRequired }} if (!{{ hasAccessor . }}) { {{ err . "value is required" }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/cc/msg.go000066400000000000000000000125231444536353100210710ustar00rootroot00000000000000package cc const declTpl = ` {{ if not (ignored .) -}} extern bool Validate(const {{ class . }}& m, pgv::ValidationMsg* err); {{- end -}} ` const msgTpl = ` {{ if not (ignored .) -}} {{ if disabled . -}} {{ cmt "Validate is disabled for " (class .) ". This method will always return true." }} {{- else -}} {{ cmt "Validate checks the field values on " (class .) " with the rules defined in the proto definition for this message. If any rules are violated, the return value is false and an error message is written to the input string argument." }} {{- end -}} {{ range .Fields }}{{ with (context .) }}{{ $f := .Field }} {{ if has .Rules "In" }}{{ if .Rules.In }} const std::set<{{ inType .Field .Rules.In }}> {{ lookup .Field "InLookup" }} = { {{- range .Rules.In }} {{ inKey $f . }}, {{- end }} }; {{ end }}{{ end }} {{ if has .Rules "NotIn" }}{{ if .Rules.NotIn }} const std::set<{{ inType .Field .Rules.NotIn }}> {{ lookup .Field "NotInLookup" }} = { {{- range .Rules.NotIn }} {{ inKey $f . }}, {{- end }} }; {{ end }}{{ end }} {{ if has .Rules "Items"}}{{ if .Rules.Items }} {{ if has .Rules.Items.GetString_ "In" }} {{ if .Rules.Items.GetString_.In }} const std::set {{ lookup .Field "InLookup" }} = { {{- range .Rules.Items.GetString_.In }} {{ inKey $f . }}, {{- end }} }; {{ end }}{{ end }} {{ if has .Rules.Items.GetEnum "In" }} {{ if .Rules.Items.GetEnum.In }} const std::set<{{ inType .Field .Rules.Items.GetEnum.In }}> {{ lookup .Field "InLookup" }} = { {{- range .Rules.Items.GetEnum.In }} {{ inKey $f . }}, {{- end }} }; {{ end }}{{ end }} {{ if has .Rules.Items.GetAny "In" }} {{ if .Rules.Items.GetAny.In }} const std::set {{ lookup .Field "InLookup" }} = { {{- range .Rules.Items.GetAny.In }} {{ inKey $f . }}, {{- end }} }; {{ end }}{{ end }} {{ end }}{{ end }} {{ if has .Rules "Items"}}{{ if .Rules.Items }} {{ if has .Rules.Items.GetString_ "NotIn" }} {{ if .Rules.Items.GetString_.NotIn }} const std::set {{ lookup .Field "NotInLookup" }} = { {{- range .Rules.Items.GetString_.NotIn }} {{ inKey $f . }}, {{- end }} }; {{ end }}{{ end }} {{ if has .Rules.Items.GetEnum "NotIn" }} {{ if .Rules.Items.GetEnum.NotIn }} const std::set<{{ inType .Field .Rules.Items.GetEnum.NotIn }}> {{ lookup .Field "NotInLookup" }} = { {{- range .Rules.Items.GetEnum.NotIn }} {{ inKey $f . }}, {{- end }} }; {{ end }}{{ end }} {{ if has .Rules.Items.GetAny "NotIn" }} {{ if .Rules.Items.GetAny.NotIn }} const std::set {{ lookup .Field "NotInLookup" }} = { {{- range .Rules.Items.GetAny.NotIn }} {{ inKey $f . }}, {{- end }} }; {{ end }}{{ end }} {{ end }}{{ end }} {{ if has .Rules "Pattern"}}{{ if .Rules.Pattern }} const re2::RE2 {{ lookup .Field "Pattern" }}(re2::StringPiece({{ lit .Rules.GetPattern }}, sizeof({{ lit .Rules.GetPattern }}) - 1)); {{ end }}{{ end }} {{ if has .Rules "Items"}}{{ if .Rules.Items }} {{ if has .Rules.Items.GetString_ "Pattern" }} {{ if .Rules.Items.GetString_.Pattern }} const re2::RE2 {{ lookup .Field "Pattern" }}(re2::StringPiece({{ lit .Rules.Items.GetString_.GetPattern }}, sizeof({{ lit .Rules.Items.GetString_.GetPattern }}) - 1)); {{ end }}{{ end }} {{ end }}{{ end }} {{ if has .Rules "Keys"}}{{ if .Rules.Keys }} {{ if has .Rules.Keys.GetString_ "In" }} {{ if .Rules.Keys.GetString_.In }} const std::set {{ lookup .Field "InLookup" }} = { {{- range .Rules.Keys.GetString_.In }} {{ inKey $f . }}, {{- end }} }; {{ end }}{{ end }} {{ if has .Rules.Keys.GetString_ "NotIn" }} {{ if .Rules.Keys.GetString_.NotIn }} const std::set {{ lookup .Field "NotInLookup" }} = { {{- range .Rules.Keys.GetString_.NotIn }} {{ inKey $f . }}, {{- end }} }; {{ end }}{{ end }} {{ if has .Rules.Keys.GetString_ "Pattern" }} {{ if .Rules.Keys.GetString_.Pattern }} const re2::RE2 {{ lookup .Field "Pattern" }}(re2::StringPiece({{ lit .Rules.Keys.GetString_.GetPattern }}, sizeof({{ lit .Rules.Keys.GetString_.GetPattern }}) - 1)); {{ end }}{{ end }} {{ end }}{{ end }} {{ if has .Rules "Values"}}{{ if .Rules.Values }} {{ if has .Rules.Values.GetString_ "Pattern" }} {{ if .Rules.Values.GetString_.Pattern }} const re2::RE2 {{ lookup .Field "Pattern" }}(re2::StringPiece({{ lit .Rules.Values.GetString_.GetPattern }}, sizeof({{ lit .Rules.Values.GetString_.GetPattern }}) - 1)); {{ end }}{{ end }} {{ end }}{{ end }} {{ end }}{{ end }} bool Validate(const {{ class . }}& m, pgv::ValidationMsg* err) { (void)m; (void)err; {{- if disabled . }} return true; {{ else -}} {{ range .NonOneOfFields }} {{- render (context .) -}} {{ end -}} {{ range .SyntheticOneOfFields }} if ({{ hasAccessor (context .) }}) { {{ render (context .) }} } {{ end }} {{ range .RealOneOfs }} switch (m.{{ .Name }}_case()) { {{ range .Fields -}} case {{ oneof . }}: {{ render (context .) }} break; {{ end -}} default: {{- if required . }} *err = "field: " {{ .Name | quote | lit }} ", reason: is required"; return false; {{ end }} break; } {{ end }} return true; {{ end -}} } {{- end -}} ` protoc-gen-validate-1.0.2/templates/cc/none.go000066400000000000000000000002251444536353100212360ustar00rootroot00000000000000package cc const noneTpl = `// no validation rules for {{ .Field.Name }} {{- if .Index }}[{{ .Index }}]{{ end }} {{- if .OnKey }} (key){{ end }}` protoc-gen-validate-1.0.2/templates/cc/num.go000066400000000000000000000003421444536353100210760ustar00rootroot00000000000000package cc const numTpl = ` {{ if .Rules.GetIgnoreEmpty }} if ({{ accessor . }} != 0) { {{ end }} {{ template "const" . }} {{ template "ltgt" . }} {{ template "in" . }} {{ if .Rules.GetIgnoreEmpty }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/cc/register.go000066400000000000000000000273331444536353100221340ustar00rootroot00000000000000package cc import ( "fmt" "reflect" "strconv" "strings" "text/template" "github.com/envoyproxy/protoc-gen-validate/templates/shared" "github.com/iancoleman/strcase" pgs "github.com/lyft/protoc-gen-star/v2" pgsgo "github.com/lyft/protoc-gen-star/v2/lang/go" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/timestamppb" ) func RegisterModule(tpl *template.Template, params pgs.Parameters) { fns := CCFuncs{pgsgo.InitContext(params)} tpl.Funcs(map[string]interface{}{ "accessor": fns.accessor, "byteStr": fns.byteStr, "class": fns.className, "cmt": pgs.C80, "ctype": fns.cType, "durGt": fns.durGt, "durLit": fns.durLit, "durStr": fns.durStr, "err": fns.err, "errCause": fns.errCause, "errIdx": fns.errIdx, "errIdxCause": fns.errIdxCause, "hasAccessor": fns.hasAccessor, "inKey": fns.inKey, "inType": fns.inType, "isBytes": fns.isBytes, "lit": fns.lit, "lookup": fns.lookup, "oneof": fns.oneofTypeName, "output": fns.output, "package": fns.packageName, "quote": fns.quote, "staticVarName": fns.staticVarName, "tsGt": fns.tsGt, "tsLit": fns.tsLit, "tsStr": fns.tsStr, "typ": fns.Type, "unimplemented": fns.failUnimplemented, "unwrap": fns.unwrap, }) template.Must(tpl.Parse(moduleFileTpl)) template.Must(tpl.New("msg").Parse(msgTpl)) template.Must(tpl.New("const").Parse(constTpl)) template.Must(tpl.New("ltgt").Parse(ltgtTpl)) template.Must(tpl.New("in").Parse(inTpl)) template.Must(tpl.New("required").Parse(requiredTpl)) template.Must(tpl.New("none").Parse(noneTpl)) template.Must(tpl.New("float").Parse(numTpl)) template.Must(tpl.New("double").Parse(numTpl)) template.Must(tpl.New("int32").Parse(numTpl)) template.Must(tpl.New("int64").Parse(numTpl)) template.Must(tpl.New("uint32").Parse(numTpl)) template.Must(tpl.New("uint64").Parse(numTpl)) template.Must(tpl.New("sint32").Parse(numTpl)) template.Must(tpl.New("sint64").Parse(numTpl)) template.Must(tpl.New("fixed32").Parse(numTpl)) template.Must(tpl.New("fixed64").Parse(numTpl)) template.Must(tpl.New("sfixed32").Parse(numTpl)) template.Must(tpl.New("sfixed64").Parse(numTpl)) template.Must(tpl.New("bool").Parse(constTpl)) template.Must(tpl.New("string").Parse(strTpl)) template.Must(tpl.New("bytes").Parse(bytesTpl)) template.Must(tpl.New("email").Parse(emailTpl)) template.Must(tpl.New("hostname").Parse(hostTpl)) template.Must(tpl.New("address").Parse(hostTpl)) template.Must(tpl.New("uuid").Parse(uuidTpl)) template.Must(tpl.New("enum").Parse(enumTpl)) template.Must(tpl.New("message").Parse(messageTpl)) template.Must(tpl.New("repeated").Parse(repTpl)) template.Must(tpl.New("map").Parse(mapTpl)) template.Must(tpl.New("any").Parse(anyTpl)) template.Must(tpl.New("duration").Parse(durationTpl)) template.Must(tpl.New("timestamp").Parse(timestampTpl)) template.Must(tpl.New("wrapper").Parse(wrapperTpl)) } func RegisterHeader(tpl *template.Template, params pgs.Parameters) { fns := CCFuncs{pgsgo.InitContext(params)} tpl.Funcs(map[string]interface{}{ "class": fns.className, "output": fns.output, "screaming_snake_case": strcase.ToScreamingSnake, }) template.Must(tpl.Parse(headerFileTpl)) template.Must(tpl.New("decl").Parse(declTpl)) } // TODO(rodaine): break pgsgo dependency here (with equivalent pgscc subpackage) type CCFuncs struct{ pgsgo.Context } func CcFilePath(f pgs.File, ctx pgsgo.Context, tpl *template.Template) *pgs.FilePath { out := pgs.FilePath(f.Name().String()) out = out.SetExt(".pb.validate." + tpl.Name()) return &out } func (fns CCFuncs) methodName(name interface{}) string { nameStr := fmt.Sprintf("%s", name) switch nameStr { case "const": return "const_" case "inline": return "inline_" default: return nameStr } } func (fns CCFuncs) accessor(ctx shared.RuleContext) string { if ctx.AccessorOverride != "" { return ctx.AccessorOverride } return fmt.Sprintf( "m.%s()", fns.methodName(ctx.Field.Name())) } func (fns CCFuncs) hasAccessor(ctx shared.RuleContext) string { if ctx.AccessorOverride != "" { return "true" } return fmt.Sprintf( "m.has_%s()", fns.methodName(ctx.Field.Name())) } type childEntity interface { pgs.Entity Parent() pgs.ParentEntity } func (fns CCFuncs) classBaseName(ent childEntity) string { if m, ok := ent.Parent().(pgs.Message); ok { return fmt.Sprintf("%s_%s", fns.classBaseName(m), ent.Name().String()) } return ent.Name().String() } func (fns CCFuncs) className(ent childEntity) string { return fns.packageName(ent) + "::" + fns.classBaseName(ent) } func (fns CCFuncs) packageName(msg pgs.Entity) string { return "::" + strings.Join(msg.Package().ProtoName().Split(), "::") } func (fns CCFuncs) quote(s interface { String() string }) string { return strconv.Quote(s.String()) } func (fns CCFuncs) err(ctx shared.RuleContext, reason ...interface{}) string { return fns.errIdxCause(ctx, "", "nil", reason...) } func (fns CCFuncs) errCause(ctx shared.RuleContext, cause string, reason ...interface{}) string { return fns.errIdxCause(ctx, "", cause, reason...) } func (fns CCFuncs) errIdx(ctx shared.RuleContext, idx string, reason ...interface{}) string { return fns.errIdxCause(ctx, idx, "nil", reason...) } func (fns CCFuncs) errIdxCause(ctx shared.RuleContext, idx, cause string, reason ...interface{}) string { f := ctx.Field errName := fmt.Sprintf("%sValidationError", f.Message().Name()) output := []string{ "{", `std::ostringstream msg("invalid ");`, } if ctx.OnKey { output = append(output, `msg << "key for ";`) } output = append(output, fmt.Sprintf(`msg << %q << "." << %s;`, errName, fns.lit(pgsgo.PGGUpperCamelCase(f.Name())))) if idx != "" { output = append(output, fmt.Sprintf(`msg << "[" << %s << "]";`, idx)) } else if ctx.Index != "" { output = append(output, fmt.Sprintf(`msg << "[" << %s << "]";`, ctx.Index)) } output = append(output, fmt.Sprintf(`msg << ": " << %q;`, fmt.Sprint(reason...))) if cause != "nil" && cause != "" { output = append(output, fmt.Sprintf(`msg << " | caused by " << %s;`, cause)) } output = append(output, "*err = msg.str();", "return false;", "}") return strings.Join(output, "\n") } func (fns CCFuncs) lookup(f pgs.Field, name string) string { return fmt.Sprintf( "_%s_%s_%s", pgsgo.PGGUpperCamelCase(f.Message().Name()), pgsgo.PGGUpperCamelCase(f.Name()), name, ) } func (fns CCFuncs) lit(x interface{}) string { val := reflect.ValueOf(x) if val.Kind() == reflect.Interface { val = val.Elem() } if val.Kind() == reflect.Ptr { val = val.Elem() } switch val.Kind() { case reflect.String: return fmt.Sprintf("%q", x) case reflect.Uint8: return fmt.Sprintf("%d", x) case reflect.Slice: els := make([]string, val.Len()) switch reflect.TypeOf(x).Elem().Kind() { case reflect.Uint8: for i, l := 0, val.Len(); i < l; i++ { els[i] = fmt.Sprintf("\\x%x", val.Index(i).Interface()) } return fmt.Sprintf("\"%s\"", strings.Join(els, "")) default: panic(fmt.Sprintf("don't know how to format literals of type %v", val.Kind())) } case reflect.Float32: return fmt.Sprintf("%fF", x) default: return fmt.Sprint(x) } } func (fns CCFuncs) isBytes(f interface { ProtoType() pgs.ProtoType }) bool { return f.ProtoType() == pgs.BytesT } func (fns CCFuncs) byteStr(x []byte) string { elms := make([]string, len(x)) for i, b := range x { elms[i] = fmt.Sprintf(`\x%X`, b) } return fmt.Sprintf(`"%s"`, strings.Join(elms, "")) } func (fns CCFuncs) oneofTypeName(f pgs.Field) pgsgo.TypeName { return pgsgo.TypeName(fmt.Sprintf("%s::%sCase::k%s", fns.className(f.Message()), pgsgo.PGGUpperCamelCase(f.OneOf().Name()), strings.ReplaceAll(pgsgo.PGGUpperCamelCase(f.Name()).String(), "_", ""))) } func (fns CCFuncs) inType(f pgs.Field, x interface{}) string { switch f.Type().ProtoType() { case pgs.BytesT: return "string" case pgs.MessageT: switch x.(type) { case []string: return "string" case []*durationpb.Duration: return "pgv::protobuf_wkt::Duration" default: return fns.className(f.Type().Element().Embed()) } case pgs.EnumT: var fldEn = f.Type().Enum() if f.Type().IsRepeated() { fldEn = f.Type().Element().Enum() } if fns.ImportPath(f) == fns.ImportPath(fldEn) { if f.Type().IsRepeated() { return fns.cTypeOfString(fns.Type(f).Value().String()[2:]) } return fns.cTypeOfString(fns.Type(f).Value().String()) } return fns.PackageName(fldEn).String() + "::" + fns.Type(f).Value().String() default: return fns.cType(f.Type()) } } func (fns CCFuncs) cType(t pgs.FieldType) string { if t.IsEmbed() { return fns.className(t.Embed()) } if t.IsRepeated() { if t.ProtoType() == pgs.MessageT { return fns.className(t.Element().Embed()) } // Strip the leading [] return fns.cTypeOfString(fns.Type(t.Field()).String()[2:]) } else if t.IsMap() { if t.Element().IsEmbed() { return fns.className(t.Element().Embed()) } return fns.cTypeOfString(fns.Type(t.Field()).Element().String()) } // Use Value() to strip any potential pointer type. return fns.cTypeOfString(fns.Type(t.Field()).Value().String()) } func (fns CCFuncs) cTypeOfString(s string) string { switch s { case "float32": return "float" case "float64": return "double" case "int32": return "int32_t" case "int64": return "int64_t" case "uint32": return "uint32_t" case "uint64": return "uint64_t" case "[]byte": return "string" default: return s } } func (fns CCFuncs) inKey(f pgs.Field, x interface{}) string { switch f.Type().ProtoType() { case pgs.BytesT: return fns.byteStr(x.([]byte)) case pgs.MessageT: switch x := x.(type) { case *durationpb.Duration: return fns.durLit(x) default: return fns.lit(x) } case pgs.EnumT: return fmt.Sprintf("%s(%d)", fns.inType(f, x), x.(int32)) default: return fns.lit(x) } } func (fns CCFuncs) durLit(dur *durationpb.Duration) string { return fmt.Sprintf( "pgv::protobuf::util::TimeUtil::SecondsToDuration(%d) + pgv::protobuf::util::TimeUtil::NanosecondsToDuration(%d)", dur.GetSeconds(), dur.GetNanos()) } func (fns CCFuncs) durStr(dur *durationpb.Duration) string { d := dur.AsDuration() return d.String() } func (fns CCFuncs) durGt(a, b *durationpb.Duration) bool { ad := a.AsDuration() bd := b.AsDuration() return ad > bd } func (fns CCFuncs) tsLit(ts *timestamppb.Timestamp) string { return fmt.Sprintf( "time.Unix(%d, %d)", ts.GetSeconds(), ts.GetNanos(), ) } func (fns CCFuncs) tsGt(a, b *timestamppb.Timestamp) bool { at := a.AsTime() bt := b.AsTime() return !bt.Before(at) } func (fns CCFuncs) tsStr(ts *timestamppb.Timestamp) string { t := ts.AsTime() return t.String() } func (fns CCFuncs) unwrap(ctx shared.RuleContext, name string) (shared.RuleContext, error) { ctx, err := ctx.Unwrap("wrapper") if err != nil { return ctx, err } ctx.AccessorOverride = fmt.Sprintf("%s.%s()", name, ctx.Field.Type().Embed().Fields()[0].Name()) return ctx, nil } func (fns CCFuncs) failUnimplemented(message string) string { if len(message) == 0 { return "throw pgv::UnimplementedException();" } return fmt.Sprintf(`throw pgv::UnimplementedException(%q);`, message) } func (fns CCFuncs) staticVarName(msg pgs.Message) string { return "validator_" + strings.Replace(fns.className(msg), ":", "_", -1) } func (fns CCFuncs) output(file pgs.File, ext string) string { return pgs.FilePath(file.Name().String()).SetExt(".pb" + ext).String() } func (fns CCFuncs) Type(f pgs.Field) pgsgo.TypeName { typ := fns.Context.Type(f) // Adaptation of repeated types if f.Type().ProtoType() == pgs.EnumT { parts := strings.Split(typ.String(), ".") typ = pgsgo.TypeName(parts[len(parts)-1]) } return typ } protoc-gen-validate-1.0.2/templates/cc/repeated.go000066400000000000000000000040171444536353100220730ustar00rootroot00000000000000package cc const repTpl = ` {{ $f := .Field }}{{ $r := .Rules }}{{ $typ := inType $f nil }} {{ if $r.GetIgnoreEmpty }} if ({{ accessor . }}.size() > 0) { {{ end }} {{ if $r.GetMinItems }} {{ if eq $r.GetMinItems $r.GetMaxItems }} if ({{ accessor . }}.size() != {{ $r.GetMinItems }}) { {{ err . "value must contain exactly " $r.GetMinItems " item(s)" }} } {{ else if $r.MaxItems }} if ({{ accessor . }}.size() < {{ $r.GetMinItems }} || {{ accessor . }}.size() > {{ $r.GetMaxItems }}) { {{ err . "value must contain between " $r.GetMinItems " and " $r.GetMaxItems " items, inclusive" }} } {{ else }} if ({{ accessor . }}.size() < {{ $r.GetMinItems }}) { {{ err . "value must contain at least " $r.GetMinItems " item(s)" }} } {{ end }} {{ else if $r.MaxItems }} if ({{ accessor . }}.size() > {{ $r.GetMaxItems }}) { {{ err . "value must contain no more than " $r.GetMaxItems " item(s)" }} } {{ end }} {{ if $r.GetUnique }} // Implement comparison for wrapped reference types struct cmp { bool operator() (const std::reference_wrapper<{{ $typ }}> lhs, const std::reference_wrapper<{{ $typ }}> rhs) const { return lhs.get() == rhs.get(); } }; // Implement hashing for wrapped reference types struct hash { std::hash<{{ $typ }}> hash_fn; bool operator() (const std::reference_wrapper<{{ $typ }}> ref) const { return hash_fn(ref.get()); } }; // Save a set of references to avoid copying overhead std::unordered_set, hash, cmp> {{ lookup $f "Unique" }}; {{ end }} {{ if or $r.GetUnique (ne (.Elem "" "").Typ "none") }} for (int i = 0; i < {{ accessor . }}.size(); i++) { const auto& item = {{ accessor . }}.Get(i); (void)item; {{ if $r.GetUnique }} auto p = {{ lookup $f "Unique" }}.emplace(const_cast<{{ $typ }}&>(item)); if (p.second == false) { {{ errIdx . "i" "repeated value must contain unique items" }} } {{ end }} {{ render (.Elem "item" "i") }} } {{ end }} {{ if $r.GetIgnoreEmpty }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/cc/string.go000066400000000000000000000127011444536353100216070ustar00rootroot00000000000000package cc const strTpl = ` {{ $f := .Field }}{{ $r := .Rules }} {{ if $r.GetIgnoreEmpty }} if ({{ accessor . }} != "") { {{ end }} {{ template "const" . }} {{ template "in" . }} {{ if or $r.Len (and $r.MinLen $r.MaxLen (eq $r.GetMinLen $r.GetMaxLen)) }} {{ if $r.Len }} if (pgv::Utf8Len({{ accessor . }}) != {{ $r.GetLen }}) { {{ err . "value must be " $r.GetLen " characters" }} } {{ else }} if (pgv::Utf8Len({{ accessor . }}) != {{ $r.GetMinLen }}) { {{ err . "value must be " $r.GetMinLen " characters" }} } {{ end }} {{ else if $r.MinLen }} {{ if $r.MaxLen }} { const auto length = pgv::Utf8Len({{ accessor . }}); if (length < {{ $r.GetMinLen }} || length > {{ $r.GetMaxLen }}) { {{ err . "value must have between " $r.GetMinLen " and " $r.GetMaxLen " characters inclusive" }} } } {{ else }} if (pgv::Utf8Len({{ accessor . }}) < {{ $r.GetMinLen }}) { {{ err . "value length must be at least " $r.GetMinLen " characters" }} } {{ end }} {{ else if $r.MaxLen }} if (pgv::Utf8Len({{ accessor . }}) > {{ $r.GetMaxLen }}) { {{ err . "value length must be at most " $r.GetMaxLen " characters" }} } {{ end }} {{ if or $r.LenBytes (and $r.MinBytes $r.MaxBytes (eq $r.GetMinBytes $r.GetMaxBytes)) }} { const auto length = {{ accessor . }}.size(); {{ if $r.LenBytes }} if (length != {{ $r.GetLenBytes }}) { {{ err . "value length must be " $r.GetLenBytes " bytes" }} } {{ else }} if (length != {{ $r.GetMinBytes }}) { {{ err . "value length must be " $r.GetMinBytes " bytes" }} } {{ end }} } {{ else if $r.MinBytes }} { const auto length = {{ accessor . }}.size(); {{ if $r.MaxBytes }} {{ if eq $r.GetMinBytes $r.GetMaxBytes }} if (length != {{ $r.GetMinBytes }}) { {{ err . "value length must be " $r.GetMinBytes " bytes" }} } {{ else }} if (length < {{ $r.GetMinBytes }} || length > {{ $r.GetMaxBytes }}) { {{ err . "value length must be between " $r.GetMinBytes " and " $r.GetMaxBytes " bytes, inclusive" }} } {{ end }} {{ else }} if (length < {{ $r.GetMinBytes }}) { {{ err . "value length must be at least " $r.GetMinBytes " bytes" }} } {{ end }} } {{ else if $r.MaxBytes }} if ({{ accessor . }}.size() > {{ $r.GetMaxBytes }}) { {{ err . "value length must be at most " $r.GetMaxBytes " bytes" }} } {{ end }} {{ if $r.Prefix }} { const std::string prefix = {{ lit $r.GetPrefix }}; if (!pgv::IsPrefix(prefix, {{ accessor . }})) { {{ err . "value does not have prefix " (lit $r.GetPrefix) }} } } {{ end }} {{ if $r.Suffix }} { const std::string suffix = {{ lit $r.GetSuffix }}; const std::string& value = {{ accessor . }}; if (!pgv::IsSuffix(suffix, value)) { {{ err . "value does not have suffix " (lit $r.GetSuffix) }} } } {{ end }} {{ if $r.Contains }} { if (!pgv::Contains({{ accessor . }}, {{ lit $r.GetContains }})) { {{ err . "value does not contain substring " (lit $r.GetContains) }} } } {{ end }} {{ if $r.NotContains }} { if (pgv::Contains({{ accessor . }}, {{ lit $r.GetNotContains }})) { {{ err . "value contains substring " (lit $r.GetNotContains) }} } } {{ end }} {{ if $r.Pattern }} { if (!RE2::FullMatch(re2::StringPiece({{ accessor . }}.c_str(), {{ accessor . }}.size()), {{ lookup $f "Pattern" }})) { {{ err . "value does not match regex pattern " (lit $r.GetPattern) }} } } {{ end }} {{ if $r.GetIp }} { const std::string& value = {{ accessor . }}; if (!pgv::IsIp(value)) { {{ err . "value must be a valid IP Address" }} } } {{ else if $r.GetIpv4 }} { const std::string& value = {{ accessor . }}; if (!pgv::IsIpv4(value)) { {{ err . "value must be a valid IPv4 Address" }} } } {{ else if $r.GetIpv6 }} { const std::string& value = {{ accessor . }}; if (!pgv::IsIpv6(value)) { {{ err . "value must be a valid IPv6 Address" }} } } {{ else if $r.GetEmail }} {{ unimplemented "C++ email address validation is not implemented" }} {{/* TODO(akonradi) implement email address constraints if err := m._validateEmail({{ accessor . }}); err != nil { return {{ errCause . "err" "value must be a valid email address" }} } */}} {{ else if $r.GetAddress }} { const std::string& value = {{ accessor . }}; if (!pgv::IsHostname(value) && !pgv::IsIp(value)) { {{ err . "value must be an ip address, or a hostname." }} } } {{ else if $r.GetHostname }} { const std::string& value = {{ accessor . }}; if (!pgv::IsHostname(value)) { {{ err . "value must be a valid hostname" }} } } {{ else if $r.GetUri }} {{ unimplemented "C++ URI validation is not implemented" }} {{/* TODO(akonradi) implement URI constraints if uri, err := url.Parse({{ accessor . }}); err != nil { return {{ errCause . "err" "value must be a valid URI" }} } else if !uri.IsAbs() { return {{ err . "value must be absolute" }} } */}} {{ else if $r.GetUriRef }} {{ unimplemented "C++ URI validation is not implemented" }} {{/* TODO(akonradi) implement URI constraints if _, err := url.Parse({{ accessor . }}); err != nil { return {{ errCause . "err" "value must be a valid URI" }} } */}} {{ else if $r.GetUuid }} if (!RE2::FullMatch(re2::StringPiece({{ accessor . }}), pgv::validate::_uuidPattern)) { {{ err . "value must be a valid UUID" }} } {{ end }} {{ if $r.GetIgnoreEmpty }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/cc/timestamp.go000066400000000000000000000074051444536353100223110ustar00rootroot00000000000000package cc const timestampTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{ template "required" . }} {{ if or $r.Lt $r.Lte $r.Gt $r.Gte $r.LtNow $r.GtNow $r.Within $r.Const }} {{ unimplemented "C++ timestamp comparison validations are not implemented" }} {{/* if t := {{ accessor . }}; t != nil { ts, err := ptypes.Timestamp(t) if err != nil { return {{ errCause . "err" "value is not a valid timestamp" }} } {{ if or $r.LtNow $r.GtNow $r.Within }} now := time.Now(); {{ end }} {{- if $r.Lt }} lt := {{ tsLit $r.Lt }}; {{ end }} {{- if $r.Lte }} lte := {{ tsLit $r.Lte }}; {{ end }} {{- if $r.Gt }} gt := {{ tsLit $r.Gt }}; {{ end }} {{- if $r.Gte }} gte := {{ tsLit $r.Gte }}; {{ end }} {{- if $r.Within }} within := {{ durLit $r.Within }}; {{ end }} {{ if $r.Lt }} {{ if $r.Gt }} {{ if tsGt $r.GetLt $r.GetGt }} if ts.Sub(gt) <= 0 || ts.Sub(lt) >= 0 { return {{ err . "value must be inside range (" (tsStr $r.GetGt) ", " (tsStr $r.GetLt) ")" }} } {{ else }} if ts.Sub(lt) >= 0 && ts.Sub(gt) <= 0 { return {{ err . "value must be outside range [" (tsStr $r.GetLt) ", " (tsStr $r.GetGt) "]" }} } {{ end }} {{ else if $r.Gte }} {{ if tsGt $r.GetLt $r.GetGte }} if ts.Sub(gte) < 0 || ts.Sub(lt) >= 0 { return {{ err . "value must be inside range [" (tsStr $r.GetGte) ", " (tsStr $r.GetLt) ")" }} } {{ else }} if ts.Sub(lt) >= 0 && ts.Sub(gte) < 0 { return {{ err . "value must be outside range [" (tsStr $r.GetLt) ", " (tsStr $r.GetGte) ")" }} } {{ end }} {{ else }} if ts.Sub(lt) >= 0 { return {{ err . "value must be less than " (tsStr $r.GetLt) }} } {{ end }} {{ else if $r.Lte }} {{ if $r.Gt }} {{ if tsGt $r.GetLte $r.GetGt }} if ts.Sub(gt) <= 0 || ts.Sub(lte) > 0 { return {{ err . "value must be inside range (" (tsStr $r.GetGt) ", " (tsStr $r.GetLte) "]" }} } {{ else }} if ts.Sub(lte) > 0 && ts.Sub(gt) <= 0 { return {{ err . "value must be outside range (" (tsStr $r.GetLte) ", " (tsStr $r.GetGt) "]" }} } {{ end }} {{ else if $r.Gte }} {{ if tsGt $r.GetLte $r.GetGte }} if ts.Sub(gte) < 0 || ts.Sub(lte) > 0 { return {{ err . "value must be inside range [" (tsStr $r.GetGte) ", " (tsStr $r.GetLte) "]" }} } {{ else }} if ts.Sub(lte) > 0 && ts.Sub(gte) < 0 { return {{ err . "value must be outside range (" (tsStr $r.GetLte) ", " (tsStr $r.GetGte) ")" }} } {{ end }} {{ else }} if ts.Sub(lte) > 0 { return {{ err . "value must be less than or equal to " (tsStr $r.GetLte) }} } {{ end }} {{ else if $r.Gt }} if ts.Sub(gt) <= 0 { return {{ err . "value must be greater than " (tsStr $r.GetGt) }} } {{ else if $r.Gte }} if ts.Sub(gte) < 0 { return {{ err . "value must be greater than or equal to " (tsStr $r.GetGte) }} } {{ else if $r.LtNow }} {{ if $r.Within }} if ts.Sub(now) >= 0 || ts.Sub(now.Add(-within)) < 0 { return {{ err . "value must be less than now within " (durStr $r.GetWithin) }} } {{ else }} if ts.Sub(now) >= 0 { return {{ err . "value must be less than now" }} } {{ end }} {{ else if $r.GtNow }} {{ if $r.Within }} if ts.Sub(now) >= 0 || ts.Sub(now.Add(within)) > 0 { return {{ err . "value must be greater than now within " (durStr $r.GetWithin) }} } {{ else }} if ts.Sub(now) <= 0 { return {{ err . "value must be greater than now" }} } {{ end }} {{ else if $r.Within }} if ts.Sub(now.Add(within)) >= 0 || ts.Sub(now.Add(-within)) <= 0 { return {{ err . "value must be within " (durStr $r.GetWithin) " of now" }} } {{ end }} } */}} {{ end }} ` protoc-gen-validate-1.0.2/templates/cc/wrapper.go000066400000000000000000000004441444536353100217620ustar00rootroot00000000000000package cc const wrapperTpl = ` {{ $f := .Field }}{{ $r := .Rules }} if ({{ hasAccessor . }}) { const auto wrapped = {{ accessor . }}; {{ render (unwrap . "wrapped") }} } {{ if .MessageRules.GetRequired }} else { {{ err . "value is required and must not be nil." }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/ccnop/000077500000000000000000000000001444536353100204665ustar00rootroot00000000000000protoc-gen-validate-1.0.2/templates/ccnop/BUILD.bazel000066400000000000000000000007511444536353100223470ustar00rootroot00000000000000load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "ccnop", srcs = [ "file.go", "register.go", ], importpath = "github.com/envoyproxy/protoc-gen-validate/templates/ccnop", visibility = ["//visibility:public"], deps = [ "//templates/cc", "@com_github_lyft_protoc_gen_star_v2//:protoc-gen-star", ], ) alias( name = "go_default_library", actual = ":ccnop", visibility = ["//visibility:public"], ) protoc-gen-validate-1.0.2/templates/ccnop/file.go000066400000000000000000000014751444536353100217430ustar00rootroot00000000000000package ccnop const headerFileTpl = `// Code generated by protoc-gen-validate // source: {{ .InputPath }} // DO NOT EDIT!!! #pragma once #include #include "validate/validate.h" #include "{{ output .File ".h" }}" {{ range .Package.ProtoName.Split }} namespace {{ . }} { {{- end }} using std::string; {{ range .AllMessages }} extern inline bool Validate(__attribute__((unused)) const {{ class . }}& m, __attribute__((unused)) pgv::ValidationMsg* err) { return true; } {{ end }} {{ range .Package.ProtoName.Split -}} } // namespace {{ end }} {{ range .AllMessages -}} {{- if not (ignored .) -}} {{ end -}} {{ end }} ` const moduleFileTpl = `// Code generated by protoc-gen-validate // source: {{ .InputPath }} // DO NOT EDIT!!! namespace pgv { namespace validate { } // namespace validate } // namespace pgv ` protoc-gen-validate-1.0.2/templates/ccnop/register.go000066400000000000000000000006621444536353100226450ustar00rootroot00000000000000package ccnop import ( "text/template" "github.com/envoyproxy/protoc-gen-validate/templates/cc" pgs "github.com/lyft/protoc-gen-star/v2" ) func RegisterModule(tpl *template.Template, params pgs.Parameters) { cc.RegisterModule(tpl, params) template.Must(tpl.Parse(moduleFileTpl)) } func RegisterHeader(tpl *template.Template, params pgs.Parameters) { cc.RegisterHeader(tpl, params) template.Must(tpl.Parse(headerFileTpl)) } protoc-gen-validate-1.0.2/templates/go/000077500000000000000000000000001444536353100177715ustar00rootroot00000000000000protoc-gen-validate-1.0.2/templates/go/BUILD.bazel000066400000000000000000000013361444536353100216520ustar00rootroot00000000000000load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go", srcs = [ "duration.go", "file.go", "message.go", "register.go", "required.go", "timestamp.go", ], importpath = "github.com/envoyproxy/protoc-gen-validate/templates/go", visibility = ["//visibility:public"], deps = [ "//templates/goshared", "@com_github_lyft_protoc_gen_star_v2//:protoc-gen-star", ], ) alias( name = "go_default_library", actual = ":go", deprecation = "Use :go instead of :go_default_library. Details about the new naming convention: https://github.com/bazelbuild/bazel-gazelle/pull/863", visibility = ["//visibility:public"], ) protoc-gen-validate-1.0.2/templates/go/duration.go000066400000000000000000000007211444536353100221450ustar00rootroot00000000000000package golang const durationTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{ template "required" . }} {{ if or $r.In $r.NotIn $r.Lt $r.Lte $r.Gt $r.Gte $r.Const }} if d := {{ accessor . }}; d != nil { dur, err := d.AsDuration(), d.CheckValid() if err != nil { err = {{ errCause . "err" "value is not a valid duration" }} if !all { return err } errors = append(errors, err) } else { {{ template "durationcmp" . }} } } {{ end }} ` protoc-gen-validate-1.0.2/templates/go/file.go000066400000000000000000000021301444536353100212330ustar00rootroot00000000000000package golang const fileTpl = `// Code generated by protoc-gen-validate. DO NOT EDIT. // source: {{ .InputPath }} package {{ pkg . }} import ( "bytes" "errors" "fmt" "net" "net/mail" "net/url" "regexp" "sort" "strings" "time" "unicode/utf8" "google.golang.org/protobuf/types/known/anypb" {{ range $pkg, $enum := enumPackages (externalEnums .) }} {{ $pkg }} "{{ $enum.FilePath }}" {{ end }} ) // ensure the imports are used var ( _ = bytes.MinRead _ = errors.New("") _ = fmt.Print _ = utf8.UTFMax _ = (*regexp.Regexp)(nil) _ = (*strings.Reader)(nil) _ = net.IPv4len _ = time.Duration(0) _ = (*url.URL)(nil) _ = (*mail.Address)(nil) _ = anypb.Any{} _ = sort.Sort {{ range $pkg, $enum := enumPackages (externalEnums .) }} _ = {{ $pkg }}.{{ $enum.Name }}(0) {{ end }} ) {{- if fileneeds . "uuid" }} // define the regex for a UUID once up-front var _{{ snakeCase .File.InputPath.BaseName }}_uuidPattern = regexp.MustCompile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$") {{ end }} {{ range .AllMessages }} {{ template "msg" . }} {{ end }} ` protoc-gen-validate-1.0.2/templates/go/message.go000066400000000000000000000017721444536353100217530ustar00rootroot00000000000000package golang // Embedded message validation. const messageTpl = ` {{ $f := .Field }}{{ $r := .Rules }} {{ template "required" . }} {{ if .MessageRules.GetSkip }} // skipping validation for {{ $f.Name }} {{ else }} if all { switch v := interface{}({{ accessor . }}).(type) { case interface{ ValidateAll() error }: if err := v.ValidateAll(); err != nil { errors = append(errors, {{ errCause . "err" "embedded message failed validation" }}) } case interface{ Validate() error }: {{- /* Support legacy validation for messages that were generated with a plugin version prior to existence of ValidateAll() */ -}} if err := v.Validate(); err != nil { errors = append(errors, {{ errCause . "err" "embedded message failed validation" }}) } } } else if v, ok := interface{}({{ accessor . }}).(interface{ Validate() error }); ok { if err := v.Validate(); err != nil { return {{ errCause . "err" "embedded message failed validation" }} } } {{ end }} ` protoc-gen-validate-1.0.2/templates/go/register.go000066400000000000000000000007701444536353100221500ustar00rootroot00000000000000package golang import ( pgs "github.com/lyft/protoc-gen-star/v2" "text/template" "github.com/envoyproxy/protoc-gen-validate/templates/goshared" ) func Register(tpl *template.Template, params pgs.Parameters) { goshared.Register(tpl, params) template.Must(tpl.Parse(fileTpl)) template.Must(tpl.New("required").Parse(requiredTpl)) template.Must(tpl.New("timestamp").Parse(timestampTpl)) template.Must(tpl.New("duration").Parse(durationTpl)) template.Must(tpl.New("message").Parse(messageTpl)) } protoc-gen-validate-1.0.2/templates/go/required.go000066400000000000000000000003271444536353100221420ustar00rootroot00000000000000package golang const requiredTpl = ` {{ if .Rules.GetRequired }} if {{ accessor . }} == nil { err := {{ err . "value is required" }} if !all { return err } errors = append(errors, err) } {{ end }} ` protoc-gen-validate-1.0.2/templates/go/timestamp.go000066400000000000000000000007341444536353100223270ustar00rootroot00000000000000package golang const timestampTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{ template "required" . }} {{ if or $r.Lt $r.Lte $r.Gt $r.Gte $r.LtNow $r.GtNow $r.Within $r.Const }} if t := {{ accessor . }}; t != nil { ts, err := t.AsTime(), t.CheckValid() if err != nil { err = {{ errCause . "err" "value is not a valid timestamp" }} if !all { return err } errors = append(errors, err) } else { {{ template "timestampcmp" . }} } } {{ end }} ` protoc-gen-validate-1.0.2/templates/goshared/000077500000000000000000000000001444536353100211605ustar00rootroot00000000000000protoc-gen-validate-1.0.2/templates/goshared/BUILD.bazel000066400000000000000000000022571444536353100230440ustar00rootroot00000000000000load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "goshared", srcs = [ "any.go", "bytes.go", "const.go", "duration.go", "enum.go", "in.go", "known.go", "ltgt.go", "map.go", "msg.go", "none.go", "num.go", "register.go", "repeated.go", "string.go", "timestamp.go", "wrapper.go", ], importpath = "github.com/envoyproxy/protoc-gen-validate/templates/goshared", visibility = ["//visibility:public"], deps = [ "//templates/shared", "@com_github_iancoleman_strcase//:strcase", "@com_github_lyft_protoc_gen_star_v2//:protoc-gen-star", "@com_github_lyft_protoc_gen_star_v2//lang/go", "@org_golang_google_protobuf//types/known/durationpb", "@org_golang_google_protobuf//types/known/timestamppb", ], ) alias( name = "go_default_library", actual = ":goshared", deprecation = "Use :goshared instead of :go_default_library. Details about the new naming convention: https://github.com/bazelbuild/bazel-gazelle/pull/863", visibility = ["//visibility:public"], ) protoc-gen-validate-1.0.2/templates/goshared/any.go000066400000000000000000000011051444536353100222730ustar00rootroot00000000000000package goshared const anyTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{ template "required" . }} if a := {{ accessor . }}; a != nil { {{ if $r.In }} if _, ok := {{ lookup $f "InLookup" }}[a.GetTypeUrl()]; !ok { err := {{ err . "type URL must be in list " $r.In }} if !all { return err } errors = append(errors, err) } {{ else if $r.NotIn }} if _, ok := {{ lookup $f "NotInLookup" }}[a.GetTypeUrl()]; ok { err := {{ err . "type URL must not be in list " $r.NotIn }} if !all { return err } errors = append(errors, err) } {{ end }} } ` protoc-gen-validate-1.0.2/templates/goshared/bytes.go000066400000000000000000000070621444536353100226420ustar00rootroot00000000000000package goshared const bytesTpl = ` {{ $f := .Field }}{{ $r := .Rules }} {{ if $r.GetIgnoreEmpty }} if len({{ accessor . }}) > 0 { {{ end }} {{ if or $r.Len (and $r.MinLen $r.MaxLen (eq $r.GetMinLen $r.GetMaxLen)) }} {{ if $r.Len }} if len({{ accessor . }}) != {{ $r.GetLen }} { err := {{ err . "value length must be " $r.GetLen " bytes" }} if !all { return err } errors = append(errors, err) } {{ else }} if len({{ accessor . }}) != {{ $r.GetMinLen }} { err := {{ err . "value length must be " $r.GetMinLen " bytes" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.MinLen }} {{ if $r.MaxLen }} if l := len({{ accessor . }}); l < {{ $r.GetMinLen }} || l > {{ $r.GetMaxLen }} { err := {{ err . "value length must be between " $r.GetMinLen " and " $r.GetMaxLen " bytes, inclusive" }} if !all { return err } errors = append(errors, err) } {{ else }} if len({{ accessor . }}) < {{ $r.GetMinLen }} { err := {{ err . "value length must be at least " $r.GetMinLen " bytes" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.MaxLen }} if len({{ accessor . }}) > {{ $r.GetMaxLen }} { err := {{ err . "value length must be at most " $r.GetMaxLen " bytes" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.Prefix }} if !bytes.HasPrefix({{ accessor . }}, {{ lit $r.GetPrefix }}) { err := {{ err . "value does not have prefix " (byteStr $r.GetPrefix) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.Suffix }} if !bytes.HasSuffix({{ accessor . }}, {{ lit $r.GetSuffix }}) { err := {{ err . "value does not have suffix " (byteStr $r.GetSuffix) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.Contains }} if !bytes.Contains({{ accessor . }}, {{ lit $r.GetContains }}) { err := {{ err . "value does not contain " (byteStr $r.GetContains) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.In }} if _, ok := {{ lookup $f "InLookup" }}[string({{ accessor . }})]; !ok { err := {{ err . "value must be in list " $r.In }} if !all { return err } errors = append(errors, err) } {{ else if $r.NotIn }} if _, ok := {{ lookup $f "NotInLookup" }}[string({{ accessor . }})]; ok { err := {{ err . "value must not be in list " $r.NotIn }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.Const }} if !bytes.Equal({{ accessor . }}, {{ lit $r.Const }}) { err := {{ err . "value must equal " $r.Const }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.GetIp }} if ip := net.IP({{ accessor . }}); ip.To16() == nil { err := {{ err . "value must be a valid IP address" }} if !all { return err } errors = append(errors, err) } {{ else if $r.GetIpv4 }} if ip := net.IP({{ accessor . }}); ip.To4() == nil { err := {{ err . "value must be a valid IPv4 address" }} if !all { return err } errors = append(errors, err) } {{ else if $r.GetIpv6 }} if ip := net.IP({{ accessor . }}); ip.To16() == nil || ip.To4() != nil { err := {{ err . "value must be a valid IPv6 address" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.Pattern }} if !{{ lookup $f "Pattern" }}.Match({{ accessor . }}) { err := {{ err . "value does not match regex pattern " (lit $r.GetPattern) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.GetIgnoreEmpty }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/goshared/const.go000066400000000000000000000006051444536353100226360ustar00rootroot00000000000000package goshared const constTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{ if $r.Const }} if {{ accessor . }} != {{ lit $r.GetConst }} { {{- if isEnum $f }} err := {{ err . "value must equal " (enumVal $f $r.GetConst) }} {{- else }} err := {{ err . "value must equal " $r.GetConst }} {{- end }} if !all { return err } errors = append(errors, err) } {{ end }} ` protoc-gen-validate-1.0.2/templates/goshared/duration.go000066400000000000000000000073701444536353100233430ustar00rootroot00000000000000package goshared const durationcmpTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{ if $r.Const }} if dur != {{ durLit $r.Const }} { err := {{ err . "value must equal " (durStr $r.Const) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.Lt }} lt := {{ durLit $r.Lt }}; {{ end }} {{- if $r.Lte }} lte := {{ durLit $r.Lte }}; {{ end }} {{- if $r.Gt }} gt := {{ durLit $r.Gt }}; {{ end }} {{- if $r.Gte }} gte := {{ durLit $r.Gte }}; {{ end }} {{ if $r.Lt }} {{ if $r.Gt }} {{ if durGt $r.GetLt $r.GetGt }} if dur <= gt || dur >= lt { err := {{ err . "value must be inside range (" (durStr $r.GetGt) ", " (durStr $r.GetLt) ")" }} if !all { return err } errors = append(errors, err) } {{ else }} if dur >= lt && dur <= gt { err := {{ err . "value must be outside range [" (durStr $r.GetLt) ", " (durStr $r.GetGt) "]" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.Gte }} {{ if durGt $r.GetLt $r.GetGte }} if dur < gte || dur >= lt { err := {{ err . "value must be inside range [" (durStr $r.GetGte) ", " (durStr $r.GetLt) ")" }} if !all { return err } errors = append(errors, err) } {{ else }} if dur >= lt && dur < gte { err := {{ err . "value must be outside range [" (durStr $r.GetLt) ", " (durStr $r.GetGte) ")" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else }} if dur >= lt { err := {{ err . "value must be less than " (durStr $r.GetLt) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.Lte }} {{ if $r.Gt }} {{ if durGt $r.GetLte $r.GetGt }} if dur <= gt || dur > lte { err := {{ err . "value must be inside range (" (durStr $r.GetGt) ", " (durStr $r.GetLte) "]" }} if !all { return err } errors = append(errors, err) } {{ else }} if dur > lte && dur <= gt { err := {{ err . "value must be outside range (" (durStr $r.GetLte) ", " (durStr $r.GetGt) "]" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.Gte }} {{ if durGt $r.GetLte $r.GetGte }} if dur < gte || dur > lte { err := {{ err . "value must be inside range [" (durStr $r.GetGte) ", " (durStr $r.GetLte) "]" }} if !all { return err } errors = append(errors, err) } {{ else }} if dur > lte && dur < gte { err := {{ err . "value must be outside range (" (durStr $r.GetLte) ", " (durStr $r.GetGte) ")" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else }} if dur > lte { err := {{ err . "value must be less than or equal to " (durStr $r.GetLte) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.Gt }} if dur <= gt { err := {{ err . "value must be greater than " (durStr $r.GetGt) }} if !all { return err } errors = append(errors, err) } {{ else if $r.Gte }} if dur < gte { err := {{ err . "value must be greater than or equal to " (durStr $r.GetGte) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.In }} if _, ok := {{ lookup $f "InLookup" }}[dur]; !ok { err := {{ err . "value must be in list " $r.In }} if !all { return err } errors = append(errors, err) } {{ else if $r.NotIn }} if _, ok := {{ lookup $f "NotInLookup" }}[dur]; ok { err := {{ err . "value must not be in list " $r.NotIn }} if !all { return err } errors = append(errors, err) } {{ end }} ` protoc-gen-validate-1.0.2/templates/goshared/enum.go000066400000000000000000000006021444536353100224510ustar00rootroot00000000000000package goshared const enumTpl = ` {{ $f := .Field }}{{ $r := .Rules }} {{ template "const" . }} {{ template "in" . }} {{ if $r.GetDefinedOnly }} if _, ok := {{ (typ $f).Element.Value }}_name[int32({{ accessor . }})]; !ok { err := {{ err . "value must be one of the defined enum values" }} if !all { return err } errors = append(errors, err) } {{ end }} ` protoc-gen-validate-1.0.2/templates/goshared/in.go000066400000000000000000000013431444536353100221160ustar00rootroot00000000000000package goshared const inTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{ if $r.In }} if _, ok := {{ lookup $f "InLookup" }}[{{ accessor . }}]; !ok { {{- if isEnum $f }} err := {{ err . "value must be in list " (enumList $f $r.In) }} {{- else }} err := {{ err . "value must be in list " $r.In }} {{- end }} if !all { return err } errors = append(errors, err) } {{ else if $r.NotIn }} if _, ok := {{ lookup $f "NotInLookup" }}[{{ accessor . }}]; ok { {{- if isEnum $f }} err := {{ err . "value must not be in list " (enumList $f $r.NotIn) }} {{- else }} err := {{ err . "value must not be in list " $r.NotIn }} {{- end }} if !all { return err } errors = append(errors, err) } {{ end }} ` protoc-gen-validate-1.0.2/templates/goshared/known.go000066400000000000000000000031071444536353100226440ustar00rootroot00000000000000package goshared const hostTpl = ` func (m {{ (msgTyp .).Pointer }}) _validateHostname(host string) error { s := strings.ToLower(strings.TrimSuffix(host, ".")) if len(host) > 253 { return errors.New("hostname cannot exceed 253 characters") } for _, part := range strings.Split(s, ".") { if l := len(part); l == 0 || l > 63 { return errors.New("hostname part must be non-empty and cannot exceed 63 characters") } if part[0] == '-' { return errors.New("hostname parts cannot begin with hyphens") } if part[len(part)-1] == '-' { return errors.New("hostname parts cannot end with hyphens") } for _, r := range part { if (r < 'a' || r > 'z') && (r < '0' || r > '9') && r != '-' { return fmt.Errorf("hostname parts can only contain alphanumeric characters or hyphens, got %q", string(r)) } } } return nil } ` const emailTpl = ` func (m {{ (msgTyp .).Pointer }}) _validateEmail(addr string) error { a, err := mail.ParseAddress(addr) if err != nil { return err } addr = a.Address if len(addr) > 254 { return errors.New("email addresses cannot exceed 254 characters") } parts := strings.SplitN(addr, "@", 2) if len(parts[0]) > 64 { return errors.New("email address local phrase cannot exceed 64 characters") } return m._validateHostname(parts[1]) } ` const uuidTpl = ` func (m {{ (msgTyp .).Pointer }}) _validateUuid(uuid string) error { if matched := _{{ snakeCase .File.InputPath.BaseName }}_uuidPattern.MatchString(uuid); !matched { return errors.New("invalid uuid format") } return nil } ` protoc-gen-validate-1.0.2/templates/goshared/ltgt.go000066400000000000000000000057351444536353100224730ustar00rootroot00000000000000package goshared const ltgtTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{ if $r.Lt }} {{ if $r.Gt }} {{ if gt $r.GetLt $r.GetGt }} if val := {{ accessor . }}; val <= {{ $r.Gt }} || val >= {{ $r.Lt }} { err := {{ err . "value must be inside range (" $r.GetGt ", " $r.GetLt ")" }} if !all { return err } errors = append(errors, err) } {{ else }} if val := {{ accessor . }}; val >= {{ $r.Lt }} && val <= {{ $r.Gt }} { err := {{ err . "value must be outside range [" $r.GetLt ", " $r.GetGt "]" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.Gte }} {{ if gt $r.GetLt $r.GetGte }} if val := {{ accessor . }}; val < {{ $r.Gte }} || val >= {{ $r.Lt }} { err := {{ err . "value must be inside range [" $r.GetGte ", " $r.GetLt ")" }} if !all { return err } errors = append(errors, err) } {{ else }} if val := {{ accessor . }}; val >= {{ $r.Lt }} && val < {{ $r.Gte }} { err := {{ err . "value must be outside range [" $r.GetLt ", " $r.GetGte ")" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else }} if {{ accessor . }} >= {{ $r.Lt }} { err := {{ err . "value must be less than " $r.GetLt }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.Lte }} {{ if $r.Gt }} {{ if gt $r.GetLte $r.GetGt }} if val := {{ accessor . }}; val <= {{ $r.Gt }} || val > {{ $r.Lte }} { err := {{ err . "value must be inside range (" $r.GetGt ", " $r.GetLte "]" }} if !all { return err } errors = append(errors, err) } {{ else }} if val := {{ accessor . }}; val > {{ $r.Lte }} && val <= {{ $r.Gt }} { err := {{ err . "value must be outside range (" $r.GetLte ", " $r.GetGt "]" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.Gte }} {{ if gt $r.GetLte $r.GetGte }} if val := {{ accessor . }}; val < {{ $r.Gte }} || val > {{ $r.Lte }} { err := {{ err . "value must be inside range [" $r.GetGte ", " $r.GetLte "]" }} if !all { return err } errors = append(errors, err) } {{ else }} if val := {{ accessor . }}; val > {{ $r.Lte }} && val < {{ $r.Gte }} { err := {{ err . "value must be outside range (" $r.GetLte ", " $r.GetGte ")" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else }} if {{ accessor . }} > {{ $r.Lte }} { err := {{ err . "value must be less than or equal to " $r.GetLte }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.Gt }} if {{ accessor . }} <= {{ $r.Gt }} { err := {{ err . "value must be greater than " $r.GetGt }} if !all { return err } errors = append(errors, err) } {{ else if $r.Gte }} if {{ accessor . }} < {{ $r.Gte }} { err := {{ err . "value must be greater than or equal to " $r.GetGte }} if !all { return err } errors = append(errors, err) } {{ end }} ` protoc-gen-validate-1.0.2/templates/goshared/map.go000066400000000000000000000040101444536353100222570ustar00rootroot00000000000000package goshared const mapTpl = ` {{ $f := .Field }}{{ $r := .Rules }} {{ if $r.GetIgnoreEmpty }} if len({{ accessor . }}) > 0 { {{ end }} {{ if $r.GetMinPairs }} {{ if eq $r.GetMinPairs $r.GetMaxPairs }} if len({{ accessor . }}) != {{ $r.GetMinPairs }} { err := {{ err . "value must contain exactly " $r.GetMinPairs " pair(s)" }} if !all { return err } errors = append(errors, err) } {{ else if $r.MaxPairs }} if l := len({{ accessor . }}); l < {{ $r.GetMinPairs }} || l > {{ $r.GetMaxPairs }} { err := {{ err . "value must contain between " $r.GetMinPairs " and " $r.GetMaxPairs " pairs, inclusive" }} if !all { return err } errors = append(errors, err) } {{ else }} if len({{ accessor . }}) < {{ $r.GetMinPairs }} { err := {{ err . "value must contain at least " $r.GetMinPairs " pair(s)" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.MaxPairs }} if len({{ accessor . }}) > {{ $r.GetMaxPairs }} { err := {{ err . "value must contain no more than " $r.GetMaxPairs " pair(s)" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if or $r.GetNoSparse (ne (.Elem "" "").Typ "none") (ne (.Key "" "").Typ "none") }} {{- /* Sort the keys to make the iteration order (and therefore failure output) deterministic. */ -}} { sorted_keys := make([]{{ (typ .Field).Key }}, len({{ accessor . }})) i := 0 for key := range {{ accessor . }} { sorted_keys[i] = key i++ } sort.Slice(sorted_keys, func (i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) for _, key := range sorted_keys { val := {{ accessor .}}[key] _ = val {{ if $r.GetNoSparse }} if val == nil { err := {{ errIdx . "key" "value cannot be sparse, all pairs must be non-nil" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ render (.Key "key" "key") }} {{ render (.Elem "val" "key") }} } } {{ end }} {{ if $r.GetIgnoreEmpty }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/goshared/msg.go000066400000000000000000000201451444536353100222770ustar00rootroot00000000000000package goshared const msgTpl = ` {{ if not (ignored .) -}} {{ if disabled . -}} {{ cmt "Validate is disabled for " (msgTyp .) ". This method will always return nil." }} {{- else -}} {{ cmt "Validate checks the field values on " (msgTyp .) " with the rules defined in the proto definition for this message. If any rules are violated, the first error encountered is returned, or nil if there are no violations." }} {{- end -}} func (m {{ (msgTyp .).Pointer }}) Validate() error { return m.validate(false) } {{ if disabled . -}} {{ cmt "ValidateAll is disabled for " (msgTyp .) ". This method will always return nil." }} {{- else -}} {{ cmt "ValidateAll checks the field values on " (msgTyp .) " with the rules defined in the proto definition for this message. If any rules are violated, the result is a list of violation errors wrapped in " (multierrname .) ", or nil if none found." }} {{- end -}} func (m {{ (msgTyp .).Pointer }}) ValidateAll() error { return m.validate(true) } {{/* Unexported function to handle validation. If the need arises to add more exported functions, please consider the functional option approach outlined in protoc-gen-validate#47. */}} func (m {{ (msgTyp .).Pointer }}) validate(all bool) error { {{ if disabled . -}} return nil {{ else -}} if m == nil { return nil } var errors []error {{ range .NonOneOfFields }} {{ render (context .) }} {{ end }} {{ range .RealOneOfs }} {{- $oneof := . }} {{- if required . }} oneof{{ name $oneof }}Present := false {{- end }} switch v := m.{{ name . }}.(type) { {{- range .Fields }} {{- $context := (context .) }} case {{ oneof . }}: if v == nil { err := {{ errname .Message }}{ field: "{{ name $oneof }}", reason: "oneof value cannot be a typed-nil", } if !all { return err } errors = append(errors, err) } {{- if required $oneof }} oneof{{ name $oneof }}Present = true {{- end }} {{ render $context }} {{- end }} default: _ = v // ensures v is used } {{- if required . }} if !oneof{{ name $oneof }}Present { err := {{ errname .Message }}{ field: "{{ name $oneof }}", reason: "value is required", } if !all { return err } errors = append(errors, err) } {{- end }} {{- end }} {{ range .SyntheticOneOfFields }} if m.{{ name . }} != nil { {{ render (context .) }} } {{ end }} if len(errors) > 0 { return {{ multierrname . }}(errors) } return nil {{ end -}} } {{ if needs . "hostname" }}{{ template "hostname" . }}{{ end }} {{ if needs . "email" }}{{ template "email" . }}{{ end }} {{ if needs . "uuid" }}{{ template "uuid" . }}{{ end }} {{ cmt (multierrname .) " is an error wrapping multiple validation errors returned by " (msgTyp .) ".ValidateAll() if the designated constraints aren't met." -}} type {{ multierrname . }} []error // Error returns a concatenation of all the error messages it wraps. func (m {{ multierrname . }}) Error() string { var msgs []string for _, err := range m { msgs = append(msgs, err.Error()) } return strings.Join(msgs, "; ") } // AllErrors returns a list of validation violation errors. func (m {{ multierrname . }}) AllErrors() []error { return m } {{ cmt (errname .) " is the validation error returned by " (msgTyp .) ".Validate if the designated constraints aren't met." -}} type {{ errname . }} struct { field string reason string cause error key bool } // Field function returns field value. func (e {{ errname . }}) Field() string { return e.field } // Reason function returns reason value. func (e {{ errname . }}) Reason() string { return e.reason } // Cause function returns cause value. func (e {{ errname . }}) Cause() error { return e.cause } // Key function returns key value. func (e {{ errname . }}) Key() bool { return e.key } // ErrorName returns error name. func (e {{ errname . }}) ErrorName() string { return "{{ errname . }}" } // Error satisfies the builtin error interface func (e {{ errname . }}) Error() string { cause := "" if e.cause != nil { cause = fmt.Sprintf(" | caused by: %v", e.cause) } key := "" if e.key { key = "key for " } return fmt.Sprintf( "invalid %s{{ (msgTyp .) }}.%s: %s%s", key, e.field, e.reason, cause) } var _ error = {{ errname . }}{} var _ interface{ Field() string Reason() string Key() bool Cause() error ErrorName() string } = {{ errname . }}{} {{ range .Fields }}{{ with (context .) }}{{ $f := .Field }} {{ if has .Rules "In" }}{{ if .Rules.In }} var {{ lookup .Field "InLookup" }} = map[{{ inType .Field .Rules.In }}]struct{}{ {{- range .Rules.In }} {{ inKey $f . }}: {}, {{- end }} } {{ end }}{{ end }} {{ if has .Rules "NotIn" }}{{ if .Rules.NotIn }} var {{ lookup .Field "NotInLookup" }} = map[{{ inType .Field .Rules.In }}]struct{}{ {{- range .Rules.NotIn }} {{ inKey $f . }}: {}, {{- end }} } {{ end }}{{ end }} {{ if has .Rules "Pattern"}}{{ if .Rules.Pattern }} var {{ lookup .Field "Pattern" }} = regexp.MustCompile({{ lit .Rules.GetPattern }}) {{ end }}{{ end }} {{ if has .Rules "Items"}}{{ if .Rules.Items }} {{ if has .Rules.Items.GetString_ "Pattern" }} {{ if .Rules.Items.GetString_.Pattern }} var {{ lookup .Field "Pattern" }} = regexp.MustCompile({{ lit .Rules.Items.GetString_.GetPattern }}) {{ end }}{{ end }} {{ end }}{{ end }} {{ if has .Rules "Items"}}{{ if .Rules.Items }} {{ if has .Rules.Items.GetString_ "In" }} {{ if .Rules.Items.GetString_.In }} var {{ lookup .Field "InLookup" }} = map[string]struct{}{ {{- range .Rules.Items.GetString_.In }} {{ inKey $f . }}: {}, {{- end }} } {{ end }}{{ end }} {{ if has .Rules.Items.GetEnum "In" }} {{ if .Rules.Items.GetEnum.In }} var {{ lookup .Field "InLookup" }} = map[{{ inType .Field .Rules.Items.GetEnum.In }}]struct{}{ {{- range .Rules.Items.GetEnum.In }} {{ inKey $f . }}: {}, {{- end }} } {{ end }}{{ end }} {{ if has .Rules.Items.GetAny "In" }} {{ if .Rules.Items.GetAny.In }} var {{ lookup .Field "InLookup" }} = map[string]struct{}{ {{- range .Rules.Items.GetAny.In }} {{ inKey $f . }}: {}, {{- end }} } {{ end }}{{ end }} {{ end }}{{ end }} {{ if has .Rules "Items"}}{{ if .Rules.Items }} {{ if has .Rules.Items.GetString_ "NotIn" }} {{ if .Rules.Items.GetString_.NotIn }} var {{ lookup .Field "NotInLookup" }} = map[string]struct{}{ {{- range .Rules.Items.GetString_.NotIn }} {{ inKey $f . }}: {}, {{- end }} } {{ end }}{{ end }} {{ if has .Rules.Items.GetEnum "NotIn" }} {{ if .Rules.Items.GetEnum.NotIn }} var {{ lookup .Field "NotInLookup" }} = map[{{ inType .Field .Rules.Items.GetEnum.NotIn }}]struct{}{ {{- range .Rules.Items.GetEnum.NotIn }} {{ inKey $f . }}: {}, {{- end }} } {{ end }}{{ end }} {{ if has .Rules.Items.GetAny "NotIn" }} {{ if .Rules.Items.GetAny.NotIn }} var {{ lookup .Field "NotInLookup" }} = map[string]struct{}{ {{- range .Rules.Items.GetAny.NotIn }} {{ inKey $f . }}: {}, {{- end }} } {{ end }}{{ end }} {{ end }}{{ end }} {{ if has .Rules "Keys"}}{{ if .Rules.Keys }} {{ if has .Rules.Keys.GetString_ "In" }} {{ if .Rules.Keys.GetString_.In }} var {{ lookup .Field "InLookup" }} = map[{{ inType .Field .Rules.Keys.GetString_.In }}]struct{}{ {{- range .Rules.Keys.GetString_.In }} {{ inKey $f . }}: {}, {{- end }} } {{ end }}{{ end }} {{ if has .Rules.Keys.GetString_ "NotIn" }} {{ if .Rules.Keys.GetString_.NotIn }} var {{ lookup .Field "NotInLookup" }} = map[{{ inType .Field .Rules.Keys.GetString_.NotIn }}]struct{}{ {{- range .Rules.Keys.GetString_.NotIn }} {{ inKey $f . }}: {}, {{- end }} } {{ end }}{{ end }} {{ if has .Rules.Keys.GetString_ "Pattern" }} {{ if .Rules.Keys.GetString_.Pattern }} var {{ lookup .Field "Pattern" }} = regexp.MustCompile({{ lit .Rules.Keys.GetString_.GetPattern }}) {{ end }}{{ end }} {{ end }}{{ end }} {{ if has .Rules "Values"}}{{ if .Rules.Values }} {{ if has .Rules.Values.GetString_ "Pattern" }} {{ if .Rules.Values.GetString_.Pattern }} var {{ lookup .Field "Pattern" }} = regexp.MustCompile({{ lit .Rules.Values.GetString_.GetPattern }}) {{ end }}{{ end }} {{ end }}{{ end }} {{ end }}{{ end }} {{- end -}} ` protoc-gen-validate-1.0.2/templates/goshared/none.go000066400000000000000000000002331444536353100224440ustar00rootroot00000000000000package goshared const noneTpl = `// no validation rules for {{ name .Field }} {{- if .Index }}[{{ .Index }}]{{ end }} {{- if .OnKey }} (key){{ end }}` protoc-gen-validate-1.0.2/templates/goshared/num.go000066400000000000000000000003511444536353100223050ustar00rootroot00000000000000package goshared const numTpl = ` {{ if .Rules.GetIgnoreEmpty }} if {{ accessor . }} != 0 { {{ end }} {{ template "const" . }} {{ template "ltgt" . }} {{ template "in" . }} {{ if .Rules.GetIgnoreEmpty }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/goshared/register.go000066400000000000000000000241631444536353100233410ustar00rootroot00000000000000package goshared import ( "fmt" "reflect" "strconv" "strings" "text/template" "github.com/iancoleman/strcase" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/timestamppb" "github.com/envoyproxy/protoc-gen-validate/templates/shared" pgs "github.com/lyft/protoc-gen-star/v2" pgsgo "github.com/lyft/protoc-gen-star/v2/lang/go" ) func Register(tpl *template.Template, params pgs.Parameters) { fns := goSharedFuncs{pgsgo.InitContext(params)} tpl.Funcs(map[string]interface{}{ "accessor": fns.accessor, "byteStr": fns.byteStr, "cmt": pgs.C80, "durGt": fns.durGt, "durLit": fns.durLit, "durStr": fns.durStr, "err": fns.err, "errCause": fns.errCause, "errIdx": fns.errIdx, "errIdxCause": fns.errIdxCause, "errname": fns.errName, "multierrname": fns.multiErrName, "inKey": fns.inKey, "inType": fns.inType, "isBytes": fns.isBytes, "lit": fns.lit, "lookup": fns.lookup, "msgTyp": fns.msgTyp, "name": fns.Name, "oneof": fns.oneofTypeName, "pkg": fns.PackageName, "snakeCase": fns.snakeCase, "tsGt": fns.tsGt, "tsLit": fns.tsLit, "tsStr": fns.tsStr, "typ": fns.Type, "unwrap": fns.unwrap, "externalEnums": fns.externalEnums, "enumName": fns.enumName, "enumPackages": fns.enumPackages, }) template.Must(tpl.New("msg").Parse(msgTpl)) template.Must(tpl.New("const").Parse(constTpl)) template.Must(tpl.New("ltgt").Parse(ltgtTpl)) template.Must(tpl.New("in").Parse(inTpl)) template.Must(tpl.New("none").Parse(noneTpl)) template.Must(tpl.New("float").Parse(numTpl)) template.Must(tpl.New("double").Parse(numTpl)) template.Must(tpl.New("int32").Parse(numTpl)) template.Must(tpl.New("int64").Parse(numTpl)) template.Must(tpl.New("uint32").Parse(numTpl)) template.Must(tpl.New("uint64").Parse(numTpl)) template.Must(tpl.New("sint32").Parse(numTpl)) template.Must(tpl.New("sint64").Parse(numTpl)) template.Must(tpl.New("fixed32").Parse(numTpl)) template.Must(tpl.New("fixed64").Parse(numTpl)) template.Must(tpl.New("sfixed32").Parse(numTpl)) template.Must(tpl.New("sfixed64").Parse(numTpl)) template.Must(tpl.New("bool").Parse(constTpl)) template.Must(tpl.New("string").Parse(strTpl)) template.Must(tpl.New("bytes").Parse(bytesTpl)) template.Must(tpl.New("email").Parse(emailTpl)) template.Must(tpl.New("hostname").Parse(hostTpl)) template.Must(tpl.New("address").Parse(hostTpl)) template.Must(tpl.New("uuid").Parse(uuidTpl)) template.Must(tpl.New("enum").Parse(enumTpl)) template.Must(tpl.New("repeated").Parse(repTpl)) template.Must(tpl.New("map").Parse(mapTpl)) template.Must(tpl.New("any").Parse(anyTpl)) template.Must(tpl.New("timestampcmp").Parse(timestampcmpTpl)) template.Must(tpl.New("durationcmp").Parse(durationcmpTpl)) template.Must(tpl.New("wrapper").Parse(wrapperTpl)) } type goSharedFuncs struct{ pgsgo.Context } func (fns goSharedFuncs) accessor(ctx shared.RuleContext) string { if ctx.AccessorOverride != "" { return ctx.AccessorOverride } return fmt.Sprintf("m.Get%s()", fns.Name(ctx.Field)) } func (fns goSharedFuncs) errName(m pgs.Message) pgs.Name { return fns.Name(m) + "ValidationError" } func (fns goSharedFuncs) multiErrName(m pgs.Message) pgs.Name { return fns.Name(m) + "MultiError" } func (fns goSharedFuncs) errIdxCause(ctx shared.RuleContext, idx, cause string, reason ...interface{}) string { f := ctx.Field n := fns.Name(f) var fld string if idx != "" { fld = fmt.Sprintf(`fmt.Sprintf("%s[%%v]", %s)`, n, idx) } else if ctx.Index != "" { fld = fmt.Sprintf(`fmt.Sprintf("%s[%%v]", %s)`, n, ctx.Index) } else { fld = fmt.Sprintf("%q", n) } causeFld := "" if cause != "nil" && cause != "" { causeFld = fmt.Sprintf("cause: %s,", cause) } keyFld := "" if ctx.OnKey { keyFld = "key: true," } return fmt.Sprintf(`%s{ field: %s, reason: %q, %s%s }`, fns.errName(f.Message()), fld, fmt.Sprint(reason...), causeFld, keyFld) } func (fns goSharedFuncs) err(ctx shared.RuleContext, reason ...interface{}) string { return fns.errIdxCause(ctx, "", "nil", reason...) } func (fns goSharedFuncs) errCause(ctx shared.RuleContext, cause string, reason ...interface{}) string { return fns.errIdxCause(ctx, "", cause, reason...) } func (fns goSharedFuncs) errIdx(ctx shared.RuleContext, idx string, reason ...interface{}) string { return fns.errIdxCause(ctx, idx, "nil", reason...) } func (fns goSharedFuncs) lookup(f pgs.Field, name string) string { return fmt.Sprintf( "_%s_%s_%s", fns.Name(f.Message()), fns.Name(f), name, ) } func (fns goSharedFuncs) lit(x interface{}) string { val := reflect.ValueOf(x) if val.Kind() == reflect.Interface { val = val.Elem() } if val.Kind() == reflect.Ptr { val = val.Elem() } switch val.Kind() { case reflect.String: return fmt.Sprintf("%q", x) case reflect.Uint8: return fmt.Sprintf("0x%X", x) case reflect.Slice: els := make([]string, val.Len()) for i, l := 0, val.Len(); i < l; i++ { els[i] = fns.lit(val.Index(i).Interface()) } return fmt.Sprintf("%T{%s}", val.Interface(), strings.Join(els, ", ")) default: return fmt.Sprint(x) } } func (fns goSharedFuncs) isBytes(f interface { ProtoType() pgs.ProtoType }) bool { return f.ProtoType() == pgs.BytesT } func (fns goSharedFuncs) byteStr(x []byte) string { elms := make([]string, len(x)) for i, b := range x { elms[i] = fmt.Sprintf(`\x%X`, b) } return fmt.Sprintf(`"%s"`, strings.Join(elms, "")) } func (fns goSharedFuncs) oneofTypeName(f pgs.Field) pgsgo.TypeName { return pgsgo.TypeName(fns.OneofOption(f)).Pointer() } func (fns goSharedFuncs) inType(f pgs.Field, x interface{}) string { switch f.Type().ProtoType() { case pgs.BytesT: return "string" case pgs.MessageT: switch x.(type) { case []*durationpb.Duration: return "time.Duration" default: return pgsgo.TypeName(fmt.Sprintf("%T", x)).Element().String() } case pgs.EnumT: ens := fns.enumPackages(fns.externalEnums(f.File())) // Check if the imported name of the enum has collided and been renamed if len(ens) != 0 { var enType = f.Type().Enum() if f.Type().IsRepeated() { enType = f.Type().Element().Enum() } enImportPath := fns.ImportPath(enType) for pkg, en := range ens { if en.FilePath == enImportPath { return pkg.String() + "." + fns.enumName(enType) } } } if f.Type().IsRepeated() { return strings.TrimLeft(fns.Type(f).String(), "[]") } else { // Use Value() to strip any potential pointer type. return fns.Type(f).Value().String() } default: // Use Value() to strip any potential pointer type. return fns.Type(f).Value().String() } } func (fns goSharedFuncs) inKey(f pgs.Field, x interface{}) string { switch f.Type().ProtoType() { case pgs.BytesT: return fns.byteStr(x.([]byte)) case pgs.MessageT: switch x := x.(type) { case *durationpb.Duration: dur := x.AsDuration() return fns.lit(int64(dur)) default: return fns.lit(x) } default: return fns.lit(x) } } func (fns goSharedFuncs) durLit(dur *durationpb.Duration) string { return fmt.Sprintf( "time.Duration(%d * time.Second + %d * time.Nanosecond)", dur.GetSeconds(), dur.GetNanos()) } func (fns goSharedFuncs) durStr(dur *durationpb.Duration) string { d := dur.AsDuration() return d.String() } func (fns goSharedFuncs) durGt(a, b *durationpb.Duration) bool { ad := a.AsDuration() bd := b.AsDuration() return ad > bd } func (fns goSharedFuncs) tsLit(ts *timestamppb.Timestamp) string { return fmt.Sprintf( "time.Unix(%d, %d)", ts.GetSeconds(), ts.GetNanos(), ) } func (fns goSharedFuncs) tsGt(a, b *timestamppb.Timestamp) bool { at := a.AsTime() bt := b.AsTime() return bt.Before(at) } func (fns goSharedFuncs) tsStr(ts *timestamppb.Timestamp) string { t := ts.AsTime() return t.String() } func (fns goSharedFuncs) unwrap(ctx shared.RuleContext, name string) (shared.RuleContext, error) { ctx, err := ctx.Unwrap("wrapper") if err != nil { return ctx, err } ctx.AccessorOverride = fmt.Sprintf("%s.Get%s()", name, pgsgo.PGGUpperCamelCase(ctx.Field.Type().Embed().Fields()[0].Name())) return ctx, nil } func (fns goSharedFuncs) msgTyp(message pgs.Message) pgsgo.TypeName { return pgsgo.TypeName(fns.Name(message)) } func (fns goSharedFuncs) externalEnums(file pgs.File) []pgs.Enum { var out []pgs.Enum for _, msg := range file.AllMessages() { for _, fld := range msg.Fields() { var en pgs.Enum if fld.Type().IsEnum() { en = fld.Type().Enum() } if fld.Type().IsRepeated() { en = fld.Type().Element().Enum() } if en != nil && en.File().Package().ProtoName() != msg.File().Package().ProtoName() { out = append(out, en) } } } return out } func (fns goSharedFuncs) enumName(enum pgs.Enum) string { out := string(enum.Name()) parent := enum.Parent() for { message, ok := parent.(pgs.Message) if ok { out = string(message.Name()) + "_" + out parent = message.Parent() } else { return out } } } type NormalizedEnum struct { FilePath pgs.FilePath Name string } func (fns goSharedFuncs) enumPackages(enums []pgs.Enum) map[pgs.Name]NormalizedEnum { out := make(map[pgs.Name]NormalizedEnum, len(enums)) // Start point from ./templates/go/file.go nameCollision := map[pgs.Name]int{ "bytes": 0, "errors": 0, "fmt": 0, "net": 0, "mail": 0, "url": 0, "regexp": 0, "sort": 0, "strings": 0, "time": 0, "utf8": 0, "anypb": 0, } nameNormalized := make(map[pgs.FilePath]struct{}) for _, en := range enums { enImportPath := fns.ImportPath(en) if _, ok := nameNormalized[enImportPath]; ok { continue } pkgName := fns.PackageName(en) if collision, ok := nameCollision[pkgName]; ok { nameCollision[pkgName] = collision + 1 pkgName = pkgName + pgs.Name(strconv.Itoa(nameCollision[pkgName])) } else { nameCollision[pkgName] = 0 } nameNormalized[enImportPath] = struct{}{} out[pkgName] = NormalizedEnum{ Name: fns.enumName(en), FilePath: enImportPath, } } return out } func (fns goSharedFuncs) snakeCase(name string) string { return strcase.ToSnake(name) } protoc-gen-validate-1.0.2/templates/goshared/repeated.go000066400000000000000000000040161444536353100233010ustar00rootroot00000000000000package goshared const repTpl = ` {{ $f := .Field }}{{ $r := .Rules }} {{ if $r.GetIgnoreEmpty }} if len({{ accessor . }}) > 0 { {{ end }} {{ if $r.GetMinItems }} {{ if eq $r.GetMinItems $r.GetMaxItems }} if len({{ accessor . }}) != {{ $r.GetMinItems }} { err := {{ err . "value must contain exactly " $r.GetMinItems " item(s)" }} if !all { return err } errors = append(errors, err) } {{ else if $r.MaxItems }} if l := len({{ accessor . }}); l < {{ $r.GetMinItems }} || l > {{ $r.GetMaxItems }} { err := {{ err . "value must contain between " $r.GetMinItems " and " $r.GetMaxItems " items, inclusive" }} if !all { return err } errors = append(errors, err) } {{ else }} if len({{ accessor . }}) < {{ $r.GetMinItems }} { err := {{ err . "value must contain at least " $r.GetMinItems " item(s)" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.MaxItems }} if len({{ accessor . }}) > {{ $r.GetMaxItems }} { err := {{ err . "value must contain no more than " $r.GetMaxItems " item(s)" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.GetUnique }} {{ lookup $f "Unique" }} := {{ if isBytes $f.Type.Element -}} make(map[string]struct{}, len({{ accessor . }})) {{ else -}} make(map[{{ (typ $f).Element }}]struct{}, len({{ accessor . }})) {{ end -}} {{ end }} {{ if or $r.GetUnique (ne (.Elem "" "").Typ "none") }} for idx, item := range {{ accessor . }} { _, _ = idx, item {{ if $r.GetUnique }} if _, exists := {{ lookup $f "Unique" }}[{{ if isBytes $f.Type.Element }}string(item){{ else }}item{{ end }}]; exists { err := {{ errIdx . "idx" "repeated value must contain unique items" }} if !all { return err } errors = append(errors, err) } else { {{ lookup $f "Unique" }}[{{ if isBytes $f.Type.Element }}string(item){{ else }}item{{ end }}] = struct{}{} } {{ end }} {{ render (.Elem "item" "idx") }} } {{ end }} {{ if $r.GetIgnoreEmpty }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/goshared/string.go000066400000000000000000000140271444536353100230210ustar00rootroot00000000000000package goshared const strTpl = ` {{ $f := .Field }}{{ $r := .Rules }} {{ if $r.GetIgnoreEmpty }} if {{ accessor . }} != "" { {{ end }} {{ template "const" . }} {{ template "in" . }} {{ if or $r.Len (and $r.MinLen $r.MaxLen (eq $r.GetMinLen $r.GetMaxLen)) }} {{ if $r.Len }} if utf8.RuneCountInString({{ accessor . }}) != {{ $r.GetLen }} { err := {{ err . "value length must be " $r.GetLen " runes" }} if !all { return err } errors = append(errors, err) {{ else }} if utf8.RuneCountInString({{ accessor . }}) != {{ $r.GetMinLen }} { err := {{ err . "value length must be " $r.GetMinLen " runes" }} if !all { return err } errors = append(errors, err) {{ end }} } {{ else if $r.MinLen }} {{ if $r.MaxLen }} if l := utf8.RuneCountInString({{ accessor . }}); l < {{ $r.GetMinLen }} || l > {{ $r.GetMaxLen }} { err := {{ err . "value length must be between " $r.GetMinLen " and " $r.GetMaxLen " runes, inclusive" }} if !all { return err } errors = append(errors, err) } {{ else }} if utf8.RuneCountInString({{ accessor . }}) < {{ $r.GetMinLen }} { err := {{ err . "value length must be at least " $r.GetMinLen " runes" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.MaxLen }} if utf8.RuneCountInString({{ accessor . }}) > {{ $r.GetMaxLen }} { err := {{ err . "value length must be at most " $r.GetMaxLen " runes" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if or $r.LenBytes (and $r.MinBytes $r.MaxBytes (eq $r.GetMinBytes $r.GetMaxBytes)) }} {{ if $r.LenBytes }} if len({{ accessor . }}) != {{ $r.GetLenBytes }} { err := {{ err . "value length must be " $r.GetLenBytes " bytes" }} if !all { return err } errors = append(errors, err) } {{ else }} if len({{ accessor . }}) != {{ $r.GetMinBytes }} { err := {{ err . "value length must be " $r.GetMinBytes " bytes" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.MinBytes }} {{ if $r.MaxBytes }} if l := len({{ accessor . }}); l < {{ $r.GetMinBytes }} || l > {{ $r.GetMaxBytes }} { err := {{ err . "value length must be between " $r.GetMinBytes " and " $r.GetMaxBytes " bytes, inclusive" }} if !all { return err } errors = append(errors, err) } {{ else }} if len({{ accessor . }}) < {{ $r.GetMinBytes }} { err := {{ err . "value length must be at least " $r.GetMinBytes " bytes" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.MaxBytes }} if len({{ accessor . }}) > {{ $r.GetMaxBytes }} { err := {{ err . "value length must be at most " $r.GetMaxBytes " bytes" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.Prefix }} if !strings.HasPrefix({{ accessor . }}, {{ lit $r.GetPrefix }}) { err := {{ err . "value does not have prefix " (lit $r.GetPrefix) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.Suffix }} if !strings.HasSuffix({{ accessor . }}, {{ lit $r.GetSuffix }}) { err := {{ err . "value does not have suffix " (lit $r.GetSuffix) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.Contains }} if !strings.Contains({{ accessor . }}, {{ lit $r.GetContains }}) { err := {{ err . "value does not contain substring " (lit $r.GetContains) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.NotContains }} if strings.Contains({{ accessor . }}, {{ lit $r.GetNotContains }}) { err := {{ err . "value contains substring " (lit $r.GetNotContains) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.GetIp }} if ip := net.ParseIP({{ accessor . }}); ip == nil { err := {{ err . "value must be a valid IP address" }} if !all { return err } errors = append(errors, err) } {{ else if $r.GetIpv4 }} if ip := net.ParseIP({{ accessor . }}); ip == nil || ip.To4() == nil { err := {{ err . "value must be a valid IPv4 address" }} if !all { return err } errors = append(errors, err) } {{ else if $r.GetIpv6 }} if ip := net.ParseIP({{ accessor . }}); ip == nil || ip.To4() != nil { err := {{ err . "value must be a valid IPv6 address" }} if !all { return err } errors = append(errors, err) } {{ else if $r.GetEmail }} if err := m._validateEmail({{ accessor . }}); err != nil { err = {{ errCause . "err" "value must be a valid email address" }} if !all { return err } errors = append(errors, err) } {{ else if $r.GetHostname }} if err := m._validateHostname({{ accessor . }}); err != nil { err = {{ errCause . "err" "value must be a valid hostname" }} if !all { return err } errors = append(errors, err) } {{ else if $r.GetAddress }} if err := m._validateHostname({{ accessor . }}); err != nil { if ip := net.ParseIP({{ accessor . }}); ip == nil { err := {{ err . "value must be a valid hostname, or ip address" }} if !all { return err } errors = append(errors, err) } } {{ else if $r.GetUri }} if uri, err := url.Parse({{ accessor . }}); err != nil { err = {{ errCause . "err" "value must be a valid URI" }} if !all { return err } errors = append(errors, err) } else if !uri.IsAbs() { err := {{ err . "value must be absolute" }} if !all { return err } errors = append(errors, err) } {{ else if $r.GetUriRef }} if _, err := url.Parse({{ accessor . }}); err != nil { err = {{ errCause . "err" "value must be a valid URI" }} if !all { return err } errors = append(errors, err) } {{ else if $r.GetUuid }} if err := m._validateUuid({{ accessor . }}); err != nil { err = {{ errCause . "err" "value must be a valid UUID" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.Pattern }} if !{{ lookup $f "Pattern" }}.MatchString({{ accessor . }}) { err := {{ err . "value does not match regex pattern " (lit $r.GetPattern) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if $r.GetIgnoreEmpty }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/goshared/timestamp.go000066400000000000000000000112601444536353100235120ustar00rootroot00000000000000package goshared const timestampcmpTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{ if $r.Const }} if !ts.Equal({{ tsLit $r.Const }}) { err := {{ err . "value must equal " (tsStr $r.Const) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ if or $r.LtNow $r.GtNow $r.Within }} now := time.Now(); {{ end }} {{- if $r.Lt }} lt := {{ tsLit $r.Lt }}; {{ end }} {{- if $r.Lte }} lte := {{ tsLit $r.Lte }}; {{ end }} {{- if $r.Gt }} gt := {{ tsLit $r.Gt }}; {{ end }} {{- if $r.Gte }} gte := {{ tsLit $r.Gte }}; {{ end }} {{- if $r.Within }} within := {{ durLit $r.Within }}; {{ end }} {{ if $r.Lt }} {{ if $r.Gt }} {{ if tsGt $r.GetLt $r.GetGt }} if ts.Sub(gt) <= 0 || ts.Sub(lt) >= 0 { err := {{ err . "value must be inside range (" (tsStr $r.GetGt) ", " (tsStr $r.GetLt) ")" }} if !all { return err } errors = append(errors, err) } {{ else }} if ts.Sub(lt) >= 0 && ts.Sub(gt) <= 0 { err := {{ err . "value must be outside range [" (tsStr $r.GetLt) ", " (tsStr $r.GetGt) "]" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.Gte }} {{ if tsGt $r.GetLt $r.GetGte }} if ts.Sub(gte) < 0 || ts.Sub(lt) >= 0 { err := {{ err . "value must be inside range [" (tsStr $r.GetGte) ", " (tsStr $r.GetLt) ")" }} if !all { return err } errors = append(errors, err) } {{ else }} if ts.Sub(lt) >= 0 && ts.Sub(gte) < 0 { err := {{ err . "value must be outside range [" (tsStr $r.GetLt) ", " (tsStr $r.GetGte) ")" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else }} if ts.Sub(lt) >= 0 { err := {{ err . "value must be less than " (tsStr $r.GetLt) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.Lte }} {{ if $r.Gt }} {{ if tsGt $r.GetLte $r.GetGt }} if ts.Sub(gt) <= 0 || ts.Sub(lte) > 0 { err := {{ err . "value must be inside range (" (tsStr $r.GetGt) ", " (tsStr $r.GetLte) "]" }} if !all { return err } errors = append(errors, err) } {{ else }} if ts.Sub(lte) > 0 && ts.Sub(gt) <= 0 { err := {{ err . "value must be outside range (" (tsStr $r.GetLte) ", " (tsStr $r.GetGt) "]" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.Gte }} {{ if tsGt $r.GetLte $r.GetGte }} if ts.Sub(gte) < 0 || ts.Sub(lte) > 0 { err := {{ err . "value must be inside range [" (tsStr $r.GetGte) ", " (tsStr $r.GetLte) "]" }} if !all { return err } errors = append(errors, err) } {{ else }} if ts.Sub(lte) > 0 && ts.Sub(gte) < 0 { err := {{ err . "value must be outside range (" (tsStr $r.GetLte) ", " (tsStr $r.GetGte) ")" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else }} if ts.Sub(lte) > 0 { err := {{ err . "value must be less than or equal to " (tsStr $r.GetLte) }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.Gt }} if ts.Sub(gt) <= 0 { err := {{ err . "value must be greater than " (tsStr $r.GetGt) }} if !all { return err } errors = append(errors, err) } {{ else if $r.Gte }} if ts.Sub(gte) < 0 { err := {{ err . "value must be greater than or equal to " (tsStr $r.GetGte) }} if !all { return err } errors = append(errors, err) } {{ else if $r.LtNow }} {{ if $r.Within }} if ts.Sub(now) >= 0 || ts.Sub(now.Add(-within)) < 0 { err := {{ err . "value must be less than now within " (durStr $r.GetWithin) }} if !all { return err } errors = append(errors, err) } {{ else }} if ts.Sub(now) >= 0 { err := {{ err . "value must be less than now" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.GtNow }} {{ if $r.Within }} if ts.Sub(now) <= 0 || ts.Sub(now.Add(within)) > 0 { err := {{ err . "value must be greater than now within " (durStr $r.GetWithin) }} if !all { return err } errors = append(errors, err) } {{ else }} if ts.Sub(now) <= 0 { err := {{ err . "value must be greater than now" }} if !all { return err } errors = append(errors, err) } {{ end }} {{ else if $r.Within }} if ts.Sub(now.Add(within)) >= 0 || ts.Sub(now.Add(-within)) <= 0 { err := {{ err . "value must be within " (durStr $r.GetWithin) " of now" }} if !all { return err } errors = append(errors, err) } {{ end }} ` protoc-gen-validate-1.0.2/templates/goshared/wrapper.go000066400000000000000000000005261444536353100231720ustar00rootroot00000000000000package goshared const wrapperTpl = ` {{ $f := .Field }}{{ $r := .Rules }} if wrapper := {{ accessor . }}; wrapper != nil { {{ render (unwrap . "wrapper") }} } {{ if .MessageRules.GetRequired }} else { err := {{ err . "value is required and must not be nil." }} if !all { return err } errors = append(errors, err) } {{ end }} ` protoc-gen-validate-1.0.2/templates/java/000077500000000000000000000000001444536353100203055ustar00rootroot00000000000000protoc-gen-validate-1.0.2/templates/java/BUILD.bazel000066400000000000000000000023261444536353100221660ustar00rootroot00000000000000load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "java", srcs = [ "any.go", "bool.go", "bytes.go", "duration.go", "enum.go", "file.go", "map.go", "message.go", "msg.go", "none.go", "num.go", "oneof.go", "register.go", "repeated.go", "required.go", "string.go", "timestamp.go", "unimplemented.go", "wrapper.go", ], importpath = "github.com/envoyproxy/protoc-gen-validate/templates/java", visibility = ["//visibility:public"], deps = [ "//templates/shared", "@com_github_iancoleman_strcase//:strcase", "@com_github_lyft_protoc_gen_star_v2//:protoc-gen-star", "@com_github_lyft_protoc_gen_star_v2//lang/go", "@org_golang_google_protobuf//types/known/durationpb", "@org_golang_google_protobuf//types/known/timestamppb", ], ) alias( name = "go_default_library", actual = ":java", deprecation = "Use :java instead of :go_default_library. Details about the new naming convention: https://github.com/bazelbuild/bazel-gazelle/pull/863", visibility = ["//visibility:public"], ) protoc-gen-validate-1.0.2/templates/java/any.go000066400000000000000000000015331444536353100214250ustar00rootroot00000000000000package java const anyConstTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{- if $r.In }} private final String[] {{ constantName . "In" }} = new String[]{ {{- range $r.In }} "{{ . }}", {{- end }} }; {{- end -}} {{- if $r.NotIn }} private final String[] {{ constantName . "NotIn" }} = new String[]{ {{- range $r.NotIn }} "{{ . }}", {{- end }} }; {{- end -}}` const anyTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{- template "required" . -}} {{- if $r.In }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.CollectiveValidation.in("{{ $f.FullyQualifiedName }}", {{ accessor . }}.getTypeUrl(), {{ constantName . "In" }}); {{- end -}} {{- if $r.NotIn }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.CollectiveValidation.notIn("{{ $f.FullyQualifiedName }}", {{ accessor . }}.getTypeUrl(), {{ constantName . "NotIn" }}); {{- end -}} ` protoc-gen-validate-1.0.2/templates/java/bool.go000066400000000000000000000003321444536353100215650ustar00rootroot00000000000000package java const boolTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- if $r.Const }} io.envoyproxy.pgv.ConstantValidation.constant("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetConst }}); {{- end }}` protoc-gen-validate-1.0.2/templates/java/bytes.go000066400000000000000000000065211444536353100217660ustar00rootroot00000000000000package java const bytesConstTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- if $r.Const }} private final com.google.protobuf.ByteString {{ constantName . "Const" }} = com.google.protobuf.ByteString.copyFrom({{ byteArrayLit $r.GetConst }}); {{- end -}} {{- if $r.In }} private final com.google.protobuf.ByteString[] {{ constantName . "In" }} = new com.google.protobuf.ByteString[]{ {{- range $r.In }} com.google.protobuf.ByteString.copyFrom({{ byteArrayLit . }}), {{- end }} }; {{- end -}} {{- if $r.NotIn }} private final com.google.protobuf.ByteString[] {{ constantName . "NotIn" }} = new com.google.protobuf.ByteString[]{ {{- range $r.NotIn }} com.google.protobuf.ByteString.copyFrom({{ byteArrayLit . }}), {{- end }} }; {{- end -}} {{- if $r.Pattern }} private final com.google.re2j.Pattern {{ constantName . "Pattern" }} = com.google.re2j.Pattern.compile({{ javaStringEscape $r.GetPattern }}); {{- end -}} {{- if $r.Prefix }} private final byte[] {{ constantName . "Prefix" }} = {{ byteArrayLit $r.GetPrefix }}; {{- end -}} {{- if $r.Contains }} private final byte[] {{ constantName . "Contains" }} = {{ byteArrayLit $r.GetContains }}; {{- end -}} {{- if $r.Suffix }} private final byte[] {{ constantName . "Suffix" }} = {{ byteArrayLit $r.GetSuffix }}; {{- end -}}` const bytesTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- if $r.GetIgnoreEmpty }} if ( !{{ accessor . }}.isEmpty() ) { {{- end -}} {{- if $r.Const }} io.envoyproxy.pgv.ConstantValidation.constant("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Const" }}); {{- end -}} {{- if $r.Len }} io.envoyproxy.pgv.BytesValidation.length("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetLen }}); {{- end -}} {{- if $r.MinLen }} io.envoyproxy.pgv.BytesValidation.minLength("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetMinLen }}); {{- end -}} {{- if $r.MaxLen }} io.envoyproxy.pgv.BytesValidation.maxLength("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetMaxLen }}); {{- end -}} {{- if $r.Pattern }} io.envoyproxy.pgv.BytesValidation.pattern("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Pattern" }}); {{- end -}} {{- if $r.Prefix }} io.envoyproxy.pgv.BytesValidation.prefix("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Prefix" }}); {{- end -}} {{- if $r.Contains }} io.envoyproxy.pgv.BytesValidation.contains("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Contains" }}); {{- end -}} {{- if $r.Suffix }} io.envoyproxy.pgv.BytesValidation.suffix("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Suffix" }}); {{- end -}} {{- if $r.GetIp }} io.envoyproxy.pgv.BytesValidation.ip("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{- if $r.GetIpv4 }} io.envoyproxy.pgv.BytesValidation.ipv4("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{- if $r.GetIpv6 }} io.envoyproxy.pgv.BytesValidation.ipv6("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{- if $r.In }} io.envoyproxy.pgv.CollectiveValidation.in("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "In" }}); {{- end -}} {{- if $r.NotIn }} io.envoyproxy.pgv.CollectiveValidation.notIn("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "NotIn" }}); {{- end -}} {{- if $r.GetIgnoreEmpty }} } {{- end -}} ` protoc-gen-validate-1.0.2/templates/java/duration.go000066400000000000000000000062151444536353100224650ustar00rootroot00000000000000package java const durationConstTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- if $r.Const }} private final com.google.protobuf.Duration {{ constantName . "Const" }} = {{ durLit $r.GetConst }}; {{- end -}} {{- if $r.Lt }} private final com.google.protobuf.Duration {{ constantName . "Lt" }} = {{ durLit $r.GetLt }}; {{- end -}} {{- if $r.Lte }} private final com.google.protobuf.Duration {{ constantName . "Lte" }} = {{ durLit $r.GetLte }}; {{- end -}} {{- if $r.Gt }} private final com.google.protobuf.Duration {{ constantName . "Gt" }} = {{ durLit $r.GetGt }}; {{- end -}} {{- if $r.Gte }} private final com.google.protobuf.Duration {{ constantName . "Gte" }} = {{ durLit $r.GetGte }}; {{- end -}} {{- if $r.In }} private final com.google.protobuf.Duration[] {{ constantName . "In" }} = new com.google.protobuf.Duration[]{ {{- range $r.In }} {{ durLit . }}, {{- end }} }; {{- end -}} {{- if $r.NotIn }} private final com.google.protobuf.Duration[] {{ constantName . "NotIn" }} = new com.google.protobuf.Duration[]{ {{- range $r.NotIn }} {{ durLit . }}, {{- end }} }; {{- end -}}` const durationTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- template "required" . -}} {{- if $r.Const }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ConstantValidation.constant("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Const" }}); {{- end -}} {{- if and (or $r.Lt $r.Lte) (or $r.Gt $r.Gte)}} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ComparativeValidation.range("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ if $r.Lt }}{{ constantName . "Lt" }}{{ else }}null{{ end }}, {{ if $r.Lte }}{{ constantName . "Lte" }}{{ else }}null{{ end }}, {{ if $r.Gt }}{{ constantName . "Gt" }}{{ else }}null{{ end }}, {{ if $r.Gte }}{{ constantName . "Gte" }}{{ else }}null{{ end }}, com.google.protobuf.util.Durations.comparator()); {{- else -}} {{- if $r.Lt }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ComparativeValidation.lessThan("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Lt" }}, com.google.protobuf.util.Durations.comparator()); {{- end -}} {{- if $r.Lte }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ComparativeValidation.lessThanOrEqual("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Lte" }}, com.google.protobuf.util.Durations.comparator()); {{- end -}} {{- if $r.Gt }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ComparativeValidation.greaterThan("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Gt" }}, com.google.protobuf.util.Durations.comparator()); {{- end -}} {{- if $r.Gte }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ComparativeValidation.greaterThanOrEqual("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Gte" }}, com.google.protobuf.util.Durations.comparator()); {{- end -}} {{- end -}} {{- if $r.In }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.CollectiveValidation.in("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "In" }}); {{- end -}} {{- if $r.NotIn }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.CollectiveValidation.notIn("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "NotIn" }}); {{- end -}} ` protoc-gen-validate-1.0.2/templates/java/enum.go000066400000000000000000000023231444536353100216000ustar00rootroot00000000000000package java const enumConstTpl = `{{ $ctx := . }}{{ $f := .Field }}{{ $r := .Rules -}} {{- if $r.In }} private final {{ javaTypeFor . }}[] {{ constantName . "In" }} = new {{ javaTypeFor . }}[]{ {{- range $r.In }} {{ javaTypeFor $ctx }}.forNumber({{- sprintf "%v" . -}}), {{- end }} }; {{- end -}} {{- if $r.NotIn }} private final {{ javaTypeFor . }}[] {{ constantName . "NotIn" }} = new {{ javaTypeFor . }}[]{ {{- range $r.NotIn }} {{ javaTypeFor $ctx }}.forNumber({{- sprintf "%v" . -}}), {{- end }} }; {{- end -}}` const enumTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- if $r.Const }} io.envoyproxy.pgv.ConstantValidation.constant("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ javaTypeFor . }}.forNumber({{ $r.GetConst }})); {{- end -}} {{- if $r.GetDefinedOnly }} io.envoyproxy.pgv.EnumValidation.definedOnly("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{- if $r.In }} io.envoyproxy.pgv.CollectiveValidation.in("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "In" }}); {{- end -}} {{- if $r.NotIn }} io.envoyproxy.pgv.CollectiveValidation.notIn("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "NotIn" }}); {{- end -}} ` protoc-gen-validate-1.0.2/templates/java/file.go000066400000000000000000000023501444536353100215530ustar00rootroot00000000000000package java const fileTpl = `// Code generated by protoc-gen-validate. DO NOT EDIT. // source: {{ .File.InputPath }} package {{ javaPackage .File }}; {{ if isOfFileType . }} @SuppressWarnings("all") public class {{ classNameFile . }}Validator { public static io.envoyproxy.pgv.ValidatorImpl validatorFor(Class clazz) { {{ range .AllMessages }} {{ if not (ignored .) -}} if (clazz.equals({{ qualifiedName . }}.class)) return new {{ simpleName .}}Validator(); {{- end }} {{- end }} return null; } {{ range .AllMessages -}} {{- template "msg" . -}} {{- end }} } {{ else }} /** * Validates {@code {{ simpleName . }}} protobuf objects. */ @SuppressWarnings("all") public class {{ classNameMessage .}}Validator implements io.envoyproxy.pgv.ValidatorImpl<{{ qualifiedName . }}>{ public static io.envoyproxy.pgv.ValidatorImpl validatorFor(Class clazz) { if (clazz.equals({{ qualifiedName . }}.class)) return new {{ simpleName .}}Validator(); {{ range .AllMessages }} {{ if not (ignored .) -}} if (clazz.equals({{ qualifiedName . }}.class)) return new {{ simpleName .}}Validator(); {{- end }} {{- end }} return null; } {{- template "msgInner" . -}} {{ range .AllMessages -}} {{- template "msg" . -}} {{- end }} } {{ end }} ` protoc-gen-validate-1.0.2/templates/java/map.go000066400000000000000000000022641444536353100214150ustar00rootroot00000000000000package java const mapConstTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{ if or (ne (.Elem "" "").Typ "none") (ne (.Key "" "").Typ "none") }} {{ renderConstants (.Key "key" "Key") }} {{ renderConstants (.Elem "value" "Value") }} {{- end -}} ` const mapTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- if $r.GetIgnoreEmpty }} if ( !{{ accessor . }}.isEmpty() ) { {{- end -}} {{- if $r.GetMinPairs }} io.envoyproxy.pgv.MapValidation.min("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetMinPairs }}); {{- end -}} {{- if $r.GetMaxPairs }} io.envoyproxy.pgv.MapValidation.max("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetMaxPairs }}); {{- end -}} {{- if $r.GetNoSparse }} io.envoyproxy.pgv.MapValidation.noSparse("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{ if or (ne (.Elem "" "").Typ "none") (ne (.Key "" "").Typ "none") }} io.envoyproxy.pgv.MapValidation.validateParts({{ accessor . }}.keySet(), key -> { {{ render (.Key "key" "Key") }} }); io.envoyproxy.pgv.MapValidation.validateParts({{ accessor . }}.values(), value -> { {{ render (.Elem "value" "Value") }} }); {{- end -}} {{- if $r.GetIgnoreEmpty }} } {{- end -}} ` protoc-gen-validate-1.0.2/templates/java/message.go000066400000000000000000000005741444536353100222660ustar00rootroot00000000000000package java const messageTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{- if .MessageRules.GetSkip }} // skipping validation for {{ $f.Name }} {{- else -}} {{- template "required" . }} {{- if (isOfMessageType $f) }} // Validate {{ $f.Name }} if ({{ hasAccessor . }}) index.validatorFor({{ accessor . }}).assertValid({{ accessor . }}); {{- end -}} {{- end -}} ` protoc-gen-validate-1.0.2/templates/java/msg.go000066400000000000000000000020261444536353100214220ustar00rootroot00000000000000package java const msgTpl = ` {{ if not (ignored .) -}} /** * Validates {@code {{ simpleName . }}} protobuf objects. */ public static class {{ simpleName . }}Validator implements io.envoyproxy.pgv.ValidatorImpl<{{ qualifiedName . }}> { {{- template "msgInner" . -}} } {{- end -}} ` const msgInnerTpl = ` {{- range .NonOneOfFields }} {{ renderConstants (context .) }} {{ end }} {{ range .SyntheticOneOfFields }} {{ renderConstants (context .) }} {{ end }} {{ range .RealOneOfs }} {{ template "oneOfConst" . }} {{ end }} public void assertValid({{ qualifiedName . }} proto, io.envoyproxy.pgv.ValidatorIndex index) throws io.envoyproxy.pgv.ValidationException { {{ if disabled . }} // Validate is disabled for {{ simpleName . }} return; {{- else -}} {{ range .NonOneOfFields -}} {{ render (context .) }} {{ end -}} {{ range .SyntheticOneOfFields }} if ({{ hasAccessor (context .) }}) { {{ render (context .) }} } {{ end }} {{ range .RealOneOfs }} {{ template "oneOf" . }} {{- end -}} {{- end }} } ` protoc-gen-validate-1.0.2/templates/java/none.go000066400000000000000000000001241444536353100215700ustar00rootroot00000000000000package java const noneTpl = `// no validation rules for {{ simpleName .Field }} ` protoc-gen-validate-1.0.2/templates/java/num.go000066400000000000000000000061241444536353100214360ustar00rootroot00000000000000package java const numConstTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- if $r.Const }} private final {{ javaTypeFor .}} {{ constantName . "Const" }} = {{ $r.GetConst }}{{ javaTypeLiteralSuffixFor . }}; {{- end -}} {{- if $r.Lt }} private final {{ javaTypeFor .}} {{ constantName . "Lt" }} = {{ $r.GetLt }}{{ javaTypeLiteralSuffixFor . }}; {{- end -}} {{- if $r.Lte }} private final {{ javaTypeFor .}} {{ constantName . "Lte" }} = {{ $r.GetLte }}{{ javaTypeLiteralSuffixFor . }}; {{- end -}} {{- if $r.Gt }} private final {{ javaTypeFor .}} {{ constantName . "Gt" }} = {{ $r.GetGt }}{{ javaTypeLiteralSuffixFor . }}; {{- end -}} {{- if $r.Gte }} private final {{ javaTypeFor .}} {{ constantName . "Gte" }} = {{ $r.GetGte }}{{ javaTypeLiteralSuffixFor . }}; {{- end -}} {{- if $r.In }} private final {{ javaTypeFor . }}[] {{ constantName . "In" }} = new {{ javaTypeFor . }}[]{ {{- range $r.In -}} {{- sprintf "%v" . -}}{{ javaTypeLiteralSuffixFor $ }}, {{- end -}} }; {{- end -}} {{- if $r.NotIn }} private final {{ javaTypeFor . }}[] {{ constantName . "NotIn" }} = new {{ javaTypeFor . }}[]{ {{- range $r.NotIn -}} {{- sprintf "%v" . -}}{{ javaTypeLiteralSuffixFor $ }}, {{- end -}} }; {{- end -}}` const numTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- if $r.GetIgnoreEmpty }} if ( {{ accessor . }} != 0 ) { {{- end -}} {{- if $r.Const }} io.envoyproxy.pgv.ConstantValidation.constant("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Const" }}); {{- end -}} {{- if and (or $r.Lt $r.Lte) (or $r.Gt $r.Gte)}} io.envoyproxy.pgv.ComparativeValidation.range("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ if $r.Lt }}{{ constantName . "Lt" }}{{ else }}null{{ end }}, {{ if $r.Lte }}{{ constantName . "Lte" }}{{ else }}null{{ end }}, {{ if $r.Gt }}{{ constantName . "Gt" }}{{ else }}null{{ end }}, {{ if $r.Gte }}{{ constantName . "Gte" }}{{ else }}null{{ end }}, java.util.Comparator.naturalOrder()); {{- else -}} {{- if $r.Lt }} io.envoyproxy.pgv.ComparativeValidation.lessThan("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Lt" }}, java.util.Comparator.naturalOrder()); {{- end -}} {{- if $r.Lte }} io.envoyproxy.pgv.ComparativeValidation.lessThanOrEqual("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Lte" }}, java.util.Comparator.naturalOrder()); {{- end -}} {{- if $r.Gt }} io.envoyproxy.pgv.ComparativeValidation.greaterThan("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Gt" }}, java.util.Comparator.naturalOrder()); {{- end -}} {{- if $r.Gte }} io.envoyproxy.pgv.ComparativeValidation.greaterThanOrEqual("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Gte" }}, java.util.Comparator.naturalOrder()); {{- end -}} {{- end -}} {{- if $r.In }} io.envoyproxy.pgv.CollectiveValidation.in("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "In" }}); {{- end -}} {{- if $r.NotIn }} io.envoyproxy.pgv.CollectiveValidation.notIn("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "NotIn" }}); {{- end -}} {{- if $r.GetIgnoreEmpty }} } {{- end -}} ` protoc-gen-validate-1.0.2/templates/java/oneof.go000066400000000000000000000006521444536353100217450ustar00rootroot00000000000000package java const oneOfConstTpl = ` {{ range .Fields }}{{ renderConstants (context .) }}{{ end }} ` const oneOfTpl = ` switch (proto.get{{camelCase .Name }}Case()) { {{ range .Fields -}} case {{ oneof . }}: {{ render (context .) }} break; {{ end -}} {{- if required . }} default: io.envoyproxy.pgv.RequiredValidation.required("{{ .FullyQualifiedName }}", null); {{- end }} } ` protoc-gen-validate-1.0.2/templates/java/register.go000066400000000000000000000354071444536353100224710ustar00rootroot00000000000000package java import ( "bytes" "fmt" "os" "strings" "text/template" "unicode" "github.com/envoyproxy/protoc-gen-validate/templates/shared" "github.com/iancoleman/strcase" pgs "github.com/lyft/protoc-gen-star/v2" pgsgo "github.com/lyft/protoc-gen-star/v2/lang/go" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/timestamppb" ) func RegisterIndex(tpl *template.Template, params pgs.Parameters) { fns := javaFuncs{pgsgo.InitContext(params)} tpl.Funcs(map[string]interface{}{ "classNameFile": classNameFile, "importsPvg": importsPvg, "javaPackage": javaPackage, "simpleName": fns.Name, "qualifiedName": fns.qualifiedName, }) } func Register(tpl *template.Template, params pgs.Parameters) { fns := javaFuncs{pgsgo.InitContext(params)} tpl.Funcs(map[string]interface{}{ "accessor": fns.accessor, "byteArrayLit": fns.byteArrayLit, "camelCase": fns.camelCase, "classNameFile": classNameFile, "classNameMessage": classNameMessage, "durLit": fns.durLit, "fieldName": fns.fieldName, "javaPackage": javaPackage, "javaStringEscape": fns.javaStringEscape, "javaTypeFor": fns.javaTypeFor, "javaTypeLiteralSuffixFor": fns.javaTypeLiteralSuffixFor, "hasAccessor": fns.hasAccessor, "oneof": fns.oneofTypeName, "sprintf": fmt.Sprintf, "simpleName": fns.Name, "tsLit": fns.tsLit, "qualifiedName": fns.qualifiedName, "isOfFileType": fns.isOfFileType, "isOfMessageType": fns.isOfMessageType, "isOfStringType": fns.isOfStringType, "unwrap": fns.unwrap, "renderConstants": fns.renderConstants(tpl), "constantName": fns.constantName, }) template.Must(tpl.Parse(fileTpl)) template.Must(tpl.New("msg").Parse(msgTpl)) template.Must(tpl.New("msgInner").Parse(msgInnerTpl)) template.Must(tpl.New("none").Parse(noneTpl)) template.Must(tpl.New("float").Parse(numTpl)) template.Must(tpl.New("floatConst").Parse(numConstTpl)) template.Must(tpl.New("double").Parse(numTpl)) template.Must(tpl.New("doubleConst").Parse(numConstTpl)) template.Must(tpl.New("int32").Parse(numTpl)) template.Must(tpl.New("int32Const").Parse(numConstTpl)) template.Must(tpl.New("int64").Parse(numTpl)) template.Must(tpl.New("int64Const").Parse(numConstTpl)) template.Must(tpl.New("uint32").Parse(numTpl)) template.Must(tpl.New("uint32Const").Parse(numConstTpl)) template.Must(tpl.New("uint64").Parse(numTpl)) template.Must(tpl.New("uint64Const").Parse(numConstTpl)) template.Must(tpl.New("sint32").Parse(numTpl)) template.Must(tpl.New("sint32Const").Parse(numConstTpl)) template.Must(tpl.New("sint64").Parse(numTpl)) template.Must(tpl.New("sint64Const").Parse(numConstTpl)) template.Must(tpl.New("fixed32").Parse(numTpl)) template.Must(tpl.New("fixed32Const").Parse(numConstTpl)) template.Must(tpl.New("fixed64").Parse(numTpl)) template.Must(tpl.New("fixed64Const").Parse(numConstTpl)) template.Must(tpl.New("sfixed32").Parse(numTpl)) template.Must(tpl.New("sfixed32Const").Parse(numConstTpl)) template.Must(tpl.New("sfixed64").Parse(numTpl)) template.Must(tpl.New("sfixed64Const").Parse(numConstTpl)) template.Must(tpl.New("bool").Parse(boolTpl)) template.Must(tpl.New("string").Parse(stringTpl)) template.Must(tpl.New("stringConst").Parse(stringConstTpl)) template.Must(tpl.New("bytes").Parse(bytesTpl)) template.Must(tpl.New("bytesConst").Parse(bytesConstTpl)) template.Must(tpl.New("any").Parse(anyTpl)) template.Must(tpl.New("anyConst").Parse(anyConstTpl)) template.Must(tpl.New("enum").Parse(enumTpl)) template.Must(tpl.New("enumConst").Parse(enumConstTpl)) template.Must(tpl.New("message").Parse(messageTpl)) template.Must(tpl.New("repeated").Parse(repeatedTpl)) template.Must(tpl.New("repeatedConst").Parse(repeatedConstTpl)) template.Must(tpl.New("map").Parse(mapTpl)) template.Must(tpl.New("mapConst").Parse(mapConstTpl)) template.Must(tpl.New("oneOf").Parse(oneOfTpl)) template.Must(tpl.New("oneOfConst").Parse(oneOfConstTpl)) template.Must(tpl.New("required").Parse(requiredTpl)) template.Must(tpl.New("timestamp").Parse(timestampTpl)) template.Must(tpl.New("timestampConst").Parse(timestampConstTpl)) template.Must(tpl.New("duration").Parse(durationTpl)) template.Must(tpl.New("durationConst").Parse(durationConstTpl)) template.Must(tpl.New("wrapper").Parse(wrapperTpl)) template.Must(tpl.New("wrapperConst").Parse(wrapperConstTpl)) } type javaFuncs struct{ pgsgo.Context } func JavaFilePath(f pgs.File, ctx pgsgo.Context, tpl *template.Template) *pgs.FilePath { // Don't generate validators for files that don't import PGV if !importsPvg(f) { return nil } fullPath := strings.Replace(javaPackage(f), ".", string(os.PathSeparator), -1) fileName := classNameFile(f) + "Validator.java" filePath := pgs.JoinPaths(fullPath, fileName) return &filePath } func JavaMultiFilePath(f pgs.File, m pgs.Message) pgs.FilePath { fullPath := strings.Replace(javaPackage(f), ".", string(os.PathSeparator), -1) fileName := classNameMessage(m) + "Validator.java" filePath := pgs.JoinPaths(fullPath, fileName) return filePath } func importsPvg(f pgs.File) bool { for _, dep := range f.Descriptor().Dependency { if strings.HasSuffix(dep, "validate.proto") { return true } } return false } func classNameFile(f pgs.File) string { // Explicit outer class name overrides implicit name options := f.Descriptor().GetOptions() if options != nil && !options.GetJavaMultipleFiles() && options.JavaOuterClassname != nil { return options.GetJavaOuterClassname() } protoName := pgs.FilePath(f.Name().String()).BaseName() className := sanitizeClassName(protoName) className = appendOuterClassName(className, f) return className } func classNameMessage(m pgs.Message) string { className := m.Name().String() // This is really silly, but when the multiple files option is true, protoc puts underscores in file names. // When multiple files is false, underscores are stripped. Short of rewriting all the name sanitization // logic for java, using "UnderscoreUnderscoreUnderscore" is an escape sequence seems to work with an extremely // small likelihood of name conflict. className = strings.Replace(className, "_", "UnderscoreUnderscoreUnderscore", -1) className = sanitizeClassName(className) className = strings.Replace(className, "UnderscoreUnderscoreUnderscore", "_", -1) return className } func sanitizeClassName(className string) string { className = makeInvalidClassnameCharactersUnderscores(className) className = underscoreBetweenConsecutiveUppercase(className) className = strcase.ToCamel(strcase.ToSnake(className)) className = upperCaseAfterNumber(className) return className } func javaPackage(file pgs.File) string { // Explicit java package overrides implicit package options := file.Descriptor().GetOptions() if options != nil && options.JavaPackage != nil { return options.GetJavaPackage() } return file.Package().ProtoName().String() } func (fns javaFuncs) qualifiedName(entity pgs.Entity) string { file, isFile := entity.(pgs.File) if isFile { name := javaPackage(file) if file.Descriptor().GetOptions() != nil { if !file.Descriptor().GetOptions().GetJavaMultipleFiles() { name += ("." + classNameFile(file)) } } else { name += ("." + classNameFile(file)) } return name } message, isMessage := entity.(pgs.Message) if isMessage && message.Parent() != nil { // recurse return fns.qualifiedName(message.Parent()) + "." + entity.Name().String() } enum, isEnum := entity.(pgs.Enum) if isEnum && enum.Parent() != nil { // recurse return fns.qualifiedName(enum.Parent()) + "." + entity.Name().String() } return entity.Name().String() } // Replace invalid identifier characters with an underscore func makeInvalidClassnameCharactersUnderscores(name string) string { var sb string for _, c := range name { switch { case c >= '0' && c <= '9': sb += string(c) case c >= 'a' && c <= 'z': sb += string(c) case c >= 'A' && c <= 'Z': sb += string(c) default: sb += "_" } } return sb } func upperCaseAfterNumber(name string) string { var sb string var p rune for _, c := range name { if unicode.IsDigit(p) { sb += string(unicode.ToUpper(c)) } else { sb += string(c) } p = c } return sb } func underscoreBetweenConsecutiveUppercase(name string) string { var sb string var p rune for _, c := range name { if unicode.IsUpper(p) && unicode.IsUpper(c) { sb += "_" + string(c) } else { sb += string(c) } p = c } return sb } func appendOuterClassName(outerClassName string, file pgs.File) string { conflict := false for _, enum := range file.AllEnums() { if enum.Name().String() == outerClassName { conflict = true } } for _, message := range file.AllMessages() { if message.Name().String() == outerClassName { conflict = true } } for _, service := range file.Services() { if service.Name().String() == outerClassName { conflict = true } } if conflict { return outerClassName + "OuterClass" } else { return outerClassName } } func (fns javaFuncs) accessor(ctx shared.RuleContext) string { if ctx.AccessorOverride != "" { return ctx.AccessorOverride } return fns.fieldAccessor(ctx.Field) } func (fns javaFuncs) fieldAccessor(f pgs.Field) string { fieldName := strcase.ToCamel(f.Name().String()) if f.Type().IsMap() { fieldName += "Map" } if f.Type().IsRepeated() { fieldName += "List" } fieldName = upperCaseAfterNumber(fieldName) return fmt.Sprintf("proto.get%s()", fieldName) } func (fns javaFuncs) hasAccessor(ctx shared.RuleContext) string { if ctx.AccessorOverride != "" { return "true" } fiedlName := strcase.ToCamel(ctx.Field.Name().String()) fiedlName = upperCaseAfterNumber(fiedlName) return "proto.has" + fiedlName + "()" } func (fns javaFuncs) fieldName(ctx shared.RuleContext) string { return ctx.Field.Name().String() } func (fns javaFuncs) javaTypeFor(ctx shared.RuleContext) string { t := ctx.Field.Type() // Map key and value types if t.IsMap() { switch ctx.AccessorOverride { case "key": return fns.javaTypeForProtoType(t.Key().ProtoType()) case "value": return fns.javaTypeForProtoType(t.Element().ProtoType()) } } if t.IsEmbed() { if embed := t.Embed(); embed.IsWellKnown() { switch embed.WellKnownType() { case pgs.AnyWKT: return "String" case pgs.DurationWKT: return "com.google.protobuf.Duration" case pgs.TimestampWKT: return "com.google.protobuf.Timestamp" case pgs.Int32ValueWKT, pgs.UInt32ValueWKT: return "Integer" case pgs.Int64ValueWKT, pgs.UInt64ValueWKT: return "Long" case pgs.DoubleValueWKT: return "Double" case pgs.FloatValueWKT: return "Float" } } } if t.IsRepeated() { if t.ProtoType() == pgs.MessageT { return fns.qualifiedName(t.Element().Embed()) } else if t.ProtoType() == pgs.EnumT { return fns.qualifiedName(t.Element().Enum()) } } if t.IsEnum() { return fns.qualifiedName(t.Enum()) } return fns.javaTypeForProtoType(t.ProtoType()) } func (fns javaFuncs) javaTypeForProtoType(t pgs.ProtoType) string { switch t { case pgs.Int32T, pgs.UInt32T, pgs.SInt32, pgs.Fixed32T, pgs.SFixed32: return "Integer" case pgs.Int64T, pgs.UInt64T, pgs.SInt64, pgs.Fixed64T, pgs.SFixed64: return "Long" case pgs.DoubleT: return "Double" case pgs.FloatT: return "Float" case pgs.BoolT: return "Boolean" case pgs.StringT: return "String" case pgs.BytesT: return "com.google.protobuf.ByteString" default: return "Object" } } func (fns javaFuncs) javaTypeLiteralSuffixFor(ctx shared.RuleContext) string { t := ctx.Field.Type() if t.IsMap() { switch ctx.AccessorOverride { case "key": return fns.javaTypeLiteralSuffixForPrototype(t.Key().ProtoType()) case "value": return fns.javaTypeLiteralSuffixForPrototype(t.Element().ProtoType()) } } if t.IsEmbed() { if embed := t.Embed(); embed.IsWellKnown() { switch embed.WellKnownType() { case pgs.Int64ValueWKT, pgs.UInt64ValueWKT: return "L" case pgs.FloatValueWKT: return "F" case pgs.DoubleValueWKT: return "D" } } } return fns.javaTypeLiteralSuffixForPrototype(t.ProtoType()) } func (fns javaFuncs) javaTypeLiteralSuffixForPrototype(t pgs.ProtoType) string { switch t { case pgs.Int64T, pgs.UInt64T, pgs.SInt64, pgs.Fixed64T, pgs.SFixed64: return "L" case pgs.FloatT: return "F" case pgs.DoubleT: return "D" default: return "" } } func (fns javaFuncs) javaStringEscape(s string) string { s = fmt.Sprintf("%q", s) s = s[1 : len(s)-1] s = strings.Replace(s, `\u00`, `\x`, -1) s = strings.Replace(s, `\x`, `\\x`, -1) // s = strings.Replace(s, `\`, `\\`, -1) s = strings.Replace(s, `"`, `\"`, -1) return `"` + s + `"` } func (fns javaFuncs) camelCase(name pgs.Name) string { return strcase.ToCamel(name.String()) } func (fns javaFuncs) byteArrayLit(bytes []uint8) string { var sb string sb += "new byte[]{" for _, b := range bytes { sb += fmt.Sprintf("(byte)%#x,", b) } sb += "}" return sb } func (fns javaFuncs) durLit(dur *durationpb.Duration) string { return fmt.Sprintf( "io.envoyproxy.pgv.TimestampValidation.toDuration(%dL,%d)", dur.GetSeconds(), dur.GetNanos()) } func (fns javaFuncs) tsLit(ts *timestamppb.Timestamp) string { return fmt.Sprintf( "io.envoyproxy.pgv.TimestampValidation.toTimestamp(%dL,%d)", ts.GetSeconds(), ts.GetNanos()) } func (fns javaFuncs) oneofTypeName(f pgs.Field) pgsgo.TypeName { return pgsgo.TypeName(strings.ToUpper(f.Name().String())) } func (fns javaFuncs) isOfFileType(o interface{}) bool { switch o.(type) { case pgs.File: return true default: return false } } func (fns javaFuncs) isOfMessageType(f pgs.Field) bool { return f.Type().ProtoType() == pgs.MessageT } func (fns javaFuncs) isOfStringType(f pgs.Field) bool { return f.Type().ProtoType() == pgs.StringT } func (fns javaFuncs) unwrap(ctx shared.RuleContext) (shared.RuleContext, error) { ctx, err := ctx.Unwrap("wrapped") if err != nil { return ctx, err } ctx.AccessorOverride = fmt.Sprintf("%s.get%s()", fns.fieldAccessor(ctx.Field), fns.camelCase(ctx.Field.Type().Embed().Fields()[0].Name())) return ctx, nil } func (fns javaFuncs) renderConstants(tpl *template.Template) func(ctx shared.RuleContext) (string, error) { return func(ctx shared.RuleContext) (string, error) { var b bytes.Buffer var err error hasConstTemplate := false for _, t := range tpl.Templates() { if t.Name() == ctx.Typ+"Const" { hasConstTemplate = true } } if hasConstTemplate { err = tpl.ExecuteTemplate(&b, ctx.Typ+"Const", ctx) } return b.String(), err } } func (fns javaFuncs) constantName(ctx shared.RuleContext, rule string) string { return strcase.ToScreamingSnake(ctx.Field.Name().String() + "_" + ctx.Index + "_" + rule) } protoc-gen-validate-1.0.2/templates/java/repeated.go000066400000000000000000000014751444536353100224340ustar00rootroot00000000000000package java const repeatedConstTpl = `{{ renderConstants (.Elem "" "") }}` const repeatedTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- if $r.GetIgnoreEmpty }} if ( !{{ accessor . }}.isEmpty() ) { {{- end -}} {{- if $r.GetMinItems }} io.envoyproxy.pgv.RepeatedValidation.minItems("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetMinItems }}); {{- end -}} {{- if $r.GetMaxItems }} io.envoyproxy.pgv.RepeatedValidation.maxItems("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetMaxItems }}); {{- end -}} {{- if $r.GetUnique }} io.envoyproxy.pgv.RepeatedValidation.unique("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end }} io.envoyproxy.pgv.RepeatedValidation.forEach({{ accessor . }}, item -> { {{ render (.Elem "item" "") }} }); {{- if $r.GetIgnoreEmpty }} } {{- end -}} ` protoc-gen-validate-1.0.2/templates/java/required.go000066400000000000000000000005121444536353100224520ustar00rootroot00000000000000package java const requiredTpl = `{{ $f := .Field }} {{- if .Rules.GetRequired }} if ({{ hasAccessor . }}) { io.envoyproxy.pgv.RequiredValidation.required("{{ $f.FullyQualifiedName }}", {{ accessor . }}); } else { io.envoyproxy.pgv.RequiredValidation.required("{{ $f.FullyQualifiedName }}", null); }; {{- end -}} ` protoc-gen-validate-1.0.2/templates/java/string.go000066400000000000000000000100141444536353100221360ustar00rootroot00000000000000package java const stringConstTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- if $r.In }} private final {{ javaTypeFor . }}[] {{ constantName . "In" }} = new {{ javaTypeFor . }}[]{ {{- range $r.In -}} "{{- sprintf "%v" . -}}", {{- end -}} }; {{- end -}} {{- if $r.NotIn }} private final {{ javaTypeFor . }}[] {{ constantName . "NotIn" }} = new {{ javaTypeFor . }}[]{ {{- range $r.NotIn -}} "{{- sprintf "%v" . -}}", {{- end -}} }; {{- end -}} {{- if $r.Pattern }} com.google.re2j.Pattern {{ constantName . "Pattern" }} = com.google.re2j.Pattern.compile({{ javaStringEscape $r.GetPattern }}); {{- end -}}` const stringTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- if $r.GetIgnoreEmpty }} if ( !{{ accessor . }}.isEmpty() ) { {{- end -}} {{- if $r.Const }} io.envoyproxy.pgv.ConstantValidation.constant("{{ $f.FullyQualifiedName }}", {{ accessor . }}, "{{ $r.GetConst }}"); {{- end -}} {{- if $r.In }} io.envoyproxy.pgv.CollectiveValidation.in("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "In" }}); {{- end -}} {{- if $r.NotIn }} io.envoyproxy.pgv.CollectiveValidation.notIn("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "NotIn" }}); {{- end -}} {{- if $r.Len }} io.envoyproxy.pgv.StringValidation.length("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetLen }}); {{- end -}} {{- if $r.MinLen }} io.envoyproxy.pgv.StringValidation.minLength("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetMinLen }}); {{- end -}} {{- if $r.MaxLen }} io.envoyproxy.pgv.StringValidation.maxLength("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetMaxLen }}); {{- end -}} {{- if $r.LenBytes }} io.envoyproxy.pgv.StringValidation.lenBytes("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetLenBytes }}); {{- end -}} {{- if $r.MinBytes }} io.envoyproxy.pgv.StringValidation.minBytes("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetMinBytes }}); {{- end -}} {{- if $r.MaxBytes }} io.envoyproxy.pgv.StringValidation.maxBytes("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ $r.GetMaxBytes }}); {{- end -}} {{- if $r.Pattern }} io.envoyproxy.pgv.StringValidation.pattern("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Pattern" }}); {{- end -}} {{- if $r.Prefix }} io.envoyproxy.pgv.StringValidation.prefix("{{ $f.FullyQualifiedName }}", {{ accessor . }}, "{{ $r.GetPrefix }}"); {{- end -}} {{- if $r.Contains }} io.envoyproxy.pgv.StringValidation.contains("{{ $f.FullyQualifiedName }}", {{ accessor . }}, "{{ $r.GetContains }}"); {{- end -}} {{- if $r.NotContains }} io.envoyproxy.pgv.StringValidation.notContains("{{ $f.FullyQualifiedName }}", {{ accessor . }}, "{{ $r.GetNotContains }}"); {{- end -}} {{- if $r.Suffix }} io.envoyproxy.pgv.StringValidation.suffix("{{ $f.FullyQualifiedName }}", {{ accessor . }}, "{{ $r.GetSuffix }}"); {{- end -}} {{- if $r.GetEmail }} io.envoyproxy.pgv.StringValidation.email("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{- if $r.GetAddress }} io.envoyproxy.pgv.StringValidation.address("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{- if $r.GetHostname }} io.envoyproxy.pgv.StringValidation.hostName("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{- if $r.GetIp }} io.envoyproxy.pgv.StringValidation.ip("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{- if $r.GetIpv4 }} io.envoyproxy.pgv.StringValidation.ipv4("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{- if $r.GetIpv6 }} io.envoyproxy.pgv.StringValidation.ipv6("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{- if $r.GetUri }} io.envoyproxy.pgv.StringValidation.uri("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{- if $r.GetUriRef }} io.envoyproxy.pgv.StringValidation.uriRef("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{- if $r.GetUuid }} io.envoyproxy.pgv.StringValidation.uuid("{{ $f.FullyQualifiedName }}", {{ accessor . }}); {{- end -}} {{- if $r.GetIgnoreEmpty }} } {{- end -}} ` protoc-gen-validate-1.0.2/templates/java/timestamp.go000066400000000000000000000064461444536353100226510ustar00rootroot00000000000000package java const timestampConstTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- if $r.Const }} private final com.google.protobuf.Timestamp {{ constantName . "Const" }} = {{ tsLit $r.GetConst }}; {{- end -}} {{- if $r.Lt }} private final com.google.protobuf.Timestamp {{ constantName . "Lt" }} = {{ tsLit $r.GetLt }}; {{- end -}} {{- if $r.Lte }} private final com.google.protobuf.Timestamp {{ constantName . "Lte" }} = {{ tsLit $r.Lte }}; {{- end -}} {{- if $r.Gt }} private final com.google.protobuf.Timestamp {{ constantName . "Gt" }} = {{ tsLit $r.GetGt }}; {{- end -}} {{- if $r.Gte }} private final com.google.protobuf.Timestamp {{ constantName . "Gte" }} = {{ tsLit $r.GetGte }}; {{- end -}} {{- if $r.Within }} private final com.google.protobuf.Duration {{ constantName . "Within" }} = {{ durLit $r.GetWithin }}; {{- end -}}` const timestampTpl = `{{ $f := .Field }}{{ $r := .Rules -}} {{- template "required" . -}} {{- if $r.Const }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ConstantValidation.constant("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Const" }}); {{- end -}} {{- if and (or $r.Lt $r.Lte) (or $r.Gt $r.Gte)}} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ComparativeValidation.range("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ if $r.Lt }}{{ constantName . "Lt" }}{{ else }}null{{ end }}, {{ if $r.Lte }}{{ constantName . "Lte" }}{{ else }}null{{ end }}, {{ if $r.Gt }}{{ constantName . "Gt" }}{{ else }}null{{ end }}, {{ if $r.Gte }}{{ constantName . "Gte" }}{{ else }}null{{ end }}, com.google.protobuf.util.Timestamps.comparator()); {{- else -}} {{- if $r.Lt }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ComparativeValidation.lessThan("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Lt" }}, com.google.protobuf.util.Timestamps.comparator()); {{- end -}} {{- if $r.Lte }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ComparativeValidation.lessThanOrEqual("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Lte" }}, com.google.protobuf.util.Timestamps.comparator()); {{- end -}} {{- if $r.Gt }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ComparativeValidation.greaterThan("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Gt" }}, com.google.protobuf.util.Timestamps.comparator()); {{- end -}} {{- if $r.Gte }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ComparativeValidation.greaterThanOrEqual("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Gte" }}, com.google.protobuf.util.Timestamps.comparator()); {{- end -}} {{- end -}} {{- if $r.LtNow }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ComparativeValidation.lessThan("{{ $f.FullyQualifiedName }}", {{ accessor . }}, io.envoyproxy.pgv.TimestampValidation.currentTimestamp(), com.google.protobuf.util.Timestamps.comparator()); {{- end -}} {{- if $r.GtNow }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.ComparativeValidation.greaterThan("{{ $f.FullyQualifiedName }}", {{ accessor . }}, io.envoyproxy.pgv.TimestampValidation.currentTimestamp(), com.google.protobuf.util.Timestamps.comparator()); {{- end -}} {{- if $r.Within }} if ({{ hasAccessor . }}) io.envoyproxy.pgv.TimestampValidation.within("{{ $f.FullyQualifiedName }}", {{ accessor . }}, {{ constantName . "Within" }}, io.envoyproxy.pgv.TimestampValidation.currentTimestamp()); {{- end -}} ` protoc-gen-validate-1.0.2/templates/java/unimplemented.go000066400000000000000000000001041444536353100234750ustar00rootroot00000000000000package java const notImplementedTpl = `/* NOT YET IMPLEMENTED */` protoc-gen-validate-1.0.2/templates/java/wrapper.go000066400000000000000000000006071444536353100223170ustar00rootroot00000000000000package java const wrapperConstTpl = `{{ $f := .Field }}{{ $r := .Rules }} {{- renderConstants (unwrap .) }}` const wrapperTpl = `{{ $f := .Field }}{{ $r := .Rules }} if ({{ hasAccessor . }}) { {{- render (unwrap .) }} } {{ if .MessageRules.GetRequired }} else { throw new io.envoyproxy.pgv.ValidationException("{{ $f }}", "null", "is required"); } {{ end }}` protoc-gen-validate-1.0.2/templates/pkg.go000066400000000000000000000031701444536353100204750ustar00rootroot00000000000000package templates import ( "github.com/envoyproxy/protoc-gen-validate/templates/cc" pgs "github.com/lyft/protoc-gen-star/v2" pgsgo "github.com/lyft/protoc-gen-star/v2/lang/go" "text/template" "github.com/envoyproxy/protoc-gen-validate/templates/ccnop" "github.com/envoyproxy/protoc-gen-validate/templates/go" "github.com/envoyproxy/protoc-gen-validate/templates/java" "github.com/envoyproxy/protoc-gen-validate/templates/shared" ) type RegisterFn func(tpl *template.Template, params pgs.Parameters) type FilePathFn func(f pgs.File, ctx pgsgo.Context, tpl *template.Template) *pgs.FilePath func makeTemplate(ext string, fn RegisterFn, params pgs.Parameters) *template.Template { tpl := template.New(ext) shared.RegisterFunctions(tpl, params) fn(tpl, params) return tpl } func Template(params pgs.Parameters) map[string][]*template.Template { return map[string][]*template.Template{ "cc": {makeTemplate("h", cc.RegisterHeader, params), makeTemplate("cc", cc.RegisterModule, params)}, "ccnop": {makeTemplate("h", ccnop.RegisterHeader, params), makeTemplate("cc", ccnop.RegisterModule, params)}, "go": {makeTemplate("go", golang.Register, params)}, "java": {makeTemplate("java", java.Register, params)}, } } func FilePathFor(tpl *template.Template) FilePathFn { switch tpl.Name() { case "h": return cc.CcFilePath case "ccnop": return cc.CcFilePath case "cc": return cc.CcFilePath case "java": return java.JavaFilePath default: return func(f pgs.File, ctx pgsgo.Context, tpl *template.Template) *pgs.FilePath { out := ctx.OutputPath(f) out = out.SetExt(".validate." + tpl.Name()) return &out } } } protoc-gen-validate-1.0.2/templates/shared/000077500000000000000000000000001444536353100206325ustar00rootroot00000000000000protoc-gen-validate-1.0.2/templates/shared/BUILD.bazel000066400000000000000000000014421444536353100225110ustar00rootroot00000000000000load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "shared", srcs = [ "context.go", "disabled.go", "functions.go", "reflection.go", "well_known.go", "enums.go" ], importpath = "github.com/envoyproxy/protoc-gen-validate/templates/shared", visibility = ["//visibility:public"], deps = [ "//validate:validate_go", "@com_github_lyft_protoc_gen_star_v2//:protoc-gen-star", "@org_golang_google_protobuf//proto", ], ) alias( name = "go_default_library", actual = ":shared", deprecation = "Use :shared instead of :go_default_library. Details about the new naming convention: https://github.com/bazelbuild/bazel-gazelle/pull/863", visibility = ["//visibility:public"], ) protoc-gen-validate-1.0.2/templates/shared/context.go000066400000000000000000000122271444536353100226510ustar00rootroot00000000000000package shared import ( "bytes" "fmt" "text/template" "github.com/envoyproxy/protoc-gen-validate/validate" pgs "github.com/lyft/protoc-gen-star/v2" "google.golang.org/protobuf/proto" ) type RuleContext struct { Field pgs.Field Rules proto.Message MessageRules *validate.MessageRules Typ string WrapperTyp string OnKey bool Index string AccessorOverride string } func rulesContext(f pgs.Field) (out RuleContext, err error) { out.Field = f var rules validate.FieldRules if _, err = f.Extension(validate.E_Rules, &rules); err != nil { return } var wrapped bool if out.Typ, out.Rules, out.MessageRules, wrapped = resolveRules(f.Type(), &rules); wrapped { out.WrapperTyp = out.Typ out.Typ = "wrapper" } if out.Typ == "error" { err = fmt.Errorf("unknown rule type (%T)", rules.Type) } return } func (ctx RuleContext) Key(name, idx string) (out RuleContext, err error) { rules, ok := ctx.Rules.(*validate.MapRules) if !ok { err = fmt.Errorf("cannot get Key RuleContext from %T", ctx.Field) return } out.Field = ctx.Field out.AccessorOverride = name out.Index = idx out.Typ, out.Rules, out.MessageRules, _ = resolveRules(ctx.Field.Type().Key(), rules.GetKeys()) if out.Typ == "error" { err = fmt.Errorf("unknown rule type (%T)", rules) } return } func (ctx RuleContext) Elem(name, idx string) (out RuleContext, err error) { out.Field = ctx.Field out.AccessorOverride = name out.Index = idx var rules *validate.FieldRules switch r := ctx.Rules.(type) { case *validate.MapRules: rules = r.GetValues() case *validate.RepeatedRules: rules = r.GetItems() default: err = fmt.Errorf("cannot get Elem RuleContext from %T", ctx.Field) return } var wrapped bool if out.Typ, out.Rules, out.MessageRules, wrapped = resolveRules(ctx.Field.Type().Element(), rules); wrapped { out.WrapperTyp = out.Typ out.Typ = "wrapper" } if out.Typ == "error" { err = fmt.Errorf("unknown rule type (%T)", rules) } return } func (ctx RuleContext) Unwrap(name string) (out RuleContext, err error) { if ctx.Typ != "wrapper" { err = fmt.Errorf("cannot unwrap non-wrapper type %q", ctx.Typ) return } return RuleContext{ Field: ctx.Field, Rules: ctx.Rules, MessageRules: ctx.MessageRules, Typ: ctx.WrapperTyp, AccessorOverride: name, }, nil } func Render(tpl *template.Template) func(ctx RuleContext) (string, error) { return func(ctx RuleContext) (string, error) { var b bytes.Buffer err := tpl.ExecuteTemplate(&b, ctx.Typ, ctx) return b.String(), err } } func resolveRules(typ interface{ IsEmbed() bool }, rules *validate.FieldRules) (ruleType string, rule proto.Message, messageRule *validate.MessageRules, wrapped bool) { switch r := rules.GetType().(type) { case *validate.FieldRules_Float: ruleType, rule, wrapped = "float", r.Float, typ.IsEmbed() case *validate.FieldRules_Double: ruleType, rule, wrapped = "double", r.Double, typ.IsEmbed() case *validate.FieldRules_Int32: ruleType, rule, wrapped = "int32", r.Int32, typ.IsEmbed() case *validate.FieldRules_Int64: ruleType, rule, wrapped = "int64", r.Int64, typ.IsEmbed() case *validate.FieldRules_Uint32: ruleType, rule, wrapped = "uint32", r.Uint32, typ.IsEmbed() case *validate.FieldRules_Uint64: ruleType, rule, wrapped = "uint64", r.Uint64, typ.IsEmbed() case *validate.FieldRules_Sint32: ruleType, rule, wrapped = "sint32", r.Sint32, false case *validate.FieldRules_Sint64: ruleType, rule, wrapped = "sint64", r.Sint64, false case *validate.FieldRules_Fixed32: ruleType, rule, wrapped = "fixed32", r.Fixed32, false case *validate.FieldRules_Fixed64: ruleType, rule, wrapped = "fixed64", r.Fixed64, false case *validate.FieldRules_Sfixed32: ruleType, rule, wrapped = "sfixed32", r.Sfixed32, false case *validate.FieldRules_Sfixed64: ruleType, rule, wrapped = "sfixed64", r.Sfixed64, false case *validate.FieldRules_Bool: ruleType, rule, wrapped = "bool", r.Bool, typ.IsEmbed() case *validate.FieldRules_String_: ruleType, rule, wrapped = "string", r.String_, typ.IsEmbed() case *validate.FieldRules_Bytes: ruleType, rule, wrapped = "bytes", r.Bytes, typ.IsEmbed() case *validate.FieldRules_Enum: ruleType, rule, wrapped = "enum", r.Enum, false case *validate.FieldRules_Repeated: ruleType, rule, wrapped = "repeated", r.Repeated, false case *validate.FieldRules_Map: ruleType, rule, wrapped = "map", r.Map, false case *validate.FieldRules_Any: ruleType, rule, wrapped = "any", r.Any, false case *validate.FieldRules_Duration: ruleType, rule, wrapped = "duration", r.Duration, false case *validate.FieldRules_Timestamp: ruleType, rule, wrapped = "timestamp", r.Timestamp, false case nil: if ft, ok := typ.(pgs.FieldType); ok && ft.IsRepeated() { return "repeated", &validate.RepeatedRules{}, rules.Message, false } else if ok && ft.IsMap() && ft.Element().IsEmbed() { return "map", &validate.MapRules{}, rules.Message, false } else if typ.IsEmbed() { return "message", rules.GetMessage(), rules.GetMessage(), false } return "none", nil, nil, false default: ruleType, rule, wrapped = "error", nil, false } return ruleType, rule, rules.Message, wrapped } protoc-gen-validate-1.0.2/templates/shared/disabled.go000066400000000000000000000013031444536353100227250ustar00rootroot00000000000000package shared import ( "github.com/envoyproxy/protoc-gen-validate/validate" pgs "github.com/lyft/protoc-gen-star/v2" ) // Disabled returns true if validations are disabled for msg func Disabled(msg pgs.Message) (disabled bool, err error) { _, err = msg.Extension(validate.E_Disabled, &disabled) return } // Ignore returns true if validations aren't to be generated for msg func Ignored(msg pgs.Message) (ignored bool, err error) { _, err = msg.Extension(validate.E_Ignored, &ignored) return } // RequiredOneOf returns true if the oneof field requires a field to be set func RequiredOneOf(oo pgs.OneOf) (required bool, err error) { _, err = oo.Extension(validate.E_Required, &required) return } protoc-gen-validate-1.0.2/templates/shared/enums.go000066400000000000000000000020151444536353100223060ustar00rootroot00000000000000package shared import ( "fmt" "strings" pgs "github.com/lyft/protoc-gen-star/v2" ) func isEnum(f pgs.Field) bool { return f.Type().IsEnum() } func enumNamesMap(values []pgs.EnumValue) (m map[int32]string) { m = make(map[int32]string) for _, v := range values { if _, exists := m[v.Value()]; !exists { m[v.Value()] = v.Name().String() } } return m } // enumList - if type is ENUM, enum values are returned func enumList(f pgs.Field, list []int32) string { stringList := make([]string, 0, len(list)) if enum := f.Type().Enum(); enum != nil { names := enumNamesMap(enum.Values()) for _, n := range list { stringList = append(stringList, names[n]) } } else { for _, n := range list { stringList = append(stringList, fmt.Sprint(n)) } } return "[" + strings.Join(stringList, " ") + "]" } // enumVal - if type is ENUM, enum value is returned func enumVal(f pgs.Field, val int32) string { if enum := f.Type().Enum(); enum != nil { return enumNamesMap(enum.Values())[val] } return fmt.Sprint(val) } protoc-gen-validate-1.0.2/templates/shared/functions.go000066400000000000000000000007351444536353100231760ustar00rootroot00000000000000package shared import ( "text/template" pgs "github.com/lyft/protoc-gen-star/v2" ) func RegisterFunctions(tpl *template.Template, params pgs.Parameters) { tpl.Funcs(map[string]interface{}{ "disabled": Disabled, "ignored": Ignored, "required": RequiredOneOf, "context": rulesContext, "render": Render(tpl), "has": Has, "needs": Needs, "fileneeds": FileNeeds, "isEnum": isEnum, "enumList": enumList, "enumVal": enumVal, }) } protoc-gen-validate-1.0.2/templates/shared/reflection.go000066400000000000000000000007401444536353100233140ustar00rootroot00000000000000package shared import ( "reflect" "google.golang.org/protobuf/proto" ) func extractVal(r proto.Message) reflect.Value { val := reflect.ValueOf(r) if val.Kind() == reflect.Interface { val = val.Elem() } if val.Kind() == reflect.Ptr { val = val.Elem() } return val } // Has returns true if the provided Message has the a field fld. func Has(msg proto.Message, fld string) bool { val := extractVal(msg) return val.IsValid() && val.FieldByName(fld).IsValid() } protoc-gen-validate-1.0.2/templates/shared/well_known.go000066400000000000000000000034431444536353100233440ustar00rootroot00000000000000package shared import ( "github.com/envoyproxy/protoc-gen-validate/validate" pgs "github.com/lyft/protoc-gen-star/v2" ) type WellKnown string const ( Email WellKnown = "email" Hostname WellKnown = "hostname" UUID WellKnown = "uuid" ) func FileNeeds(f pgs.File, wk WellKnown) bool { for _, msg := range f.AllMessages() { needed := Needs(msg, wk) if needed { return true } } return false } // Needs returns true if a well-known string validator is needed for this // message. func Needs(m pgs.Message, wk WellKnown) bool { for _, f := range m.Fields() { var rules validate.FieldRules if _, err := f.Extension(validate.E_Rules, &rules); err != nil { continue } switch { case f.Type().IsRepeated() && f.Type().Element().ProtoType() == pgs.StringT: if strRulesNeeds(rules.GetRepeated().GetItems().GetString_(), wk) { return true } case f.Type().IsMap(): if f.Type().Key().ProtoType() == pgs.StringT && strRulesNeeds(rules.GetMap().GetKeys().GetString_(), wk) { return true } if f.Type().Element().ProtoType() == pgs.StringT && strRulesNeeds(rules.GetMap().GetValues().GetString_(), wk) { return true } case f.Type().ProtoType() == pgs.StringT: if strRulesNeeds(rules.GetString_(), wk) { return true } case f.Type().ProtoType() == pgs.MessageT && f.Type().IsEmbed() && f.Type().Embed().WellKnownType() == pgs.StringValueWKT: if strRulesNeeds(rules.GetString_(), wk) { return true } } } return false } func strRulesNeeds(rules *validate.StringRules, wk WellKnown) bool { switch wk { case Email: if rules.GetEmail() { return true } case Hostname: if rules.GetEmail() || rules.GetHostname() || rules.GetAddress() { return true } case UUID: if rules.GetUuid() { return true } } return false } protoc-gen-validate-1.0.2/tests/000077500000000000000000000000001444536353100165305ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/generation/000077500000000000000000000000001444536353100206635ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/generation/multi_file_java_test/000077500000000000000000000000001444536353100250545ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/generation/multi_file_java_test/BUILD000066400000000000000000000012221444536353100256330ustar00rootroot00000000000000load("@rules_cc//cc:defs.bzl", "cc_binary") load("@rules_proto//proto:defs.bzl", "proto_library") load( "//bazel:pgv_proto_library.bzl", "pgv_cc_proto_library", ) # gazelle:go_generate_proto false proto_library( name = "test_proto", srcs = ["test.proto"], visibility = ["//visibility:public"], deps = [ "@com_google_protobuf//:any_proto", ], ) pgv_cc_proto_library( name = "test_cc_proto", visibility = ["//visibility:public"], deps = [":test_proto"], ) cc_binary( name = "cc-mfjt-test", srcs = ["main.cc"], visibility = ["//visibility:public"], deps = [ ":test_cc_proto", ], ) protoc-gen-validate-1.0.2/tests/generation/multi_file_java_test/README.md000066400000000000000000000004031444536353100263300ustar00rootroot00000000000000# Multi File Java Test # Test that a file with: `option java_multiple_files = true;` not generated in java can properly be generated without error. Due to `java` not needing to be in the generation path at all we had to split it out into it's own directory. protoc-gen-validate-1.0.2/tests/generation/multi_file_java_test/main.cc000066400000000000000000000003051444536353100263050ustar00rootroot00000000000000#include #include "tests/generation/multi_file_java_test/test.pb.h" #include "tests/generation/multi_file_java_test/test.pb.validate.h" int main(int argc, char** argv) { return 0; } protoc-gen-validate-1.0.2/tests/generation/multi_file_java_test/test.proto000066400000000000000000000003061444536353100271170ustar00rootroot00000000000000syntax = "proto3"; package tests.mfjt; option go_package = "harness"; option java_multiple_files = true; import "google/protobuf/any.proto"; message Message { google.protobuf.Any data = 1; } protoc-gen-validate-1.0.2/tests/go.mod000066400000000000000000000004121444536353100176330ustar00rootroot00000000000000module github.com/envoyproxy/protoc-gen-validate/tests go 1.12 require ( golang.org/x/net v0.11.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/protobuf v1.30.0 ) replace github.com/envoyproxy/protoc-gen-validate => ../ protoc-gen-validate-1.0.2/tests/go.sum000066400000000000000000000103311444536353100176610ustar00rootroot00000000000000github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= protoc-gen-validate-1.0.2/tests/harness/000077500000000000000000000000001444536353100201735ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/harness/BUILD000066400000000000000000000025371444536353100207640ustar00rootroot00000000000000load("@io_bazel_rules_go//go:def.bzl", "go_library") load("@rules_cc//cc:defs.bzl", "cc_proto_library") load("@rules_java//java:defs.bzl", "java_proto_library") load("@rules_proto//proto:defs.bzl", "proto_library") load("@com_google_protobuf//:protobuf.bzl", "py_proto_library") load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") proto_library( name = "harness_proto", srcs = ["harness.proto"], visibility = ["//visibility:public"], deps = [ "@com_google_protobuf//:any_proto", ], ) go_proto_library( name = "harness_go_proto", importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/go", proto = ":harness_proto", visibility = ["//visibility:public"], ) cc_proto_library( name = "harness_cc_proto", visibility = ["//visibility:public"], deps = [ ":harness_proto", ], ) java_proto_library( name = "harness_java_proto", visibility = ["//visibility:public"], deps = [":harness_proto"], ) go_library( name = "go_default_library", embed = [":harness_go_proto"], importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness", visibility = ["//visibility:public"], ) py_proto_library( name = "harness_py_proto", srcs = ["harness.proto"], visibility = ["//visibility:public"], deps = ["@com_google_protobuf//:protobuf_python"], ) protoc-gen-validate-1.0.2/tests/harness/cases/000077500000000000000000000000001444536353100212715ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/harness/cases/.gitignore000066400000000000000000000000171444536353100232570ustar00rootroot00000000000000*.pb.cc *.pb.h protoc-gen-validate-1.0.2/tests/harness/cases/BUILD000066400000000000000000000073631444536353100220640ustar00rootroot00000000000000load("@rules_java//java:defs.bzl", "java_proto_library") load("@rules_proto//proto:defs.bzl", "proto_library") load("@com_google_protobuf//:protobuf.bzl", "py_proto_library") load( "//bazel:pgv_proto_library.bzl", "pgv_cc_proto_library", "pgv_go_proto_library", "pgv_java_proto_library", ) # gazelle:go_generate_proto false proto_library( name = "cases_proto", srcs = [ "bool.proto", "bytes.proto", "enums.proto", "filename-with-dash.proto", "kitchen_sink.proto", "maps.proto", "messages.proto", "numbers.proto", "oneofs.proto", "repeated.proto", "strings.proto", "subdirectory/in_subdirectory.proto", "wkt_any.proto", "wkt_duration.proto", "wkt_nested.proto", "wkt_timestamp.proto", "wkt_wrappers.proto", ], visibility = ["//visibility:public"], deps = [ "//tests/harness/cases/other_package:embed_proto", "//tests/harness/cases/yet_another_package:embed_proto", "//tests/harness/cases/sort:sort_proto", "//validate:validate_proto", "@com_google_protobuf//:any_proto", "@com_google_protobuf//:duration_proto", "@com_google_protobuf//:timestamp_proto", "@com_google_protobuf//:wrappers_proto", ], ) pgv_go_proto_library( name = "go", importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go", proto = ":cases_proto", deps = [ "//tests/harness/cases/other_package:go", "//tests/harness/cases/yet_another_package:go", "//tests/harness/cases/sort:go", "@org_golang_google_protobuf//types/known/anypb:go_default_library", "@org_golang_google_protobuf//types/known/durationpb:go_default_library", "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", "@org_golang_google_protobuf//types/known/wrapperspb:go_default_library", ], ) pgv_cc_proto_library( name = "cc", cc_deps = [ "//tests/harness/cases/other_package:cc", "//tests/harness/cases/yet_another_package:cc", "//tests/harness/cases/sort:cc", ], visibility = ["//tests:__subpackages__"], deps = [":cases_proto"], ) java_proto_library( name = "cases_java_proto", visibility = ["//visibility:public"], deps = [":cases_proto"], ) pgv_java_proto_library( name = "java", java_deps = [ ":cases_java_proto", "//tests/harness/cases/other_package:java", "//tests/harness/cases/yet_another_package:java", "//tests/harness/cases/sort:java", ], visibility = ["//visibility:public"], deps = [":cases_proto"], ) # There is not currently a canonical implementation of py_proto_library in Bazel. # This py_proto_library implementation is from "github.com/protocolbuffers/protobuf" and works differently from other # languages' canonical implementations - for example, it doesn't take "proto_library" targets as input. py_proto_library( name = "cases_py_proto", srcs = [ "bool.proto", "bytes.proto", "enums.proto", "kitchen_sink.proto", "maps.proto", "messages.proto", "numbers.proto", "oneofs.proto", "repeated.proto", "strings.proto", "wkt_any.proto", "wkt_duration.proto", "wkt_nested.proto", "wkt_timestamp.proto", "wkt_wrappers.proto", ], visibility = ["//visibility:public"], deps = [ "//validate:validate_py", "//tests/harness/cases/other_package:embed_python_proto", "//tests/harness/cases/yet_another_package:embed_python_proto", "//tests/harness/cases/sort:sort_python_proto", "@com_google_protobuf//:protobuf_python", ], ) protoc-gen-validate-1.0.2/tests/harness/cases/bool.proto000066400000000000000000000005701444536353100233130ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; message BoolNone { bool val = 1; } message BoolConstTrue { bool val = 1 [(validate.rules).bool.const = true]; } message BoolConstFalse { bool val = 1 [(validate.rules).bool.const = false]; } protoc-gen-validate-1.0.2/tests/harness/cases/bytes.proto000066400000000000000000000031371444536353100235100ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; message BytesNone { bytes val = 1; } message BytesConst { bytes val = 1 [(validate.rules).bytes.const = "foo"]; } message BytesIn { bytes val = 1 [(validate.rules).bytes = {in: ["bar", "baz"]}]; } message BytesNotIn { bytes val = 1 [(validate.rules).bytes = {not_in: ["fizz", "buzz"]}]; } message BytesLen { bytes val = 1 [(validate.rules).bytes.len = 3]; } message BytesMinLen { bytes val = 1 [(validate.rules).bytes.min_len = 3]; } message BytesMaxLen { bytes val = 1 [(validate.rules).bytes.max_len = 5]; } message BytesMinMaxLen { bytes val = 1 [(validate.rules).bytes = {min_len: 3, max_len: 5}]; } message BytesEqualMinMaxLen { bytes val = 1 [(validate.rules).bytes = {min_len: 5, max_len: 5}]; } message BytesPattern { bytes val = 1 [(validate.rules).bytes.pattern = "^[\x00-\x7F]+$"]; } message BytesPrefix { bytes val = 1 [(validate.rules).bytes.prefix = "\x99"]; } message BytesContains { bytes val = 1 [(validate.rules).bytes.contains = "bar"]; } message BytesSuffix { bytes val = 1 [(validate.rules).bytes.suffix = "buz\x7a"]; } message BytesIP { bytes val = 1 [(validate.rules).bytes.ip = true]; } message BytesIPv4 { bytes val = 1 [(validate.rules).bytes.ipv4 = true]; } message BytesIPv6 { bytes val = 1 [(validate.rules).bytes.ipv6 = true]; } message BytesIPv6Ignore { bytes val = 1 [(validate.rules).bytes = {ipv6: true, ignore_empty: true}]; } protoc-gen-validate-1.0.2/tests/harness/cases/enums.proto000066400000000000000000000056341444536353100235150ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; import "tests/harness/cases/other_package/embed.proto"; import "tests/harness/cases/yet_another_package/embed.proto"; import "tests/harness/cases/sort/sort.proto"; enum TestEnum { ZERO = 0; ONE = 1; TWO = 2; } enum TestEnumAlias { option allow_alias = true; A = 0; B = 1; C = 2; ALPHA = 0; BETA = 1; GAMMA = 2; } message EnumNone { TestEnum val = 1; } message EnumConst { TestEnum val = 1 [(validate.rules).enum.const = 2];} message EnumAliasConst { TestEnumAlias val = 1 [(validate.rules).enum.const = 2];} message EnumDefined { TestEnum val = 1 [(validate.rules).enum.defined_only = true];} message EnumAliasDefined { TestEnumAlias val = 1 [(validate.rules).enum.defined_only = true];} message EnumIn { TestEnum val = 1 [(validate.rules).enum = { in: [0, 2]}];} message EnumAliasIn { TestEnumAlias val = 1 [(validate.rules).enum = { in: [0, 2]}];} message EnumNotIn { TestEnum val = 1 [(validate.rules).enum = { not_in: [1]}];} message EnumAliasNotIn { TestEnumAlias val = 1 [(validate.rules).enum = { not_in: [1]}]; } message EnumExternal { other_package.Embed.Enumerated val = 1 [(validate.rules).enum.defined_only = true]; } message EnumExternal2 { other_package.Embed.DoubleEmbed.DoubleEnumerated val = 1 [(validate.rules).enum.defined_only = true]; } message EnumExternal3 { other_package.Embed.FooNumber foo = 1 [(validate.rules).enum = { in: [0, 2] }]; yet_another_package.Embed.BarNumber bar = 2 [(validate.rules).enum = { not_in: [1] }]; } message EnumExternal4 { sort.Direction sort_direction = 1 [(validate.rules).enum.const = 1]; } message RepeatedEnumDefined { repeated TestEnum val = 1 [(validate.rules).repeated.items.enum.defined_only = true]; } message RepeatedExternalEnumDefined { repeated other_package.Embed.Enumerated val = 1 [(validate.rules).repeated.items.enum.defined_only = true]; } message RepeatedYetAnotherExternalEnumDefined { repeated yet_another_package.Embed.Enumerated val = 1 [(validate.rules).repeated.items.enum.defined_only = true]; } message RepeatedEnumExternal { repeated other_package.Embed.FooNumber foo = 1 [(validate.rules).repeated.items.enum = { in: [0, 2] }]; repeated yet_another_package.Embed.BarNumber bar = 2 [(validate.rules).repeated.items.enum = { not_in: [1] }]; } message MapEnumDefined { map val = 1 [(validate.rules).map.values.enum.defined_only = true]; } message MapExternalEnumDefined { map val = 1 [(validate.rules).map.values.enum.defined_only = true]; } message EnumInsideOneOf { oneof foo { TestEnum val = 1 [(validate.rules).enum.defined_only = true]; } oneof bar { TestEnum val2 = 2 [(validate.rules).enum = {defined_only : true not_in : 0}]; } } protoc-gen-validate-1.0.2/tests/harness/cases/filename-with-dash.proto000066400000000000000000000002611444536353100260230ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; protoc-gen-validate-1.0.2/tests/harness/cases/kitchen_sink.proto000066400000000000000000000040551444536353100250330ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; import "google/protobuf/wrappers.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; import "google/protobuf/any.proto"; enum ComplexTestEnum { ComplexZero = 0; ComplexONE = 1; ComplexTWO = 2; } message ComplexTestMsg { string const = 1 [(validate.rules).string.const = "abcd"]; ComplexTestMsg nested = 2; int32 int_const = 3 [(validate.rules).int32.const = 5]; bool bool_const = 4 [(validate.rules).bool.const = false]; google.protobuf.FloatValue float_val = 5 [(validate.rules).float.gt = 0]; google.protobuf.Duration dur_val = 6 [(validate.rules).duration.lt = {seconds: 17}, (validate.rules).duration.required = true]; google.protobuf.Timestamp ts_val = 7 [(validate.rules).timestamp.gt = {seconds: 7}]; ComplexTestMsg another = 8; float float_const = 9 [(validate.rules).float.lt = 8]; double double_in = 10 [(validate.rules).double = {in: [456.789, 123]}]; ComplexTestEnum enum_const = 11 [(validate.rules).enum.const = 2]; google.protobuf.Any any_val = 12 [(validate.rules).any = {in: ["type.googleapis.com/google.protobuf.Duration"]}]; repeated google.protobuf.Timestamp rep_ts_val = 13 [(validate.rules).repeated = { items { timestamp { gte { nanos: 1000000}}}}]; map map_val = 14 [(validate.rules).map.keys.sint32.lt = 0]; bytes bytes_val = 15 [(validate.rules).bytes.const = "\x00\x99"]; oneof o { option (validate.required) = true; string x = 16; int32 y = 17; } } message KitchenSinkMessage { ComplexTestMsg val = 1; } protoc-gen-validate-1.0.2/tests/harness/cases/maps.proto000066400000000000000000000035531444536353100233240ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; message MapNone { map val = 1; } message MapMin { map val = 1 [(validate.rules).map.min_pairs = 2]; } message MapMax { map val = 1 [(validate.rules).map.max_pairs = 3]; } message MapMinMax { map val = 1 [(validate.rules).map = {min_pairs: 2, max_pairs: 4}]; } message MapExact { map val = 1 [(validate.rules).map = {min_pairs: 3, max_pairs: 3}]; } message MapNoSparse { map val = 1 [(validate.rules).map.no_sparse = true]; message Msg {} } message MapKeys { map val = 1 [(validate.rules).map.keys.sint64.lt = 0]; } message MapValues { map val = 1 [(validate.rules).map.values.string.min_len = 3]; } message MapKeysPattern { map val = 1 [(validate.rules).map.keys.string.pattern = "(?i)^[a-z0-9]+$"]; } message MapValuesPattern { map val = 1 [(validate.rules).map.values.string.pattern = "(?i)^[a-z0-9]+$"]; } message MapRecursive { map val = 1; message Msg { string val = 1 [(validate.rules).string.min_len = 3]; } } message MapExactIgnore { map val = 1 [(validate.rules).map = {min_pairs: 3, max_pairs: 3, ignore_empty: true}]; } message MultipleMaps { map first = 1 [(validate.rules).map.keys.uint32.gt = 0]; map second = 2 [(validate.rules).map.keys.int32.lt = 0]; map third = 3 [(validate.rules).map.keys.int32.gt = 0]; } message MapKeysIn {map val = 1 [(validate.rules).map.keys.string = {in: ["foo", "bar"]}]; } message MapKeysNotIn {map val = 1 [(validate.rules).map.keys.string = {not_in: ["foo", "bar"]}]; } protoc-gen-validate-1.0.2/tests/harness/cases/messages.proto000066400000000000000000000023411444536353100241650ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "tests/harness/cases/other_package/embed.proto"; import "validate/validate.proto"; message TestMsg { string const = 1 [(validate.rules).string.const = "foo"]; TestMsg nested = 2; } message MessageNone { NoneMsg val = 1; message NoneMsg {} } message MessageDisabled { option (validate.disabled) = true; uint64 val = 1 [(validate.rules).uint64.gt = 123]; } message MessageIgnored { option (validate.ignored) = true; uint64 val = 1 [(validate.rules).uint64.gt = 123]; } message Message { TestMsg val = 1; } message MessageCrossPackage { tests.harness.cases.other_package.Embed val = 1; } message MessageSkip { TestMsg val = 1 [(validate.rules).message.skip = true];} message MessageRequired { TestMsg val = 1 [(validate.rules).message.required = true]; } message MessageRequiredButOptional { optional TestMsg val = 1 [(validate.rules).message.required = true]; } message MessageRequiredOneof { oneof one { option (validate.required) = true; TestMsg val = 1 [(validate.rules).message.required = true]; } } message MessageWith3dInside {} protoc-gen-validate-1.0.2/tests/harness/cases/numbers.proto000066400000000000000000000316721444536353100240420ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; message FloatNone { float val = 1; } message FloatConst { float val = 1 [(validate.rules).float.const = 1.23]; } message FloatIn { float val = 1 [(validate.rules).float = {in: [4.56, 7.89]}]; } message FloatNotIn { float val = 1 [(validate.rules).float = {not_in: [0]}]; } message FloatLT { float val = 1 [(validate.rules).float.lt = 0]; } message FloatLTE { float val = 1 [(validate.rules).float.lte = 64]; } message FloatGT { float val = 1 [(validate.rules).float.gt = 16]; } message FloatGTE { float val = 1 [(validate.rules).float.gte = 8]; } message FloatGTLT { float val = 1 [(validate.rules).float = {gt: 0, lt: 10}]; } message FloatExLTGT { float val = 1 [(validate.rules).float = {lt: 0, gt: 10}]; } message FloatGTELTE { float val = 1 [(validate.rules).float = {gte: 128, lte: 256}]; } message FloatExGTELTE { float val = 1 [(validate.rules).float = {lte: 128, gte: 256}]; } message FloatIgnore { float val = 1 [(validate.rules).float = {gte: 128, lte: 256, ignore_empty: true}]; } message DoubleNone { double val = 1; } message DoubleConst { double val = 1 [(validate.rules).double.const = 1.23]; } message DoubleIn { double val = 1 [(validate.rules).double = {in: [4.56, 7.89]}]; } message DoubleNotIn { double val = 1 [(validate.rules).double = {not_in: [0]}]; } message DoubleLT { double val = 1 [(validate.rules).double.lt = 0]; } message DoubleLTE { double val = 1 [(validate.rules).double.lte = 64]; } message DoubleGT { double val = 1 [(validate.rules).double.gt = 16]; } message DoubleGTE { double val = 1 [(validate.rules).double.gte = 8]; } message DoubleGTLT { double val = 1 [(validate.rules).double = {gt: 0, lt: 10}]; } message DoubleExLTGT { double val = 1 [(validate.rules).double = {lt: 0, gt: 10}]; } message DoubleGTELTE { double val = 1 [(validate.rules).double = {gte: 128, lte: 256}]; } message DoubleExGTELTE { double val = 1 [(validate.rules).double = {lte: 128, gte: 256}]; } message DoubleIgnore { double val = 1 [(validate.rules).double = {lte: 128, gte: 256, ignore_empty: true}]; } message Int32None { int32 val = 1; } message Int32Const { int32 val = 1 [(validate.rules).int32.const = 1]; } message Int32In { int32 val = 1 [(validate.rules).int32 = {in: [2, 3]}]; } message Int32NotIn { int32 val = 1 [(validate.rules).int32 = {not_in: [0]}]; } message Int32LT { int32 val = 1 [(validate.rules).int32.lt = 0]; } message Int32LTE { int32 val = 1 [(validate.rules).int32.lte = 64]; } message Int32GT { int32 val = 1 [(validate.rules).int32.gt = 16]; } message Int32GTE { int32 val = 1 [(validate.rules).int32.gte = 8]; } message Int32GTLT { int32 val = 1 [(validate.rules).int32 = {gt: 0, lt: 10}]; } message Int32ExLTGT { int32 val = 1 [(validate.rules).int32 = {lt: 0, gt: 10}]; } message Int32GTELTE { int32 val = 1 [(validate.rules).int32 = {gte: 128, lte: 256}]; } message Int32ExGTELTE { int32 val = 1 [(validate.rules).int32 = {lte: 128, gte: 256}]; } message Int32Ignore { int32 val = 1 [(validate.rules).int32 = {lte: 128, gte: 256, ignore_empty: true}]; } message Int64None { int64 val = 1; } message Int64Const { int64 val = 1 [(validate.rules).int64.const = 1]; } message Int64In { int64 val = 1 [(validate.rules).int64 = {in: [2, 3]}]; } message Int64NotIn { int64 val = 1 [(validate.rules).int64 = {not_in: [0]}]; } message Int64LT { int64 val = 1 [(validate.rules).int64.lt = 0]; } message Int64LTE { int64 val = 1 [(validate.rules).int64.lte = 64]; } message Int64GT { int64 val = 1 [(validate.rules).int64.gt = 16]; } message Int64GTE { int64 val = 1 [(validate.rules).int64.gte = 8]; } message Int64GTLT { int64 val = 1 [(validate.rules).int64 = {gt: 0, lt: 10}]; } message Int64ExLTGT { int64 val = 1 [(validate.rules).int64 = {lt: 0, gt: 10}]; } message Int64GTELTE { int64 val = 1 [(validate.rules).int64 = {gte: 128, lte: 256}]; } message Int64ExGTELTE { int64 val = 1 [(validate.rules).int64 = {lte: 128, gte: 256}]; } message Int64Ignore { int64 val = 1 [(validate.rules).int64 = {lte: 128, gte: 256, ignore_empty: true}]; } message UInt32None { uint32 val = 1; } message UInt32Const { uint32 val = 1 [(validate.rules).uint32.const = 1]; } message UInt32In { uint32 val = 1 [(validate.rules).uint32 = {in: [2, 3]}]; } message UInt32NotIn { uint32 val = 1 [(validate.rules).uint32 = {not_in: [0]}]; } message UInt32LT { uint32 val = 1 [(validate.rules).uint32.lt = 5]; } message UInt32LTE { uint32 val = 1 [(validate.rules).uint32.lte = 64]; } message UInt32GT { uint32 val = 1 [(validate.rules).uint32.gt = 16]; } message UInt32GTE { uint32 val = 1 [(validate.rules).uint32.gte = 8]; } message UInt32GTLT { uint32 val = 1 [(validate.rules).uint32 = {gt: 5, lt: 10}]; } message UInt32ExLTGT { uint32 val = 1 [(validate.rules).uint32 = {lt: 5, gt: 10}]; } message UInt32GTELTE { uint32 val = 1 [(validate.rules).uint32 = {gte: 128, lte: 256}]; } message UInt32ExGTELTE { uint32 val = 1 [(validate.rules).uint32 = {lte: 128, gte: 256}]; } message UInt32Ignore { uint32 val = 1 [(validate.rules).uint32 = {lte: 128, gte: 256, ignore_empty: true}]; } message UInt64None { uint64 val = 1; } message UInt64Const { uint64 val = 1 [(validate.rules).uint64.const = 1]; } message UInt64In { uint64 val = 1 [(validate.rules).uint64 = {in: [2, 3]}]; } message UInt64NotIn { uint64 val = 1 [(validate.rules).uint64 = {not_in: [0]}]; } message UInt64LT { uint64 val = 1 [(validate.rules).uint64.lt = 5]; } message UInt64LTE { uint64 val = 1 [(validate.rules).uint64.lte = 64]; } message UInt64GT { uint64 val = 1 [(validate.rules).uint64.gt = 16]; } message UInt64GTE { uint64 val = 1 [(validate.rules).uint64.gte = 8]; } message UInt64GTLT { uint64 val = 1 [(validate.rules).uint64 = {gt: 5, lt: 10}]; } message UInt64ExLTGT { uint64 val = 1 [(validate.rules).uint64 = {lt: 5, gt: 10}]; } message UInt64GTELTE { uint64 val = 1 [(validate.rules).uint64 = {gte: 128, lte: 256}]; } message UInt64ExGTELTE { uint64 val = 1 [(validate.rules).uint64 = {lte: 128, gte: 256}]; } message UInt64Ignore { uint64 val = 1 [(validate.rules).uint64 = {lte: 128, gte: 256, ignore_empty: true}]; } message SInt32None { sint32 val = 1; } message SInt32Const { sint32 val = 1 [(validate.rules).sint32.const = 1]; } message SInt32In { sint32 val = 1 [(validate.rules).sint32 = {in: [2, 3]}]; } message SInt32NotIn { sint32 val = 1 [(validate.rules).sint32 = {not_in: [0]}]; } message SInt32LT { sint32 val = 1 [(validate.rules).sint32.lt = 0]; } message SInt32LTE { sint32 val = 1 [(validate.rules).sint32.lte = 64]; } message SInt32GT { sint32 val = 1 [(validate.rules).sint32.gt = 16]; } message SInt32GTE { sint32 val = 1 [(validate.rules).sint32.gte = 8]; } message SInt32GTLT { sint32 val = 1 [(validate.rules).sint32 = {gt: 0, lt: 10}]; } message SInt32ExLTGT { sint32 val = 1 [(validate.rules).sint32 = {lt: 0, gt: 10}]; } message SInt32GTELTE { sint32 val = 1 [(validate.rules).sint32 = {gte: 128, lte: 256}]; } message SInt32ExGTELTE { sint32 val = 1 [(validate.rules).sint32 = {lte: 128, gte: 256}]; } message SInt32Ignore { sint32 val = 1 [(validate.rules).sint32 = {lte: 128, gte: 256, ignore_empty: true}]; } message SInt64None { sint64 val = 1; } message SInt64Const { sint64 val = 1 [(validate.rules).sint64.const = 1]; } message SInt64In { sint64 val = 1 [(validate.rules).sint64 = {in: [2, 3]}]; } message SInt64NotIn { sint64 val = 1 [(validate.rules).sint64 = {not_in: [0]}]; } message SInt64LT { sint64 val = 1 [(validate.rules).sint64.lt = 0]; } message SInt64LTE { sint64 val = 1 [(validate.rules).sint64.lte = 64]; } message SInt64GT { sint64 val = 1 [(validate.rules).sint64.gt = 16]; } message SInt64GTE { sint64 val = 1 [(validate.rules).sint64.gte = 8]; } message SInt64GTLT { sint64 val = 1 [(validate.rules).sint64 = {gt: 0, lt: 10}]; } message SInt64ExLTGT { sint64 val = 1 [(validate.rules).sint64 = {lt: 0, gt: 10}]; } message SInt64GTELTE { sint64 val = 1 [(validate.rules).sint64 = {gte: 128, lte: 256}]; } message SInt64ExGTELTE { sint64 val = 1 [(validate.rules).sint64 = {lte: 128, gte: 256}]; } message SInt64Ignore { sint64 val = 1 [(validate.rules).sint64 = {lte: 128, gte: 256, ignore_empty: true}]; } message Fixed32None { fixed32 val = 1; } message Fixed32Const { fixed32 val = 1 [(validate.rules).fixed32.const = 1]; } message Fixed32In { fixed32 val = 1 [(validate.rules).fixed32 = {in: [2, 3]}]; } message Fixed32NotIn { fixed32 val = 1 [(validate.rules).fixed32 = {not_in: [0]}]; } message Fixed32LT { fixed32 val = 1 [(validate.rules).fixed32.lt = 5]; } message Fixed32LTE { fixed32 val = 1 [(validate.rules).fixed32.lte = 64]; } message Fixed32GT { fixed32 val = 1 [(validate.rules).fixed32.gt = 16]; } message Fixed32GTE { fixed32 val = 1 [(validate.rules).fixed32.gte = 8]; } message Fixed32GTLT { fixed32 val = 1 [(validate.rules).fixed32 = {gt: 5, lt: 10}]; } message Fixed32ExLTGT { fixed32 val = 1 [(validate.rules).fixed32 = {lt: 5, gt: 10}]; } message Fixed32GTELTE { fixed32 val = 1 [(validate.rules).fixed32 = {gte: 128, lte: 256}]; } message Fixed32ExGTELTE { fixed32 val = 1 [(validate.rules).fixed32 = {lte: 128, gte: 256}]; } message Fixed32Ignore { fixed32 val = 1 [(validate.rules).fixed32 = {lte: 128, gte: 256, ignore_empty: true}]; } message Fixed64None { fixed64 val = 1; } message Fixed64Const { fixed64 val = 1 [(validate.rules).fixed64.const = 1]; } message Fixed64In { fixed64 val = 1 [(validate.rules).fixed64 = {in: [2, 3]}]; } message Fixed64NotIn { fixed64 val = 1 [(validate.rules).fixed64 = {not_in: [0]}]; } message Fixed64LT { fixed64 val = 1 [(validate.rules).fixed64.lt = 5]; } message Fixed64LTE { fixed64 val = 1 [(validate.rules).fixed64.lte = 64]; } message Fixed64GT { fixed64 val = 1 [(validate.rules).fixed64.gt = 16]; } message Fixed64GTE { fixed64 val = 1 [(validate.rules).fixed64.gte = 8]; } message Fixed64GTLT { fixed64 val = 1 [(validate.rules).fixed64 = {gt: 5, lt: 10}]; } message Fixed64ExLTGT { fixed64 val = 1 [(validate.rules).fixed64 = {lt: 5, gt: 10}]; } message Fixed64GTELTE { fixed64 val = 1 [(validate.rules).fixed64 = {gte: 128, lte: 256}]; } message Fixed64ExGTELTE { fixed64 val = 1 [(validate.rules).fixed64 = {lte: 128, gte: 256}]; } message Fixed64Ignore { fixed64 val = 1 [(validate.rules).fixed64 = {lte: 128, gte: 256, ignore_empty: true}]; } message SFixed32None { sfixed32 val = 1; } message SFixed32Const { sfixed32 val = 1 [(validate.rules).sfixed32.const = 1]; } message SFixed32In { sfixed32 val = 1 [(validate.rules).sfixed32 = {in: [2, 3]}]; } message SFixed32NotIn { sfixed32 val = 1 [(validate.rules).sfixed32 = {not_in: [0]}]; } message SFixed32LT { sfixed32 val = 1 [(validate.rules).sfixed32.lt = 0]; } message SFixed32LTE { sfixed32 val = 1 [(validate.rules).sfixed32.lte = 64]; } message SFixed32GT { sfixed32 val = 1 [(validate.rules).sfixed32.gt = 16]; } message SFixed32GTE { sfixed32 val = 1 [(validate.rules).sfixed32.gte = 8]; } message SFixed32GTLT { sfixed32 val = 1 [(validate.rules).sfixed32 = {gt: 0, lt: 10}]; } message SFixed32ExLTGT { sfixed32 val = 1 [(validate.rules).sfixed32 = {lt: 0, gt: 10}]; } message SFixed32GTELTE { sfixed32 val = 1 [(validate.rules).sfixed32 = {gte: 128, lte: 256}]; } message SFixed32ExGTELTE { sfixed32 val = 1 [(validate.rules).sfixed32 = {lte: 128, gte: 256}]; } message SFixed32Ignore { sfixed32 val = 1 [(validate.rules).sfixed32 = {lte: 128, gte: 256, ignore_empty: true}]; } message SFixed64None { sfixed64 val = 1; } message SFixed64Const { sfixed64 val = 1 [(validate.rules).sfixed64.const = 1]; } message SFixed64In { sfixed64 val = 1 [(validate.rules).sfixed64 = {in: [2, 3]}]; } message SFixed64NotIn { sfixed64 val = 1 [(validate.rules).sfixed64 = {not_in: [0]}]; } message SFixed64LT { sfixed64 val = 1 [(validate.rules).sfixed64.lt = 0]; } message SFixed64LTE { sfixed64 val = 1 [(validate.rules).sfixed64.lte = 64]; } message SFixed64GT { sfixed64 val = 1 [(validate.rules).sfixed64.gt = 16]; } message SFixed64GTE { sfixed64 val = 1 [(validate.rules).sfixed64.gte = 8]; } message SFixed64GTLT { sfixed64 val = 1 [(validate.rules).sfixed64 = {gt: 0, lt: 10}]; } message SFixed64ExLTGT { sfixed64 val = 1 [(validate.rules).sfixed64 = {lt: 0, gt: 10}]; } message SFixed64GTELTE { sfixed64 val = 1 [(validate.rules).sfixed64 = {gte: 128, lte: 256}]; } message SFixed64ExGTELTE { sfixed64 val = 1 [(validate.rules).sfixed64 = {lte: 128, gte: 256}]; } message SFixed64Ignore { sfixed64 val = 1 [(validate.rules).sfixed64 = {lte: 128, gte: 256, ignore_empty: true}]; } message Int64LTEOptional { optional int64 val = 1 [(validate.rules).int64.lte = 64]; } protoc-gen-validate-1.0.2/tests/harness/cases/oneofs.proto000066400000000000000000000021641444536353100236520ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; message TestOneOfMsg { bool val = 1 [(validate.rules).bool.const = true]; } message OneOfNone { oneof o { string x = 1; int32 y = 2; } } message OneOf { oneof o { string x = 1 [(validate.rules).string.prefix = "foo"]; int32 y = 2 [(validate.rules).int32.gt = 0]; TestOneOfMsg z = 3; } } message OneOfRequired { oneof o { option (validate.required) = true; string x = 1; int32 y = 2; int32 name_with_underscores = 3; int32 under_and_1_number = 4; } } message OneOfIgnoreEmpty { oneof o { string x = 1 [(validate.rules).string = {ignore_empty: true, min_len: 3, max_len: 5}]; bytes y = 2 [(validate.rules).bytes = {ignore_empty: true, min_len: 3, max_len: 5}]; int32 z = 3 [(validate.rules).int32 = {lte: 128, gte: 256, ignore_empty: true}]; } } protoc-gen-validate-1.0.2/tests/harness/cases/other_package/000077500000000000000000000000001444536353100240655ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/harness/cases/other_package/BUILD000066400000000000000000000041511444536353100246500ustar00rootroot00000000000000load("@rules_java//java:defs.bzl", "java_proto_library") load("@com_google_protobuf//:protobuf.bzl", "py_proto_library") load("@io_bazel_rules_go//go:def.bzl", "go_library") load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") load("@rules_proto//proto:defs.bzl", "proto_library") load( "//bazel:pgv_proto_library.bzl", "pgv_cc_proto_library", "pgv_go_proto_library", "pgv_java_proto_library", ) proto_library( name = "embed_proto", srcs = [ "embed.proto", ], visibility = ["//visibility:public"], deps = ["//validate:validate_proto"], ) pgv_go_proto_library( name = "go", importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/other_package/go", proto = ":embed_proto", deps = [ "@org_golang_google_protobuf//types/known/anypb:go_default_library", ], ) pgv_cc_proto_library( name = "cc", visibility = ["//tests:__subpackages__"], deps = [":embed_proto"], ) proto_library( name = "other_package_proto", srcs = ["embed.proto"], visibility = ["//visibility:public"], deps = ["//validate:validate_proto"], ) go_proto_library( name = "other_package_go_proto", importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/other_package", proto = ":other_package_proto", visibility = ["//visibility:public"], deps = ["//validate:go_default_library"], ) go_library( name = "go_default_library", embed = [":other_package_go_proto"], importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/other_package", visibility = ["//visibility:public"], ) java_proto_library( name = "embed_java_proto", visibility = ["//visibility:public"], deps = [":embed_proto"], ) pgv_java_proto_library( name = "java", java_deps = [":embed_java_proto"], visibility = ["//visibility:public"], deps = [":embed_proto"], ) py_proto_library( name = "embed_python_proto", srcs = ["embed.proto"], visibility = ["//visibility:public"], deps = [ "//validate:validate_py", "@com_google_protobuf//:protobuf_python", ], ) protoc-gen-validate-1.0.2/tests/harness/cases/other_package/embed.proto000066400000000000000000000010171444536353100262250ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases.other_package; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/other_package/go;other_package"; import "validate/validate.proto"; // Validate message embedding across packages. message Embed { message DoubleEmbed { enum DoubleEnumerated { VALUE = 0; } } int64 val = 1 [(validate.rules).int64.gt = 0]; enum Enumerated { VALUE = 0; } enum FooNumber { ZERO = 0; ONE = 1; TWO = 2; } } protoc-gen-validate-1.0.2/tests/harness/cases/repeated.proto000066400000000000000000000061021444536353100241460ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "tests/harness/cases/other_package/embed.proto"; import "validate/validate.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/any.proto"; message Embed { int64 val = 1 [(validate.rules).int64.gt = 0]; } enum AnEnum { X = 0; Y = 1; } message RepeatedNone { repeated int64 val = 1; } message RepeatedEmbedNone { repeated Embed val = 1; } message RepeatedEmbedCrossPackageNone { repeated tests.harness.cases.other_package.Embed val = 1; } message RepeatedMin { repeated Embed val = 1 [(validate.rules).repeated.min_items = 2]; } message RepeatedMax { repeated double val = 1 [(validate.rules).repeated.max_items = 3]; } message RepeatedMinMax { repeated sfixed32 val = 1 [(validate.rules).repeated = {min_items: 2, max_items: 4}]; } message RepeatedExact { repeated uint32 val = 1 [(validate.rules).repeated = {min_items: 3, max_items: 3}]; } message RepeatedUnique { repeated string val = 1 [(validate.rules).repeated.unique = true]; } message RepeatedItemRule { repeated float val = 1 [(validate.rules).repeated.items.float.gt = 0]; } message RepeatedItemPattern { repeated string val = 1 [(validate.rules).repeated.items.string.pattern = "(?i)^[a-z0-9]+$"]; } message RepeatedEmbedSkip { repeated Embed val = 1 [(validate.rules).repeated.items.message.skip = true]; } message RepeatedItemIn { repeated string val = 1 [(validate.rules).repeated.items.string = {in: ["foo", "bar"]}]; } message RepeatedItemNotIn { repeated string val = 1 [(validate.rules).repeated.items.string = {not_in: ["foo", "bar"]}]; } message RepeatedEnumIn { repeated AnEnum val = 1 [(validate.rules).repeated.items.enum = {in: [0]}]; } message RepeatedEnumNotIn { repeated AnEnum val = 1 [(validate.rules).repeated.items.enum = {not_in: [0]}]; } message RepeatedEmbeddedEnumIn { repeated AnotherInEnum val = 1 [(validate.rules).repeated.items.enum = {in: [0]}]; enum AnotherInEnum {A = 0; B = 1; }} message RepeatedEmbeddedEnumNotIn { repeated AnotherNotInEnum val = 1 [(validate.rules).repeated.items.enum = {not_in: [0]}]; enum AnotherNotInEnum {A = 0; B = 1; }} message RepeatedAnyIn { repeated google.protobuf.Any val = 1 [(validate.rules).repeated.items.any = {in: ["type.googleapis.com/google.protobuf.Duration"]}]; } message RepeatedAnyNotIn { repeated google.protobuf.Any val = 1 [(validate.rules).repeated.items.any = {not_in: ["type.googleapis.com/google.protobuf.Timestamp"]}]; } message RepeatedMinAndItemLen { repeated string val = 1 [(validate.rules).repeated = { items { string { len: 3 } }, min_items: 1 }]; } message RepeatedMinAndMaxItemLen { repeated string val = 1 [(validate.rules).repeated.min_items = 1, (validate.rules).repeated.max_items = 3]; } message RepeatedDuration { repeated google.protobuf.Duration val = 1 [(validate.rules).repeated = { items { duration { gte { nanos: 1000000}}}}]; } message RepeatedExactIgnore { repeated uint32 val = 1 [(validate.rules).repeated = {min_items: 3, max_items: 3, ignore_empty: true}]; } protoc-gen-validate-1.0.2/tests/harness/cases/sort/000077500000000000000000000000001444536353100222605ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/harness/cases/sort/BUILD000066400000000000000000000040561444536353100230470ustar00rootroot00000000000000load("@rules_java//java:defs.bzl", "java_proto_library") load("@com_google_protobuf//:protobuf.bzl", "py_proto_library") load("@io_bazel_rules_go//go:def.bzl", "go_library") load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") load("@rules_proto//proto:defs.bzl", "proto_library") load( "//bazel:pgv_proto_library.bzl", "pgv_cc_proto_library", "pgv_go_proto_library", "pgv_java_proto_library", ) proto_library( name = "sort_proto", srcs = [ "sort.proto", ], visibility = ["//visibility:public"], deps = ["//validate:validate_proto"], ) pgv_go_proto_library( name = "go", importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/sort/go", proto = ":sort_proto", deps = [ "@org_golang_google_protobuf//types/known/anypb:go_default_library", ], ) pgv_cc_proto_library( name = "cc", visibility = ["//tests:__subpackages__"], deps = [":sort_proto"], ) proto_library( name = "sort_sort_proto", srcs = ["sort.proto"], visibility = ["//visibility:public"], deps = ["//validate:validate_proto"], ) go_proto_library( name = "sort_sort_go_proto", importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/sort", proto = ":sort_proto", visibility = ["//visibility:public"], deps = ["//validate:go_default_library"], ) go_library( name = "go_default_library", embed = [":sort_sort_go_proto"], importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/sort", visibility = ["//visibility:public"], ) java_proto_library( name = "sort_java_proto", visibility = ["//visibility:public"], deps = [":sort_proto"], ) pgv_java_proto_library( name = "java", java_deps = [":sort_java_proto"], visibility = ["//visibility:public"], deps = [":sort_proto"], ) py_proto_library( name = "sort_python_proto", srcs = ["sort.proto"], visibility = ["//visibility:public"], deps = [ "//validate:validate_py", "@com_google_protobuf//:protobuf_python", ], ) protoc-gen-validate-1.0.2/tests/harness/cases/sort/sort.proto000066400000000000000000000003411444536353100243320ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases.sort; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/sort/go;sort"; enum Direction { UNKNOWN_DIRECTION = 0; ASC = 1; DESC = 2; }protoc-gen-validate-1.0.2/tests/harness/cases/strings.proto000066400000000000000000000065311444536353100240540ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; message StringNone { string val = 1; } message StringConst { string val = 1 [(validate.rules).string.const = "foo"]; } message StringIn { string val = 1 [(validate.rules).string = {in: ["bar", "baz"]}]; } message StringNotIn { string val = 1 [(validate.rules).string = {not_in: ["fizz", "buzz"]}]; } message StringLen { string val = 1 [(validate.rules).string.len = 3]; } message StringMinLen { string val = 1 [(validate.rules).string.min_len = 3]; } message StringMaxLen { string val = 1 [(validate.rules).string.max_len = 5]; } message StringMinMaxLen { string val = 1 [(validate.rules).string = {min_len: 3, max_len: 5}]; } message StringEqualMinMaxLen { string val = 1 [(validate.rules).string = {min_len: 5, max_len: 5}]; } message StringLenBytes { string val = 1 [(validate.rules).string.len_bytes = 4]; } message StringMinBytes { string val = 1 [(validate.rules).string.min_bytes = 4]; } message StringMaxBytes { string val = 1 [(validate.rules).string.max_bytes = 8]; } message StringMinMaxBytes { string val = 1 [(validate.rules).string = {min_bytes: 4, max_bytes: 8}]; } message StringEqualMinMaxBytes { string val = 1 [(validate.rules).string = {min_bytes: 4, max_bytes: 8}]; } message StringPattern { string val = 1 [(validate.rules).string.pattern = "(?i)^[a-z0-9]+$"]; } message StringPatternEscapes { string val = 1 [(validate.rules).string.pattern = "\\* \\\\ \\w"]; } message StringPrefix { string val = 1 [(validate.rules).string.prefix = "foo"]; } message StringContains { string val = 1 [(validate.rules).string.contains = "bar"]; } message StringNotContains { string val = 1 [(validate.rules).string.not_contains = "bar"]; } message StringSuffix { string val = 1 [(validate.rules).string.suffix = "baz"]; } message StringEmail { string val = 1 [(validate.rules).string.email = true]; } message StringAddress { string val = 1 [(validate.rules).string.address = true]; } message StringHostname { string val = 1 [(validate.rules).string.hostname = true]; } message StringIP { string val = 1 [(validate.rules).string.ip = true]; } message StringIPv4 { string val = 1 [(validate.rules).string.ipv4 = true]; } message StringIPv6 { string val = 1 [(validate.rules).string.ipv6 = true]; } message StringURI { string val = 1 [(validate.rules).string.uri = true]; } message StringURIRef { string val = 1 [(validate.rules).string.uri_ref = true]; } message StringUUID { string val = 1 [(validate.rules).string.uuid = true]; } message StringHttpHeaderName { string val = 1 [(validate.rules).string.well_known_regex = HTTP_HEADER_NAME]; } message StringHttpHeaderValue { string val = 1 [(validate.rules).string.well_known_regex = HTTP_HEADER_VALUE]; } message StringValidHeader { string val = 1 [(validate.rules).string = {well_known_regex: HTTP_HEADER_VALUE, strict: false}]; } message StringUUIDIgnore { string val = 1 [(validate.rules).string = {uuid: true, ignore_empty: true}]; } message StringInOneOf { oneof foo { string bar = 1 [(validate.rules).string = {in: "a" in: "b"}]; } } protoc-gen-validate-1.0.2/tests/harness/cases/subdirectory/000077500000000000000000000000001444536353100240075ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/harness/cases/subdirectory/in_subdirectory.proto000066400000000000000000000002621444536353100303000ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; protoc-gen-validate-1.0.2/tests/harness/cases/wkt_any.proto000066400000000000000000000011641444536353100240340ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; import "google/protobuf/any.proto"; message AnyNone { google.protobuf.Any val = 1; } message AnyRequired { google.protobuf.Any val = 1 [(validate.rules).any.required = true]; } message AnyIn { google.protobuf.Any val = 1 [(validate.rules).any = {in: ["type.googleapis.com/google.protobuf.Duration"]}];} message AnyNotIn { google.protobuf.Any val = 1 [(validate.rules).any = {not_in: ["type.googleapis.com/google.protobuf.Timestamp"]}];} protoc-gen-validate-1.0.2/tests/harness/cases/wkt_duration.proto000066400000000000000000000040131444536353100250660ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; import "google/protobuf/duration.proto"; message DurationNone { google.protobuf.Duration val = 1; } message DurationRequired { google.protobuf.Duration val = 1 [(validate.rules).duration.required = true]; } // TODO(htuch): Add a very large duration, e.g. {seconds: 315576000000}, once // #34 is resolved. message DurationConst { google.protobuf.Duration val = 1 [(validate.rules).duration.const = {seconds: 3}]; } message DurationIn { google.protobuf.Duration val = 1 [(validate.rules).duration = {in: [{seconds:1}, {nanos:1000}]}]; } message DurationNotIn { google.protobuf.Duration val = 1 [(validate.rules).duration = {not_in: [{}]}]; } message DurationLT { google.protobuf.Duration val = 1 [(validate.rules).duration.lt = {}]; } message DurationLTE { google.protobuf.Duration val = 1 [(validate.rules).duration.lte = {seconds: 1}]; } message DurationGT { google.protobuf.Duration val = 1 [(validate.rules).duration.gt = {nanos: 1000}]; } message DurationGTE { google.protobuf.Duration val = 1 [(validate.rules).duration.gte = {nanos: 1000000}]; } message DurationGTLT { google.protobuf.Duration val = 1 [(validate.rules).duration = {gt: {}, lt: {seconds: 1}}]; } message DurationExLTGT { google.protobuf.Duration val = 1 [(validate.rules).duration = {lt: {}, gt: {seconds: 1}}]; } message DurationGTELTE { google.protobuf.Duration val = 1 [(validate.rules).duration = {gte: {seconds: 60}, lte: {seconds: 3600}}]; } message DurationExGTELTE { google.protobuf.Duration val = 1 [(validate.rules).duration = {lte: {seconds: 60}, gte: {seconds: 3600}}]; } // Regression for earlier bug where missing Duration field would short circuit // evaluation in C++. message DurationFieldWithOtherFields { google.protobuf.Duration duration_val = 1 [(validate.rules).duration.lte = {seconds: 1}]; int32 int_val = 2 [(validate.rules).int32.gt = 16]; } protoc-gen-validate-1.0.2/tests/harness/cases/wkt_nested.proto000066400000000000000000000007511444536353100245300ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; message WktLevelOne { message WktLevelTwo { message WktLevelThree { string uuid = 1 [(validate.rules).string.uuid = true]; } WktLevelThree three = 1 [(validate.rules).message.required = true]; } WktLevelTwo two = 1 [(validate.rules).message.required = true]; }protoc-gen-validate-1.0.2/tests/harness/cases/wkt_timestamp.proto000066400000000000000000000040451444536353100252510ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; import "google/protobuf/timestamp.proto"; message TimestampNone { google.protobuf.Timestamp val = 1; } message TimestampRequired { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp.required = true]; } message TimestampConst { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp.const = {seconds: 3}]; } message TimestampLT { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp.lt = {}]; } message TimestampLTE { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp.lte = {seconds: 1}]; } message TimestampGT { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp.gt = {nanos: 1000}]; } message TimestampGTE { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp.gte = {nanos: 1000000}]; } message TimestampGTLT { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp = {gt: {}, lt: {seconds: 1}}]; } message TimestampExLTGT { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp = {lt: {}, gt: {seconds: 1}}]; } message TimestampGTELTE { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp = {gte: {seconds: 60}, lte: {seconds: 3600}}]; } message TimestampExGTELTE { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp = {lte: {seconds: 60}, gte: {seconds: 3600}}]; } message TimestampLTNow { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp.lt_now = true]; } message TimestampGTNow { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp.gt_now = true]; } message TimestampWithin { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp.within.seconds = 3600]; } message TimestampLTNowWithin { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp = {lt_now: true, within: {seconds: 3600}}]; } message TimestampGTNowWithin { google.protobuf.Timestamp val = 1 [(validate.rules).timestamp = {gt_now: true, within: {seconds: 3600}}]; } protoc-gen-validate-1.0.2/tests/harness/cases/wkt_wrappers.proto000066400000000000000000000033361444536353100251130ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go;cases"; import "validate/validate.proto"; import "google/protobuf/wrappers.proto"; message WrapperNone { google.protobuf.Int32Value val = 1; } message WrapperFloat { google.protobuf.FloatValue val = 1 [(validate.rules).float.gt = 0]; } message WrapperDouble { google.protobuf.DoubleValue val = 1 [(validate.rules).double.gt = 0]; } message WrapperInt64 { google.protobuf.Int64Value val = 1 [(validate.rules).int64.gt = 0]; } message WrapperInt32 { google.protobuf.Int32Value val = 1 [(validate.rules).int32.gt = 0]; } message WrapperUInt64 { google.protobuf.UInt64Value val = 1 [(validate.rules).uint64.gt = 0]; } message WrapperUInt32 { google.protobuf.UInt32Value val = 1 [(validate.rules).uint32.gt = 0]; } message WrapperBool { google.protobuf.BoolValue val = 1 [(validate.rules).bool.const = true]; } message WrapperString { google.protobuf.StringValue val = 1 [(validate.rules).string.suffix = "bar"]; } message WrapperBytes { google.protobuf.BytesValue val = 1 [(validate.rules).bytes.min_len = 3]; } message WrapperRequiredString { google.protobuf.StringValue val = 1 [(validate.rules).string.const = "bar", (validate.rules).message.required = true]; } message WrapperRequiredEmptyString { google.protobuf.StringValue val = 1 [(validate.rules).string.const = "", (validate.rules).message.required = true]; } message WrapperOptionalUuidString { google.protobuf.StringValue val = 1 [(validate.rules).string.uuid = true, (validate.rules).message.required = false]; } message WrapperRequiredFloat { google.protobuf.FloatValue val = 1 [(validate.rules).float.gt = 0, (validate.rules).message.required = true]; } protoc-gen-validate-1.0.2/tests/harness/cases/yet_another_package/000077500000000000000000000000001444536353100252655ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/harness/cases/yet_another_package/BUILD000066400000000000000000000042231444536353100260500ustar00rootroot00000000000000load("@rules_java//java:defs.bzl", "java_proto_library") load("@com_google_protobuf//:protobuf.bzl", "py_proto_library") load("@io_bazel_rules_go//go:def.bzl", "go_library") load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") load("@rules_proto//proto:defs.bzl", "proto_library") load( "//bazel:pgv_proto_library.bzl", "pgv_cc_proto_library", "pgv_go_proto_library", "pgv_java_proto_library", ) proto_library( name = "embed_proto", srcs = [ "embed.proto", ], visibility = ["//visibility:public"], deps = ["//validate:validate_proto"], ) pgv_go_proto_library( name = "go", importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/yet_another_package/go", proto = ":embed_proto", deps = [ "@org_golang_google_protobuf//types/known/anypb:go_default_library", ], ) pgv_cc_proto_library( name = "cc", visibility = ["//tests:__subpackages__"], deps = [":embed_proto"], ) proto_library( name = "yet_another_package_proto", srcs = ["embed.proto"], visibility = ["//visibility:public"], deps = ["//validate:validate_proto"], ) go_proto_library( name = "yet_another_package_go_proto", importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/yet_another_package", proto = ":yet_another_package_proto", visibility = ["//visibility:public"], deps = ["//validate:go_default_library"], ) go_library( name = "go_default_library", embed = [":yet_another_package_go_proto"], importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/yet_another_package", visibility = ["//visibility:public"], ) java_proto_library( name = "embed_java_proto", visibility = ["//visibility:public"], deps = [":embed_proto"], ) pgv_java_proto_library( name = "java", java_deps = [":embed_java_proto"], visibility = ["//visibility:public"], deps = [":embed_proto"], ) py_proto_library( name = "embed_python_proto", srcs = ["embed.proto"], visibility = ["//visibility:public"], deps = [ "//validate:validate_py", "@com_google_protobuf//:protobuf_python", ], ) protoc-gen-validate-1.0.2/tests/harness/cases/yet_another_package/embed.proto000066400000000000000000000007231444536353100274300ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cases.yet_another_package; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/yet_another_package/go;yet_another_package"; import "validate/validate.proto"; // Validate message embedding across packages. message Embed { int64 val = 1 [(validate.rules).int64.gt = 0]; enum Enumerated { VALUE = 0; } enum BarNumber { ZERO = 0; ONE = 1; TWO = 2; } } protoc-gen-validate-1.0.2/tests/harness/cc/000077500000000000000000000000001444536353100205605ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/harness/cc/BUILD000066400000000000000000000043041444536353100213430ustar00rootroot00000000000000load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_proto_library", "cc_test") load("@rules_proto//proto:defs.bzl", "proto_library") MSVC_C_OPTS = [ "-WX", "-DWIN32", "-DWIN32_LEAN_AND_MEAN", ] POSIX_C_OPTS = [ "-Wall", "-Wextra", "-Werror", "-Wnon-virtual-dtor", "-Woverloaded-virtual", "-Wold-style-cast", "-std=c++14", ] config_setting( name = "windows_x86_64", values = {"cpu": "x64_windows"}, ) cc_binary( name = "cc-harness", srcs = ["harness.cc"], # These ensure that we are at least compatible with what Envoy is expecting. copts = select({ ":windows_x86_64": MSVC_C_OPTS, "//conditions:default": POSIX_C_OPTS, }), visibility = ["//visibility:public"], deps = [ "//tests/harness:harness_cc_proto", "//tests/harness/cases:cc", ], ) proto_library( name = "other_proto", srcs = ["other.proto"], ) cc_proto_library( name = "other_cc_proto", deps = ["other_proto"], ) cc_test( name = "polymorphic_test", srcs = ["polymorphic_test.cc"], copts = select({ ":windows_x86_64": MSVC_C_OPTS, "//conditions:default": POSIX_C_OPTS, }), deps = [ ":other_cc_proto", "//tests/harness/cases:cc", ], ) # Ensure that if the headers are included in multiple libraries, those libraries # can be linked without conflicts. cc_test( name = "cc_diamond_test", srcs = ["diamond_test.cc"], copts = select({ ":windows_x86_64": MSVC_C_OPTS, "//conditions:default": POSIX_C_OPTS, }), linkstatic = 1, # Forces both libraries to be linked in. DO NOT REMOVE THIS deps = [ "cc_diamond_0", "cc_diamond_1", ], ) cc_library( name = "cc_diamond_0", srcs = ["diamond_lib.cc"], copts = select({ ":windows_x86_64": MSVC_C_OPTS, "//conditions:default": POSIX_C_OPTS, }), deps = ["//tests/harness/cases:cc"], alwayslink = 1, ) cc_library( name = "cc_diamond_1", srcs = ["diamond_lib.cc"], copts = select({ ":windows_x86_64": MSVC_C_OPTS, "//conditions:default": POSIX_C_OPTS, }), deps = ["//tests/harness/cases:cc"], alwayslink = 1, ) protoc-gen-validate-1.0.2/tests/harness/cc/diamond_lib.cc000066400000000000000000000023651444536353100233360ustar00rootroot00000000000000#include "tests/harness/cases/bool.pb.h" #include "tests/harness/cases/bool.pb.validate.h" #include "tests/harness/cases/bytes.pb.h" #include "tests/harness/cases/bytes.pb.validate.h" #include "tests/harness/cases/enums.pb.h" #include "tests/harness/cases/enums.pb.validate.h" #include "tests/harness/cases/maps.pb.h" #include "tests/harness/cases/messages.pb.h" #include "tests/harness/cases/messages.pb.validate.h" #include "tests/harness/cases/numbers.pb.h" #include "tests/harness/cases/numbers.pb.validate.h" #include "tests/harness/cases/oneofs.pb.h" #include "tests/harness/cases/oneofs.pb.validate.h" #include "tests/harness/cases/repeated.pb.h" #include "tests/harness/cases/repeated.pb.validate.h" #include "tests/harness/cases/strings.pb.h" #include "tests/harness/cases/strings.pb.validate.h" #include "tests/harness/cases/wkt_any.pb.h" #include "tests/harness/cases/wkt_any.pb.validate.h" #include "tests/harness/cases/wkt_duration.pb.h" #include "tests/harness/cases/wkt_duration.pb.validate.h" #include "tests/harness/cases/wkt_nested.pb.h" #include "tests/harness/cases/wkt_nested.pb.validate.h" #include "tests/harness/cases/wkt_timestamp.pb.h" #include "tests/harness/cases/wkt_wrappers.pb.h" #include "tests/harness/cases/wkt_wrappers.pb.validate.h" protoc-gen-validate-1.0.2/tests/harness/cc/diamond_test.cc000066400000000000000000000024321444536353100235420ustar00rootroot00000000000000#include "tests/harness/cases/bool.pb.h" #include "tests/harness/cases/bool.pb.validate.h" #include "tests/harness/cases/bytes.pb.h" #include "tests/harness/cases/bytes.pb.validate.h" #include "tests/harness/cases/enums.pb.h" #include "tests/harness/cases/enums.pb.validate.h" #include "tests/harness/cases/maps.pb.h" #include "tests/harness/cases/messages.pb.h" #include "tests/harness/cases/messages.pb.validate.h" #include "tests/harness/cases/numbers.pb.h" #include "tests/harness/cases/numbers.pb.validate.h" #include "tests/harness/cases/oneofs.pb.h" #include "tests/harness/cases/oneofs.pb.validate.h" #include "tests/harness/cases/repeated.pb.h" #include "tests/harness/cases/repeated.pb.validate.h" #include "tests/harness/cases/strings.pb.h" #include "tests/harness/cases/strings.pb.validate.h" #include "tests/harness/cases/wkt_any.pb.h" #include "tests/harness/cases/wkt_any.pb.validate.h" #include "tests/harness/cases/wkt_duration.pb.h" #include "tests/harness/cases/wkt_duration.pb.validate.h" #include "tests/harness/cases/wkt_nested.pb.h" #include "tests/harness/cases/wkt_nested.pb.validate.h" #include "tests/harness/cases/wkt_timestamp.pb.h" #include "tests/harness/cases/wkt_wrappers.pb.h" #include "tests/harness/cases/wkt_wrappers.pb.validate.h" int main() { return EXIT_SUCCESS; } protoc-gen-validate-1.0.2/tests/harness/cc/harness.cc000066400000000000000000000143741444536353100225430ustar00rootroot00000000000000#include #include #if defined(WIN32) #include #include #include #endif #include "validate/validate.h" #include "tests/harness/cases/bool.pb.h" #include "tests/harness/cases/bool.pb.validate.h" #include "tests/harness/cases/bytes.pb.h" #include "tests/harness/cases/bytes.pb.validate.h" #include "tests/harness/cases/enums.pb.h" #include "tests/harness/cases/enums.pb.validate.h" #include "tests/harness/cases/filename-with-dash.pb.h" #include "tests/harness/cases/filename-with-dash.pb.validate.h" #include "tests/harness/cases/maps.pb.h" #include "tests/harness/cases/maps.pb.validate.h" #include "tests/harness/cases/messages.pb.h" #include "tests/harness/cases/messages.pb.validate.h" #include "tests/harness/cases/numbers.pb.h" #include "tests/harness/cases/numbers.pb.validate.h" #include "tests/harness/cases/oneofs.pb.h" #include "tests/harness/cases/oneofs.pb.validate.h" #include "tests/harness/cases/repeated.pb.h" #include "tests/harness/cases/repeated.pb.validate.h" #include "tests/harness/cases/strings.pb.h" #include "tests/harness/cases/strings.pb.validate.h" #include "tests/harness/cases/wkt_any.pb.h" #include "tests/harness/cases/wkt_any.pb.validate.h" #include "tests/harness/cases/wkt_duration.pb.h" #include "tests/harness/cases/wkt_duration.pb.validate.h" #include "tests/harness/cases/wkt_nested.pb.h" #include "tests/harness/cases/wkt_nested.pb.validate.h" #include "tests/harness/cases/wkt_timestamp.pb.h" #include "tests/harness/cases/wkt_timestamp.pb.validate.h" #include "tests/harness/cases/wkt_wrappers.pb.h" #include "tests/harness/cases/wkt_wrappers.pb.validate.h" #include "tests/harness/cases/kitchen_sink.pb.h" #include "tests/harness/cases/kitchen_sink.pb.validate.h" #include "tests/harness/harness.pb.h" // These macros are defined in the various validation headers and call the // X macro once for each message class in the header. Add macros here with new // pb.validate.h headers. #define X_TESTS_HARNESS_CASES(X) \ X_TESTS_HARNESS_CASES_BOOL(X) \ X_TESTS_HARNESS_CASES_BYTES(X) \ X_TESTS_HARNESS_CASES_ENUMS(X) \ X_TESTS_HARNESS_CASES_FILENAME_WITH_DASH(X) \ X_TESTS_HARNESS_CASES_MAPS(X) \ X_TESTS_HARNESS_CASES_MESSAGES(X) \ X_TESTS_HARNESS_CASES_NUMBERS(X) \ X_TESTS_HARNESS_CASES_ONEOFS(X) \ X_TESTS_HARNESS_CASES_REPEATED(X) \ X_TESTS_HARNESS_CASES_STRINGS(X) \ X_TESTS_HARNESS_CASES_WKT_ANY(X) \ X_TESTS_HARNESS_CASES_WKT_DURATION(X) \ X_TESTS_HARNESS_CASES_WKT_NESTED(X) \ X_TESTS_HARNESS_CASES_WKT_TIMESTAMP(X) \ X_TESTS_HARNESS_CASES_WKT_WRAPPERS(X) \ X_TESTS_HARNESS_CASES_KITCHEN_SINK(X) \ namespace { using tests::harness::TestCase; using tests::harness::TestResult; using google::protobuf::Any; std::ostream& operator<<(std::ostream& out, const TestResult& result) { if (result.reasons_size() > 0) { out << "valid: " << result.valid() << " reason: '" << result.reasons(0) << "'" << std::endl; } else { out << "valid: " << result.valid() << " reason: unknown" << std::endl; } return out; } void WriteTestResultAndExit(const TestResult& result) { if (!result.SerializeToOstream(&std::cout)) { std::cerr << "could not martial response: "; std::cerr << result << std::endl; exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } void ExitIfFailed(bool succeeded, const pgv::ValidationMsg& err_msg) { if (succeeded) { return; } TestResult result; result.set_error(true); result.add_reasons(pgv::String(err_msg)); WriteTestResultAndExit(result); } std::function GetValidationCheck(const Any& msg) { // This macro is intended to be called once for each message type with the // fully-qualified class name passed in as the only argument CLS. It checks // whether the msg argument above can be unpacked as a CLS. If so, it returns // a lambda that, when called, unpacks the message and validates it as a CLS. // This is here to work around the lack of duck-typing in C++, and because the // validation function can't be specified as a virtual method on the // google::protobuf::Message class. #define TRY_RETURN_VALIDATE_CALLABLE(CLS) \ if (msg.Is()) { \ return [msg] () { \ pgv::ValidationMsg err_msg; \ TestResult result; \ CLS unpacked; \ msg.UnpackTo(&unpacked); \ try { \ result.set_valid(Validate(unpacked, &err_msg)); \ result.add_reasons(std::move(err_msg)); \ } catch (pgv::UnimplementedException& e) { \ /* don't fail for unimplemented validations */ \ result.set_valid(false); \ result.set_allowfailure(true); \ result.add_reasons(e.what()); \ } \ return result; \ }; \ } X_TESTS_HARNESS_CASES(TRY_RETURN_VALIDATE_CALLABLE) #undef TRY_RETURN_VALIDATE_CALLABLE // Special handling for ignored messages, which don't have any code generated // for them. if (msg.Is<::tests::harness::cases::MessageIgnored>()) { return []() { TestResult result; result.set_valid(true); result.set_allowfailure(true); result.add_reasons("no validation possible for ignored messages"); return result; }; } // By default, return a null callable to signal that the message cannot be // handled. return nullptr; } } // namespace int main() { TestCase test_case; #if defined(WIN32) // need to explicitly set the stdin file mode to binary on Windows ExitIfFailed(_setmode(_fileno(stdin), _O_BINARY) != -1, "failed to set stdin to binary mode"); #endif ExitIfFailed(test_case.ParseFromIstream(&std::cin), "failed to parse TestCase"); auto validate_fn = GetValidationCheck(test_case.message()); if (validate_fn == nullptr) { std::cerr << "No known validator for message type " << test_case.message().type_url() << "; did you add it to the harness?"; return 1; } WriteTestResultAndExit(validate_fn()); return 0; } protoc-gen-validate-1.0.2/tests/harness/cc/other.proto000066400000000000000000000000761444536353100227710ustar00rootroot00000000000000syntax = "proto3"; package tests.harness.cc; message Foo {} protoc-gen-validate-1.0.2/tests/harness/cc/polymorphic_test.cc000066400000000000000000000010551444536353100244740ustar00rootroot00000000000000#include "tests/harness/cases/bool.pb.h" #include "tests/harness/cc/other.pb.h" #include "validate/validate.h" int main() { tests::harness::cc::Foo foo; // This does not have an associated validator but should still pass. std::string err; if (!pgv::BaseValidator::AbstractCheckMessage(foo, &err)) { return EXIT_FAILURE; } tests::harness::cases::BoolConstTrue bool_const_true; bool_const_true.set_val(false); if (pgv::BaseValidator::AbstractCheckMessage(bool_const_true, &err)) { return EXIT_FAILURE; } return EXIT_SUCCESS; } protoc-gen-validate-1.0.2/tests/harness/executor/000077500000000000000000000000001444536353100220315ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/harness/executor/BUILD000066400000000000000000000042341444536353100226160ustar00rootroot00000000000000load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") config_setting( name = "windows_x86_64", values = {"cpu": "x64_windows"}, ) go_library( name = "go_default_library", srcs = [ "cases.go", "executor.go", "harness.go", "worker.go", ], importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/executor", visibility = ["//visibility:private"], deps = [ "//tests/harness:harness_go_proto", "//tests/harness/cases:go", "//tests/harness/cases/other_package:go", "//tests/harness/cases/yet_another_package:go", "//tests/harness/cases/sort:go", "@org_golang_google_protobuf//proto:go_default_library", "@org_golang_google_protobuf//types/known/anypb:go_default_library", "@org_golang_google_protobuf//types/known/durationpb:go_default_library", "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", "@org_golang_google_protobuf//types/known/wrapperspb:go_default_library", "@org_golang_x_net//context:go_default_library", ], ) go_binary( name = "executor", data = ["//tests/harness/cc:cc-harness"] + select({ ":windows_x86_64": [ "//tests/harness/go/main:go-harness-exe", ], "//conditions:default": [ "//tests/harness/go/main:go-harness-bin", "//tests/harness/java:java-harness", "//tests/harness/python:python-harness", ], }), embed = [":go_default_library"], importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/executor", visibility = ["//visibility:private"], ) [ sh_test( name = "executor_" + lang + "_test", srcs = ["executor_test.sh"], args = [ "$(location :executor)", "-" + lang, ], data = [":executor"], # This could be sharded more, but each shard incurs overhead and test # execution is already sharded by having separate test rules for each language. shard_count = 5, deps = ["@bazel_tools//tools/bash/runfiles"], ) for lang in ("cc", "go", "java", "python") ] protoc-gen-validate-1.0.2/tests/harness/executor/cases.go000066400000000000000000002576351444536353100235000ustar00rootroot00000000000000package main import ( "math" "time" cases "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go" other_package "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/other_package/go" sort "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/sort/go" yet_another_package "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/yet_another_package/go" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/wrapperspb" ) type TestCase struct { Name string Message proto.Message Failures int // expected number of failed validation errors } type TestResult struct { OK, Skipped bool } var TestCases []TestCase func init() { sets := [][]TestCase{ floatCases, doubleCases, int32Cases, int64Cases, uint32Cases, uint64Cases, sint32Cases, sint64Cases, fixed32Cases, fixed64Cases, sfixed32Cases, sfixed64Cases, boolCases, stringCases, bytesCases, enumCases, messageCases, repeatedCases, mapCases, oneofCases, wrapperCases, durationCases, timestampCases, anyCases, kitchenSink, nestedCases, } for _, set := range sets { TestCases = append(TestCases, set...) } } var floatCases = []TestCase{ {"float - none - valid", &cases.FloatNone{Val: -1.23456}, 0}, {"float - const - valid", &cases.FloatConst{Val: 1.23}, 0}, {"float - const - invalid", &cases.FloatConst{Val: 4.56}, 1}, {"float - in - valid", &cases.FloatIn{Val: 7.89}, 0}, {"float - in - invalid", &cases.FloatIn{Val: 10.11}, 1}, {"float - not in - valid", &cases.FloatNotIn{Val: 1}, 0}, {"float - not in - invalid", &cases.FloatNotIn{Val: 0}, 1}, {"float - lt - valid", &cases.FloatLT{Val: -1}, 0}, {"float - lt - invalid (equal)", &cases.FloatLT{Val: 0}, 1}, {"float - lt - invalid", &cases.FloatLT{Val: 1}, 1}, {"float - lte - valid", &cases.FloatLTE{Val: 63}, 0}, {"float - lte - valid (equal)", &cases.FloatLTE{Val: 64}, 0}, {"float - lte - invalid", &cases.FloatLTE{Val: 65}, 1}, {"float - gt - valid", &cases.FloatGT{Val: 17}, 0}, {"float - gt - invalid (equal)", &cases.FloatGT{Val: 16}, 1}, {"float - gt - invalid", &cases.FloatGT{Val: 15}, 1}, {"float - gte - valid", &cases.FloatGTE{Val: 9}, 0}, {"float - gte - valid (equal)", &cases.FloatGTE{Val: 8}, 0}, {"float - gte - invalid", &cases.FloatGTE{Val: 7}, 1}, {"float - gt & lt - valid", &cases.FloatGTLT{Val: 5}, 0}, {"float - gt & lt - invalid (above)", &cases.FloatGTLT{Val: 11}, 1}, {"float - gt & lt - invalid (below)", &cases.FloatGTLT{Val: -1}, 1}, {"float - gt & lt - invalid (max)", &cases.FloatGTLT{Val: 10}, 1}, {"float - gt & lt - invalid (min)", &cases.FloatGTLT{Val: 0}, 1}, {"float - exclusive gt & lt - valid (above)", &cases.FloatExLTGT{Val: 11}, 0}, {"float - exclusive gt & lt - valid (below)", &cases.FloatExLTGT{Val: -1}, 0}, {"float - exclusive gt & lt - invalid", &cases.FloatExLTGT{Val: 5}, 1}, {"float - exclusive gt & lt - invalid (max)", &cases.FloatExLTGT{Val: 10}, 1}, {"float - exclusive gt & lt - invalid (min)", &cases.FloatExLTGT{Val: 0}, 1}, {"float - gte & lte - valid", &cases.FloatGTELTE{Val: 200}, 0}, {"float - gte & lte - valid (max)", &cases.FloatGTELTE{Val: 256}, 0}, {"float - gte & lte - valid (min)", &cases.FloatGTELTE{Val: 128}, 0}, {"float - gte & lte - invalid (above)", &cases.FloatGTELTE{Val: 300}, 1}, {"float - gte & lte - invalid (below)", &cases.FloatGTELTE{Val: 100}, 1}, {"float - exclusive gte & lte - valid (above)", &cases.FloatExGTELTE{Val: 300}, 0}, {"float - exclusive gte & lte - valid (below)", &cases.FloatExGTELTE{Val: 100}, 0}, {"float - exclusive gte & lte - valid (max)", &cases.FloatExGTELTE{Val: 256}, 0}, {"float - exclusive gte & lte - valid (min)", &cases.FloatExGTELTE{Val: 128}, 0}, {"float - exclusive gte & lte - invalid", &cases.FloatExGTELTE{Val: 200}, 1}, {"float - ignore_empty gte & lte - valid", &cases.FloatIgnore{Val: 0}, 0}, } var doubleCases = []TestCase{ {"double - none - valid", &cases.DoubleNone{Val: -1.23456}, 0}, {"double - const - valid", &cases.DoubleConst{Val: 1.23}, 0}, {"double - const - invalid", &cases.DoubleConst{Val: 4.56}, 1}, {"double - in - valid", &cases.DoubleIn{Val: 7.89}, 0}, {"double - in - invalid", &cases.DoubleIn{Val: 10.11}, 1}, {"double - not in - valid", &cases.DoubleNotIn{Val: 1}, 0}, {"double - not in - invalid", &cases.DoubleNotIn{Val: 0}, 1}, {"double - lt - valid", &cases.DoubleLT{Val: -1}, 0}, {"double - lt - invalid (equal)", &cases.DoubleLT{Val: 0}, 1}, {"double - lt - invalid", &cases.DoubleLT{Val: 1}, 1}, {"double - lte - valid", &cases.DoubleLTE{Val: 63}, 0}, {"double - lte - valid (equal)", &cases.DoubleLTE{Val: 64}, 0}, {"double - lte - invalid", &cases.DoubleLTE{Val: 65}, 1}, {"double - gt - valid", &cases.DoubleGT{Val: 17}, 0}, {"double - gt - invalid (equal)", &cases.DoubleGT{Val: 16}, 1}, {"double - gt - invalid", &cases.DoubleGT{Val: 15}, 1}, {"double - gte - valid", &cases.DoubleGTE{Val: 9}, 0}, {"double - gte - valid (equal)", &cases.DoubleGTE{Val: 8}, 0}, {"double - gte - invalid", &cases.DoubleGTE{Val: 7}, 1}, {"double - gt & lt - valid", &cases.DoubleGTLT{Val: 5}, 0}, {"double - gt & lt - invalid (above)", &cases.DoubleGTLT{Val: 11}, 1}, {"double - gt & lt - invalid (below)", &cases.DoubleGTLT{Val: -1}, 1}, {"double - gt & lt - invalid (max)", &cases.DoubleGTLT{Val: 10}, 1}, {"double - gt & lt - invalid (min)", &cases.DoubleGTLT{Val: 0}, 1}, {"double - exclusive gt & lt - valid (above)", &cases.DoubleExLTGT{Val: 11}, 0}, {"double - exclusive gt & lt - valid (below)", &cases.DoubleExLTGT{Val: -1}, 0}, {"double - exclusive gt & lt - invalid", &cases.DoubleExLTGT{Val: 5}, 1}, {"double - exclusive gt & lt - invalid (max)", &cases.DoubleExLTGT{Val: 10}, 1}, {"double - exclusive gt & lt - invalid (min)", &cases.DoubleExLTGT{Val: 0}, 1}, {"double - gte & lte - valid", &cases.DoubleGTELTE{Val: 200}, 0}, {"double - gte & lte - valid (max)", &cases.DoubleGTELTE{Val: 256}, 0}, {"double - gte & lte - valid (min)", &cases.DoubleGTELTE{Val: 128}, 0}, {"double - gte & lte - invalid (above)", &cases.DoubleGTELTE{Val: 300}, 1}, {"double - gte & lte - invalid (below)", &cases.DoubleGTELTE{Val: 100}, 1}, {"double - exclusive gte & lte - valid (above)", &cases.DoubleExGTELTE{Val: 300}, 0}, {"double - exclusive gte & lte - valid (below)", &cases.DoubleExGTELTE{Val: 100}, 0}, {"double - exclusive gte & lte - valid (max)", &cases.DoubleExGTELTE{Val: 256}, 0}, {"double - exclusive gte & lte - valid (min)", &cases.DoubleExGTELTE{Val: 128}, 0}, {"double - exclusive gte & lte - invalid", &cases.DoubleExGTELTE{Val: 200}, 1}, {"double - ignore_empty gte & lte - valid", &cases.DoubleIgnore{Val: 0}, 0}, } var int32Cases = []TestCase{ {"int32 - none - valid", &cases.Int32None{Val: 123}, 0}, {"int32 - const - valid", &cases.Int32Const{Val: 1}, 0}, {"int32 - const - invalid", &cases.Int32Const{Val: 2}, 1}, {"int32 - in - valid", &cases.Int32In{Val: 3}, 0}, {"int32 - in - invalid", &cases.Int32In{Val: 5}, 1}, {"int32 - not in - valid", &cases.Int32NotIn{Val: 1}, 0}, {"int32 - not in - invalid", &cases.Int32NotIn{Val: 0}, 1}, {"int32 - lt - valid", &cases.Int32LT{Val: -1}, 0}, {"int32 - lt - invalid (equal)", &cases.Int32LT{Val: 0}, 1}, {"int32 - lt - invalid", &cases.Int32LT{Val: 1}, 1}, {"int32 - lte - valid", &cases.Int32LTE{Val: 63}, 0}, {"int32 - lte - valid (equal)", &cases.Int32LTE{Val: 64}, 0}, {"int32 - lte - invalid", &cases.Int32LTE{Val: 65}, 1}, {"int32 - gt - valid", &cases.Int32GT{Val: 17}, 0}, {"int32 - gt - invalid (equal)", &cases.Int32GT{Val: 16}, 1}, {"int32 - gt - invalid", &cases.Int32GT{Val: 15}, 1}, {"int32 - gte - valid", &cases.Int32GTE{Val: 9}, 0}, {"int32 - gte - valid (equal)", &cases.Int32GTE{Val: 8}, 0}, {"int32 - gte - invalid", &cases.Int32GTE{Val: 7}, 1}, {"int32 - gt & lt - valid", &cases.Int32GTLT{Val: 5}, 0}, {"int32 - gt & lt - invalid (above)", &cases.Int32GTLT{Val: 11}, 1}, {"int32 - gt & lt - invalid (below)", &cases.Int32GTLT{Val: -1}, 1}, {"int32 - gt & lt - invalid (max)", &cases.Int32GTLT{Val: 10}, 1}, {"int32 - gt & lt - invalid (min)", &cases.Int32GTLT{Val: 0}, 1}, {"int32 - exclusive gt & lt - valid (above)", &cases.Int32ExLTGT{Val: 11}, 0}, {"int32 - exclusive gt & lt - valid (below)", &cases.Int32ExLTGT{Val: -1}, 0}, {"int32 - exclusive gt & lt - invalid", &cases.Int32ExLTGT{Val: 5}, 1}, {"int32 - exclusive gt & lt - invalid (max)", &cases.Int32ExLTGT{Val: 10}, 1}, {"int32 - exclusive gt & lt - invalid (min)", &cases.Int32ExLTGT{Val: 0}, 1}, {"int32 - gte & lte - valid", &cases.Int32GTELTE{Val: 200}, 0}, {"int32 - gte & lte - valid (max)", &cases.Int32GTELTE{Val: 256}, 0}, {"int32 - gte & lte - valid (min)", &cases.Int32GTELTE{Val: 128}, 0}, {"int32 - gte & lte - invalid (above)", &cases.Int32GTELTE{Val: 300}, 1}, {"int32 - gte & lte - invalid (below)", &cases.Int32GTELTE{Val: 100}, 1}, {"int32 - exclusive gte & lte - valid (above)", &cases.Int32ExGTELTE{Val: 300}, 0}, {"int32 - exclusive gte & lte - valid (below)", &cases.Int32ExGTELTE{Val: 100}, 0}, {"int32 - exclusive gte & lte - valid (max)", &cases.Int32ExGTELTE{Val: 256}, 0}, {"int32 - exclusive gte & lte - valid (min)", &cases.Int32ExGTELTE{Val: 128}, 0}, {"int32 - exclusive gte & lte - invalid", &cases.Int32ExGTELTE{Val: 200}, 1}, {"int32 - ignore_empty gte & lte - valid", &cases.Int32Ignore{Val: 0}, 0}, } var int64Cases = []TestCase{ {"int64 - none - valid", &cases.Int64None{Val: 123}, 0}, {"int64 - const - valid", &cases.Int64Const{Val: 1}, 0}, {"int64 - const - invalid", &cases.Int64Const{Val: 2}, 1}, {"int64 - in - valid", &cases.Int64In{Val: 3}, 0}, {"int64 - in - invalid", &cases.Int64In{Val: 5}, 1}, {"int64 - not in - valid", &cases.Int64NotIn{Val: 1}, 0}, {"int64 - not in - invalid", &cases.Int64NotIn{Val: 0}, 1}, {"int64 - lt - valid", &cases.Int64LT{Val: -1}, 0}, {"int64 - lt - invalid (equal)", &cases.Int64LT{Val: 0}, 1}, {"int64 - lt - invalid", &cases.Int64LT{Val: 1}, 1}, {"int64 - lte - valid", &cases.Int64LTE{Val: 63}, 0}, {"int64 - lte - valid (equal)", &cases.Int64LTE{Val: 64}, 0}, {"int64 - lte - invalid", &cases.Int64LTE{Val: 65}, 1}, {"int64 - gt - valid", &cases.Int64GT{Val: 17}, 0}, {"int64 - gt - invalid (equal)", &cases.Int64GT{Val: 16}, 1}, {"int64 - gt - invalid", &cases.Int64GT{Val: 15}, 1}, {"int64 - gte - valid", &cases.Int64GTE{Val: 9}, 0}, {"int64 - gte - valid (equal)", &cases.Int64GTE{Val: 8}, 0}, {"int64 - gte - invalid", &cases.Int64GTE{Val: 7}, 1}, {"int64 - gt & lt - valid", &cases.Int64GTLT{Val: 5}, 0}, {"int64 - gt & lt - invalid (above)", &cases.Int64GTLT{Val: 11}, 1}, {"int64 - gt & lt - invalid (below)", &cases.Int64GTLT{Val: -1}, 1}, {"int64 - gt & lt - invalid (max)", &cases.Int64GTLT{Val: 10}, 1}, {"int64 - gt & lt - invalid (min)", &cases.Int64GTLT{Val: 0}, 1}, {"int64 - exclusive gt & lt - valid (above)", &cases.Int64ExLTGT{Val: 11}, 0}, {"int64 - exclusive gt & lt - valid (below)", &cases.Int64ExLTGT{Val: -1}, 0}, {"int64 - exclusive gt & lt - invalid", &cases.Int64ExLTGT{Val: 5}, 1}, {"int64 - exclusive gt & lt - invalid (max)", &cases.Int64ExLTGT{Val: 10}, 1}, {"int64 - exclusive gt & lt - invalid (min)", &cases.Int64ExLTGT{Val: 0}, 1}, {"int64 - gte & lte - valid", &cases.Int64GTELTE{Val: 200}, 0}, {"int64 - gte & lte - valid (max)", &cases.Int64GTELTE{Val: 256}, 0}, {"int64 - gte & lte - valid (min)", &cases.Int64GTELTE{Val: 128}, 0}, {"int64 - gte & lte - invalid (above)", &cases.Int64GTELTE{Val: 300}, 1}, {"int64 - gte & lte - invalid (below)", &cases.Int64GTELTE{Val: 100}, 1}, {"int64 - exclusive gte & lte - valid (above)", &cases.Int64ExGTELTE{Val: 300}, 0}, {"int64 - exclusive gte & lte - valid (below)", &cases.Int64ExGTELTE{Val: 100}, 0}, {"int64 - exclusive gte & lte - valid (max)", &cases.Int64ExGTELTE{Val: 256}, 0}, {"int64 - exclusive gte & lte - valid (min)", &cases.Int64ExGTELTE{Val: 128}, 0}, {"int64 - exclusive gte & lte - invalid", &cases.Int64ExGTELTE{Val: 200}, 1}, {"int64 - ignore_empty gte & lte - valid", &cases.Int64Ignore{Val: 0}, 0}, {"int64 optional - lte - valid", &cases.Int64LTEOptional{Val: &wrapperspb.Int64(63).Value}, 0}, {"int64 optional - lte - valid (equal)", &cases.Int64LTEOptional{Val: &wrapperspb.Int64(64).Value}, 0}, {"int64 optional - lte - valid (unset)", &cases.Int64LTEOptional{}, 0}, } var uint32Cases = []TestCase{ {"uint32 - none - valid", &cases.UInt32None{Val: 123}, 0}, {"uint32 - const - valid", &cases.UInt32Const{Val: 1}, 0}, {"uint32 - const - invalid", &cases.UInt32Const{Val: 2}, 1}, {"uint32 - in - valid", &cases.UInt32In{Val: 3}, 0}, {"uint32 - in - invalid", &cases.UInt32In{Val: 5}, 1}, {"uint32 - not in - valid", &cases.UInt32NotIn{Val: 1}, 0}, {"uint32 - not in - invalid", &cases.UInt32NotIn{Val: 0}, 1}, {"uint32 - lt - valid", &cases.UInt32LT{Val: 4}, 0}, {"uint32 - lt - invalid (equal)", &cases.UInt32LT{Val: 5}, 1}, {"uint32 - lt - invalid", &cases.UInt32LT{Val: 6}, 1}, {"uint32 - lte - valid", &cases.UInt32LTE{Val: 63}, 0}, {"uint32 - lte - valid (equal)", &cases.UInt32LTE{Val: 64}, 0}, {"uint32 - lte - invalid", &cases.UInt32LTE{Val: 65}, 1}, {"uint32 - gt - valid", &cases.UInt32GT{Val: 17}, 0}, {"uint32 - gt - invalid (equal)", &cases.UInt32GT{Val: 16}, 1}, {"uint32 - gt - invalid", &cases.UInt32GT{Val: 15}, 1}, {"uint32 - gte - valid", &cases.UInt32GTE{Val: 9}, 0}, {"uint32 - gte - valid (equal)", &cases.UInt32GTE{Val: 8}, 0}, {"uint32 - gte - invalid", &cases.UInt32GTE{Val: 7}, 1}, {"uint32 - gt & lt - valid", &cases.UInt32GTLT{Val: 7}, 0}, {"uint32 - gt & lt - invalid (above)", &cases.UInt32GTLT{Val: 11}, 1}, {"uint32 - gt & lt - invalid (below)", &cases.UInt32GTLT{Val: 1}, 1}, {"uint32 - gt & lt - invalid (max)", &cases.UInt32GTLT{Val: 10}, 1}, {"uint32 - gt & lt - invalid (min)", &cases.UInt32GTLT{Val: 5}, 1}, {"uint32 - exclusive gt & lt - valid (above)", &cases.UInt32ExLTGT{Val: 11}, 0}, {"uint32 - exclusive gt & lt - valid (below)", &cases.UInt32ExLTGT{Val: 4}, 0}, {"uint32 - exclusive gt & lt - invalid", &cases.UInt32ExLTGT{Val: 7}, 1}, {"uint32 - exclusive gt & lt - invalid (max)", &cases.UInt32ExLTGT{Val: 10}, 1}, {"uint32 - exclusive gt & lt - invalid (min)", &cases.UInt32ExLTGT{Val: 5}, 1}, {"uint32 - gte & lte - valid", &cases.UInt32GTELTE{Val: 200}, 0}, {"uint32 - gte & lte - valid (max)", &cases.UInt32GTELTE{Val: 256}, 0}, {"uint32 - gte & lte - valid (min)", &cases.UInt32GTELTE{Val: 128}, 0}, {"uint32 - gte & lte - invalid (above)", &cases.UInt32GTELTE{Val: 300}, 1}, {"uint32 - gte & lte - invalid (below)", &cases.UInt32GTELTE{Val: 100}, 1}, {"uint32 - exclusive gte & lte - valid (above)", &cases.UInt32ExGTELTE{Val: 300}, 0}, {"uint32 - exclusive gte & lte - valid (below)", &cases.UInt32ExGTELTE{Val: 100}, 0}, {"uint32 - exclusive gte & lte - valid (max)", &cases.UInt32ExGTELTE{Val: 256}, 0}, {"uint32 - exclusive gte & lte - valid (min)", &cases.UInt32ExGTELTE{Val: 128}, 0}, {"uint32 - exclusive gte & lte - invalid", &cases.UInt32ExGTELTE{Val: 200}, 1}, {"uint32 - ignore_empty gte & lte - valid", &cases.UInt32Ignore{Val: 0}, 0}, } var uint64Cases = []TestCase{ {"uint64 - none - valid", &cases.UInt64None{Val: 123}, 0}, {"uint64 - const - valid", &cases.UInt64Const{Val: 1}, 0}, {"uint64 - const - invalid", &cases.UInt64Const{Val: 2}, 1}, {"uint64 - in - valid", &cases.UInt64In{Val: 3}, 0}, {"uint64 - in - invalid", &cases.UInt64In{Val: 5}, 1}, {"uint64 - not in - valid", &cases.UInt64NotIn{Val: 1}, 0}, {"uint64 - not in - invalid", &cases.UInt64NotIn{Val: 0}, 1}, {"uint64 - lt - valid", &cases.UInt64LT{Val: 4}, 0}, {"uint64 - lt - invalid (equal)", &cases.UInt64LT{Val: 5}, 1}, {"uint64 - lt - invalid", &cases.UInt64LT{Val: 6}, 1}, {"uint64 - lte - valid", &cases.UInt64LTE{Val: 63}, 0}, {"uint64 - lte - valid (equal)", &cases.UInt64LTE{Val: 64}, 0}, {"uint64 - lte - invalid", &cases.UInt64LTE{Val: 65}, 1}, {"uint64 - gt - valid", &cases.UInt64GT{Val: 17}, 0}, {"uint64 - gt - invalid (equal)", &cases.UInt64GT{Val: 16}, 1}, {"uint64 - gt - invalid", &cases.UInt64GT{Val: 15}, 1}, {"uint64 - gte - valid", &cases.UInt64GTE{Val: 9}, 0}, {"uint64 - gte - valid (equal)", &cases.UInt64GTE{Val: 8}, 0}, {"uint64 - gte - invalid", &cases.UInt64GTE{Val: 7}, 1}, {"uint64 - gt & lt - valid", &cases.UInt64GTLT{Val: 7}, 0}, {"uint64 - gt & lt - invalid (above)", &cases.UInt64GTLT{Val: 11}, 1}, {"uint64 - gt & lt - invalid (below)", &cases.UInt64GTLT{Val: 1}, 1}, {"uint64 - gt & lt - invalid (max)", &cases.UInt64GTLT{Val: 10}, 1}, {"uint64 - gt & lt - invalid (min)", &cases.UInt64GTLT{Val: 5}, 1}, {"uint64 - exclusive gt & lt - valid (above)", &cases.UInt64ExLTGT{Val: 11}, 0}, {"uint64 - exclusive gt & lt - valid (below)", &cases.UInt64ExLTGT{Val: 4}, 0}, {"uint64 - exclusive gt & lt - invalid", &cases.UInt64ExLTGT{Val: 7}, 1}, {"uint64 - exclusive gt & lt - invalid (max)", &cases.UInt64ExLTGT{Val: 10}, 1}, {"uint64 - exclusive gt & lt - invalid (min)", &cases.UInt64ExLTGT{Val: 5}, 1}, {"uint64 - gte & lte - valid", &cases.UInt64GTELTE{Val: 200}, 0}, {"uint64 - gte & lte - valid (max)", &cases.UInt64GTELTE{Val: 256}, 0}, {"uint64 - gte & lte - valid (min)", &cases.UInt64GTELTE{Val: 128}, 0}, {"uint64 - gte & lte - invalid (above)", &cases.UInt64GTELTE{Val: 300}, 1}, {"uint64 - gte & lte - invalid (below)", &cases.UInt64GTELTE{Val: 100}, 1}, {"uint64 - exclusive gte & lte - valid (above)", &cases.UInt64ExGTELTE{Val: 300}, 0}, {"uint64 - exclusive gte & lte - valid (below)", &cases.UInt64ExGTELTE{Val: 100}, 0}, {"uint64 - exclusive gte & lte - valid (max)", &cases.UInt64ExGTELTE{Val: 256}, 0}, {"uint64 - exclusive gte & lte - valid (min)", &cases.UInt64ExGTELTE{Val: 128}, 0}, {"uint64 - exclusive gte & lte - invalid", &cases.UInt64ExGTELTE{Val: 200}, 1}, {"uint64 - ignore_empty gte & lte - valid", &cases.UInt64Ignore{Val: 0}, 0}, } var sint32Cases = []TestCase{ {"sint32 - none - valid", &cases.SInt32None{Val: 123}, 0}, {"sint32 - const - valid", &cases.SInt32Const{Val: 1}, 0}, {"sint32 - const - invalid", &cases.SInt32Const{Val: 2}, 1}, {"sint32 - in - valid", &cases.SInt32In{Val: 3}, 0}, {"sint32 - in - invalid", &cases.SInt32In{Val: 5}, 1}, {"sint32 - not in - valid", &cases.SInt32NotIn{Val: 1}, 0}, {"sint32 - not in - invalid", &cases.SInt32NotIn{Val: 0}, 1}, {"sint32 - lt - valid", &cases.SInt32LT{Val: -1}, 0}, {"sint32 - lt - invalid (equal)", &cases.SInt32LT{Val: 0}, 1}, {"sint32 - lt - invalid", &cases.SInt32LT{Val: 1}, 1}, {"sint32 - lte - valid", &cases.SInt32LTE{Val: 63}, 0}, {"sint32 - lte - valid (equal)", &cases.SInt32LTE{Val: 64}, 0}, {"sint32 - lte - invalid", &cases.SInt32LTE{Val: 65}, 1}, {"sint32 - gt - valid", &cases.SInt32GT{Val: 17}, 0}, {"sint32 - gt - invalid (equal)", &cases.SInt32GT{Val: 16}, 1}, {"sint32 - gt - invalid", &cases.SInt32GT{Val: 15}, 1}, {"sint32 - gte - valid", &cases.SInt32GTE{Val: 9}, 0}, {"sint32 - gte - valid (equal)", &cases.SInt32GTE{Val: 8}, 0}, {"sint32 - gte - invalid", &cases.SInt32GTE{Val: 7}, 1}, {"sint32 - gt & lt - valid", &cases.SInt32GTLT{Val: 5}, 0}, {"sint32 - gt & lt - invalid (above)", &cases.SInt32GTLT{Val: 11}, 1}, {"sint32 - gt & lt - invalid (below)", &cases.SInt32GTLT{Val: -1}, 1}, {"sint32 - gt & lt - invalid (max)", &cases.SInt32GTLT{Val: 10}, 1}, {"sint32 - gt & lt - invalid (min)", &cases.SInt32GTLT{Val: 0}, 1}, {"sint32 - exclusive gt & lt - valid (above)", &cases.SInt32ExLTGT{Val: 11}, 0}, {"sint32 - exclusive gt & lt - valid (below)", &cases.SInt32ExLTGT{Val: -1}, 0}, {"sint32 - exclusive gt & lt - invalid", &cases.SInt32ExLTGT{Val: 5}, 1}, {"sint32 - exclusive gt & lt - invalid (max)", &cases.SInt32ExLTGT{Val: 10}, 1}, {"sint32 - exclusive gt & lt - invalid (min)", &cases.SInt32ExLTGT{Val: 0}, 1}, {"sint32 - gte & lte - valid", &cases.SInt32GTELTE{Val: 200}, 0}, {"sint32 - gte & lte - valid (max)", &cases.SInt32GTELTE{Val: 256}, 0}, {"sint32 - gte & lte - valid (min)", &cases.SInt32GTELTE{Val: 128}, 0}, {"sint32 - gte & lte - invalid (above)", &cases.SInt32GTELTE{Val: 300}, 1}, {"sint32 - gte & lte - invalid (below)", &cases.SInt32GTELTE{Val: 100}, 1}, {"sint32 - exclusive gte & lte - valid (above)", &cases.SInt32ExGTELTE{Val: 300}, 0}, {"sint32 - exclusive gte & lte - valid (below)", &cases.SInt32ExGTELTE{Val: 100}, 0}, {"sint32 - exclusive gte & lte - valid (max)", &cases.SInt32ExGTELTE{Val: 256}, 0}, {"sint32 - exclusive gte & lte - valid (min)", &cases.SInt32ExGTELTE{Val: 128}, 0}, {"sint32 - exclusive gte & lte - invalid", &cases.SInt32ExGTELTE{Val: 200}, 1}, {"sint32 - ignore_empty gte & lte - valid", &cases.SInt32Ignore{Val: 0}, 0}, } var sint64Cases = []TestCase{ {"sint64 - none - valid", &cases.SInt64None{Val: 123}, 0}, {"sint64 - const - valid", &cases.SInt64Const{Val: 1}, 0}, {"sint64 - const - invalid", &cases.SInt64Const{Val: 2}, 1}, {"sint64 - in - valid", &cases.SInt64In{Val: 3}, 0}, {"sint64 - in - invalid", &cases.SInt64In{Val: 5}, 1}, {"sint64 - not in - valid", &cases.SInt64NotIn{Val: 1}, 0}, {"sint64 - not in - invalid", &cases.SInt64NotIn{Val: 0}, 1}, {"sint64 - lt - valid", &cases.SInt64LT{Val: -1}, 0}, {"sint64 - lt - invalid (equal)", &cases.SInt64LT{Val: 0}, 1}, {"sint64 - lt - invalid", &cases.SInt64LT{Val: 1}, 1}, {"sint64 - lte - valid", &cases.SInt64LTE{Val: 63}, 0}, {"sint64 - lte - valid (equal)", &cases.SInt64LTE{Val: 64}, 0}, {"sint64 - lte - invalid", &cases.SInt64LTE{Val: 65}, 1}, {"sint64 - gt - valid", &cases.SInt64GT{Val: 17}, 0}, {"sint64 - gt - invalid (equal)", &cases.SInt64GT{Val: 16}, 1}, {"sint64 - gt - invalid", &cases.SInt64GT{Val: 15}, 1}, {"sint64 - gte - valid", &cases.SInt64GTE{Val: 9}, 0}, {"sint64 - gte - valid (equal)", &cases.SInt64GTE{Val: 8}, 0}, {"sint64 - gte - invalid", &cases.SInt64GTE{Val: 7}, 1}, {"sint64 - gt & lt - valid", &cases.SInt64GTLT{Val: 5}, 0}, {"sint64 - gt & lt - invalid (above)", &cases.SInt64GTLT{Val: 11}, 1}, {"sint64 - gt & lt - invalid (below)", &cases.SInt64GTLT{Val: -1}, 1}, {"sint64 - gt & lt - invalid (max)", &cases.SInt64GTLT{Val: 10}, 1}, {"sint64 - gt & lt - invalid (min)", &cases.SInt64GTLT{Val: 0}, 1}, {"sint64 - exclusive gt & lt - valid (above)", &cases.SInt64ExLTGT{Val: 11}, 0}, {"sint64 - exclusive gt & lt - valid (below)", &cases.SInt64ExLTGT{Val: -1}, 0}, {"sint64 - exclusive gt & lt - invalid", &cases.SInt64ExLTGT{Val: 5}, 1}, {"sint64 - exclusive gt & lt - invalid (max)", &cases.SInt64ExLTGT{Val: 10}, 1}, {"sint64 - exclusive gt & lt - invalid (min)", &cases.SInt64ExLTGT{Val: 0}, 1}, {"sint64 - gte & lte - valid", &cases.SInt64GTELTE{Val: 200}, 0}, {"sint64 - gte & lte - valid (max)", &cases.SInt64GTELTE{Val: 256}, 0}, {"sint64 - gte & lte - valid (min)", &cases.SInt64GTELTE{Val: 128}, 0}, {"sint64 - gte & lte - invalid (above)", &cases.SInt64GTELTE{Val: 300}, 1}, {"sint64 - gte & lte - invalid (below)", &cases.SInt64GTELTE{Val: 100}, 1}, {"sint64 - exclusive gte & lte - valid (above)", &cases.SInt64ExGTELTE{Val: 300}, 0}, {"sint64 - exclusive gte & lte - valid (below)", &cases.SInt64ExGTELTE{Val: 100}, 0}, {"sint64 - exclusive gte & lte - valid (max)", &cases.SInt64ExGTELTE{Val: 256}, 0}, {"sint64 - exclusive gte & lte - valid (min)", &cases.SInt64ExGTELTE{Val: 128}, 0}, {"sint64 - exclusive gte & lte - invalid", &cases.SInt64ExGTELTE{Val: 200}, 1}, {"sint64 - ignore_empty gte & lte - valid", &cases.SInt64Ignore{Val: 0}, 0}, } var fixed32Cases = []TestCase{ {"fixed32 - none - valid", &cases.Fixed32None{Val: 123}, 0}, {"fixed32 - const - valid", &cases.Fixed32Const{Val: 1}, 0}, {"fixed32 - const - invalid", &cases.Fixed32Const{Val: 2}, 1}, {"fixed32 - in - valid", &cases.Fixed32In{Val: 3}, 0}, {"fixed32 - in - invalid", &cases.Fixed32In{Val: 5}, 1}, {"fixed32 - not in - valid", &cases.Fixed32NotIn{Val: 1}, 0}, {"fixed32 - not in - invalid", &cases.Fixed32NotIn{Val: 0}, 1}, {"fixed32 - lt - valid", &cases.Fixed32LT{Val: 4}, 0}, {"fixed32 - lt - invalid (equal)", &cases.Fixed32LT{Val: 5}, 1}, {"fixed32 - lt - invalid", &cases.Fixed32LT{Val: 6}, 1}, {"fixed32 - lte - valid", &cases.Fixed32LTE{Val: 63}, 0}, {"fixed32 - lte - valid (equal)", &cases.Fixed32LTE{Val: 64}, 0}, {"fixed32 - lte - invalid", &cases.Fixed32LTE{Val: 65}, 1}, {"fixed32 - gt - valid", &cases.Fixed32GT{Val: 17}, 0}, {"fixed32 - gt - invalid (equal)", &cases.Fixed32GT{Val: 16}, 1}, {"fixed32 - gt - invalid", &cases.Fixed32GT{Val: 15}, 1}, {"fixed32 - gte - valid", &cases.Fixed32GTE{Val: 9}, 0}, {"fixed32 - gte - valid (equal)", &cases.Fixed32GTE{Val: 8}, 0}, {"fixed32 - gte - invalid", &cases.Fixed32GTE{Val: 7}, 1}, {"fixed32 - gt & lt - valid", &cases.Fixed32GTLT{Val: 7}, 0}, {"fixed32 - gt & lt - invalid (above)", &cases.Fixed32GTLT{Val: 11}, 1}, {"fixed32 - gt & lt - invalid (below)", &cases.Fixed32GTLT{Val: 1}, 1}, {"fixed32 - gt & lt - invalid (max)", &cases.Fixed32GTLT{Val: 10}, 1}, {"fixed32 - gt & lt - invalid (min)", &cases.Fixed32GTLT{Val: 5}, 1}, {"fixed32 - exclusive gt & lt - valid (above)", &cases.Fixed32ExLTGT{Val: 11}, 0}, {"fixed32 - exclusive gt & lt - valid (below)", &cases.Fixed32ExLTGT{Val: 4}, 0}, {"fixed32 - exclusive gt & lt - invalid", &cases.Fixed32ExLTGT{Val: 7}, 1}, {"fixed32 - exclusive gt & lt - invalid (max)", &cases.Fixed32ExLTGT{Val: 10}, 1}, {"fixed32 - exclusive gt & lt - invalid (min)", &cases.Fixed32ExLTGT{Val: 5}, 1}, {"fixed32 - gte & lte - valid", &cases.Fixed32GTELTE{Val: 200}, 0}, {"fixed32 - gte & lte - valid (max)", &cases.Fixed32GTELTE{Val: 256}, 0}, {"fixed32 - gte & lte - valid (min)", &cases.Fixed32GTELTE{Val: 128}, 0}, {"fixed32 - gte & lte - invalid (above)", &cases.Fixed32GTELTE{Val: 300}, 1}, {"fixed32 - gte & lte - invalid (below)", &cases.Fixed32GTELTE{Val: 100}, 1}, {"fixed32 - exclusive gte & lte - valid (above)", &cases.Fixed32ExGTELTE{Val: 300}, 0}, {"fixed32 - exclusive gte & lte - valid (below)", &cases.Fixed32ExGTELTE{Val: 100}, 0}, {"fixed32 - exclusive gte & lte - valid (max)", &cases.Fixed32ExGTELTE{Val: 256}, 0}, {"fixed32 - exclusive gte & lte - valid (min)", &cases.Fixed32ExGTELTE{Val: 128}, 0}, {"fixed32 - exclusive gte & lte - invalid", &cases.Fixed32ExGTELTE{Val: 200}, 1}, {"fixed32 - ignore_empty gte & lte - valid", &cases.Fixed32Ignore{Val: 0}, 0}, } var fixed64Cases = []TestCase{ {"fixed64 - none - valid", &cases.Fixed64None{Val: 123}, 0}, {"fixed64 - const - valid", &cases.Fixed64Const{Val: 1}, 0}, {"fixed64 - const - invalid", &cases.Fixed64Const{Val: 2}, 1}, {"fixed64 - in - valid", &cases.Fixed64In{Val: 3}, 0}, {"fixed64 - in - invalid", &cases.Fixed64In{Val: 5}, 1}, {"fixed64 - not in - valid", &cases.Fixed64NotIn{Val: 1}, 0}, {"fixed64 - not in - invalid", &cases.Fixed64NotIn{Val: 0}, 1}, {"fixed64 - lt - valid", &cases.Fixed64LT{Val: 4}, 0}, {"fixed64 - lt - invalid (equal)", &cases.Fixed64LT{Val: 5}, 1}, {"fixed64 - lt - invalid", &cases.Fixed64LT{Val: 6}, 1}, {"fixed64 - lte - valid", &cases.Fixed64LTE{Val: 63}, 0}, {"fixed64 - lte - valid (equal)", &cases.Fixed64LTE{Val: 64}, 0}, {"fixed64 - lte - invalid", &cases.Fixed64LTE{Val: 65}, 1}, {"fixed64 - gt - valid", &cases.Fixed64GT{Val: 17}, 0}, {"fixed64 - gt - invalid (equal)", &cases.Fixed64GT{Val: 16}, 1}, {"fixed64 - gt - invalid", &cases.Fixed64GT{Val: 15}, 1}, {"fixed64 - gte - valid", &cases.Fixed64GTE{Val: 9}, 0}, {"fixed64 - gte - valid (equal)", &cases.Fixed64GTE{Val: 8}, 0}, {"fixed64 - gte - invalid", &cases.Fixed64GTE{Val: 7}, 1}, {"fixed64 - gt & lt - valid", &cases.Fixed64GTLT{Val: 7}, 0}, {"fixed64 - gt & lt - invalid (above)", &cases.Fixed64GTLT{Val: 11}, 1}, {"fixed64 - gt & lt - invalid (below)", &cases.Fixed64GTLT{Val: 1}, 1}, {"fixed64 - gt & lt - invalid (max)", &cases.Fixed64GTLT{Val: 10}, 1}, {"fixed64 - gt & lt - invalid (min)", &cases.Fixed64GTLT{Val: 5}, 1}, {"fixed64 - exclusive gt & lt - valid (above)", &cases.Fixed64ExLTGT{Val: 11}, 0}, {"fixed64 - exclusive gt & lt - valid (below)", &cases.Fixed64ExLTGT{Val: 4}, 0}, {"fixed64 - exclusive gt & lt - invalid", &cases.Fixed64ExLTGT{Val: 7}, 1}, {"fixed64 - exclusive gt & lt - invalid (max)", &cases.Fixed64ExLTGT{Val: 10}, 1}, {"fixed64 - exclusive gt & lt - invalid (min)", &cases.Fixed64ExLTGT{Val: 5}, 1}, {"fixed64 - gte & lte - valid", &cases.Fixed64GTELTE{Val: 200}, 0}, {"fixed64 - gte & lte - valid (max)", &cases.Fixed64GTELTE{Val: 256}, 0}, {"fixed64 - gte & lte - valid (min)", &cases.Fixed64GTELTE{Val: 128}, 0}, {"fixed64 - gte & lte - invalid (above)", &cases.Fixed64GTELTE{Val: 300}, 1}, {"fixed64 - gte & lte - invalid (below)", &cases.Fixed64GTELTE{Val: 100}, 1}, {"fixed64 - exclusive gte & lte - valid (above)", &cases.Fixed64ExGTELTE{Val: 300}, 0}, {"fixed64 - exclusive gte & lte - valid (below)", &cases.Fixed64ExGTELTE{Val: 100}, 0}, {"fixed64 - exclusive gte & lte - valid (max)", &cases.Fixed64ExGTELTE{Val: 256}, 0}, {"fixed64 - exclusive gte & lte - valid (min)", &cases.Fixed64ExGTELTE{Val: 128}, 0}, {"fixed64 - exclusive gte & lte - invalid", &cases.Fixed64ExGTELTE{Val: 200}, 1}, {"fixed64 - ignore_empty gte & lte - valid", &cases.Fixed64Ignore{Val: 0}, 0}, } var sfixed32Cases = []TestCase{ {"sfixed32 - none - valid", &cases.SFixed32None{Val: 123}, 0}, {"sfixed32 - const - valid", &cases.SFixed32Const{Val: 1}, 0}, {"sfixed32 - const - invalid", &cases.SFixed32Const{Val: 2}, 1}, {"sfixed32 - in - valid", &cases.SFixed32In{Val: 3}, 0}, {"sfixed32 - in - invalid", &cases.SFixed32In{Val: 5}, 1}, {"sfixed32 - not in - valid", &cases.SFixed32NotIn{Val: 1}, 0}, {"sfixed32 - not in - invalid", &cases.SFixed32NotIn{Val: 0}, 1}, {"sfixed32 - lt - valid", &cases.SFixed32LT{Val: -1}, 0}, {"sfixed32 - lt - invalid (equal)", &cases.SFixed32LT{Val: 0}, 1}, {"sfixed32 - lt - invalid", &cases.SFixed32LT{Val: 1}, 1}, {"sfixed32 - lte - valid", &cases.SFixed32LTE{Val: 63}, 0}, {"sfixed32 - lte - valid (equal)", &cases.SFixed32LTE{Val: 64}, 0}, {"sfixed32 - lte - invalid", &cases.SFixed32LTE{Val: 65}, 1}, {"sfixed32 - gt - valid", &cases.SFixed32GT{Val: 17}, 0}, {"sfixed32 - gt - invalid (equal)", &cases.SFixed32GT{Val: 16}, 1}, {"sfixed32 - gt - invalid", &cases.SFixed32GT{Val: 15}, 1}, {"sfixed32 - gte - valid", &cases.SFixed32GTE{Val: 9}, 0}, {"sfixed32 - gte - valid (equal)", &cases.SFixed32GTE{Val: 8}, 0}, {"sfixed32 - gte - invalid", &cases.SFixed32GTE{Val: 7}, 1}, {"sfixed32 - gt & lt - valid", &cases.SFixed32GTLT{Val: 5}, 0}, {"sfixed32 - gt & lt - invalid (above)", &cases.SFixed32GTLT{Val: 11}, 1}, {"sfixed32 - gt & lt - invalid (below)", &cases.SFixed32GTLT{Val: -1}, 1}, {"sfixed32 - gt & lt - invalid (max)", &cases.SFixed32GTLT{Val: 10}, 1}, {"sfixed32 - gt & lt - invalid (min)", &cases.SFixed32GTLT{Val: 0}, 1}, {"sfixed32 - exclusive gt & lt - valid (above)", &cases.SFixed32ExLTGT{Val: 11}, 0}, {"sfixed32 - exclusive gt & lt - valid (below)", &cases.SFixed32ExLTGT{Val: -1}, 0}, {"sfixed32 - exclusive gt & lt - invalid", &cases.SFixed32ExLTGT{Val: 5}, 1}, {"sfixed32 - exclusive gt & lt - invalid (max)", &cases.SFixed32ExLTGT{Val: 10}, 1}, {"sfixed32 - exclusive gt & lt - invalid (min)", &cases.SFixed32ExLTGT{Val: 0}, 1}, {"sfixed32 - gte & lte - valid", &cases.SFixed32GTELTE{Val: 200}, 0}, {"sfixed32 - gte & lte - valid (max)", &cases.SFixed32GTELTE{Val: 256}, 0}, {"sfixed32 - gte & lte - valid (min)", &cases.SFixed32GTELTE{Val: 128}, 0}, {"sfixed32 - gte & lte - invalid (above)", &cases.SFixed32GTELTE{Val: 300}, 1}, {"sfixed32 - gte & lte - invalid (below)", &cases.SFixed32GTELTE{Val: 100}, 1}, {"sfixed32 - exclusive gte & lte - valid (above)", &cases.SFixed32ExGTELTE{Val: 300}, 0}, {"sfixed32 - exclusive gte & lte - valid (below)", &cases.SFixed32ExGTELTE{Val: 100}, 0}, {"sfixed32 - exclusive gte & lte - valid (max)", &cases.SFixed32ExGTELTE{Val: 256}, 0}, {"sfixed32 - exclusive gte & lte - valid (min)", &cases.SFixed32ExGTELTE{Val: 128}, 0}, {"sfixed32 - exclusive gte & lte - invalid", &cases.SFixed32ExGTELTE{Val: 200}, 1}, {"sfixed32 - ignore_empty gte & lte - valid", &cases.SFixed32Ignore{Val: 0}, 0}, } var sfixed64Cases = []TestCase{ {"sfixed64 - none - valid", &cases.SFixed64None{Val: 123}, 0}, {"sfixed64 - const - valid", &cases.SFixed64Const{Val: 1}, 0}, {"sfixed64 - const - invalid", &cases.SFixed64Const{Val: 2}, 1}, {"sfixed64 - in - valid", &cases.SFixed64In{Val: 3}, 0}, {"sfixed64 - in - invalid", &cases.SFixed64In{Val: 5}, 1}, {"sfixed64 - not in - valid", &cases.SFixed64NotIn{Val: 1}, 0}, {"sfixed64 - not in - invalid", &cases.SFixed64NotIn{Val: 0}, 1}, {"sfixed64 - lt - valid", &cases.SFixed64LT{Val: -1}, 0}, {"sfixed64 - lt - invalid (equal)", &cases.SFixed64LT{Val: 0}, 1}, {"sfixed64 - lt - invalid", &cases.SFixed64LT{Val: 1}, 1}, {"sfixed64 - lte - valid", &cases.SFixed64LTE{Val: 63}, 0}, {"sfixed64 - lte - valid (equal)", &cases.SFixed64LTE{Val: 64}, 0}, {"sfixed64 - lte - invalid", &cases.SFixed64LTE{Val: 65}, 1}, {"sfixed64 - gt - valid", &cases.SFixed64GT{Val: 17}, 0}, {"sfixed64 - gt - invalid (equal)", &cases.SFixed64GT{Val: 16}, 1}, {"sfixed64 - gt - invalid", &cases.SFixed64GT{Val: 15}, 1}, {"sfixed64 - gte - valid", &cases.SFixed64GTE{Val: 9}, 0}, {"sfixed64 - gte - valid (equal)", &cases.SFixed64GTE{Val: 8}, 0}, {"sfixed64 - gte - invalid", &cases.SFixed64GTE{Val: 7}, 1}, {"sfixed64 - gt & lt - valid", &cases.SFixed64GTLT{Val: 5}, 0}, {"sfixed64 - gt & lt - invalid (above)", &cases.SFixed64GTLT{Val: 11}, 1}, {"sfixed64 - gt & lt - invalid (below)", &cases.SFixed64GTLT{Val: -1}, 1}, {"sfixed64 - gt & lt - invalid (max)", &cases.SFixed64GTLT{Val: 10}, 1}, {"sfixed64 - gt & lt - invalid (min)", &cases.SFixed64GTLT{Val: 0}, 1}, {"sfixed64 - exclusive gt & lt - valid (above)", &cases.SFixed64ExLTGT{Val: 11}, 0}, {"sfixed64 - exclusive gt & lt - valid (below)", &cases.SFixed64ExLTGT{Val: -1}, 0}, {"sfixed64 - exclusive gt & lt - invalid", &cases.SFixed64ExLTGT{Val: 5}, 1}, {"sfixed64 - exclusive gt & lt - invalid (max)", &cases.SFixed64ExLTGT{Val: 10}, 1}, {"sfixed64 - exclusive gt & lt - invalid (min)", &cases.SFixed64ExLTGT{Val: 0}, 1}, {"sfixed64 - gte & lte - valid", &cases.SFixed64GTELTE{Val: 200}, 0}, {"sfixed64 - gte & lte - valid (max)", &cases.SFixed64GTELTE{Val: 256}, 0}, {"sfixed64 - gte & lte - valid (min)", &cases.SFixed64GTELTE{Val: 128}, 0}, {"sfixed64 - gte & lte - invalid (above)", &cases.SFixed64GTELTE{Val: 300}, 1}, {"sfixed64 - gte & lte - invalid (below)", &cases.SFixed64GTELTE{Val: 100}, 1}, {"sfixed64 - exclusive gte & lte - valid (above)", &cases.SFixed64ExGTELTE{Val: 300}, 0}, {"sfixed64 - exclusive gte & lte - valid (below)", &cases.SFixed64ExGTELTE{Val: 100}, 0}, {"sfixed64 - exclusive gte & lte - valid (max)", &cases.SFixed64ExGTELTE{Val: 256}, 0}, {"sfixed64 - exclusive gte & lte - valid (min)", &cases.SFixed64ExGTELTE{Val: 128}, 0}, {"sfixed64 - exclusive gte & lte - invalid", &cases.SFixed64ExGTELTE{Val: 200}, 1}, {"sfixed64 - ignore_empty gte & lte - valid", &cases.SFixed64Ignore{Val: 0}, 0}, } var boolCases = []TestCase{ {"bool - none - valid", &cases.BoolNone{Val: true}, 0}, {"bool - const (true) - valid", &cases.BoolConstTrue{Val: true}, 0}, {"bool - const (true) - invalid", &cases.BoolConstTrue{Val: false}, 1}, {"bool - const (false) - valid", &cases.BoolConstFalse{Val: false}, 0}, {"bool - const (false) - invalid", &cases.BoolConstFalse{Val: true}, 1}, } var stringCases = []TestCase{ {"string - none - valid", &cases.StringNone{Val: "quux"}, 0}, {"string - const - valid", &cases.StringConst{Val: "foo"}, 0}, {"string - const - invalid", &cases.StringConst{Val: "bar"}, 1}, {"string - in - valid", &cases.StringIn{Val: "bar"}, 0}, {"string - in - invalid", &cases.StringIn{Val: "quux"}, 1}, {"string - not in - valid", &cases.StringNotIn{Val: "quux"}, 0}, {"string - not in - invalid", &cases.StringNotIn{Val: "fizz"}, 1}, {"string - len - valid", &cases.StringLen{Val: "baz"}, 0}, {"string - len - valid (multibyte)", &cases.StringLen{Val: "你好吖"}, 0}, {"string - len - invalid (lt)", &cases.StringLen{Val: "go"}, 1}, {"string - len - invalid (gt)", &cases.StringLen{Val: "fizz"}, 1}, {"string - len - invalid (multibyte)", &cases.StringLen{Val: "你好"}, 1}, {"string - min len - valid", &cases.StringMinLen{Val: "protoc"}, 0}, {"string - min len - valid (min)", &cases.StringMinLen{Val: "baz"}, 0}, {"string - min len - invalid", &cases.StringMinLen{Val: "go"}, 1}, {"string - min len - invalid (multibyte)", &cases.StringMinLen{Val: "你好"}, 1}, {"string - max len - valid", &cases.StringMaxLen{Val: "foo"}, 0}, {"string - max len - valid (max)", &cases.StringMaxLen{Val: "proto"}, 0}, {"string - max len - valid (multibyte)", &cases.StringMaxLen{Val: "你好你好"}, 0}, {"string - max len - invalid", &cases.StringMaxLen{Val: "1234567890"}, 1}, {"string - min/max len - valid", &cases.StringMinMaxLen{Val: "quux"}, 0}, {"string - min/max len - valid (min)", &cases.StringMinMaxLen{Val: "foo"}, 0}, {"string - min/max len - valid (max)", &cases.StringMinMaxLen{Val: "proto"}, 0}, {"string - min/max len - valid (multibyte)", &cases.StringMinMaxLen{Val: "你好你好"}, 0}, {"string - min/max len - invalid (below)", &cases.StringMinMaxLen{Val: "go"}, 1}, {"string - min/max len - invalid (above)", &cases.StringMinMaxLen{Val: "validate"}, 1}, {"string - equal min/max len - valid", &cases.StringEqualMinMaxLen{Val: "proto"}, 0}, {"string - equal min/max len - invalid", &cases.StringEqualMinMaxLen{Val: "validate"}, 1}, {"string - len bytes - valid", &cases.StringLenBytes{Val: "pace"}, 0}, {"string - len bytes - invalid (lt)", &cases.StringLenBytes{Val: "val"}, 1}, {"string - len bytes - invalid (gt)", &cases.StringLenBytes{Val: "world"}, 1}, {"string - len bytes - invalid (multibyte)", &cases.StringLenBytes{Val: "世界和平"}, 1}, {"string - min bytes - valid", &cases.StringMinBytes{Val: "proto"}, 0}, {"string - min bytes - valid (min)", &cases.StringMinBytes{Val: "quux"}, 0}, {"string - min bytes - valid (multibyte)", &cases.StringMinBytes{Val: "你好"}, 0}, {"string - min bytes - invalid", &cases.StringMinBytes{Val: ""}, 1}, {"string - max bytes - valid", &cases.StringMaxBytes{Val: "foo"}, 0}, {"string - max bytes - valid (max)", &cases.StringMaxBytes{Val: "12345678"}, 0}, {"string - max bytes - invalid", &cases.StringMaxBytes{Val: "123456789"}, 1}, {"string - max bytes - invalid (multibyte)", &cases.StringMaxBytes{Val: "你好你好你好"}, 1}, {"string - min/max bytes - valid", &cases.StringMinMaxBytes{Val: "protoc"}, 0}, {"string - min/max bytes - valid (min)", &cases.StringMinMaxBytes{Val: "quux"}, 0}, {"string - min/max bytes - valid (max)", &cases.StringMinMaxBytes{Val: "fizzbuzz"}, 0}, {"string - min/max bytes - valid (multibyte)", &cases.StringMinMaxBytes{Val: "你好"}, 0}, {"string - min/max bytes - invalid (below)", &cases.StringMinMaxBytes{Val: "foo"}, 1}, {"string - min/max bytes - invalid (above)", &cases.StringMinMaxBytes{Val: "你好你好你"}, 1}, {"string - equal min/max bytes - valid", &cases.StringEqualMinMaxBytes{Val: "protoc"}, 0}, {"string - equal min/max bytes - invalid", &cases.StringEqualMinMaxBytes{Val: "foo"}, 1}, {"string - pattern - valid", &cases.StringPattern{Val: "Foo123"}, 0}, {"string - pattern - invalid", &cases.StringPattern{Val: "!@#$%^&*()"}, 1}, {"string - pattern - invalid (empty)", &cases.StringPattern{Val: ""}, 1}, {"string - pattern - invalid (null)", &cases.StringPattern{Val: "a\000"}, 1}, {"string - pattern (escapes) - valid", &cases.StringPatternEscapes{Val: "* \\ x"}, 0}, {"string - pattern (escapes) - invalid", &cases.StringPatternEscapes{Val: "invalid"}, 1}, {"string - pattern (escapes) - invalid (empty)", &cases.StringPatternEscapes{Val: ""}, 1}, {"string - prefix - valid", &cases.StringPrefix{Val: "foobar"}, 0}, {"string - prefix - valid (only)", &cases.StringPrefix{Val: "foo"}, 0}, {"string - prefix - invalid", &cases.StringPrefix{Val: "bar"}, 1}, {"string - prefix - invalid (case-sensitive)", &cases.StringPrefix{Val: "Foobar"}, 1}, {"string - contains - valid", &cases.StringContains{Val: "candy bars"}, 0}, {"string - contains - valid (only)", &cases.StringContains{Val: "bar"}, 0}, {"string - contains - invalid", &cases.StringContains{Val: "candy bazs"}, 1}, {"string - contains - invalid (case-sensitive)", &cases.StringContains{Val: "Candy Bars"}, 1}, {"string - not contains - valid", &cases.StringNotContains{Val: "candy bazs"}, 0}, {"string - not contains - valid (case-sensitive)", &cases.StringNotContains{Val: "Candy Bars"}, 0}, {"string - not contains - invalid", &cases.StringNotContains{Val: "candy bars"}, 1}, {"string - not contains - invalid (equal)", &cases.StringNotContains{Val: "bar"}, 1}, {"string - suffix - valid", &cases.StringSuffix{Val: "foobaz"}, 0}, {"string - suffix - valid (only)", &cases.StringSuffix{Val: "baz"}, 0}, {"string - suffix - invalid", &cases.StringSuffix{Val: "foobar"}, 1}, {"string - suffix - invalid (case-sensitive)", &cases.StringSuffix{Val: "FooBaz"}, 1}, {"string - email - valid", &cases.StringEmail{Val: "foo@bar.com"}, 0}, {"string - email - valid (name)", &cases.StringEmail{Val: "John Smith "}, 0}, {"string - email - invalid", &cases.StringEmail{Val: "foobar"}, 1}, {"string - email - invalid (local segment too long)", &cases.StringEmail{Val: "x0123456789012345678901234567890123456789012345678901234567890123456789@example.com"}, 1}, {"string - email - invalid (hostname too long)", &cases.StringEmail{Val: "foo@x0123456789012345678901234567890123456789012345678901234567890123456789.com"}, 1}, {"string - email - invalid (bad hostname)", &cases.StringEmail{Val: "foo@-bar.com"}, 1}, {"string - email - empty", &cases.StringEmail{Val: ""}, 1}, {"string - address - valid hostname", &cases.StringAddress{Val: "example.com"}, 0}, {"string - address - valid hostname (uppercase)", &cases.StringAddress{Val: "ASD.example.com"}, 0}, {"string - address - valid hostname (hyphens)", &cases.StringAddress{Val: "foo-bar.com"}, 0}, {"string - address - valid hostname (trailing dot)", &cases.StringAddress{Val: "example.com."}, 0}, {"string - address - invalid hostname", &cases.StringAddress{Val: "!@#$%^&"}, 1}, {"string - address - invalid hostname (underscore)", &cases.StringAddress{Val: "foo_bar.com"}, 1}, {"string - address - invalid hostname (too long)", &cases.StringAddress{Val: "x0123456789012345678901234567890123456789012345678901234567890123456789.com"}, 1}, {"string - address - invalid hostname (trailing hyphens)", &cases.StringAddress{Val: "foo-bar-.com"}, 1}, {"string - address - invalid hostname (leading hyphens)", &cases.StringAddress{Val: "foo-bar.-com"}, 1}, {"string - address - invalid hostname (empty)", &cases.StringAddress{Val: "asd..asd.com"}, 1}, {"string - address - invalid hostname (IDNs)", &cases.StringAddress{Val: "你好.com"}, 1}, {"string - address - valid ip (v4)", &cases.StringAddress{Val: "192.168.0.1"}, 0}, {"string - address - valid ip (v6)", &cases.StringAddress{Val: "3e::99"}, 0}, {"string - address - invalid ip", &cases.StringAddress{Val: "ff::fff::0b"}, 1}, {"string - hostname - valid", &cases.StringHostname{Val: "example.com"}, 0}, {"string - hostname - valid (uppercase)", &cases.StringHostname{Val: "ASD.example.com"}, 0}, {"string - hostname - valid (hyphens)", &cases.StringHostname{Val: "foo-bar.com"}, 0}, {"string - hostname - valid (trailing dot)", &cases.StringHostname{Val: "example.com."}, 0}, {"string - hostname - invalid", &cases.StringHostname{Val: "!@#$%^&"}, 1}, {"string - hostname - invalid (underscore)", &cases.StringHostname{Val: "foo_bar.com"}, 1}, {"string - hostname - invalid (too long)", &cases.StringHostname{Val: "x0123456789012345678901234567890123456789012345678901234567890123456789.com"}, 1}, {"string - hostname - invalid (trailing hyphens)", &cases.StringHostname{Val: "foo-bar-.com"}, 1}, {"string - hostname - invalid (leading hyphens)", &cases.StringHostname{Val: "foo-bar.-com"}, 1}, {"string - hostname - invalid (empty)", &cases.StringHostname{Val: "asd..asd.com"}, 1}, {"string - hostname - invalid (IDNs)", &cases.StringHostname{Val: "你好.com"}, 1}, {"string - IP - valid (v4)", &cases.StringIP{Val: "192.168.0.1"}, 0}, {"string - IP - valid (v6)", &cases.StringIP{Val: "3e::99"}, 0}, {"string - IP - invalid", &cases.StringIP{Val: "foobar"}, 1}, {"string - IPv4 - valid", &cases.StringIPv4{Val: "192.168.0.1"}, 0}, {"string - IPv4 - invalid", &cases.StringIPv4{Val: "foobar"}, 1}, {"string - IPv4 - invalid (erroneous)", &cases.StringIPv4{Val: "256.0.0.0"}, 1}, {"string - IPv4 - invalid (v6)", &cases.StringIPv4{Val: "3e::99"}, 1}, {"string - IPv6 - valid", &cases.StringIPv6{Val: "2001:0db8:85a3:0000:0000:8a2e:0370:7334"}, 0}, {"string - IPv6 - valid (collapsed)", &cases.StringIPv6{Val: "2001:db8:85a3::8a2e:370:7334"}, 0}, {"string - IPv6 - invalid", &cases.StringIPv6{Val: "foobar"}, 1}, {"string - IPv6 - invalid (v4)", &cases.StringIPv6{Val: "192.168.0.1"}, 1}, {"string - IPv6 - invalid (erroneous)", &cases.StringIPv6{Val: "ff::fff::0b"}, 1}, {"string - URI - valid", &cases.StringURI{Val: "http://example.com/foo/bar?baz=quux"}, 0}, {"string - URI - invalid", &cases.StringURI{Val: "!@#$%^&*%$#"}, 1}, {"string - URI - invalid (relative)", &cases.StringURI{Val: "/foo/bar?baz=quux"}, 1}, {"string - URI - valid", &cases.StringURIRef{Val: "http://example.com/foo/bar?baz=quux"}, 0}, {"string - URI - valid (relative)", &cases.StringURIRef{Val: "/foo/bar?baz=quux"}, 0}, {"string - URI - invalid", &cases.StringURIRef{Val: "!@#$%^&*%$#"}, 1}, {"string - UUID - valid (nil)", &cases.StringUUID{Val: "00000000-0000-0000-0000-000000000000"}, 0}, {"string - UUID - valid (v1)", &cases.StringUUID{Val: "b45c0c80-8880-11e9-a5b1-000000000000"}, 0}, {"string - UUID - valid (v1 - case-insensitive)", &cases.StringUUID{Val: "B45C0C80-8880-11E9-A5B1-000000000000"}, 0}, {"string - UUID - valid (v2)", &cases.StringUUID{Val: "b45c0c80-8880-21e9-a5b1-000000000000"}, 0}, {"string - UUID - valid (v2 - case-insensitive)", &cases.StringUUID{Val: "B45C0C80-8880-21E9-A5B1-000000000000"}, 0}, {"string - UUID - valid (v3)", &cases.StringUUID{Val: "a3bb189e-8bf9-3888-9912-ace4e6543002"}, 0}, {"string - UUID - valid (v3 - case-insensitive)", &cases.StringUUID{Val: "A3BB189E-8BF9-3888-9912-ACE4E6543002"}, 0}, {"string - UUID - valid (v4)", &cases.StringUUID{Val: "8b208305-00e8-4460-a440-5e0dcd83bb0a"}, 0}, {"string - UUID - valid (v4 - case-insensitive)", &cases.StringUUID{Val: "8B208305-00E8-4460-A440-5E0DCD83BB0A"}, 0}, {"string - UUID - valid (v5)", &cases.StringUUID{Val: "a6edc906-2f9f-5fb2-a373-efac406f0ef2"}, 0}, {"string - UUID - valid (v5 - case-insensitive)", &cases.StringUUID{Val: "A6EDC906-2F9F-5FB2-A373-EFAC406F0EF2"}, 0}, {"string - UUID - invalid", &cases.StringUUID{Val: "foobar"}, 1}, {"string - UUID - invalid (bad UUID)", &cases.StringUUID{Val: "ffffffff-ffff-ffff-ffff-fffffffffffff"}, 1}, {"string - UUID - valid (ignore_empty)", &cases.StringUUIDIgnore{Val: ""}, 0}, {"string - http header name - valid", &cases.StringHttpHeaderName{Val: "clustername"}, 0}, {"string - http header name - valid", &cases.StringHttpHeaderName{Val: ":path"}, 0}, {"string - http header name - valid (nums)", &cases.StringHttpHeaderName{Val: "cluster-123"}, 0}, {"string - http header name - valid (special token)", &cases.StringHttpHeaderName{Val: "!+#&.%"}, 0}, {"string - http header name - valid (period)", &cases.StringHttpHeaderName{Val: "CLUSTER.NAME"}, 0}, {"string - http header name - invalid", &cases.StringHttpHeaderName{Val: ":"}, 1}, {"string - http header name - invalid", &cases.StringHttpHeaderName{Val: ":path:"}, 1}, {"string - http header name - invalid (space)", &cases.StringHttpHeaderName{Val: "cluster name"}, 1}, {"string - http header name - invalid (return)", &cases.StringHttpHeaderName{Val: "example\r"}, 1}, {"string - http header name - invalid (tab)", &cases.StringHttpHeaderName{Val: "example\t"}, 1}, {"string - http header name - invalid (slash)", &cases.StringHttpHeaderName{Val: "/test/long/url"}, 1}, {"string - http header value - valid", &cases.StringHttpHeaderValue{Val: "cluster.name.123"}, 0}, {"string - http header value - valid (uppercase)", &cases.StringHttpHeaderValue{Val: "/TEST/LONG/URL"}, 0}, {"string - http header value - valid (spaces)", &cases.StringHttpHeaderValue{Val: "cluster name"}, 0}, {"string - http header value - valid (tab)", &cases.StringHttpHeaderValue{Val: "example\t"}, 0}, {"string - http header value - valid (special token)", &cases.StringHttpHeaderValue{Val: "!#%&./+"}, 0}, {"string - http header value - invalid (NUL)", &cases.StringHttpHeaderValue{Val: "foo\u0000bar"}, 1}, {"string - http header value - invalid (DEL)", &cases.StringHttpHeaderValue{Val: "\u007f"}, 1}, {"string - http header value - invalid", &cases.StringHttpHeaderValue{Val: "example\r"}, 1}, {"string - non-strict valid header - valid", &cases.StringValidHeader{Val: "cluster.name.123"}, 0}, {"string - non-strict valid header - valid (uppercase)", &cases.StringValidHeader{Val: "/TEST/LONG/URL"}, 0}, {"string - non-strict valid header - valid (spaces)", &cases.StringValidHeader{Val: "cluster name"}, 0}, {"string - non-strict valid header - valid (tab)", &cases.StringValidHeader{Val: "example\t"}, 0}, {"string - non-strict valid header - valid (DEL)", &cases.StringValidHeader{Val: "\u007f"}, 0}, {"string - non-strict valid header - invalid (NUL)", &cases.StringValidHeader{Val: "foo\u0000bar"}, 1}, {"string - non-strict valid header - invalid (CR)", &cases.StringValidHeader{Val: "example\r"}, 1}, {"string - non-strict valid header - invalid (NL)", &cases.StringValidHeader{Val: "exa\u000Ample"}, 1}, } var bytesCases = []TestCase{ {"bytes - none - valid", &cases.BytesNone{Val: []byte("quux")}, 0}, {"bytes - const - valid", &cases.BytesConst{Val: []byte("foo")}, 0}, {"bytes - const - invalid", &cases.BytesConst{Val: []byte("bar")}, 1}, {"bytes - in - valid", &cases.BytesIn{Val: []byte("bar")}, 0}, {"bytes - in - invalid", &cases.BytesIn{Val: []byte("quux")}, 1}, {"bytes - not in - valid", &cases.BytesNotIn{Val: []byte("quux")}, 0}, {"bytes - not in - invalid", &cases.BytesNotIn{Val: []byte("fizz")}, 1}, {"bytes - len - valid", &cases.BytesLen{Val: []byte("baz")}, 0}, {"bytes - len - invalid (lt)", &cases.BytesLen{Val: []byte("go")}, 1}, {"bytes - len - invalid (gt)", &cases.BytesLen{Val: []byte("fizz")}, 1}, {"bytes - min len - valid", &cases.BytesMinLen{Val: []byte("fizz")}, 0}, {"bytes - min len - valid (min)", &cases.BytesMinLen{Val: []byte("baz")}, 0}, {"bytes - min len - invalid", &cases.BytesMinLen{Val: []byte("go")}, 1}, {"bytes - max len - valid", &cases.BytesMaxLen{Val: []byte("foo")}, 0}, {"bytes - max len - valid (max)", &cases.BytesMaxLen{Val: []byte("proto")}, 0}, {"bytes - max len - invalid", &cases.BytesMaxLen{Val: []byte("1234567890")}, 1}, {"bytes - min/max len - valid", &cases.BytesMinMaxLen{Val: []byte("quux")}, 0}, {"bytes - min/max len - valid (min)", &cases.BytesMinMaxLen{Val: []byte("foo")}, 0}, {"bytes - min/max len - valid (max)", &cases.BytesMinMaxLen{Val: []byte("proto")}, 0}, {"bytes - min/max len - invalid (below)", &cases.BytesMinMaxLen{Val: []byte("go")}, 1}, {"bytes - min/max len - invalid (above)", &cases.BytesMinMaxLen{Val: []byte("validate")}, 1}, {"bytes - equal min/max len - valid", &cases.BytesEqualMinMaxLen{Val: []byte("proto")}, 0}, {"bytes - equal min/max len - invalid", &cases.BytesEqualMinMaxLen{Val: []byte("validate")}, 1}, {"bytes - pattern - valid", &cases.BytesPattern{Val: []byte("Foo123")}, 0}, {"bytes - pattern - invalid", &cases.BytesPattern{Val: []byte("你好你好")}, 1}, {"bytes - pattern - invalid (empty)", &cases.BytesPattern{Val: []byte("")}, 1}, {"bytes - prefix - valid", &cases.BytesPrefix{Val: []byte{0x99, 0x9f, 0x08}}, 0}, {"bytes - prefix - valid (only)", &cases.BytesPrefix{Val: []byte{0x99}}, 0}, {"bytes - prefix - invalid", &cases.BytesPrefix{Val: []byte("bar")}, 1}, {"bytes - contains - valid", &cases.BytesContains{Val: []byte("candy bars")}, 0}, {"bytes - contains - valid (only)", &cases.BytesContains{Val: []byte("bar")}, 0}, {"bytes - contains - invalid", &cases.BytesContains{Val: []byte("candy bazs")}, 1}, {"bytes - suffix - valid", &cases.BytesSuffix{Val: []byte{0x62, 0x75, 0x7A, 0x7A}}, 0}, {"bytes - suffix - valid (only)", &cases.BytesSuffix{Val: []byte("\x62\x75\x7A\x7A")}, 0}, {"bytes - suffix - invalid", &cases.BytesSuffix{Val: []byte("foobar")}, 1}, {"bytes - suffix - invalid (case-sensitive)", &cases.BytesSuffix{Val: []byte("FooBaz")}, 1}, {"bytes - IP - valid (v4)", &cases.BytesIP{Val: []byte{0xC0, 0xA8, 0x00, 0x01}}, 0}, {"bytes - IP - valid (v6)", &cases.BytesIP{Val: []byte("\x20\x01\x0D\xB8\x85\xA3\x00\x00\x00\x00\x8A\x2E\x03\x70\x73\x34")}, 0}, {"bytes - IP - invalid", &cases.BytesIP{Val: []byte("foobar")}, 1}, {"bytes - IPv4 - valid", &cases.BytesIPv4{Val: []byte{0xC0, 0xA8, 0x00, 0x01}}, 0}, {"bytes - IPv4 - invalid", &cases.BytesIPv4{Val: []byte("foobar")}, 1}, {"bytes - IPv4 - invalid (v6)", &cases.BytesIPv4{Val: []byte("\x20\x01\x0D\xB8\x85\xA3\x00\x00\x00\x00\x8A\x2E\x03\x70\x73\x34")}, 1}, {"bytes - IPv6 - valid", &cases.BytesIPv6{Val: []byte("\x20\x01\x0D\xB8\x85\xA3\x00\x00\x00\x00\x8A\x2E\x03\x70\x73\x34")}, 0}, {"bytes - IPv6 - invalid", &cases.BytesIPv6{Val: []byte("fooar")}, 1}, {"bytes - IPv6 - invalid (v4)", &cases.BytesIPv6{Val: []byte{0xC0, 0xA8, 0x00, 0x01}}, 1}, {"bytes - IPv6 - valid (ignore_empty)", &cases.BytesIPv6Ignore{Val: nil}, 0}, } var enumCases = []TestCase{ {"enum - none - valid", &cases.EnumNone{Val: cases.TestEnum_ONE}, 0}, {"enum - const - valid", &cases.EnumConst{Val: cases.TestEnum_TWO}, 0}, {"enum - const - invalid", &cases.EnumConst{Val: cases.TestEnum_ONE}, 1}, {"enum alias - const - valid", &cases.EnumAliasConst{Val: cases.TestEnumAlias_C}, 0}, {"enum alias - const - valid (alias)", &cases.EnumAliasConst{Val: cases.TestEnumAlias_GAMMA}, 0}, {"enum alias - const - invalid", &cases.EnumAliasConst{Val: cases.TestEnumAlias_ALPHA}, 1}, {"enum - defined_only - valid", &cases.EnumDefined{Val: 0}, 0}, {"enum - defined_only - invalid", &cases.EnumDefined{Val: math.MaxInt32}, 1}, {"enum alias - defined_only - valid", &cases.EnumAliasDefined{Val: 1}, 0}, {"enum alias - defined_only - invalid", &cases.EnumAliasDefined{Val: math.MaxInt32}, 1}, {"enum - in - valid", &cases.EnumIn{Val: cases.TestEnum_TWO}, 0}, {"enum - in - invalid", &cases.EnumIn{Val: cases.TestEnum_ONE}, 1}, {"enum alias - in - valid", &cases.EnumAliasIn{Val: cases.TestEnumAlias_A}, 0}, {"enum alias - in - valid (alias)", &cases.EnumAliasIn{Val: cases.TestEnumAlias_ALPHA}, 0}, {"enum alias - in - invalid", &cases.EnumAliasIn{Val: cases.TestEnumAlias_BETA}, 1}, {"enum - not in - valid", &cases.EnumNotIn{Val: cases.TestEnum_ZERO}, 0}, {"enum - not in - valid (undefined)", &cases.EnumNotIn{Val: math.MaxInt32}, 0}, {"enum - not in - invalid", &cases.EnumNotIn{Val: cases.TestEnum_ONE}, 1}, {"enum alias - not in - valid", &cases.EnumAliasNotIn{Val: cases.TestEnumAlias_ALPHA}, 0}, {"enum alias - not in - invalid", &cases.EnumAliasNotIn{Val: cases.TestEnumAlias_B}, 1}, {"enum alias - not in - invalid (alias)", &cases.EnumAliasNotIn{Val: cases.TestEnumAlias_BETA}, 1}, {"enum external - defined_only - valid", &cases.EnumExternal{Val: other_package.Embed_VALUE}, 0}, {"enum external - defined_only - invalid", &cases.EnumExternal{Val: math.MaxInt32}, 1}, {"enum external - in - valid", &cases.EnumExternal3{Foo: other_package.Embed_ZERO}, 0}, {"enum external - in - invalid", &cases.EnumExternal3{Foo: other_package.Embed_ONE}, 1}, {"enum external - not in - valid", &cases.EnumExternal3{Bar: yet_another_package.Embed_ZERO}, 0}, {"enum external - not in - invalid", &cases.EnumExternal3{Bar: yet_another_package.Embed_ONE}, 1}, {"enum external - const - valid", &cases.EnumExternal4{SortDirection: sort.Direction_ASC}, 0}, {"enum external - const - invalid", &cases.EnumExternal4{SortDirection: sort.Direction_DESC}, 1}, {"enum repeated - defined_only - valid", &cases.RepeatedEnumDefined{Val: []cases.TestEnum{cases.TestEnum_ONE, cases.TestEnum_TWO}}, 0}, {"enum repeated - defined_only - invalid", &cases.RepeatedEnumDefined{Val: []cases.TestEnum{cases.TestEnum_ONE, math.MaxInt32}}, 1}, {"enum repeated (external) - defined_only - valid", &cases.RepeatedExternalEnumDefined{Val: []other_package.Embed_Enumerated{other_package.Embed_VALUE}}, 0}, {"enum repeated (external) - defined_only - invalid", &cases.RepeatedExternalEnumDefined{Val: []other_package.Embed_Enumerated{math.MaxInt32}}, 1}, {"enum repeated (another external) - defined_only - valid", &cases.RepeatedYetAnotherExternalEnumDefined{Val: []yet_another_package.Embed_Enumerated{yet_another_package.Embed_VALUE}}, 0}, {"enum repeated (external) - in - valid", &cases.RepeatedEnumExternal{Foo: []other_package.Embed_FooNumber{other_package.Embed_ZERO, other_package.Embed_TWO}}, 0}, {"enum repeated (external) - in - invalid", &cases.RepeatedEnumExternal{Foo: []other_package.Embed_FooNumber{other_package.Embed_ONE}}, 1}, {"enum repeated (external) - not in - valid", &cases.RepeatedEnumExternal{Bar: []yet_another_package.Embed_BarNumber{yet_another_package.Embed_ZERO, yet_another_package.Embed_TWO}}, 0}, {"enum repeated (external) - not in - invalid", &cases.RepeatedEnumExternal{Bar: []yet_another_package.Embed_BarNumber{yet_another_package.Embed_ONE}}, 1}, {"enum map - defined_only - valid", &cases.MapEnumDefined{Val: map[string]cases.TestEnum{"foo": cases.TestEnum_TWO}}, 0}, {"enum map - defined_only - invalid", &cases.MapEnumDefined{Val: map[string]cases.TestEnum{"foo": math.MaxInt32}}, 1}, {"enum map (external) - defined_only - valid", &cases.MapExternalEnumDefined{Val: map[string]other_package.Embed_Enumerated{"foo": other_package.Embed_VALUE}}, 0}, {"enum map (external) - defined_only - invalid", &cases.MapExternalEnumDefined{Val: map[string]other_package.Embed_Enumerated{"foo": math.MaxInt32}}, 1}, } var messageCases = []TestCase{ {"message - none - valid", &cases.MessageNone{Val: &cases.MessageNone_NoneMsg{}}, 0}, {"message - none - valid (unset)", &cases.MessageNone{}, 0}, {"message - disabled - valid", &cases.MessageDisabled{Val: 456}, 0}, {"message - disabled - valid (invalid field)", &cases.MessageDisabled{Val: 0}, 0}, {"message - ignored - valid", &cases.MessageIgnored{Val: 456}, 0}, {"message - ignored - valid (invalid field)", &cases.MessageIgnored{Val: 0}, 0}, {"message - field - valid", &cases.Message{Val: &cases.TestMsg{Const: "foo"}}, 0}, {"message - field - valid (unset)", &cases.Message{}, 0}, {"message - field - invalid", &cases.Message{Val: &cases.TestMsg{}}, 1}, {"message - field - invalid (transitive)", &cases.Message{Val: &cases.TestMsg{Const: "foo", Nested: &cases.TestMsg{}}}, 1}, {"message - skip - valid", &cases.MessageSkip{Val: &cases.TestMsg{}}, 0}, {"message - required - valid", &cases.MessageRequired{Val: &cases.TestMsg{Const: "foo"}}, 0}, {"message - required - valid (oneof)", &cases.MessageRequiredOneof{One: &cases.MessageRequiredOneof_Val{Val: &cases.TestMsg{Const: "foo"}}}, 0}, {"message - required - invalid", &cases.MessageRequired{}, 1}, {"message - required - invalid (oneof)", &cases.MessageRequiredOneof{}, 1}, {"message - cross-package embed none - valid", &cases.MessageCrossPackage{Val: &other_package.Embed{Val: 1}}, 0}, {"message - cross-package embed none - valid (nil)", &cases.MessageCrossPackage{}, 0}, {"message - cross-package embed none - valid (empty)", &cases.MessageCrossPackage{Val: &other_package.Embed{}}, 1}, {"message - cross-package embed none - invalid", &cases.MessageCrossPackage{Val: &other_package.Embed{Val: -1}}, 1}, {"message - required - valid", &cases.MessageRequiredButOptional{Val: &cases.TestMsg{Const: "foo"}}, 0}, {"message - required - valid (unset)", &cases.MessageRequiredButOptional{}, 0}, } var repeatedCases = []TestCase{ {"repeated - none - valid", &cases.RepeatedNone{Val: []int64{1, 2, 3}}, 0}, {"repeated - embed none - valid", &cases.RepeatedEmbedNone{Val: []*cases.Embed{{Val: 1}}}, 0}, {"repeated - embed none - valid (nil)", &cases.RepeatedEmbedNone{}, 0}, {"repeated - embed none - valid (empty)", &cases.RepeatedEmbedNone{Val: []*cases.Embed{}}, 0}, {"repeated - embed none - invalid", &cases.RepeatedEmbedNone{Val: []*cases.Embed{{Val: -1}}}, 1}, {"repeated - cross-package embed none - valid", &cases.RepeatedEmbedCrossPackageNone{Val: []*other_package.Embed{{Val: 1}}}, 0}, {"repeated - cross-package embed none - valid (nil)", &cases.RepeatedEmbedCrossPackageNone{}, 0}, {"repeated - cross-package embed none - valid (empty)", &cases.RepeatedEmbedCrossPackageNone{Val: []*other_package.Embed{}}, 0}, {"repeated - cross-package embed none - invalid", &cases.RepeatedEmbedCrossPackageNone{Val: []*other_package.Embed{{Val: -1}}}, 1}, {"repeated - min - valid", &cases.RepeatedMin{Val: []*cases.Embed{{Val: 1}, {Val: 2}, {Val: 3}}}, 0}, {"repeated - min - valid (equal)", &cases.RepeatedMin{Val: []*cases.Embed{{Val: 1}, {Val: 2}}}, 0}, {"repeated - min - invalid", &cases.RepeatedMin{Val: []*cases.Embed{{Val: 1}}}, 1}, {"repeated - min - invalid (element)", &cases.RepeatedMin{Val: []*cases.Embed{{Val: 1}, {Val: -1}}}, 1}, {"repeated - max - valid", &cases.RepeatedMax{Val: []float64{1, 2}}, 0}, {"repeated - max - valid (equal)", &cases.RepeatedMax{Val: []float64{1, 2, 3}}, 0}, {"repeated - max - invalid", &cases.RepeatedMax{Val: []float64{1, 2, 3, 4}}, 1}, {"repeated - min/max - valid", &cases.RepeatedMinMax{Val: []int32{1, 2, 3}}, 0}, {"repeated - min/max - valid (min)", &cases.RepeatedMinMax{Val: []int32{1, 2}}, 0}, {"repeated - min/max - valid (max)", &cases.RepeatedMinMax{Val: []int32{1, 2, 3, 4}}, 0}, {"repeated - min/max - invalid (below)", &cases.RepeatedMinMax{Val: []int32{}}, 1}, {"repeated - min/max - invalid (above)", &cases.RepeatedMinMax{Val: []int32{1, 2, 3, 4, 5}}, 1}, {"repeated - exact - valid", &cases.RepeatedExact{Val: []uint32{1, 2, 3}}, 0}, {"repeated - exact - invalid (below)", &cases.RepeatedExact{Val: []uint32{1, 2}}, 1}, {"repeated - exact - invalid (above)", &cases.RepeatedExact{Val: []uint32{1, 2, 3, 4}}, 1}, {"repeated - unique - valid", &cases.RepeatedUnique{Val: []string{"foo", "bar", "baz"}}, 0}, {"repeated - unique - valid (empty)", &cases.RepeatedUnique{}, 0}, {"repeated - unique - valid (case sensitivity)", &cases.RepeatedUnique{Val: []string{"foo", "Foo"}}, 0}, {"repeated - unique - invalid", &cases.RepeatedUnique{Val: []string{"foo", "bar", "foo", "baz"}}, 1}, {"repeated - items - valid", &cases.RepeatedItemRule{Val: []float32{1, 2, 3}}, 0}, {"repeated - items - valid (empty)", &cases.RepeatedItemRule{Val: []float32{}}, 0}, {"repeated - items - valid (pattern)", &cases.RepeatedItemPattern{Val: []string{"Alpha", "Beta123"}}, 0}, {"repeated - items - invalid", &cases.RepeatedItemRule{Val: []float32{1, -2, 3}}, 1}, {"repeated - items - invalid (pattern)", &cases.RepeatedItemPattern{Val: []string{"Alpha", "!@#$%^&*()"}}, 1}, {"repeated - items - invalid (in)", &cases.RepeatedItemIn{Val: []string{"baz"}}, 1}, {"repeated - items - valid (in)", &cases.RepeatedItemIn{Val: []string{"foo"}}, 0}, {"repeated - items - invalid (not_in)", &cases.RepeatedItemNotIn{Val: []string{"foo"}}, 1}, {"repeated - items - valid (not_in)", &cases.RepeatedItemNotIn{Val: []string{"baz"}}, 0}, {"repeated - items - invalid (enum in)", &cases.RepeatedEnumIn{Val: []cases.AnEnum{1}}, 1}, {"repeated - items - valid (enum in)", &cases.RepeatedEnumIn{Val: []cases.AnEnum{0}}, 0}, {"repeated - items - invalid (enum not_in)", &cases.RepeatedEnumNotIn{Val: []cases.AnEnum{0}}, 1}, {"repeated - items - valid (enum not_in)", &cases.RepeatedEnumNotIn{Val: []cases.AnEnum{1}}, 0}, {"repeated - items - invalid (embedded enum in)", &cases.RepeatedEmbeddedEnumIn{Val: []cases.RepeatedEmbeddedEnumIn_AnotherInEnum{1}}, 1}, {"repeated - items - valid (embedded enum in)", &cases.RepeatedEmbeddedEnumIn{Val: []cases.RepeatedEmbeddedEnumIn_AnotherInEnum{0}}, 0}, {"repeated - items - invalid (embedded enum not_in)", &cases.RepeatedEmbeddedEnumNotIn{Val: []cases.RepeatedEmbeddedEnumNotIn_AnotherNotInEnum{0}}, 1}, {"repeated - items - valid (embedded enum not_in)", &cases.RepeatedEmbeddedEnumNotIn{Val: []cases.RepeatedEmbeddedEnumNotIn_AnotherNotInEnum{1}}, 0}, {"repeated - items - invalid (any in)", &cases.RepeatedAnyIn{Val: []*anypb.Any{{TypeUrl: "type.googleapis.com/google.protobuf.Timestamp"}}}, 1}, {"repeated - items - valid (any in)", &cases.RepeatedAnyIn{Val: []*anypb.Any{{TypeUrl: "type.googleapis.com/google.protobuf.Duration"}}}, 0}, {"repeated - items - invalid (any not_in)", &cases.RepeatedAnyNotIn{Val: []*anypb.Any{{TypeUrl: "type.googleapis.com/google.protobuf.Timestamp"}}}, 1}, {"repeated - items - valid (any not_in)", &cases.RepeatedAnyNotIn{Val: []*anypb.Any{{TypeUrl: "type.googleapis.com/google.protobuf.Duration"}}}, 0}, {"repeated - embed skip - valid", &cases.RepeatedEmbedSkip{Val: []*cases.Embed{{Val: 1}}}, 0}, {"repeated - embed skip - valid (invalid element)", &cases.RepeatedEmbedSkip{Val: []*cases.Embed{{Val: -1}}}, 0}, {"repeated - min and items len - valid", &cases.RepeatedMinAndItemLen{Val: []string{"aaa", "bbb"}}, 0}, {"repeated - min and items len - invalid (min)", &cases.RepeatedMinAndItemLen{Val: []string{}}, 1}, {"repeated - min and items len - invalid (len)", &cases.RepeatedMinAndItemLen{Val: []string{"x"}}, 1}, {"repeated - min and max items len - valid", &cases.RepeatedMinAndMaxItemLen{Val: []string{"aaa", "bbb"}}, 0}, {"repeated - min and max items len - invalid (min_len)", &cases.RepeatedMinAndMaxItemLen{}, 1}, {"repeated - min and max items len - invalid (max_len)", &cases.RepeatedMinAndMaxItemLen{Val: []string{"aaa", "bbb", "ccc", "ddd"}}, 1}, {"repeated - duration - gte - valid", &cases.RepeatedDuration{Val: []*durationpb.Duration{{Seconds: 3}}}, 0}, {"repeated - duration - gte - valid (empty)", &cases.RepeatedDuration{}, 0}, {"repeated - duration - gte - valid (equal)", &cases.RepeatedDuration{Val: []*durationpb.Duration{{Nanos: 1000000}}}, 0}, {"repeated - duration - gte - invalid", &cases.RepeatedDuration{Val: []*durationpb.Duration{{Seconds: -1}}}, 1}, {"repeated - exact - valid (ignore_empty)", &cases.RepeatedExactIgnore{Val: nil}, 0}, } var mapCases = []TestCase{ {"map - none - valid", &cases.MapNone{Val: map[uint32]bool{123: true, 456: false}}, 0}, {"map - min pairs - valid", &cases.MapMin{Val: map[int32]float32{1: 2, 3: 4, 5: 6}}, 0}, {"map - min pairs - valid (equal)", &cases.MapMin{Val: map[int32]float32{1: 2, 3: 4}}, 0}, {"map - min pairs - invalid", &cases.MapMin{Val: map[int32]float32{1: 2}}, 1}, {"map - max pairs - valid", &cases.MapMax{Val: map[int64]float64{1: 2, 3: 4}}, 0}, {"map - max pairs - valid (equal)", &cases.MapMax{Val: map[int64]float64{1: 2, 3: 4, 5: 6}}, 0}, {"map - max pairs - invalid", &cases.MapMax{Val: map[int64]float64{1: 2, 3: 4, 5: 6, 7: 8}}, 1}, {"map - min/max - valid", &cases.MapMinMax{Val: map[string]bool{"a": true, "b": false, "c": true}}, 0}, {"map - min/max - valid (min)", &cases.MapMinMax{Val: map[string]bool{"a": true, "b": false}}, 0}, {"map - min/max - valid (max)", &cases.MapMinMax{Val: map[string]bool{"a": true, "b": false, "c": true, "d": false}}, 0}, {"map - min/max - invalid (below)", &cases.MapMinMax{Val: map[string]bool{}}, 1}, {"map - min/max - invalid (above)", &cases.MapMinMax{Val: map[string]bool{"a": true, "b": false, "c": true, "d": false, "e": true}}, 1}, {"map - exact - valid", &cases.MapExact{Val: map[uint64]string{1: "a", 2: "b", 3: "c"}}, 0}, {"map - exact - invalid (below)", &cases.MapExact{Val: map[uint64]string{1: "a", 2: "b"}}, 1}, {"map - exact - invalid (above)", &cases.MapExact{Val: map[uint64]string{1: "a", 2: "b", 3: "c", 4: "d"}}, 1}, {"map - no sparse - valid", &cases.MapNoSparse{Val: map[uint32]*cases.MapNoSparse_Msg{1: {}, 2: {}}}, 0}, {"map - no sparse - valid (empty)", &cases.MapNoSparse{Val: map[uint32]*cases.MapNoSparse_Msg{}}, 0}, // sparse maps are no longer supported, so this case is no longer possible //{"map - no sparse - invalid", &cases.MapNoSparse{Val: map[uint32]*cases.MapNoSparse_Msg{1: {}, 2: nil}}, 1}, {"map - keys - valid", &cases.MapKeys{Val: map[int64]string{-1: "a", -2: "b"}}, 0}, {"map - keys - valid (empty)", &cases.MapKeys{Val: map[int64]string{}}, 0}, {"map - keys - valid (pattern)", &cases.MapKeysPattern{Val: map[string]string{"A": "a"}}, 0}, {"map - keys - valid (in)", &cases.MapKeysIn{Val: map[string]string{"foo": "value"}}, 0}, {"map - keys - valid (not_in)", &cases.MapKeysNotIn{Val: map[string]string{"baz": "value"}}, 0}, {"map - keys - invalid", &cases.MapKeys{Val: map[int64]string{1: "a"}}, 1}, {"map - keys - invalid (pattern)", &cases.MapKeysPattern{Val: map[string]string{"A": "a", "!@#$%^&*()": "b"}}, 1}, {"map - keys - invalid (in)", &cases.MapKeysIn{Val: map[string]string{"baz": "value"}}, 1}, {"map - keys - invalid (not_in)", &cases.MapKeysNotIn{Val: map[string]string{"foo": "value"}}, 1}, {"map - values - valid", &cases.MapValues{Val: map[string]string{"a": "Alpha", "b": "Beta"}}, 0}, {"map - values - valid (empty)", &cases.MapValues{Val: map[string]string{}}, 0}, {"map - values - valid (pattern)", &cases.MapValuesPattern{Val: map[string]string{"a": "A"}}, 0}, {"map - values - invalid", &cases.MapValues{Val: map[string]string{"a": "A", "b": "B"}}, 2}, {"map - values - invalid (pattern)", &cases.MapValuesPattern{Val: map[string]string{"a": "A", "b": "!@#$%^&*()"}}, 1}, {"map - recursive - valid", &cases.MapRecursive{Val: map[uint32]*cases.MapRecursive_Msg{1: {Val: "abc"}}}, 0}, {"map - recursive - invalid", &cases.MapRecursive{Val: map[uint32]*cases.MapRecursive_Msg{1: {}}}, 1}, {"map - exact - valid (ignore_empty)", &cases.MapExactIgnore{Val: nil}, 0}, {"map - multiple - valid", &cases.MultipleMaps{First: map[uint32]string{1: "a", 2: "b"}, Second: map[int32]bool{-1: true, -2: false}}, 0}, } var oneofCases = []TestCase{ {"oneof - none - valid", &cases.OneOfNone{O: &cases.OneOfNone_X{X: "foo"}}, 0}, {"oneof - none - valid (empty)", &cases.OneOfNone{}, 0}, {"oneof - field - valid (X)", &cases.OneOf{O: &cases.OneOf_X{X: "foobar"}}, 0}, {"oneof - field - valid (Y)", &cases.OneOf{O: &cases.OneOf_Y{Y: 123}}, 0}, {"oneof - field - valid (Z)", &cases.OneOf{O: &cases.OneOf_Z{Z: &cases.TestOneOfMsg{Val: true}}}, 0}, {"oneof - field - valid (empty)", &cases.OneOf{}, 0}, {"oneof - field - invalid (X)", &cases.OneOf{O: &cases.OneOf_X{X: "fizzbuzz"}}, 1}, {"oneof - field - invalid (Y)", &cases.OneOf{O: &cases.OneOf_Y{Y: -1}}, 1}, {"oneof - filed - invalid (Z)", &cases.OneOf{O: &cases.OneOf_Z{Z: &cases.TestOneOfMsg{}}}, 1}, {"oneof - required - valid", &cases.OneOfRequired{O: &cases.OneOfRequired_X{X: ""}}, 0}, {"oneof - require - invalid", &cases.OneOfRequired{}, 1}, {"oneof - ignore_empty - valid (X)", &cases.OneOfIgnoreEmpty{O: &cases.OneOfIgnoreEmpty_X{X: ""}}, 0}, {"oneof - ignore_empty - valid (Y)", &cases.OneOfIgnoreEmpty{O: &cases.OneOfIgnoreEmpty_Y{Y: []byte("")}}, 0}, {"oneof - ignore_empty - valid (Z)", &cases.OneOfIgnoreEmpty{O: &cases.OneOfIgnoreEmpty_Z{Z: 0}}, 0}, } var wrapperCases = []TestCase{ {"wrapper - none - valid", &cases.WrapperNone{Val: &wrapperspb.Int32Value{Value: 123}}, 0}, {"wrapper - none - valid (empty)", &cases.WrapperNone{Val: nil}, 0}, {"wrapper - float - valid", &cases.WrapperFloat{Val: &wrapperspb.FloatValue{Value: 1}}, 0}, {"wrapper - float - valid (empty)", &cases.WrapperFloat{Val: nil}, 0}, {"wrapper - float - invalid", &cases.WrapperFloat{Val: &wrapperspb.FloatValue{Value: 0}}, 1}, {"wrapper - double - valid", &cases.WrapperDouble{Val: &wrapperspb.DoubleValue{Value: 1}}, 0}, {"wrapper - double - valid (empty)", &cases.WrapperDouble{Val: nil}, 0}, {"wrapper - double - invalid", &cases.WrapperDouble{Val: &wrapperspb.DoubleValue{Value: 0}}, 1}, {"wrapper - int64 - valid", &cases.WrapperInt64{Val: &wrapperspb.Int64Value{Value: 1}}, 0}, {"wrapper - int64 - valid (empty)", &cases.WrapperInt64{Val: nil}, 0}, {"wrapper - int64 - invalid", &cases.WrapperInt64{Val: &wrapperspb.Int64Value{Value: 0}}, 1}, {"wrapper - int32 - valid", &cases.WrapperInt32{Val: &wrapperspb.Int32Value{Value: 1}}, 0}, {"wrapper - int32 - valid (empty)", &cases.WrapperInt32{Val: nil}, 0}, {"wrapper - int32 - invalid", &cases.WrapperInt32{Val: &wrapperspb.Int32Value{Value: 0}}, 1}, {"wrapper - uint64 - valid", &cases.WrapperUInt64{Val: &wrapperspb.UInt64Value{Value: 1}}, 0}, {"wrapper - uint64 - valid (empty)", &cases.WrapperUInt64{Val: nil}, 0}, {"wrapper - uint64 - invalid", &cases.WrapperUInt64{Val: &wrapperspb.UInt64Value{Value: 0}}, 1}, {"wrapper - uint32 - valid", &cases.WrapperUInt32{Val: &wrapperspb.UInt32Value{Value: 1}}, 0}, {"wrapper - uint32 - valid (empty)", &cases.WrapperUInt32{Val: nil}, 0}, {"wrapper - uint32 - invalid", &cases.WrapperUInt32{Val: &wrapperspb.UInt32Value{Value: 0}}, 1}, {"wrapper - bool - valid", &cases.WrapperBool{Val: &wrapperspb.BoolValue{Value: true}}, 0}, {"wrapper - bool - valid (empty)", &cases.WrapperBool{Val: nil}, 0}, {"wrapper - bool - invalid", &cases.WrapperBool{Val: &wrapperspb.BoolValue{Value: false}}, 1}, {"wrapper - string - valid", &cases.WrapperString{Val: &wrapperspb.StringValue{Value: "foobar"}}, 0}, {"wrapper - string - valid (empty)", &cases.WrapperString{Val: nil}, 0}, {"wrapper - string - invalid", &cases.WrapperString{Val: &wrapperspb.StringValue{Value: "fizzbuzz"}}, 1}, {"wrapper - bytes - valid", &cases.WrapperBytes{Val: &wrapperspb.BytesValue{Value: []byte("foo")}}, 0}, {"wrapper - bytes - valid (empty)", &cases.WrapperBytes{Val: nil}, 0}, {"wrapper - bytes - invalid", &cases.WrapperBytes{Val: &wrapperspb.BytesValue{Value: []byte("x")}}, 1}, {"wrapper - required - string - valid", &cases.WrapperRequiredString{Val: &wrapperspb.StringValue{Value: "bar"}}, 0}, {"wrapper - required - string - invalid", &cases.WrapperRequiredString{Val: &wrapperspb.StringValue{Value: "foo"}}, 1}, {"wrapper - required - string - invalid (empty)", &cases.WrapperRequiredString{}, 1}, {"wrapper - required - string (empty) - valid", &cases.WrapperRequiredEmptyString{Val: &wrapperspb.StringValue{Value: ""}}, 0}, {"wrapper - required - string (empty) - invalid", &cases.WrapperRequiredEmptyString{Val: &wrapperspb.StringValue{Value: "foo"}}, 1}, {"wrapper - required - string (empty) - invalid (empty)", &cases.WrapperRequiredEmptyString{}, 1}, {"wrapper - optional - string (uuid) - valid", &cases.WrapperOptionalUuidString{Val: &wrapperspb.StringValue{Value: "8b72987b-024a-43b3-b4cf-647a1f925c5d"}}, 0}, {"wrapper - optional - string (uuid) - valid (empty)", &cases.WrapperOptionalUuidString{}, 0}, {"wrapper - optional - string (uuid) - invalid", &cases.WrapperOptionalUuidString{Val: &wrapperspb.StringValue{Value: "foo"}}, 1}, {"wrapper - required - float - valid", &cases.WrapperRequiredFloat{Val: &wrapperspb.FloatValue{Value: 1}}, 0}, {"wrapper - required - float - invalid", &cases.WrapperRequiredFloat{Val: &wrapperspb.FloatValue{Value: -5}}, 1}, {"wrapper - required - float - invalid (empty)", &cases.WrapperRequiredFloat{}, 1}, } var durationCases = []TestCase{ {"duration - none - valid", &cases.DurationNone{Val: &durationpb.Duration{Seconds: 123}}, 0}, {"duration - required - valid", &cases.DurationRequired{Val: &durationpb.Duration{}}, 0}, {"duration - required - invalid", &cases.DurationRequired{Val: nil}, 1}, {"duration - const - valid", &cases.DurationConst{Val: &durationpb.Duration{Seconds: 3}}, 0}, {"duration - const - valid (empty)", &cases.DurationConst{}, 0}, {"duration - const - invalid", &cases.DurationConst{Val: &durationpb.Duration{Nanos: 3}}, 1}, {"duration - in - valid", &cases.DurationIn{Val: &durationpb.Duration{Seconds: 1}}, 0}, {"duration - in - valid (empty)", &cases.DurationIn{}, 0}, {"duration - in - invalid", &cases.DurationIn{Val: &durationpb.Duration{}}, 1}, {"duration - not in - valid", &cases.DurationNotIn{Val: &durationpb.Duration{Nanos: 1}}, 0}, {"duration - not in - valid (empty)", &cases.DurationNotIn{}, 0}, {"duration - not in - invalid", &cases.DurationNotIn{Val: &durationpb.Duration{}}, 1}, {"duration - lt - valid", &cases.DurationLT{Val: &durationpb.Duration{Nanos: -1}}, 0}, {"duration - lt - valid (empty)", &cases.DurationLT{}, 0}, {"duration - lt - invalid (equal)", &cases.DurationLT{Val: &durationpb.Duration{}}, 1}, {"duration - lt - invalid", &cases.DurationLT{Val: &durationpb.Duration{Seconds: 1}}, 1}, {"duration - lte - valid", &cases.DurationLTE{Val: &durationpb.Duration{}}, 0}, {"duration - lte - valid (empty)", &cases.DurationLTE{}, 0}, {"duration - lte - valid (equal)", &cases.DurationLTE{Val: &durationpb.Duration{Seconds: 1}}, 0}, {"duration - lte - invalid", &cases.DurationLTE{Val: &durationpb.Duration{Seconds: 1, Nanos: 1}}, 1}, {"duration - gt - valid", &cases.DurationGT{Val: &durationpb.Duration{Seconds: 1}}, 0}, {"duration - gt - valid (empty)", &cases.DurationGT{}, 0}, {"duration - gt - invalid (equal)", &cases.DurationGT{Val: &durationpb.Duration{Nanos: 1000}}, 1}, {"duration - gt - invalid", &cases.DurationGT{Val: &durationpb.Duration{}}, 1}, {"duration - gte - valid", &cases.DurationGTE{Val: &durationpb.Duration{Seconds: 3}}, 0}, {"duration - gte - valid (empty)", &cases.DurationGTE{}, 0}, {"duration - gte - valid (equal)", &cases.DurationGTE{Val: &durationpb.Duration{Nanos: 1000000}}, 0}, {"duration - gte - invalid", &cases.DurationGTE{Val: &durationpb.Duration{Seconds: -1}}, 1}, {"duration - gt & lt - valid", &cases.DurationGTLT{Val: &durationpb.Duration{Nanos: 1000}}, 0}, {"duration - gt & lt - valid (empty)", &cases.DurationGTLT{}, 0}, {"duration - gt & lt - invalid (above)", &cases.DurationGTLT{Val: &durationpb.Duration{Seconds: 1000}}, 1}, {"duration - gt & lt - invalid (below)", &cases.DurationGTLT{Val: &durationpb.Duration{Nanos: -1000}}, 1}, {"duration - gt & lt - invalid (max)", &cases.DurationGTLT{Val: &durationpb.Duration{Seconds: 1}}, 1}, {"duration - gt & lt - invalid (min)", &cases.DurationGTLT{Val: &durationpb.Duration{}}, 1}, {"duration - exclusive gt & lt - valid (empty)", &cases.DurationExLTGT{}, 0}, {"duration - exclusive gt & lt - valid (above)", &cases.DurationExLTGT{Val: &durationpb.Duration{Seconds: 2}}, 0}, {"duration - exclusive gt & lt - valid (below)", &cases.DurationExLTGT{Val: &durationpb.Duration{Nanos: -1}}, 0}, {"duration - exclusive gt & lt - invalid", &cases.DurationExLTGT{Val: &durationpb.Duration{Nanos: 1000}}, 1}, {"duration - exclusive gt & lt - invalid (max)", &cases.DurationExLTGT{Val: &durationpb.Duration{Seconds: 1}}, 1}, {"duration - exclusive gt & lt - invalid (min)", &cases.DurationExLTGT{Val: &durationpb.Duration{}}, 1}, {"duration - gte & lte - valid", &cases.DurationGTELTE{Val: &durationpb.Duration{Seconds: 60, Nanos: 1}}, 0}, {"duration - gte & lte - valid (empty)", &cases.DurationGTELTE{}, 0}, {"duration - gte & lte - valid (max)", &cases.DurationGTELTE{Val: &durationpb.Duration{Seconds: 3600}}, 0}, {"duration - gte & lte - valid (min)", &cases.DurationGTELTE{Val: &durationpb.Duration{Seconds: 60}}, 0}, {"duration - gte & lte - invalid (above)", &cases.DurationGTELTE{Val: &durationpb.Duration{Seconds: 3600, Nanos: 1}}, 1}, {"duration - gte & lte - invalid (below)", &cases.DurationGTELTE{Val: &durationpb.Duration{Seconds: 59}}, 1}, {"duration - gte & lte - valid (empty)", &cases.DurationExGTELTE{}, 0}, {"duration - exclusive gte & lte - valid (above)", &cases.DurationExGTELTE{Val: &durationpb.Duration{Seconds: 3601}}, 0}, {"duration - exclusive gte & lte - valid (below)", &cases.DurationExGTELTE{Val: &durationpb.Duration{}}, 0}, {"duration - exclusive gte & lte - valid (max)", &cases.DurationExGTELTE{Val: &durationpb.Duration{Seconds: 3600}}, 0}, {"duration - exclusive gte & lte - valid (min)", &cases.DurationExGTELTE{Val: &durationpb.Duration{Seconds: 60}}, 0}, {"duration - exclusive gte & lte - invalid", &cases.DurationExGTELTE{Val: &durationpb.Duration{Seconds: 61}}, 1}, {"duration - fields with other fields - invalid other field", &cases.DurationFieldWithOtherFields{DurationVal: nil, IntVal: 12}, 1}, } var timestampCases = []TestCase{ {"timestamp - none - valid", &cases.TimestampNone{Val: ×tamppb.Timestamp{Seconds: 123}}, 0}, {"timestamp - required - valid", &cases.TimestampRequired{Val: ×tamppb.Timestamp{}}, 0}, {"timestamp - required - invalid", &cases.TimestampRequired{Val: nil}, 1}, {"timestamp - const - valid", &cases.TimestampConst{Val: ×tamppb.Timestamp{Seconds: 3}}, 0}, {"timestamp - const - valid (empty)", &cases.TimestampConst{}, 0}, {"timestamp - const - invalid", &cases.TimestampConst{Val: ×tamppb.Timestamp{Nanos: 3}}, 1}, {"timestamp - lt - valid", &cases.TimestampLT{Val: ×tamppb.Timestamp{Seconds: -1}}, 0}, {"timestamp - lt - valid (empty)", &cases.TimestampLT{}, 0}, {"timestamp - lt - invalid (equal)", &cases.TimestampLT{Val: ×tamppb.Timestamp{}}, 1}, {"timestamp - lt - invalid", &cases.TimestampLT{Val: ×tamppb.Timestamp{Seconds: 1}}, 1}, {"timestamp - lte - valid", &cases.TimestampLTE{Val: ×tamppb.Timestamp{}}, 0}, {"timestamp - lte - valid (empty)", &cases.TimestampLTE{}, 0}, {"timestamp - lte - valid (equal)", &cases.TimestampLTE{Val: ×tamppb.Timestamp{Seconds: 1}}, 0}, {"timestamp - lte - invalid", &cases.TimestampLTE{Val: ×tamppb.Timestamp{Seconds: 1, Nanos: 1}}, 1}, {"timestamp - gt - valid", &cases.TimestampGT{Val: ×tamppb.Timestamp{Seconds: 1}}, 0}, {"timestamp - gt - valid (empty)", &cases.TimestampGT{}, 0}, {"timestamp - gt - invalid (equal)", &cases.TimestampGT{Val: ×tamppb.Timestamp{Nanos: 1000}}, 1}, {"timestamp - gt - invalid", &cases.TimestampGT{Val: ×tamppb.Timestamp{}}, 1}, {"timestamp - gte - valid", &cases.TimestampGTE{Val: ×tamppb.Timestamp{Seconds: 3}}, 0}, {"timestamp - gte - valid (empty)", &cases.TimestampGTE{}, 0}, {"timestamp - gte - valid (equal)", &cases.TimestampGTE{Val: ×tamppb.Timestamp{Nanos: 1000000}}, 0}, {"timestamp - gte - invalid", &cases.TimestampGTE{Val: ×tamppb.Timestamp{Seconds: -1}}, 1}, {"timestamp - gt & lt - valid", &cases.TimestampGTLT{Val: ×tamppb.Timestamp{Nanos: 1000}}, 0}, {"timestamp - gt & lt - valid (empty)", &cases.TimestampGTLT{}, 0}, {"timestamp - gt & lt - invalid (above)", &cases.TimestampGTLT{Val: ×tamppb.Timestamp{Seconds: 1000}}, 1}, {"timestamp - gt & lt - invalid (below)", &cases.TimestampGTLT{Val: ×tamppb.Timestamp{Seconds: -1000}}, 1}, {"timestamp - gt & lt - invalid (max)", &cases.TimestampGTLT{Val: ×tamppb.Timestamp{Seconds: 1}}, 1}, {"timestamp - gt & lt - invalid (min)", &cases.TimestampGTLT{Val: ×tamppb.Timestamp{}}, 1}, {"timestamp - exclusive gt & lt - valid (empty)", &cases.TimestampExLTGT{}, 0}, {"timestamp - exclusive gt & lt - valid (above)", &cases.TimestampExLTGT{Val: ×tamppb.Timestamp{Seconds: 2}}, 0}, {"timestamp - exclusive gt & lt - valid (below)", &cases.TimestampExLTGT{Val: ×tamppb.Timestamp{Seconds: -1}}, 0}, {"timestamp - exclusive gt & lt - invalid", &cases.TimestampExLTGT{Val: ×tamppb.Timestamp{Nanos: 1000}}, 1}, {"timestamp - exclusive gt & lt - invalid (max)", &cases.TimestampExLTGT{Val: ×tamppb.Timestamp{Seconds: 1}}, 1}, {"timestamp - exclusive gt & lt - invalid (min)", &cases.TimestampExLTGT{Val: ×tamppb.Timestamp{}}, 1}, {"timestamp - gte & lte - valid", &cases.TimestampGTELTE{Val: ×tamppb.Timestamp{Seconds: 60, Nanos: 1}}, 0}, {"timestamp - gte & lte - valid (empty)", &cases.TimestampGTELTE{}, 0}, {"timestamp - gte & lte - valid (max)", &cases.TimestampGTELTE{Val: ×tamppb.Timestamp{Seconds: 3600}}, 0}, {"timestamp - gte & lte - valid (min)", &cases.TimestampGTELTE{Val: ×tamppb.Timestamp{Seconds: 60}}, 0}, {"timestamp - gte & lte - invalid (above)", &cases.TimestampGTELTE{Val: ×tamppb.Timestamp{Seconds: 3600, Nanos: 1}}, 1}, {"timestamp - gte & lte - invalid (below)", &cases.TimestampGTELTE{Val: ×tamppb.Timestamp{Seconds: 59}}, 1}, {"timestamp - gte & lte - valid (empty)", &cases.TimestampExGTELTE{}, 0}, {"timestamp - exclusive gte & lte - valid (above)", &cases.TimestampExGTELTE{Val: ×tamppb.Timestamp{Seconds: 3601}}, 0}, {"timestamp - exclusive gte & lte - valid (below)", &cases.TimestampExGTELTE{Val: ×tamppb.Timestamp{}}, 0}, {"timestamp - exclusive gte & lte - valid (max)", &cases.TimestampExGTELTE{Val: ×tamppb.Timestamp{Seconds: 3600}}, 0}, {"timestamp - exclusive gte & lte - valid (min)", &cases.TimestampExGTELTE{Val: ×tamppb.Timestamp{Seconds: 60}}, 0}, {"timestamp - exclusive gte & lte - invalid", &cases.TimestampExGTELTE{Val: ×tamppb.Timestamp{Seconds: 61}}, 1}, {"timestamp - lt now - valid", &cases.TimestampLTNow{Val: ×tamppb.Timestamp{}}, 0}, {"timestamp - lt now - valid (empty)", &cases.TimestampLTNow{}, 0}, {"timestamp - lt now - invalid", &cases.TimestampLTNow{Val: ×tamppb.Timestamp{Seconds: time.Now().Unix() + 7200}}, 1}, {"timestamp - gt now - valid", &cases.TimestampGTNow{Val: ×tamppb.Timestamp{Seconds: time.Now().Unix() + 7200}}, 0}, {"timestamp - gt now - valid (empty)", &cases.TimestampGTNow{}, 0}, {"timestamp - gt now - invalid", &cases.TimestampGTNow{Val: ×tamppb.Timestamp{}}, 1}, {"timestamp - within - valid", &cases.TimestampWithin{Val: timestamppb.Now()}, 0}, {"timestamp - within - valid (empty)", &cases.TimestampWithin{}, 0}, {"timestamp - within - invalid (below)", &cases.TimestampWithin{Val: ×tamppb.Timestamp{}}, 1}, {"timestamp - within - invalid (above)", &cases.TimestampWithin{Val: ×tamppb.Timestamp{Seconds: time.Now().Unix() + 7200}}, 1}, {"timestamp - lt now within - valid", &cases.TimestampLTNowWithin{Val: ×tamppb.Timestamp{Seconds: time.Now().Unix() - 1800}}, 0}, {"timestamp - lt now within - valid (empty)", &cases.TimestampLTNowWithin{}, 0}, {"timestamp - lt now within - invalid (lt)", &cases.TimestampLTNowWithin{Val: ×tamppb.Timestamp{Seconds: time.Now().Unix() + 1800}}, 1}, {"timestamp - lt now within - invalid (within)", &cases.TimestampLTNowWithin{Val: ×tamppb.Timestamp{Seconds: time.Now().Unix() - 7200}}, 1}, {"timestamp - gt now within - valid", &cases.TimestampGTNowWithin{Val: ×tamppb.Timestamp{Seconds: time.Now().Unix() + 1800}}, 0}, {"timestamp - gt now within - valid (empty)", &cases.TimestampGTNowWithin{}, 0}, {"timestamp - gt now within - invalid (gt)", &cases.TimestampGTNowWithin{Val: ×tamppb.Timestamp{Seconds: time.Now().Unix() - 1800}}, 1}, {"timestamp - gt now within - invalid (within)", &cases.TimestampGTNowWithin{Val: ×tamppb.Timestamp{Seconds: time.Now().Unix() + 7200}}, 1}, } var anyCases = []TestCase{ {"any - none - valid", &cases.AnyNone{Val: &anypb.Any{}}, 0}, {"any - required - valid", &cases.AnyRequired{Val: &anypb.Any{}}, 0}, {"any - required - invalid", &cases.AnyRequired{Val: nil}, 1}, {"any - in - valid", &cases.AnyIn{Val: &anypb.Any{TypeUrl: "type.googleapis.com/google.protobuf.Duration"}}, 0}, {"any - in - valid (empty)", &cases.AnyIn{}, 0}, {"any - in - invalid", &cases.AnyIn{Val: &anypb.Any{TypeUrl: "type.googleapis.com/google.protobuf.Timestamp"}}, 1}, {"any - not in - valid", &cases.AnyNotIn{Val: &anypb.Any{TypeUrl: "type.googleapis.com/google.protobuf.Duration"}}, 0}, {"any - not in - valid (empty)", &cases.AnyNotIn{}, 0}, {"any - not in - invalid", &cases.AnyNotIn{Val: &anypb.Any{TypeUrl: "type.googleapis.com/google.protobuf.Timestamp"}}, 1}, } var kitchenSink = []TestCase{ {"kitchensink - field - valid", &cases.KitchenSinkMessage{Val: &cases.ComplexTestMsg{Const: "abcd", IntConst: 5, BoolConst: false, FloatVal: &wrapperspb.FloatValue{Value: 1}, DurVal: &durationpb.Duration{Seconds: 3}, TsVal: ×tamppb.Timestamp{Seconds: 17}, FloatConst: 7, DoubleIn: 123, EnumConst: cases.ComplexTestEnum_ComplexTWO, AnyVal: &anypb.Any{TypeUrl: "type.googleapis.com/google.protobuf.Duration"}, RepTsVal: []*timestamppb.Timestamp{{Seconds: 3}}, MapVal: map[int32]string{-1: "a", -2: "b"}, BytesVal: []byte("\x00\x99"), O: &cases.ComplexTestMsg_X{X: "foobar"}}}, 0}, {"kitchensink - valid (unset)", &cases.KitchenSinkMessage{}, 0}, {"kitchensink - field - invalid", &cases.KitchenSinkMessage{Val: &cases.ComplexTestMsg{}}, 7}, {"kitchensink - field - embedded - invalid", &cases.KitchenSinkMessage{Val: &cases.ComplexTestMsg{Another: &cases.ComplexTestMsg{}}}, 14}, {"kitchensink - field - invalid (transitive)", &cases.KitchenSinkMessage{Val: &cases.ComplexTestMsg{Const: "abcd", BoolConst: true, Nested: &cases.ComplexTestMsg{}}}, 14}, {"kitchensink - many - all non-message fields invalid", &cases.KitchenSinkMessage{Val: &cases.ComplexTestMsg{BoolConst: true, FloatVal: &wrapperspb.FloatValue{}, TsVal: ×tamppb.Timestamp{}, FloatConst: 8, AnyVal: &anypb.Any{TypeUrl: "asdf"}, RepTsVal: []*timestamppb.Timestamp{{Nanos: 1}}}}, 13}, } var nestedCases = []TestCase{ {"nested wkt uuid - field - valid", &cases.WktLevelOne{Two: &cases.WktLevelOne_WktLevelTwo{Three: &cases.WktLevelOne_WktLevelTwo_WktLevelThree{Uuid: "f81d16ef-40e2-40c6-bebc-89aaf5292f9a"}}}, 0}, {"nested wkt uuid - field - invalid", &cases.WktLevelOne{Two: &cases.WktLevelOne_WktLevelTwo{Three: &cases.WktLevelOne_WktLevelTwo_WktLevelThree{Uuid: "not-a-valid-uuid"}}}, 1}, } protoc-gen-validate-1.0.2/tests/harness/executor/executor.go000066400000000000000000000053231444536353100242210ustar00rootroot00000000000000package main import ( "flag" "log" "math" "os" "runtime" "strconv" "sync" "sync/atomic" "time" ) func init() { log.SetFlags(0) } func main() { parallelism := flag.Int("parallelism", runtime.NumCPU(), "Number of test cases to run in parallel") goFlag := flag.Bool("go", false, "Run go test harness") ccFlag := flag.Bool("cc", false, "Run c++ test harness") javaFlag := flag.Bool("java", false, "Run java test harness") pythonFlag := flag.Bool("python", false, "Run python test harness") externalHarnessFlag := flag.String("external_harness", "", "Path to a binary to be executed as an external test harness") flag.Parse() test_cases := shardTestCases(TestCases) start := time.Now() harnesses := Harnesses(*goFlag, *ccFlag, *javaFlag, *pythonFlag, *externalHarnessFlag) successes, failures, skips := run(*parallelism, harnesses, test_cases) log.Printf("Successes: %d | Failures: %d | Skips: %d (%v)", successes, failures, skips, time.Since(start)) if failures > 0 { os.Exit(1) } } func shardTestCases(test_cases []TestCase) []TestCase { // Support Bazel test sharding by slicing up the list of test cases if requested. shard_count, err := strconv.Atoi(os.Getenv("TEST_TOTAL_SHARDS")) if err != nil { return test_cases } shard_index, err := strconv.Atoi(os.Getenv("TEST_SHARD_INDEX")) if err != nil { return test_cases } // Bazel expects that the test will create or modify the file with the provided name to show that it supports sharding. status_file := os.Getenv("TEST_SHARD_STATUS_FILE") if status_file == "" { return test_cases } if file, err := os.Create(status_file); err != nil { return test_cases } else { file.Close() } shard_length := int(math.Ceil(float64(len(test_cases)) / float64(shard_count))) shard_start := shard_index * shard_length shard_end := (shard_index + 1) * shard_length if shard_end >= len(test_cases) { shard_end = len(test_cases) } return test_cases[shard_start:shard_end] } func run(parallelism int, harnesses []Harness, test_cases []TestCase) (successes, failures, skips uint64) { wg := new(sync.WaitGroup) if parallelism <= 0 { panic("Parallelism must be > 0") } if len(harnesses) == 0 { panic("At least one harness must be selected with a flag") } wg.Add(parallelism) in := make(chan TestCase) out := make(chan TestResult) done := make(chan struct{}) for i := 0; i < parallelism; i++ { go Work(wg, in, out, harnesses) } go func() { for res := range out { if res.Skipped { atomic.AddUint64(&skips, 1) } else if res.OK { atomic.AddUint64(&successes, 1) } else { atomic.AddUint64(&failures, 1) } } close(done) }() for _, test := range test_cases { in <- test } close(in) wg.Wait() close(out) <-done return } protoc-gen-validate-1.0.2/tests/harness/executor/executor_test.sh000077500000000000000000000001001444536353100252540ustar00rootroot00000000000000#!/bin/bash # set -x EXECUTOR_BIN=$1 shift $EXECUTOR_BIN "$@" protoc-gen-validate-1.0.2/tests/harness/executor/harness.go000066400000000000000000000054241444536353100240300ustar00rootroot00000000000000package main import ( "bufio" "bytes" "fmt" "io" "os" "os/exec" "runtime" "strings" "sync" harness "github.com/envoyproxy/protoc-gen-validate/tests/harness/go" "golang.org/x/net/context" "google.golang.org/protobuf/proto" ) func Harnesses(goFlag, ccFlag, javaFlag, pythonFlag bool, externalHarnessFlag string) []Harness { harnesses := make([]Harness, 0) if goFlag { harnesses = append(harnesses, InitHarness("tests/harness/go/main/go-harness", "go")) } if ccFlag { harnesses = append(harnesses, InitHarness("tests/harness/cc/cc-harness", "cc")) } if javaFlag { harnesses = append(harnesses, InitHarness("tests/harness/java/java-harness", "java")) } if pythonFlag { harnesses = append(harnesses, InitHarness("tests/harness/python/python-harness", "python")) } if externalHarnessFlag != "" { harnesses = append(harnesses, InitHarness(externalHarnessFlag, "external")) } return harnesses } type Harness struct { Name string Exec func(context.Context, io.Reader) (*harness.TestResult, error) } func InitHarness(cmd string, name string, args ...string) Harness { if runtime.GOOS == "windows" { // Bazel runfiles are not symlinked in on windows, // so we have to use the manifest instead. If the manifest // doesn't exist, assume we're running in a non-Bazel context f, err := os.Open("MANIFEST") if err == nil { defer f.Close() s := bufio.NewScanner(f) manifest := map[string]string{} for s.Scan() { values := strings.Split(s.Text(), " ") manifest[values[0]] = values[1] } for k, v := range manifest { if strings.Contains(k, cmd) { cmd = v } } } } return Harness{ Name: name, Exec: initHarness(cmd, args...), } } func initHarness(cmd string, args ...string) func(context.Context, io.Reader) (*harness.TestResult, error) { return func(ctx context.Context, r io.Reader) (*harness.TestResult, error) { out, errs := getBuf(), getBuf() defer relBuf(out) defer relBuf(errs) cmd := exec.CommandContext(ctx, cmd, args...) cmd.Stdin = r cmd.Stdout = out cmd.Stderr = errs if err := cmd.Run(); err != nil { return nil, fmt.Errorf("[%s] failed execution (%v) - captured stderr:\n%s", cmdStr(cmd), err, errs.String()) } if errs.Len() > 0 { fmt.Printf("captured stderr:\n%s", errs.String()) } res := new(harness.TestResult) if err := proto.Unmarshal(out.Bytes(), res); err != nil { return nil, fmt.Errorf("[%s] failed to unmarshal result: %v", cmdStr(cmd), err) } return res, nil } } var bufPool = &sync.Pool{New: func() interface{} { return new(bytes.Buffer) }} func getBuf() *bytes.Buffer { return bufPool.Get().(*bytes.Buffer) } func relBuf(b *bytes.Buffer) { b.Reset() bufPool.Put(b) } func cmdStr(cmd *exec.Cmd) string { return fmt.Sprintf("%s %s", cmd.Path, strings.Join(cmd.Args, " ")) } protoc-gen-validate-1.0.2/tests/harness/executor/worker.go000066400000000000000000000053051444536353100236740ustar00rootroot00000000000000package main import ( "bytes" "context" "log" "strings" "sync" "time" harness "github.com/envoyproxy/protoc-gen-validate/tests/harness/go" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" ) func Work(wg *sync.WaitGroup, in <-chan TestCase, out chan<- TestResult, harnesses []Harness) { for tc := range in { execTestCase(tc, harnesses, out) } wg.Done() } func execTestCase(tc TestCase, harnesses []Harness, out chan<- TestResult) { any, err := anypb.New(tc.Message) if err != nil { log.Printf("unable to convert test case %q to Any - %v", tc.Name, err) out <- TestResult{false, false} return } b, err := proto.Marshal(&harness.TestCase{Message: any}) if err != nil { log.Printf("unable to marshal test case %q - %v", tc.Name, err) out <- TestResult{false, false} return } ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) defer cancel() wg := new(sync.WaitGroup) wg.Add(len(harnesses)) for _, h := range harnesses { h := h go func() { defer wg.Done() res, err := h.Exec(ctx, bytes.NewReader(b)) if err != nil { log.Printf("[%s] (%s harness) executor error: %s", tc.Name, h.Name, err.Error()) out <- TestResult{false, false} return } if res.Error { log.Printf("[%s] (%s harness) internal harness error: %s", tc.Name, h.Name, res.Reasons) out <- TestResult{false, false} return } // Backwards compatibility for languages with no multi-error // feature: check results of validation in "fail fast" mode only if !res.CheckMultipleErrors { tcValid := tc.Failures == 0 if res.Valid != tcValid { if res.AllowFailure { log.Printf("[%s] (%s harness) ignoring test failure: %v", tc.Name, h.Name, res.Reasons) out <- TestResult{false, true} } else if tcValid { log.Printf("[%s] (%s harness) expected valid, got invalid: %v", tc.Name, h.Name, res.Reasons) out <- TestResult{false, false} } else { log.Printf("[%s] (%s harness) expected invalid, got valid: %v", tc.Name, h.Name, res.Reasons) out <- TestResult{false, false} } } else { out <- TestResult{true, false} } return } // Check results of validation in "extensive" mode if len(res.Reasons) != tc.Failures { if res.AllowFailure { log.Printf("[%s] (%s harness) ignoring bad number of failures: %v", tc.Name, h.Name, res.Reasons) out <- TestResult{false, true} } else { log.Printf("[%s] (%s harness) expected %d failures, got %d:\n %v", tc.Name, h.Name, tc.Failures, len(res.Reasons), strings.Join(res.Reasons, "\n ")) out <- TestResult{false, false} } return } out <- TestResult{true, false} }() } wg.Wait() return } protoc-gen-validate-1.0.2/tests/harness/go/000077500000000000000000000000001444536353100206005ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/harness/go/main/000077500000000000000000000000001444536353100215245ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/harness/go/main/BUILD000066400000000000000000000024741444536353100223150ustar00rootroot00000000000000load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") go_library( name = "go_default_library", srcs = ["harness.go"], importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/go/main", visibility = ["//visibility:private"], deps = [ "//tests/harness:harness_go_proto", "//tests/harness/cases:go", "//tests/harness/cases/other_package:go", "//tests/harness/cases/yet_another_package:go", "//tests/harness/cases/sort:go", "@org_golang_google_protobuf//proto:go_default_library", "@org_golang_google_protobuf//types/known/anypb:go_default_library", "@org_golang_google_protobuf//types/known/durationpb:go_default_library", "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", ], ) genrule( name = "go-harness-bin", srcs = [":main"], outs = ["go-harness"], cmd = "cp $(SRCS) $@", visibility = ["//visibility:public"], ) genrule( name = "go-harness-exe", srcs = [":main"], outs = ["go-harness.exe"], cmd = "cp $(SRCS) $@", visibility = ["//visibility:public"], ) go_binary( name = "main", embed = [":go_default_library"], importpath = "github.com/envoyproxy/protoc-gen-validate/tests/harness/go/main", visibility = ["//visibility:public"], ) protoc-gen-validate-1.0.2/tests/harness/go/main/harness.go000066400000000000000000000063731444536353100235270ustar00rootroot00000000000000package main import ( "fmt" "io/ioutil" "log" "os" "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go" _ "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go" _ "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/other_package/go" _ "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/yet_another_package/go" "github.com/envoyproxy/protoc-gen-validate/tests/harness/go" "google.golang.org/protobuf/proto" ) func main() { b, err := ioutil.ReadAll(os.Stdin) checkErr(err) tc := new(harness.TestCase) checkErr(proto.Unmarshal(b, tc)) msg, err := tc.Message.UnmarshalNew() checkErr(err) _, isIgnored := msg.(*cases.MessageIgnored) vMsg, hasValidate := msg.(interface { Validate() error }) vAllMsg, hasValidateAll := msg.(interface { ValidateAll() error }) var multierr error if isIgnored { // confirm that ignored messages don't have a validate method if hasValidate { checkErr(fmt.Errorf("ignored message %T has Validate() method", msg)) } if hasValidateAll { checkErr(fmt.Errorf("ignored message %T has ValidateAll() method", msg)) } } else if !hasValidate { checkErr(fmt.Errorf("non-ignored message %T is missing Validate()", msg)) } else if !hasValidateAll { checkErr(fmt.Errorf("non-ignored message %T is missing ValidateAll()", msg)) } else { err = vMsg.Validate() multierr = vAllMsg.ValidateAll() } checkValid(err, multierr) } type hasAllErrors interface{ AllErrors() []error } type hasCause interface{ Cause() error } func checkValid(err, multierr error) { if err == nil && multierr == nil { resp(&harness.TestResult{Valid: true}) return } if (err != nil) != (multierr != nil) { checkErr(fmt.Errorf("different verdict of Validate() [%v] vs. ValidateAll() [%v]", err, multierr)) return } // Extract the message from "lazy" Validate(), for comparison with ValidateAll() rootCause := err for { caused, ok := rootCause.(hasCause) if !ok || caused.Cause() == nil { break } rootCause = caused.Cause() } // Retrieve the messages from "extensive" ValidateAll() and compare first one with the "lazy" message m, ok := multierr.(hasAllErrors) if !ok { checkErr(fmt.Errorf("ValidateAll() returned error without AllErrors() method: %#v", multierr)) return } reasons := mergeReasons(nil, m) if rootCause.Error() != reasons[0] { checkErr(fmt.Errorf("different first message, Validate()==%q, ValidateAll()==%q", rootCause.Error(), reasons[0])) return } resp(&harness.TestResult{Reasons: reasons}) } func mergeReasons(reasons []string, multi hasAllErrors) []string { for _, err := range multi.AllErrors() { caused, ok := err.(hasCause) if ok && caused.Cause() != nil { err = caused.Cause() } multi, ok := err.(hasAllErrors) if ok { reasons = mergeReasons(reasons, multi) } else { reasons = append(reasons, err.Error()) } } return reasons } func checkErr(err error) { if err == nil { return } resp(&harness.TestResult{ Error: true, Reasons: []string{err.Error()}, }) } func resp(result *harness.TestResult) { if b, err := proto.Marshal(result); err != nil { log.Fatalf("could not marshal response: %v", err) } else if _, err = os.Stdout.Write(b); err != nil { log.Fatalf("could not write response: %v", err) } os.Exit(0) } protoc-gen-validate-1.0.2/tests/harness/harness.proto000066400000000000000000000006151444536353100227250ustar00rootroot00000000000000syntax = "proto3"; package tests.harness; option go_package = "github.com/envoyproxy/protoc-gen-validate/tests/harness/go;harness"; import "google/protobuf/any.proto"; message TestCase { google.protobuf.Any message = 1; } message TestResult { bool Valid = 1; bool Error = 2; repeated string Reasons = 3; bool AllowFailure = 4; bool CheckMultipleErrors = 5; } protoc-gen-validate-1.0.2/tests/harness/java/000077500000000000000000000000001444536353100211145ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/harness/java/BUILD000066400000000000000000000005121444536353100216740ustar00rootroot00000000000000load("@rules_java//java:defs.bzl", "java_binary") java_binary( name = "java-harness", main_class = "io.envoyproxy.pgv.validation.JavaHarness", visibility = ["//tests/harness:__subpackages__"], runtime_deps = [ "//java/pgv-java-validation/src/main/java/io/envoyproxy/pgv/validation:java_harness", ], ) protoc-gen-validate-1.0.2/tests/harness/python/000077500000000000000000000000001444536353100215145ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tests/harness/python/BUILD000066400000000000000000000014761444536353100223060ustar00rootroot00000000000000load("@rules_python//python:defs.bzl", "py_binary", "py_test") load("@pgv_pip_deps//:requirements.bzl", "requirement") py_binary( name = "python-harness", srcs = ["harness.py"], main = "harness.py", srcs_version = "PY3", visibility = ["//visibility:public"], deps = [ # ensures we test with the package's own protobuf runtime specified in setup.cfg # and not the one riding on the py_proto_library dependencies requirement("protobuf"), "//tests/harness:harness_py_proto", "//tests/harness/cases:cases_py_proto", "//python:validator_py" ] ) py_test( name = "python-requirements-match", srcs = ["requirements_test.py"], main = "requirements_test.py", srcs_version = "PY3", data = ["//python:setup.cfg", "//python:requirements.in"], ) protoc-gen-validate-1.0.2/tests/harness/python/harness.py000066400000000000000000000050511444536353100235320ustar00rootroot00000000000000import sys import inspect from python.protoc_gen_validate.validator import validate, validate_all, ValidationFailed from tests.harness.harness_pb2 import TestCase, TestResult from tests.harness.cases.bool_pb2 import * from tests.harness.cases.bytes_pb2 import * from tests.harness.cases.enums_pb2 import * from tests.harness.cases.enums_pb2 import * from tests.harness.cases.messages_pb2 import * from tests.harness.cases.numbers_pb2 import * from tests.harness.cases.oneofs_pb2 import * from tests.harness.cases.repeated_pb2 import * from tests.harness.cases.strings_pb2 import * from tests.harness.cases.maps_pb2 import * from tests.harness.cases.wkt_any_pb2 import * from tests.harness.cases.wkt_duration_pb2 import * from tests.harness.cases.wkt_nested_pb2 import * from tests.harness.cases.wkt_wrappers_pb2 import * from tests.harness.cases.wkt_timestamp_pb2 import * from tests.harness.cases.kitchen_sink_pb2 import * message_classes = {} for k, v in inspect.getmembers(sys.modules[__name__], inspect.isclass): if 'DESCRIPTOR' in dir(v): message_classes[v.DESCRIPTOR.full_name] = v if __name__ == "__main__": read = sys.stdin.buffer.read() testcase = TestCase() testcase.ParseFromString(read) test_class = message_classes[testcase.message.TypeName()] test_msg = test_class() testcase.message.Unpack(test_msg) try: result = TestResult() valid = validate(test_msg) result.Valid = True except ValidationFailed as e: result.Valid = False result.Reasons[:] = [repr(e)] try: result_all = TestResult() valid = validate_all(test_msg) result_all.Valid = True except ValidationFailed as e: result_all.Valid = False result_all.Reasons[:] = [repr(e)] if result.Valid != result_all.Valid: raise ValueError(f"validation results mismatch, validate: {result.Valid}, " f"validate_all: {result_all.Valid}") if not result.Valid: reason = list(result.Reasons)[0] # ValidationFailed("reason") reason = reason[18:-2] # reason reason_all = list(result_all.Reasons)[0] # ValidationFailed("reason1\nreason2\n...reason") reason_all = reason_all[18:-2] # reason1\nreason2\n...reason if not reason_all.startswith(reason): raise ValueError(f"different first message, validate: {reason}, " f"validate_all: {reason_all}") sys.stdout = open(sys.stdout.fileno(), mode='w', encoding='utf8') sys.stdout.write(result.SerializeToString().decode("utf-8")) protoc-gen-validate-1.0.2/tests/harness/python/requirements_test.py000077500000000000000000000023311444536353100256520ustar00rootroot00000000000000import configparser # There's two sets of requirements relevant for python. The first set in requirements.txt is installed # during the Docker build and is used for linting, building, and uploading the PGV python package to PyPI. # # The other set is in the install_requires section of setup.cfg. This is what's needed to use the package. # # We use pip_install from @rules_python to install these requirements in order to test the package. Unfortunately: # - pip_install can't handle setup.cfg directly, it wants a file containing a simple list # - as a bazel repository_rule, pip_install won't accept generated files as input so we can't autogen # this simpler file out of setup.cfg as part of bazel build. # # So instead here we just check that requirements.in matches what's in install_requires of setup.cfg. with open('python/requirements.in', 'r') as reqs: lines = reqs.readlines() requirements_dot_in_set = {line.strip() for line in lines if line.strip() and not line.startswith("#")} config = configparser.ConfigParser() config.read('python/setup.cfg') setup_dot_cfg_set = {line for line in config['options']['install_requires'].split() if not line.startswith("#")} assert requirements_dot_in_set == setup_dot_cfg_set protoc-gen-validate-1.0.2/tools.go000066400000000000000000000003461444536353100170600ustar00rootroot00000000000000//go:build tools // +build tools package main import ( _ "golang.org/x/lint/golint" _ "golang.org/x/net/context" _ "golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow" _ "google.golang.org/protobuf/cmd/protoc-gen-go" ) protoc-gen-validate-1.0.2/tools/000077500000000000000000000000001444536353100165265ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tools/build/000077500000000000000000000000001444536353100176255ustar00rootroot00000000000000protoc-gen-validate-1.0.2/tools/build/Env.mk000066400000000000000000000004041444536353100207040ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License") # Disable cgo. export CGOENABLED := 0 # Reference: https://developers.google.com/protocol-buffers/docs/reference/go/faq#namespace-conflict. export GOLANG_PROTOBUF_REGISTRATION_CONFLICT := warn protoc-gen-validate-1.0.2/tools/build/Help.mk000066400000000000000000000025251444536353100210520ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License") # This is adopted from https://github.com/tetratelabs/func-e/blob/3df66c9593e827d67b330b7355d577f91cdcb722/Makefile#L60-L76. # ANSI escape codes. f_ means foreground, b_ background. # See https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters. f_black := $(shell printf "\33[30m") b_black := $(shell printf "\33[40m") f_white := $(shell printf "\33[97m") f_gray := $(shell printf "\33[37m") f_dark_gray := $(shell printf "\33[90m") f_bright_cyan := $(shell printf "\33[96m") b_bright_cyan := $(shell printf "\33[106m") ansi_reset := $(shell printf "\33[0m") ansi_$(name) := $(b_black)$(f_black)$(b_bright_cyan)$(name)$(ansi_reset) ansi_format_dark := $(f_gray)$(f_bright_cyan)%-10s$(ansi_reset) $(f_dark_gray)%s$(ansi_reset)\n ansi_format_bright := $(f_white)$(f_bright_cyan)%-10s$(ansi_reset) $(f_black)$(b_bright_cyan)%s$(ansi_reset)\n # This formats help statements in ANSI colors. To hide a target from help, don't comment it with a trailing '##'. help: ## Describe how to use each target @printf "$(ansi_$(name))$(f_white)\n" @awk 'BEGIN {FS = ":.*?## "} /^[0-9a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf "$(ansi_format_dark)", $$1, $$2}' $(MAKEFILE_LIST) protoc-gen-validate-1.0.2/tools/build/Installer.mk000066400000000000000000000020251444536353100221120ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License") # Catch all rules for Go-based tools. $(go_tools_dir)/bin/%: @GOBIN=$(go_tools_dir)/bin $(go) install $($(notdir $@)@v) # Install protoc from github.com/protocolbuffers/protobuf. protoc-os := $(if $(findstring $(goos),darwin),osx,$(goos)) protoc-arch := $(if $(findstring $(goarch),arm64),aarch_64,x86_64) protoc-version = $(subst github.com/protocolbuffers/protobuf@v,$(empty),$($(notdir $1)@v)) protoc-archive = protoc-$(call protoc-version,$1)-$(protoc-os)-$(protoc-arch).zip protoc-url = https://$(subst @,/releases/download/,$($(notdir $1)@v))/$(call protoc-archive,$1) protoc-zip = $(prepackaged_tools_dir)/$(call protoc-archive,$1) $(protoc): @mkdir -p $(prepackaged_tools_dir) ifeq ($(goos),linux) @curl -sSL $(call protoc-url,$@) -o $(call protoc-zip,$@) @unzip -oqq $(call protoc-zip,$@) -d $(prepackaged_tools_dir) @rm -f $(call protoc-zip,$@) else @curl -sSL $(call protoc-url,$@) | tar xf - -C $(prepackaged_tools_dir) @chmod +x $@ endif protoc-gen-validate-1.0.2/validate/000077500000000000000000000000001444536353100171575ustar00rootroot00000000000000protoc-gen-validate-1.0.2/validate/BUILD000066400000000000000000000035661444536353100177530ustar00rootroot00000000000000load("@com_google_protobuf//:protobuf.bzl", "py_proto_library") load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") load("@rules_cc//cc:defs.bzl", "cc_library", "cc_proto_library") load("@rules_java//java:defs.bzl", "java_proto_library") load("@rules_proto//proto:defs.bzl", "proto_library") load("@io_bazel_rules_go//go:def.bzl", "go_library") package( default_visibility = ["//visibility:public"], ) proto_library( name = "validate_proto", srcs = ["validate.proto"], deps = [ "@com_google_protobuf//:descriptor_proto", "@com_google_protobuf//:duration_proto", "@com_google_protobuf//:timestamp_proto", ], ) cc_proto_library( name = "validate_cc", deps = [":validate_proto"], ) py_proto_library( name = "validate_py", srcs = ["validate.proto"], deps = ["@com_google_protobuf//:protobuf_python"], ) go_proto_library( name = "validate_go_proto", importpath = "github.com/envoyproxy/protoc-gen-validate/validate", proto = ":validate_proto", ) cc_library( name = "cc_validate", hdrs = ["validate.h"], ) go_library( name = "validate_go", embed = [":validate_go_proto"], importpath = "github.com/envoyproxy/protoc-gen-validate/validate", ) java_proto_library( name = "validate_java", deps = [":validate_proto"], ) filegroup( name = "validate_src", srcs = ["validate.proto"], ) alias( name = "go_default_library", actual = ":validate", deprecation = "Use :validate instead of :go_default_library. Details about the new naming convention: https://github.com/bazelbuild/bazel-gazelle/pull/863", visibility = ["//visibility:public"], ) # this alias allows build files generated with Gazelle in other repositories # to find validate as an external dependency alias( name = "validate", actual = ":validate_go", visibility = ["//visibility:public"], ) protoc-gen-validate-1.0.2/validate/validate.h000066400000000000000000000126461444536353100211320ustar00rootroot00000000000000#ifndef _VALIDATE_H #define _VALIDATE_H #include #include #include #include #include #include #include #if !defined(_WIN32) #include #else #include #include // uses macros to #define a ton of symbols, // many of which interfere with our code here and down // the line in various extensions. #undef DELETE #undef ERROR #undef GetMessage #undef interface #undef TRUE #undef min #endif #include "google/protobuf/message.h" namespace pgv { using std::string; class UnimplementedException : public std::runtime_error { public: UnimplementedException() : std::runtime_error("not yet implemented") {} UnimplementedException(const std::string& message) : std::runtime_error(message) {} // Thrown by C++ validation code that is not yet implemented. }; using ValidationMsg = std::string; class BaseValidator { public: /** * Validate/check a generic message object with a registered validator for the concrete message * type. * @param m supplies the message to check. * @param err supplies the place to return error information. * @return true if the validation passes OR there is no registered validator for the concrete * message type. false is returned if validation explicitly fails. */ static bool AbstractCheckMessage(const google::protobuf::Message& m, ValidationMsg* err) { // Polymorphic lookup is used to see if there is a matching concrete validator. If so, call it. // Otherwise return success. auto it = abstractValidators().find(std::type_index(typeid(m))); if (it == abstractValidators().end()) { return true; } return it->second(m, err); } protected: // Used to implement AbstractCheckMessage() above. Every message that is linked into the binary // will register itself by type_index, allowing for polymorphic lookup later. static std::unordered_map>& abstractValidators() { static auto* validator_map = new std::unordered_map< std::type_index, std::function>(); return *validator_map; } }; template class Validator : public BaseValidator { public: Validator(std::function check) : check_(check) { abstractValidators()[std::type_index(typeid(T))] = [this](const google::protobuf::Message& m, ValidationMsg* err) -> bool { return check_(dynamic_cast(m), err); }; } private: std::function check_; }; static inline std::string String(const ValidationMsg& msg) { return std::string(msg); } static inline bool IsPrefix(const string& maybe_prefix, const string& search_in) { return search_in.compare(0, maybe_prefix.size(), maybe_prefix) == 0; } static inline bool IsSuffix(const string& maybe_suffix, const string& search_in) { return maybe_suffix.size() <= search_in.size() && search_in.compare(search_in.size() - maybe_suffix.size(), maybe_suffix.size(), maybe_suffix) == 0; } static inline bool Contains(const string& search_in, const string& to_find) { return search_in.find(to_find) != string::npos; } static inline bool NotContains(const string& search_in, const string& to_find) { return !Contains(search_in, to_find); } static inline bool IsIpv4(const string& to_validate) { struct sockaddr_in sa; return !(inet_pton(AF_INET, to_validate.c_str(), &sa.sin_addr) < 1); } static inline bool IsIpv6(const string& to_validate) { struct sockaddr_in6 sa_six; return !(inet_pton(AF_INET6, to_validate.c_str(), &sa_six.sin6_addr) < 1); } static inline bool IsIp(const string& to_validate) { return IsIpv4(to_validate) || IsIpv6(to_validate); } static inline bool IsHostname(const string& to_validate) { if (to_validate.length() > 253) { return false; } const std::regex dot_regex{"\\."}; const auto iter_end = std::sregex_token_iterator(); auto iter = std::sregex_token_iterator(to_validate.begin(), to_validate.end(), dot_regex, -1); for (; iter != iter_end; ++iter) { const std::string& part = *iter; if (part.empty() || part.length() > 63) { return false; } if (part.at(0) == '-') { return false; } if (part.at(part.length() - 1) == '-') { return false; } for (const auto& character : part) { if ((character < 'A' || character > 'Z') && (character < 'a' || character > 'z') && (character < '0' || character > '9') && character != '-') { return false; } } } return true; } namespace { inline int OneCharLen(const char* src) { return "\1\1\1\1\1\1\1\1\1\1\1\1\2\2\3\4"[(*src & 0xFF) >> 4]; } inline int UTF8FirstLetterNumBytes(const char *utf8_str, int str_len) { if (str_len == 0) return 0; return OneCharLen(utf8_str); } inline size_t Utf8Len(const string& narrow_string) { const char* str_char = narrow_string.c_str(); ptrdiff_t byte_len = narrow_string.length(); size_t unicode_len = 0; int char_len = 1; while (byte_len > 0 && char_len > 0) { char_len = UTF8FirstLetterNumBytes(str_char, byte_len); str_char += char_len; byte_len -= char_len; ++unicode_len; } return unicode_len; } } // namespace } // namespace pgv #endif // _VALIDATE_H protoc-gen-validate-1.0.2/validate/validate.pb.go000066400000000000000000004267671444536353100217250ustar00rootroot00000000000000// Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 // protoc v4.22.2 // source: validate/validate.proto package validate import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" descriptorpb "google.golang.org/protobuf/types/descriptorpb" durationpb "google.golang.org/protobuf/types/known/durationpb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // WellKnownRegex contain some well-known patterns. type KnownRegex int32 const ( KnownRegex_UNKNOWN KnownRegex = 0 // HTTP header name as defined by RFC 7230. KnownRegex_HTTP_HEADER_NAME KnownRegex = 1 // HTTP header value as defined by RFC 7230. KnownRegex_HTTP_HEADER_VALUE KnownRegex = 2 ) // Enum value maps for KnownRegex. var ( KnownRegex_name = map[int32]string{ 0: "UNKNOWN", 1: "HTTP_HEADER_NAME", 2: "HTTP_HEADER_VALUE", } KnownRegex_value = map[string]int32{ "UNKNOWN": 0, "HTTP_HEADER_NAME": 1, "HTTP_HEADER_VALUE": 2, } ) func (x KnownRegex) Enum() *KnownRegex { p := new(KnownRegex) *p = x return p } func (x KnownRegex) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (KnownRegex) Descriptor() protoreflect.EnumDescriptor { return file_validate_validate_proto_enumTypes[0].Descriptor() } func (KnownRegex) Type() protoreflect.EnumType { return &file_validate_validate_proto_enumTypes[0] } func (x KnownRegex) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *KnownRegex) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = KnownRegex(num) return nil } // Deprecated: Use KnownRegex.Descriptor instead. func (KnownRegex) EnumDescriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{0} } // FieldRules encapsulates the rules for each type of field. Depending on the // field, the correct set should be used to ensure proper validations. type FieldRules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Message *MessageRules `protobuf:"bytes,17,opt,name=message" json:"message,omitempty"` // Types that are assignable to Type: // // *FieldRules_Float // *FieldRules_Double // *FieldRules_Int32 // *FieldRules_Int64 // *FieldRules_Uint32 // *FieldRules_Uint64 // *FieldRules_Sint32 // *FieldRules_Sint64 // *FieldRules_Fixed32 // *FieldRules_Fixed64 // *FieldRules_Sfixed32 // *FieldRules_Sfixed64 // *FieldRules_Bool // *FieldRules_String_ // *FieldRules_Bytes // *FieldRules_Enum // *FieldRules_Repeated // *FieldRules_Map // *FieldRules_Any // *FieldRules_Duration // *FieldRules_Timestamp Type isFieldRules_Type `protobuf_oneof:"type"` } func (x *FieldRules) Reset() { *x = FieldRules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FieldRules) String() string { return protoimpl.X.MessageStringOf(x) } func (*FieldRules) ProtoMessage() {} func (x *FieldRules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use FieldRules.ProtoReflect.Descriptor instead. func (*FieldRules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{0} } func (x *FieldRules) GetMessage() *MessageRules { if x != nil { return x.Message } return nil } func (m *FieldRules) GetType() isFieldRules_Type { if m != nil { return m.Type } return nil } func (x *FieldRules) GetFloat() *FloatRules { if x, ok := x.GetType().(*FieldRules_Float); ok { return x.Float } return nil } func (x *FieldRules) GetDouble() *DoubleRules { if x, ok := x.GetType().(*FieldRules_Double); ok { return x.Double } return nil } func (x *FieldRules) GetInt32() *Int32Rules { if x, ok := x.GetType().(*FieldRules_Int32); ok { return x.Int32 } return nil } func (x *FieldRules) GetInt64() *Int64Rules { if x, ok := x.GetType().(*FieldRules_Int64); ok { return x.Int64 } return nil } func (x *FieldRules) GetUint32() *UInt32Rules { if x, ok := x.GetType().(*FieldRules_Uint32); ok { return x.Uint32 } return nil } func (x *FieldRules) GetUint64() *UInt64Rules { if x, ok := x.GetType().(*FieldRules_Uint64); ok { return x.Uint64 } return nil } func (x *FieldRules) GetSint32() *SInt32Rules { if x, ok := x.GetType().(*FieldRules_Sint32); ok { return x.Sint32 } return nil } func (x *FieldRules) GetSint64() *SInt64Rules { if x, ok := x.GetType().(*FieldRules_Sint64); ok { return x.Sint64 } return nil } func (x *FieldRules) GetFixed32() *Fixed32Rules { if x, ok := x.GetType().(*FieldRules_Fixed32); ok { return x.Fixed32 } return nil } func (x *FieldRules) GetFixed64() *Fixed64Rules { if x, ok := x.GetType().(*FieldRules_Fixed64); ok { return x.Fixed64 } return nil } func (x *FieldRules) GetSfixed32() *SFixed32Rules { if x, ok := x.GetType().(*FieldRules_Sfixed32); ok { return x.Sfixed32 } return nil } func (x *FieldRules) GetSfixed64() *SFixed64Rules { if x, ok := x.GetType().(*FieldRules_Sfixed64); ok { return x.Sfixed64 } return nil } func (x *FieldRules) GetBool() *BoolRules { if x, ok := x.GetType().(*FieldRules_Bool); ok { return x.Bool } return nil } func (x *FieldRules) GetString_() *StringRules { if x, ok := x.GetType().(*FieldRules_String_); ok { return x.String_ } return nil } func (x *FieldRules) GetBytes() *BytesRules { if x, ok := x.GetType().(*FieldRules_Bytes); ok { return x.Bytes } return nil } func (x *FieldRules) GetEnum() *EnumRules { if x, ok := x.GetType().(*FieldRules_Enum); ok { return x.Enum } return nil } func (x *FieldRules) GetRepeated() *RepeatedRules { if x, ok := x.GetType().(*FieldRules_Repeated); ok { return x.Repeated } return nil } func (x *FieldRules) GetMap() *MapRules { if x, ok := x.GetType().(*FieldRules_Map); ok { return x.Map } return nil } func (x *FieldRules) GetAny() *AnyRules { if x, ok := x.GetType().(*FieldRules_Any); ok { return x.Any } return nil } func (x *FieldRules) GetDuration() *DurationRules { if x, ok := x.GetType().(*FieldRules_Duration); ok { return x.Duration } return nil } func (x *FieldRules) GetTimestamp() *TimestampRules { if x, ok := x.GetType().(*FieldRules_Timestamp); ok { return x.Timestamp } return nil } type isFieldRules_Type interface { isFieldRules_Type() } type FieldRules_Float struct { // Scalar Field Types Float *FloatRules `protobuf:"bytes,1,opt,name=float,oneof"` } type FieldRules_Double struct { Double *DoubleRules `protobuf:"bytes,2,opt,name=double,oneof"` } type FieldRules_Int32 struct { Int32 *Int32Rules `protobuf:"bytes,3,opt,name=int32,oneof"` } type FieldRules_Int64 struct { Int64 *Int64Rules `protobuf:"bytes,4,opt,name=int64,oneof"` } type FieldRules_Uint32 struct { Uint32 *UInt32Rules `protobuf:"bytes,5,opt,name=uint32,oneof"` } type FieldRules_Uint64 struct { Uint64 *UInt64Rules `protobuf:"bytes,6,opt,name=uint64,oneof"` } type FieldRules_Sint32 struct { Sint32 *SInt32Rules `protobuf:"bytes,7,opt,name=sint32,oneof"` } type FieldRules_Sint64 struct { Sint64 *SInt64Rules `protobuf:"bytes,8,opt,name=sint64,oneof"` } type FieldRules_Fixed32 struct { Fixed32 *Fixed32Rules `protobuf:"bytes,9,opt,name=fixed32,oneof"` } type FieldRules_Fixed64 struct { Fixed64 *Fixed64Rules `protobuf:"bytes,10,opt,name=fixed64,oneof"` } type FieldRules_Sfixed32 struct { Sfixed32 *SFixed32Rules `protobuf:"bytes,11,opt,name=sfixed32,oneof"` } type FieldRules_Sfixed64 struct { Sfixed64 *SFixed64Rules `protobuf:"bytes,12,opt,name=sfixed64,oneof"` } type FieldRules_Bool struct { Bool *BoolRules `protobuf:"bytes,13,opt,name=bool,oneof"` } type FieldRules_String_ struct { String_ *StringRules `protobuf:"bytes,14,opt,name=string,oneof"` } type FieldRules_Bytes struct { Bytes *BytesRules `protobuf:"bytes,15,opt,name=bytes,oneof"` } type FieldRules_Enum struct { // Complex Field Types Enum *EnumRules `protobuf:"bytes,16,opt,name=enum,oneof"` } type FieldRules_Repeated struct { Repeated *RepeatedRules `protobuf:"bytes,18,opt,name=repeated,oneof"` } type FieldRules_Map struct { Map *MapRules `protobuf:"bytes,19,opt,name=map,oneof"` } type FieldRules_Any struct { // Well-Known Field Types Any *AnyRules `protobuf:"bytes,20,opt,name=any,oneof"` } type FieldRules_Duration struct { Duration *DurationRules `protobuf:"bytes,21,opt,name=duration,oneof"` } type FieldRules_Timestamp struct { Timestamp *TimestampRules `protobuf:"bytes,22,opt,name=timestamp,oneof"` } func (*FieldRules_Float) isFieldRules_Type() {} func (*FieldRules_Double) isFieldRules_Type() {} func (*FieldRules_Int32) isFieldRules_Type() {} func (*FieldRules_Int64) isFieldRules_Type() {} func (*FieldRules_Uint32) isFieldRules_Type() {} func (*FieldRules_Uint64) isFieldRules_Type() {} func (*FieldRules_Sint32) isFieldRules_Type() {} func (*FieldRules_Sint64) isFieldRules_Type() {} func (*FieldRules_Fixed32) isFieldRules_Type() {} func (*FieldRules_Fixed64) isFieldRules_Type() {} func (*FieldRules_Sfixed32) isFieldRules_Type() {} func (*FieldRules_Sfixed64) isFieldRules_Type() {} func (*FieldRules_Bool) isFieldRules_Type() {} func (*FieldRules_String_) isFieldRules_Type() {} func (*FieldRules_Bytes) isFieldRules_Type() {} func (*FieldRules_Enum) isFieldRules_Type() {} func (*FieldRules_Repeated) isFieldRules_Type() {} func (*FieldRules_Map) isFieldRules_Type() {} func (*FieldRules_Any) isFieldRules_Type() {} func (*FieldRules_Duration) isFieldRules_Type() {} func (*FieldRules_Timestamp) isFieldRules_Type() {} // FloatRules describes the constraints applied to `float` values type FloatRules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *float32 `protobuf:"fixed32,1,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *float32 `protobuf:"fixed32,2,opt,name=lt" json:"lt,omitempty"` // Lte specifies that this field must be less than or equal to the // specified value, inclusive Lte *float32 `protobuf:"fixed32,3,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. Gt *float32 `protobuf:"fixed32,4,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. Gte *float32 `protobuf:"fixed32,5,opt,name=gte" json:"gte,omitempty"` // In specifies that this field must be equal to one of the specified // values In []float32 `protobuf:"fixed32,6,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []float32 `protobuf:"fixed32,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *FloatRules) Reset() { *x = FloatRules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FloatRules) String() string { return protoimpl.X.MessageStringOf(x) } func (*FloatRules) ProtoMessage() {} func (x *FloatRules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use FloatRules.ProtoReflect.Descriptor instead. func (*FloatRules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{1} } func (x *FloatRules) GetConst() float32 { if x != nil && x.Const != nil { return *x.Const } return 0 } func (x *FloatRules) GetLt() float32 { if x != nil && x.Lt != nil { return *x.Lt } return 0 } func (x *FloatRules) GetLte() float32 { if x != nil && x.Lte != nil { return *x.Lte } return 0 } func (x *FloatRules) GetGt() float32 { if x != nil && x.Gt != nil { return *x.Gt } return 0 } func (x *FloatRules) GetGte() float32 { if x != nil && x.Gte != nil { return *x.Gte } return 0 } func (x *FloatRules) GetIn() []float32 { if x != nil { return x.In } return nil } func (x *FloatRules) GetNotIn() []float32 { if x != nil { return x.NotIn } return nil } func (x *FloatRules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // DoubleRules describes the constraints applied to `double` values type DoubleRules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *float64 `protobuf:"fixed64,1,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *float64 `protobuf:"fixed64,2,opt,name=lt" json:"lt,omitempty"` // Lte specifies that this field must be less than or equal to the // specified value, inclusive Lte *float64 `protobuf:"fixed64,3,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. Gt *float64 `protobuf:"fixed64,4,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. Gte *float64 `protobuf:"fixed64,5,opt,name=gte" json:"gte,omitempty"` // In specifies that this field must be equal to one of the specified // values In []float64 `protobuf:"fixed64,6,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []float64 `protobuf:"fixed64,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *DoubleRules) Reset() { *x = DoubleRules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DoubleRules) String() string { return protoimpl.X.MessageStringOf(x) } func (*DoubleRules) ProtoMessage() {} func (x *DoubleRules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use DoubleRules.ProtoReflect.Descriptor instead. func (*DoubleRules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{2} } func (x *DoubleRules) GetConst() float64 { if x != nil && x.Const != nil { return *x.Const } return 0 } func (x *DoubleRules) GetLt() float64 { if x != nil && x.Lt != nil { return *x.Lt } return 0 } func (x *DoubleRules) GetLte() float64 { if x != nil && x.Lte != nil { return *x.Lte } return 0 } func (x *DoubleRules) GetGt() float64 { if x != nil && x.Gt != nil { return *x.Gt } return 0 } func (x *DoubleRules) GetGte() float64 { if x != nil && x.Gte != nil { return *x.Gte } return 0 } func (x *DoubleRules) GetIn() []float64 { if x != nil { return x.In } return nil } func (x *DoubleRules) GetNotIn() []float64 { if x != nil { return x.NotIn } return nil } func (x *DoubleRules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // Int32Rules describes the constraints applied to `int32` values type Int32Rules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *int32 `protobuf:"varint,1,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *int32 `protobuf:"varint,2,opt,name=lt" json:"lt,omitempty"` // Lte specifies that this field must be less than or equal to the // specified value, inclusive Lte *int32 `protobuf:"varint,3,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. Gt *int32 `protobuf:"varint,4,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. Gte *int32 `protobuf:"varint,5,opt,name=gte" json:"gte,omitempty"` // In specifies that this field must be equal to one of the specified // values In []int32 `protobuf:"varint,6,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []int32 `protobuf:"varint,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *Int32Rules) Reset() { *x = Int32Rules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Int32Rules) String() string { return protoimpl.X.MessageStringOf(x) } func (*Int32Rules) ProtoMessage() {} func (x *Int32Rules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Int32Rules.ProtoReflect.Descriptor instead. func (*Int32Rules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{3} } func (x *Int32Rules) GetConst() int32 { if x != nil && x.Const != nil { return *x.Const } return 0 } func (x *Int32Rules) GetLt() int32 { if x != nil && x.Lt != nil { return *x.Lt } return 0 } func (x *Int32Rules) GetLte() int32 { if x != nil && x.Lte != nil { return *x.Lte } return 0 } func (x *Int32Rules) GetGt() int32 { if x != nil && x.Gt != nil { return *x.Gt } return 0 } func (x *Int32Rules) GetGte() int32 { if x != nil && x.Gte != nil { return *x.Gte } return 0 } func (x *Int32Rules) GetIn() []int32 { if x != nil { return x.In } return nil } func (x *Int32Rules) GetNotIn() []int32 { if x != nil { return x.NotIn } return nil } func (x *Int32Rules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // Int64Rules describes the constraints applied to `int64` values type Int64Rules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *int64 `protobuf:"varint,1,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *int64 `protobuf:"varint,2,opt,name=lt" json:"lt,omitempty"` // Lte specifies that this field must be less than or equal to the // specified value, inclusive Lte *int64 `protobuf:"varint,3,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. Gt *int64 `protobuf:"varint,4,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. Gte *int64 `protobuf:"varint,5,opt,name=gte" json:"gte,omitempty"` // In specifies that this field must be equal to one of the specified // values In []int64 `protobuf:"varint,6,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []int64 `protobuf:"varint,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *Int64Rules) Reset() { *x = Int64Rules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Int64Rules) String() string { return protoimpl.X.MessageStringOf(x) } func (*Int64Rules) ProtoMessage() {} func (x *Int64Rules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Int64Rules.ProtoReflect.Descriptor instead. func (*Int64Rules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{4} } func (x *Int64Rules) GetConst() int64 { if x != nil && x.Const != nil { return *x.Const } return 0 } func (x *Int64Rules) GetLt() int64 { if x != nil && x.Lt != nil { return *x.Lt } return 0 } func (x *Int64Rules) GetLte() int64 { if x != nil && x.Lte != nil { return *x.Lte } return 0 } func (x *Int64Rules) GetGt() int64 { if x != nil && x.Gt != nil { return *x.Gt } return 0 } func (x *Int64Rules) GetGte() int64 { if x != nil && x.Gte != nil { return *x.Gte } return 0 } func (x *Int64Rules) GetIn() []int64 { if x != nil { return x.In } return nil } func (x *Int64Rules) GetNotIn() []int64 { if x != nil { return x.NotIn } return nil } func (x *Int64Rules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // UInt32Rules describes the constraints applied to `uint32` values type UInt32Rules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *uint32 `protobuf:"varint,1,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *uint32 `protobuf:"varint,2,opt,name=lt" json:"lt,omitempty"` // Lte specifies that this field must be less than or equal to the // specified value, inclusive Lte *uint32 `protobuf:"varint,3,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. Gt *uint32 `protobuf:"varint,4,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. Gte *uint32 `protobuf:"varint,5,opt,name=gte" json:"gte,omitempty"` // In specifies that this field must be equal to one of the specified // values In []uint32 `protobuf:"varint,6,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []uint32 `protobuf:"varint,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *UInt32Rules) Reset() { *x = UInt32Rules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *UInt32Rules) String() string { return protoimpl.X.MessageStringOf(x) } func (*UInt32Rules) ProtoMessage() {} func (x *UInt32Rules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use UInt32Rules.ProtoReflect.Descriptor instead. func (*UInt32Rules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{5} } func (x *UInt32Rules) GetConst() uint32 { if x != nil && x.Const != nil { return *x.Const } return 0 } func (x *UInt32Rules) GetLt() uint32 { if x != nil && x.Lt != nil { return *x.Lt } return 0 } func (x *UInt32Rules) GetLte() uint32 { if x != nil && x.Lte != nil { return *x.Lte } return 0 } func (x *UInt32Rules) GetGt() uint32 { if x != nil && x.Gt != nil { return *x.Gt } return 0 } func (x *UInt32Rules) GetGte() uint32 { if x != nil && x.Gte != nil { return *x.Gte } return 0 } func (x *UInt32Rules) GetIn() []uint32 { if x != nil { return x.In } return nil } func (x *UInt32Rules) GetNotIn() []uint32 { if x != nil { return x.NotIn } return nil } func (x *UInt32Rules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // UInt64Rules describes the constraints applied to `uint64` values type UInt64Rules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *uint64 `protobuf:"varint,1,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *uint64 `protobuf:"varint,2,opt,name=lt" json:"lt,omitempty"` // Lte specifies that this field must be less than or equal to the // specified value, inclusive Lte *uint64 `protobuf:"varint,3,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. Gt *uint64 `protobuf:"varint,4,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. Gte *uint64 `protobuf:"varint,5,opt,name=gte" json:"gte,omitempty"` // In specifies that this field must be equal to one of the specified // values In []uint64 `protobuf:"varint,6,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []uint64 `protobuf:"varint,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *UInt64Rules) Reset() { *x = UInt64Rules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *UInt64Rules) String() string { return protoimpl.X.MessageStringOf(x) } func (*UInt64Rules) ProtoMessage() {} func (x *UInt64Rules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use UInt64Rules.ProtoReflect.Descriptor instead. func (*UInt64Rules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{6} } func (x *UInt64Rules) GetConst() uint64 { if x != nil && x.Const != nil { return *x.Const } return 0 } func (x *UInt64Rules) GetLt() uint64 { if x != nil && x.Lt != nil { return *x.Lt } return 0 } func (x *UInt64Rules) GetLte() uint64 { if x != nil && x.Lte != nil { return *x.Lte } return 0 } func (x *UInt64Rules) GetGt() uint64 { if x != nil && x.Gt != nil { return *x.Gt } return 0 } func (x *UInt64Rules) GetGte() uint64 { if x != nil && x.Gte != nil { return *x.Gte } return 0 } func (x *UInt64Rules) GetIn() []uint64 { if x != nil { return x.In } return nil } func (x *UInt64Rules) GetNotIn() []uint64 { if x != nil { return x.NotIn } return nil } func (x *UInt64Rules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // SInt32Rules describes the constraints applied to `sint32` values type SInt32Rules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *int32 `protobuf:"zigzag32,1,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *int32 `protobuf:"zigzag32,2,opt,name=lt" json:"lt,omitempty"` // Lte specifies that this field must be less than or equal to the // specified value, inclusive Lte *int32 `protobuf:"zigzag32,3,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. Gt *int32 `protobuf:"zigzag32,4,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. Gte *int32 `protobuf:"zigzag32,5,opt,name=gte" json:"gte,omitempty"` // In specifies that this field must be equal to one of the specified // values In []int32 `protobuf:"zigzag32,6,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []int32 `protobuf:"zigzag32,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *SInt32Rules) Reset() { *x = SInt32Rules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SInt32Rules) String() string { return protoimpl.X.MessageStringOf(x) } func (*SInt32Rules) ProtoMessage() {} func (x *SInt32Rules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use SInt32Rules.ProtoReflect.Descriptor instead. func (*SInt32Rules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{7} } func (x *SInt32Rules) GetConst() int32 { if x != nil && x.Const != nil { return *x.Const } return 0 } func (x *SInt32Rules) GetLt() int32 { if x != nil && x.Lt != nil { return *x.Lt } return 0 } func (x *SInt32Rules) GetLte() int32 { if x != nil && x.Lte != nil { return *x.Lte } return 0 } func (x *SInt32Rules) GetGt() int32 { if x != nil && x.Gt != nil { return *x.Gt } return 0 } func (x *SInt32Rules) GetGte() int32 { if x != nil && x.Gte != nil { return *x.Gte } return 0 } func (x *SInt32Rules) GetIn() []int32 { if x != nil { return x.In } return nil } func (x *SInt32Rules) GetNotIn() []int32 { if x != nil { return x.NotIn } return nil } func (x *SInt32Rules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // SInt64Rules describes the constraints applied to `sint64` values type SInt64Rules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *int64 `protobuf:"zigzag64,1,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *int64 `protobuf:"zigzag64,2,opt,name=lt" json:"lt,omitempty"` // Lte specifies that this field must be less than or equal to the // specified value, inclusive Lte *int64 `protobuf:"zigzag64,3,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. Gt *int64 `protobuf:"zigzag64,4,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. Gte *int64 `protobuf:"zigzag64,5,opt,name=gte" json:"gte,omitempty"` // In specifies that this field must be equal to one of the specified // values In []int64 `protobuf:"zigzag64,6,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []int64 `protobuf:"zigzag64,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *SInt64Rules) Reset() { *x = SInt64Rules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SInt64Rules) String() string { return protoimpl.X.MessageStringOf(x) } func (*SInt64Rules) ProtoMessage() {} func (x *SInt64Rules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use SInt64Rules.ProtoReflect.Descriptor instead. func (*SInt64Rules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{8} } func (x *SInt64Rules) GetConst() int64 { if x != nil && x.Const != nil { return *x.Const } return 0 } func (x *SInt64Rules) GetLt() int64 { if x != nil && x.Lt != nil { return *x.Lt } return 0 } func (x *SInt64Rules) GetLte() int64 { if x != nil && x.Lte != nil { return *x.Lte } return 0 } func (x *SInt64Rules) GetGt() int64 { if x != nil && x.Gt != nil { return *x.Gt } return 0 } func (x *SInt64Rules) GetGte() int64 { if x != nil && x.Gte != nil { return *x.Gte } return 0 } func (x *SInt64Rules) GetIn() []int64 { if x != nil { return x.In } return nil } func (x *SInt64Rules) GetNotIn() []int64 { if x != nil { return x.NotIn } return nil } func (x *SInt64Rules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // Fixed32Rules describes the constraints applied to `fixed32` values type Fixed32Rules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *uint32 `protobuf:"fixed32,1,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *uint32 `protobuf:"fixed32,2,opt,name=lt" json:"lt,omitempty"` // Lte specifies that this field must be less than or equal to the // specified value, inclusive Lte *uint32 `protobuf:"fixed32,3,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. Gt *uint32 `protobuf:"fixed32,4,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. Gte *uint32 `protobuf:"fixed32,5,opt,name=gte" json:"gte,omitempty"` // In specifies that this field must be equal to one of the specified // values In []uint32 `protobuf:"fixed32,6,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []uint32 `protobuf:"fixed32,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *Fixed32Rules) Reset() { *x = Fixed32Rules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Fixed32Rules) String() string { return protoimpl.X.MessageStringOf(x) } func (*Fixed32Rules) ProtoMessage() {} func (x *Fixed32Rules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Fixed32Rules.ProtoReflect.Descriptor instead. func (*Fixed32Rules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{9} } func (x *Fixed32Rules) GetConst() uint32 { if x != nil && x.Const != nil { return *x.Const } return 0 } func (x *Fixed32Rules) GetLt() uint32 { if x != nil && x.Lt != nil { return *x.Lt } return 0 } func (x *Fixed32Rules) GetLte() uint32 { if x != nil && x.Lte != nil { return *x.Lte } return 0 } func (x *Fixed32Rules) GetGt() uint32 { if x != nil && x.Gt != nil { return *x.Gt } return 0 } func (x *Fixed32Rules) GetGte() uint32 { if x != nil && x.Gte != nil { return *x.Gte } return 0 } func (x *Fixed32Rules) GetIn() []uint32 { if x != nil { return x.In } return nil } func (x *Fixed32Rules) GetNotIn() []uint32 { if x != nil { return x.NotIn } return nil } func (x *Fixed32Rules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // Fixed64Rules describes the constraints applied to `fixed64` values type Fixed64Rules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *uint64 `protobuf:"fixed64,1,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *uint64 `protobuf:"fixed64,2,opt,name=lt" json:"lt,omitempty"` // Lte specifies that this field must be less than or equal to the // specified value, inclusive Lte *uint64 `protobuf:"fixed64,3,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. Gt *uint64 `protobuf:"fixed64,4,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. Gte *uint64 `protobuf:"fixed64,5,opt,name=gte" json:"gte,omitempty"` // In specifies that this field must be equal to one of the specified // values In []uint64 `protobuf:"fixed64,6,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []uint64 `protobuf:"fixed64,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *Fixed64Rules) Reset() { *x = Fixed64Rules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Fixed64Rules) String() string { return protoimpl.X.MessageStringOf(x) } func (*Fixed64Rules) ProtoMessage() {} func (x *Fixed64Rules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Fixed64Rules.ProtoReflect.Descriptor instead. func (*Fixed64Rules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{10} } func (x *Fixed64Rules) GetConst() uint64 { if x != nil && x.Const != nil { return *x.Const } return 0 } func (x *Fixed64Rules) GetLt() uint64 { if x != nil && x.Lt != nil { return *x.Lt } return 0 } func (x *Fixed64Rules) GetLte() uint64 { if x != nil && x.Lte != nil { return *x.Lte } return 0 } func (x *Fixed64Rules) GetGt() uint64 { if x != nil && x.Gt != nil { return *x.Gt } return 0 } func (x *Fixed64Rules) GetGte() uint64 { if x != nil && x.Gte != nil { return *x.Gte } return 0 } func (x *Fixed64Rules) GetIn() []uint64 { if x != nil { return x.In } return nil } func (x *Fixed64Rules) GetNotIn() []uint64 { if x != nil { return x.NotIn } return nil } func (x *Fixed64Rules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // SFixed32Rules describes the constraints applied to `sfixed32` values type SFixed32Rules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *int32 `protobuf:"fixed32,1,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *int32 `protobuf:"fixed32,2,opt,name=lt" json:"lt,omitempty"` // Lte specifies that this field must be less than or equal to the // specified value, inclusive Lte *int32 `protobuf:"fixed32,3,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. Gt *int32 `protobuf:"fixed32,4,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. Gte *int32 `protobuf:"fixed32,5,opt,name=gte" json:"gte,omitempty"` // In specifies that this field must be equal to one of the specified // values In []int32 `protobuf:"fixed32,6,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []int32 `protobuf:"fixed32,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *SFixed32Rules) Reset() { *x = SFixed32Rules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SFixed32Rules) String() string { return protoimpl.X.MessageStringOf(x) } func (*SFixed32Rules) ProtoMessage() {} func (x *SFixed32Rules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use SFixed32Rules.ProtoReflect.Descriptor instead. func (*SFixed32Rules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{11} } func (x *SFixed32Rules) GetConst() int32 { if x != nil && x.Const != nil { return *x.Const } return 0 } func (x *SFixed32Rules) GetLt() int32 { if x != nil && x.Lt != nil { return *x.Lt } return 0 } func (x *SFixed32Rules) GetLte() int32 { if x != nil && x.Lte != nil { return *x.Lte } return 0 } func (x *SFixed32Rules) GetGt() int32 { if x != nil && x.Gt != nil { return *x.Gt } return 0 } func (x *SFixed32Rules) GetGte() int32 { if x != nil && x.Gte != nil { return *x.Gte } return 0 } func (x *SFixed32Rules) GetIn() []int32 { if x != nil { return x.In } return nil } func (x *SFixed32Rules) GetNotIn() []int32 { if x != nil { return x.NotIn } return nil } func (x *SFixed32Rules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // SFixed64Rules describes the constraints applied to `sfixed64` values type SFixed64Rules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *int64 `protobuf:"fixed64,1,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *int64 `protobuf:"fixed64,2,opt,name=lt" json:"lt,omitempty"` // Lte specifies that this field must be less than or equal to the // specified value, inclusive Lte *int64 `protobuf:"fixed64,3,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. Gt *int64 `protobuf:"fixed64,4,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. Gte *int64 `protobuf:"fixed64,5,opt,name=gte" json:"gte,omitempty"` // In specifies that this field must be equal to one of the specified // values In []int64 `protobuf:"fixed64,6,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []int64 `protobuf:"fixed64,7,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,8,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *SFixed64Rules) Reset() { *x = SFixed64Rules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SFixed64Rules) String() string { return protoimpl.X.MessageStringOf(x) } func (*SFixed64Rules) ProtoMessage() {} func (x *SFixed64Rules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use SFixed64Rules.ProtoReflect.Descriptor instead. func (*SFixed64Rules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{12} } func (x *SFixed64Rules) GetConst() int64 { if x != nil && x.Const != nil { return *x.Const } return 0 } func (x *SFixed64Rules) GetLt() int64 { if x != nil && x.Lt != nil { return *x.Lt } return 0 } func (x *SFixed64Rules) GetLte() int64 { if x != nil && x.Lte != nil { return *x.Lte } return 0 } func (x *SFixed64Rules) GetGt() int64 { if x != nil && x.Gt != nil { return *x.Gt } return 0 } func (x *SFixed64Rules) GetGte() int64 { if x != nil && x.Gte != nil { return *x.Gte } return 0 } func (x *SFixed64Rules) GetIn() []int64 { if x != nil { return x.In } return nil } func (x *SFixed64Rules) GetNotIn() []int64 { if x != nil { return x.NotIn } return nil } func (x *SFixed64Rules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // BoolRules describes the constraints applied to `bool` values type BoolRules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *bool `protobuf:"varint,1,opt,name=const" json:"const,omitempty"` } func (x *BoolRules) Reset() { *x = BoolRules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *BoolRules) String() string { return protoimpl.X.MessageStringOf(x) } func (*BoolRules) ProtoMessage() {} func (x *BoolRules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use BoolRules.ProtoReflect.Descriptor instead. func (*BoolRules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{13} } func (x *BoolRules) GetConst() bool { if x != nil && x.Const != nil { return *x.Const } return false } // StringRules describe the constraints applied to `string` values type StringRules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *string `protobuf:"bytes,1,opt,name=const" json:"const,omitempty"` // Len specifies that this field must be the specified number of // characters (Unicode code points). Note that the number of // characters may differ from the number of bytes in the string. Len *uint64 `protobuf:"varint,19,opt,name=len" json:"len,omitempty"` // MinLen specifies that this field must be the specified number of // characters (Unicode code points) at a minimum. Note that the number of // characters may differ from the number of bytes in the string. MinLen *uint64 `protobuf:"varint,2,opt,name=min_len,json=minLen" json:"min_len,omitempty"` // MaxLen specifies that this field must be the specified number of // characters (Unicode code points) at a maximum. Note that the number of // characters may differ from the number of bytes in the string. MaxLen *uint64 `protobuf:"varint,3,opt,name=max_len,json=maxLen" json:"max_len,omitempty"` // LenBytes specifies that this field must be the specified number of bytes LenBytes *uint64 `protobuf:"varint,20,opt,name=len_bytes,json=lenBytes" json:"len_bytes,omitempty"` // MinBytes specifies that this field must be the specified number of bytes // at a minimum MinBytes *uint64 `protobuf:"varint,4,opt,name=min_bytes,json=minBytes" json:"min_bytes,omitempty"` // MaxBytes specifies that this field must be the specified number of bytes // at a maximum MaxBytes *uint64 `protobuf:"varint,5,opt,name=max_bytes,json=maxBytes" json:"max_bytes,omitempty"` // Pattern specifes that this field must match against the specified // regular expression (RE2 syntax). The included expression should elide // any delimiters. Pattern *string `protobuf:"bytes,6,opt,name=pattern" json:"pattern,omitempty"` // Prefix specifies that this field must have the specified substring at // the beginning of the string. Prefix *string `protobuf:"bytes,7,opt,name=prefix" json:"prefix,omitempty"` // Suffix specifies that this field must have the specified substring at // the end of the string. Suffix *string `protobuf:"bytes,8,opt,name=suffix" json:"suffix,omitempty"` // Contains specifies that this field must have the specified substring // anywhere in the string. Contains *string `protobuf:"bytes,9,opt,name=contains" json:"contains,omitempty"` // NotContains specifies that this field cannot have the specified substring // anywhere in the string. NotContains *string `protobuf:"bytes,23,opt,name=not_contains,json=notContains" json:"not_contains,omitempty"` // In specifies that this field must be equal to one of the specified // values In []string `protobuf:"bytes,10,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []string `protobuf:"bytes,11,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // WellKnown rules provide advanced constraints against common string // patterns // // Types that are assignable to WellKnown: // // *StringRules_Email // *StringRules_Hostname // *StringRules_Ip // *StringRules_Ipv4 // *StringRules_Ipv6 // *StringRules_Uri // *StringRules_UriRef // *StringRules_Address // *StringRules_Uuid // *StringRules_WellKnownRegex WellKnown isStringRules_WellKnown `protobuf_oneof:"well_known"` // This applies to regexes HTTP_HEADER_NAME and HTTP_HEADER_VALUE to enable // strict header validation. // By default, this is true, and HTTP header validations are RFC-compliant. // Setting to false will enable a looser validations that only disallows // \r\n\0 characters, which can be used to bypass header matching rules. Strict *bool `protobuf:"varint,25,opt,name=strict,def=1" json:"strict,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,26,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } // Default values for StringRules fields. const ( Default_StringRules_Strict = bool(true) ) func (x *StringRules) Reset() { *x = StringRules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *StringRules) String() string { return protoimpl.X.MessageStringOf(x) } func (*StringRules) ProtoMessage() {} func (x *StringRules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use StringRules.ProtoReflect.Descriptor instead. func (*StringRules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{14} } func (x *StringRules) GetConst() string { if x != nil && x.Const != nil { return *x.Const } return "" } func (x *StringRules) GetLen() uint64 { if x != nil && x.Len != nil { return *x.Len } return 0 } func (x *StringRules) GetMinLen() uint64 { if x != nil && x.MinLen != nil { return *x.MinLen } return 0 } func (x *StringRules) GetMaxLen() uint64 { if x != nil && x.MaxLen != nil { return *x.MaxLen } return 0 } func (x *StringRules) GetLenBytes() uint64 { if x != nil && x.LenBytes != nil { return *x.LenBytes } return 0 } func (x *StringRules) GetMinBytes() uint64 { if x != nil && x.MinBytes != nil { return *x.MinBytes } return 0 } func (x *StringRules) GetMaxBytes() uint64 { if x != nil && x.MaxBytes != nil { return *x.MaxBytes } return 0 } func (x *StringRules) GetPattern() string { if x != nil && x.Pattern != nil { return *x.Pattern } return "" } func (x *StringRules) GetPrefix() string { if x != nil && x.Prefix != nil { return *x.Prefix } return "" } func (x *StringRules) GetSuffix() string { if x != nil && x.Suffix != nil { return *x.Suffix } return "" } func (x *StringRules) GetContains() string { if x != nil && x.Contains != nil { return *x.Contains } return "" } func (x *StringRules) GetNotContains() string { if x != nil && x.NotContains != nil { return *x.NotContains } return "" } func (x *StringRules) GetIn() []string { if x != nil { return x.In } return nil } func (x *StringRules) GetNotIn() []string { if x != nil { return x.NotIn } return nil } func (m *StringRules) GetWellKnown() isStringRules_WellKnown { if m != nil { return m.WellKnown } return nil } func (x *StringRules) GetEmail() bool { if x, ok := x.GetWellKnown().(*StringRules_Email); ok { return x.Email } return false } func (x *StringRules) GetHostname() bool { if x, ok := x.GetWellKnown().(*StringRules_Hostname); ok { return x.Hostname } return false } func (x *StringRules) GetIp() bool { if x, ok := x.GetWellKnown().(*StringRules_Ip); ok { return x.Ip } return false } func (x *StringRules) GetIpv4() bool { if x, ok := x.GetWellKnown().(*StringRules_Ipv4); ok { return x.Ipv4 } return false } func (x *StringRules) GetIpv6() bool { if x, ok := x.GetWellKnown().(*StringRules_Ipv6); ok { return x.Ipv6 } return false } func (x *StringRules) GetUri() bool { if x, ok := x.GetWellKnown().(*StringRules_Uri); ok { return x.Uri } return false } func (x *StringRules) GetUriRef() bool { if x, ok := x.GetWellKnown().(*StringRules_UriRef); ok { return x.UriRef } return false } func (x *StringRules) GetAddress() bool { if x, ok := x.GetWellKnown().(*StringRules_Address); ok { return x.Address } return false } func (x *StringRules) GetUuid() bool { if x, ok := x.GetWellKnown().(*StringRules_Uuid); ok { return x.Uuid } return false } func (x *StringRules) GetWellKnownRegex() KnownRegex { if x, ok := x.GetWellKnown().(*StringRules_WellKnownRegex); ok { return x.WellKnownRegex } return KnownRegex_UNKNOWN } func (x *StringRules) GetStrict() bool { if x != nil && x.Strict != nil { return *x.Strict } return Default_StringRules_Strict } func (x *StringRules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } type isStringRules_WellKnown interface { isStringRules_WellKnown() } type StringRules_Email struct { // Email specifies that the field must be a valid email address as // defined by RFC 5322 Email bool `protobuf:"varint,12,opt,name=email,oneof"` } type StringRules_Hostname struct { // Hostname specifies that the field must be a valid hostname as // defined by RFC 1034. This constraint does not support // internationalized domain names (IDNs). Hostname bool `protobuf:"varint,13,opt,name=hostname,oneof"` } type StringRules_Ip struct { // Ip specifies that the field must be a valid IP (v4 or v6) address. // Valid IPv6 addresses should not include surrounding square brackets. Ip bool `protobuf:"varint,14,opt,name=ip,oneof"` } type StringRules_Ipv4 struct { // Ipv4 specifies that the field must be a valid IPv4 address. Ipv4 bool `protobuf:"varint,15,opt,name=ipv4,oneof"` } type StringRules_Ipv6 struct { // Ipv6 specifies that the field must be a valid IPv6 address. Valid // IPv6 addresses should not include surrounding square brackets. Ipv6 bool `protobuf:"varint,16,opt,name=ipv6,oneof"` } type StringRules_Uri struct { // Uri specifies that the field must be a valid, absolute URI as defined // by RFC 3986 Uri bool `protobuf:"varint,17,opt,name=uri,oneof"` } type StringRules_UriRef struct { // UriRef specifies that the field must be a valid URI as defined by RFC // 3986 and may be relative or absolute. UriRef bool `protobuf:"varint,18,opt,name=uri_ref,json=uriRef,oneof"` } type StringRules_Address struct { // Address specifies that the field must be either a valid hostname as // defined by RFC 1034 (which does not support internationalized domain // names or IDNs), or it can be a valid IP (v4 or v6). Address bool `protobuf:"varint,21,opt,name=address,oneof"` } type StringRules_Uuid struct { // Uuid specifies that the field must be a valid UUID as defined by // RFC 4122 Uuid bool `protobuf:"varint,22,opt,name=uuid,oneof"` } type StringRules_WellKnownRegex struct { // WellKnownRegex specifies a common well known pattern defined as a regex. WellKnownRegex KnownRegex `protobuf:"varint,24,opt,name=well_known_regex,json=wellKnownRegex,enum=validate.KnownRegex,oneof"` } func (*StringRules_Email) isStringRules_WellKnown() {} func (*StringRules_Hostname) isStringRules_WellKnown() {} func (*StringRules_Ip) isStringRules_WellKnown() {} func (*StringRules_Ipv4) isStringRules_WellKnown() {} func (*StringRules_Ipv6) isStringRules_WellKnown() {} func (*StringRules_Uri) isStringRules_WellKnown() {} func (*StringRules_UriRef) isStringRules_WellKnown() {} func (*StringRules_Address) isStringRules_WellKnown() {} func (*StringRules_Uuid) isStringRules_WellKnown() {} func (*StringRules_WellKnownRegex) isStringRules_WellKnown() {} // BytesRules describe the constraints applied to `bytes` values type BytesRules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const []byte `protobuf:"bytes,1,opt,name=const" json:"const,omitempty"` // Len specifies that this field must be the specified number of bytes Len *uint64 `protobuf:"varint,13,opt,name=len" json:"len,omitempty"` // MinLen specifies that this field must be the specified number of bytes // at a minimum MinLen *uint64 `protobuf:"varint,2,opt,name=min_len,json=minLen" json:"min_len,omitempty"` // MaxLen specifies that this field must be the specified number of bytes // at a maximum MaxLen *uint64 `protobuf:"varint,3,opt,name=max_len,json=maxLen" json:"max_len,omitempty"` // Pattern specifes that this field must match against the specified // regular expression (RE2 syntax). The included expression should elide // any delimiters. Pattern *string `protobuf:"bytes,4,opt,name=pattern" json:"pattern,omitempty"` // Prefix specifies that this field must have the specified bytes at the // beginning of the string. Prefix []byte `protobuf:"bytes,5,opt,name=prefix" json:"prefix,omitempty"` // Suffix specifies that this field must have the specified bytes at the // end of the string. Suffix []byte `protobuf:"bytes,6,opt,name=suffix" json:"suffix,omitempty"` // Contains specifies that this field must have the specified bytes // anywhere in the string. Contains []byte `protobuf:"bytes,7,opt,name=contains" json:"contains,omitempty"` // In specifies that this field must be equal to one of the specified // values In [][]byte `protobuf:"bytes,8,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn [][]byte `protobuf:"bytes,9,rep,name=not_in,json=notIn" json:"not_in,omitempty"` // WellKnown rules provide advanced constraints against common byte // patterns // // Types that are assignable to WellKnown: // // *BytesRules_Ip // *BytesRules_Ipv4 // *BytesRules_Ipv6 WellKnown isBytesRules_WellKnown `protobuf_oneof:"well_known"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,14,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *BytesRules) Reset() { *x = BytesRules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *BytesRules) String() string { return protoimpl.X.MessageStringOf(x) } func (*BytesRules) ProtoMessage() {} func (x *BytesRules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use BytesRules.ProtoReflect.Descriptor instead. func (*BytesRules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{15} } func (x *BytesRules) GetConst() []byte { if x != nil { return x.Const } return nil } func (x *BytesRules) GetLen() uint64 { if x != nil && x.Len != nil { return *x.Len } return 0 } func (x *BytesRules) GetMinLen() uint64 { if x != nil && x.MinLen != nil { return *x.MinLen } return 0 } func (x *BytesRules) GetMaxLen() uint64 { if x != nil && x.MaxLen != nil { return *x.MaxLen } return 0 } func (x *BytesRules) GetPattern() string { if x != nil && x.Pattern != nil { return *x.Pattern } return "" } func (x *BytesRules) GetPrefix() []byte { if x != nil { return x.Prefix } return nil } func (x *BytesRules) GetSuffix() []byte { if x != nil { return x.Suffix } return nil } func (x *BytesRules) GetContains() []byte { if x != nil { return x.Contains } return nil } func (x *BytesRules) GetIn() [][]byte { if x != nil { return x.In } return nil } func (x *BytesRules) GetNotIn() [][]byte { if x != nil { return x.NotIn } return nil } func (m *BytesRules) GetWellKnown() isBytesRules_WellKnown { if m != nil { return m.WellKnown } return nil } func (x *BytesRules) GetIp() bool { if x, ok := x.GetWellKnown().(*BytesRules_Ip); ok { return x.Ip } return false } func (x *BytesRules) GetIpv4() bool { if x, ok := x.GetWellKnown().(*BytesRules_Ipv4); ok { return x.Ipv4 } return false } func (x *BytesRules) GetIpv6() bool { if x, ok := x.GetWellKnown().(*BytesRules_Ipv6); ok { return x.Ipv6 } return false } func (x *BytesRules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } type isBytesRules_WellKnown interface { isBytesRules_WellKnown() } type BytesRules_Ip struct { // Ip specifies that the field must be a valid IP (v4 or v6) address in // byte format Ip bool `protobuf:"varint,10,opt,name=ip,oneof"` } type BytesRules_Ipv4 struct { // Ipv4 specifies that the field must be a valid IPv4 address in byte // format Ipv4 bool `protobuf:"varint,11,opt,name=ipv4,oneof"` } type BytesRules_Ipv6 struct { // Ipv6 specifies that the field must be a valid IPv6 address in byte // format Ipv6 bool `protobuf:"varint,12,opt,name=ipv6,oneof"` } func (*BytesRules_Ip) isBytesRules_WellKnown() {} func (*BytesRules_Ipv4) isBytesRules_WellKnown() {} func (*BytesRules_Ipv6) isBytesRules_WellKnown() {} // EnumRules describe the constraints applied to enum values type EnumRules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Const specifies that this field must be exactly the specified value Const *int32 `protobuf:"varint,1,opt,name=const" json:"const,omitempty"` // DefinedOnly specifies that this field must be only one of the defined // values for this enum, failing on any undefined value. DefinedOnly *bool `protobuf:"varint,2,opt,name=defined_only,json=definedOnly" json:"defined_only,omitempty"` // In specifies that this field must be equal to one of the specified // values In []int32 `protobuf:"varint,3,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []int32 `protobuf:"varint,4,rep,name=not_in,json=notIn" json:"not_in,omitempty"` } func (x *EnumRules) Reset() { *x = EnumRules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EnumRules) String() string { return protoimpl.X.MessageStringOf(x) } func (*EnumRules) ProtoMessage() {} func (x *EnumRules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EnumRules.ProtoReflect.Descriptor instead. func (*EnumRules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{16} } func (x *EnumRules) GetConst() int32 { if x != nil && x.Const != nil { return *x.Const } return 0 } func (x *EnumRules) GetDefinedOnly() bool { if x != nil && x.DefinedOnly != nil { return *x.DefinedOnly } return false } func (x *EnumRules) GetIn() []int32 { if x != nil { return x.In } return nil } func (x *EnumRules) GetNotIn() []int32 { if x != nil { return x.NotIn } return nil } // MessageRules describe the constraints applied to embedded message values. // For message-type fields, validation is performed recursively. type MessageRules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Skip specifies that the validation rules of this field should not be // evaluated Skip *bool `protobuf:"varint,1,opt,name=skip" json:"skip,omitempty"` // Required specifies that this field must be set Required *bool `protobuf:"varint,2,opt,name=required" json:"required,omitempty"` } func (x *MessageRules) Reset() { *x = MessageRules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *MessageRules) String() string { return protoimpl.X.MessageStringOf(x) } func (*MessageRules) ProtoMessage() {} func (x *MessageRules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use MessageRules.ProtoReflect.Descriptor instead. func (*MessageRules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{17} } func (x *MessageRules) GetSkip() bool { if x != nil && x.Skip != nil { return *x.Skip } return false } func (x *MessageRules) GetRequired() bool { if x != nil && x.Required != nil { return *x.Required } return false } // RepeatedRules describe the constraints applied to `repeated` values type RepeatedRules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // MinItems specifies that this field must have the specified number of // items at a minimum MinItems *uint64 `protobuf:"varint,1,opt,name=min_items,json=minItems" json:"min_items,omitempty"` // MaxItems specifies that this field must have the specified number of // items at a maximum MaxItems *uint64 `protobuf:"varint,2,opt,name=max_items,json=maxItems" json:"max_items,omitempty"` // Unique specifies that all elements in this field must be unique. This // contraint is only applicable to scalar and enum types (messages are not // supported). Unique *bool `protobuf:"varint,3,opt,name=unique" json:"unique,omitempty"` // Items specifies the contraints to be applied to each item in the field. // Repeated message fields will still execute validation against each item // unless skip is specified here. Items *FieldRules `protobuf:"bytes,4,opt,name=items" json:"items,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,5,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *RepeatedRules) Reset() { *x = RepeatedRules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *RepeatedRules) String() string { return protoimpl.X.MessageStringOf(x) } func (*RepeatedRules) ProtoMessage() {} func (x *RepeatedRules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use RepeatedRules.ProtoReflect.Descriptor instead. func (*RepeatedRules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{18} } func (x *RepeatedRules) GetMinItems() uint64 { if x != nil && x.MinItems != nil { return *x.MinItems } return 0 } func (x *RepeatedRules) GetMaxItems() uint64 { if x != nil && x.MaxItems != nil { return *x.MaxItems } return 0 } func (x *RepeatedRules) GetUnique() bool { if x != nil && x.Unique != nil { return *x.Unique } return false } func (x *RepeatedRules) GetItems() *FieldRules { if x != nil { return x.Items } return nil } func (x *RepeatedRules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // MapRules describe the constraints applied to `map` values type MapRules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // MinPairs specifies that this field must have the specified number of // KVs at a minimum MinPairs *uint64 `protobuf:"varint,1,opt,name=min_pairs,json=minPairs" json:"min_pairs,omitempty"` // MaxPairs specifies that this field must have the specified number of // KVs at a maximum MaxPairs *uint64 `protobuf:"varint,2,opt,name=max_pairs,json=maxPairs" json:"max_pairs,omitempty"` // NoSparse specifies values in this field cannot be unset. This only // applies to map's with message value types. NoSparse *bool `protobuf:"varint,3,opt,name=no_sparse,json=noSparse" json:"no_sparse,omitempty"` // Keys specifies the constraints to be applied to each key in the field. Keys *FieldRules `protobuf:"bytes,4,opt,name=keys" json:"keys,omitempty"` // Values specifies the constraints to be applied to the value of each key // in the field. Message values will still have their validations evaluated // unless skip is specified here. Values *FieldRules `protobuf:"bytes,5,opt,name=values" json:"values,omitempty"` // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty IgnoreEmpty *bool `protobuf:"varint,6,opt,name=ignore_empty,json=ignoreEmpty" json:"ignore_empty,omitempty"` } func (x *MapRules) Reset() { *x = MapRules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *MapRules) String() string { return protoimpl.X.MessageStringOf(x) } func (*MapRules) ProtoMessage() {} func (x *MapRules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use MapRules.ProtoReflect.Descriptor instead. func (*MapRules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{19} } func (x *MapRules) GetMinPairs() uint64 { if x != nil && x.MinPairs != nil { return *x.MinPairs } return 0 } func (x *MapRules) GetMaxPairs() uint64 { if x != nil && x.MaxPairs != nil { return *x.MaxPairs } return 0 } func (x *MapRules) GetNoSparse() bool { if x != nil && x.NoSparse != nil { return *x.NoSparse } return false } func (x *MapRules) GetKeys() *FieldRules { if x != nil { return x.Keys } return nil } func (x *MapRules) GetValues() *FieldRules { if x != nil { return x.Values } return nil } func (x *MapRules) GetIgnoreEmpty() bool { if x != nil && x.IgnoreEmpty != nil { return *x.IgnoreEmpty } return false } // AnyRules describe constraints applied exclusively to the // `google.protobuf.Any` well-known type type AnyRules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required specifies that this field must be set Required *bool `protobuf:"varint,1,opt,name=required" json:"required,omitempty"` // In specifies that this field's `type_url` must be equal to one of the // specified values. In []string `protobuf:"bytes,2,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field's `type_url` must not be equal to any of // the specified values. NotIn []string `protobuf:"bytes,3,rep,name=not_in,json=notIn" json:"not_in,omitempty"` } func (x *AnyRules) Reset() { *x = AnyRules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AnyRules) String() string { return protoimpl.X.MessageStringOf(x) } func (*AnyRules) ProtoMessage() {} func (x *AnyRules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AnyRules.ProtoReflect.Descriptor instead. func (*AnyRules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{20} } func (x *AnyRules) GetRequired() bool { if x != nil && x.Required != nil { return *x.Required } return false } func (x *AnyRules) GetIn() []string { if x != nil { return x.In } return nil } func (x *AnyRules) GetNotIn() []string { if x != nil { return x.NotIn } return nil } // DurationRules describe the constraints applied exclusively to the // `google.protobuf.Duration` well-known type type DurationRules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required specifies that this field must be set Required *bool `protobuf:"varint,1,opt,name=required" json:"required,omitempty"` // Const specifies that this field must be exactly the specified value Const *durationpb.Duration `protobuf:"bytes,2,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *durationpb.Duration `protobuf:"bytes,3,opt,name=lt" json:"lt,omitempty"` // Lt specifies that this field must be less than the specified value, // inclusive Lte *durationpb.Duration `protobuf:"bytes,4,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive Gt *durationpb.Duration `protobuf:"bytes,5,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than the specified value, // inclusive Gte *durationpb.Duration `protobuf:"bytes,6,opt,name=gte" json:"gte,omitempty"` // In specifies that this field must be equal to one of the specified // values In []*durationpb.Duration `protobuf:"bytes,7,rep,name=in" json:"in,omitempty"` // NotIn specifies that this field cannot be equal to one of the specified // values NotIn []*durationpb.Duration `protobuf:"bytes,8,rep,name=not_in,json=notIn" json:"not_in,omitempty"` } func (x *DurationRules) Reset() { *x = DurationRules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DurationRules) String() string { return protoimpl.X.MessageStringOf(x) } func (*DurationRules) ProtoMessage() {} func (x *DurationRules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use DurationRules.ProtoReflect.Descriptor instead. func (*DurationRules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{21} } func (x *DurationRules) GetRequired() bool { if x != nil && x.Required != nil { return *x.Required } return false } func (x *DurationRules) GetConst() *durationpb.Duration { if x != nil { return x.Const } return nil } func (x *DurationRules) GetLt() *durationpb.Duration { if x != nil { return x.Lt } return nil } func (x *DurationRules) GetLte() *durationpb.Duration { if x != nil { return x.Lte } return nil } func (x *DurationRules) GetGt() *durationpb.Duration { if x != nil { return x.Gt } return nil } func (x *DurationRules) GetGte() *durationpb.Duration { if x != nil { return x.Gte } return nil } func (x *DurationRules) GetIn() []*durationpb.Duration { if x != nil { return x.In } return nil } func (x *DurationRules) GetNotIn() []*durationpb.Duration { if x != nil { return x.NotIn } return nil } // TimestampRules describe the constraints applied exclusively to the // `google.protobuf.Timestamp` well-known type type TimestampRules struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Required specifies that this field must be set Required *bool `protobuf:"varint,1,opt,name=required" json:"required,omitempty"` // Const specifies that this field must be exactly the specified value Const *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=const" json:"const,omitempty"` // Lt specifies that this field must be less than the specified value, // exclusive Lt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=lt" json:"lt,omitempty"` // Lte specifies that this field must be less than the specified value, // inclusive Lte *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=lte" json:"lte,omitempty"` // Gt specifies that this field must be greater than the specified value, // exclusive Gt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=gt" json:"gt,omitempty"` // Gte specifies that this field must be greater than the specified value, // inclusive Gte *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=gte" json:"gte,omitempty"` // LtNow specifies that this must be less than the current time. LtNow // can only be used with the Within rule. LtNow *bool `protobuf:"varint,7,opt,name=lt_now,json=ltNow" json:"lt_now,omitempty"` // GtNow specifies that this must be greater than the current time. GtNow // can only be used with the Within rule. GtNow *bool `protobuf:"varint,8,opt,name=gt_now,json=gtNow" json:"gt_now,omitempty"` // Within specifies that this field must be within this duration of the // current time. This constraint can be used alone or with the LtNow and // GtNow rules. Within *durationpb.Duration `protobuf:"bytes,9,opt,name=within" json:"within,omitempty"` } func (x *TimestampRules) Reset() { *x = TimestampRules{} if protoimpl.UnsafeEnabled { mi := &file_validate_validate_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *TimestampRules) String() string { return protoimpl.X.MessageStringOf(x) } func (*TimestampRules) ProtoMessage() {} func (x *TimestampRules) ProtoReflect() protoreflect.Message { mi := &file_validate_validate_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use TimestampRules.ProtoReflect.Descriptor instead. func (*TimestampRules) Descriptor() ([]byte, []int) { return file_validate_validate_proto_rawDescGZIP(), []int{22} } func (x *TimestampRules) GetRequired() bool { if x != nil && x.Required != nil { return *x.Required } return false } func (x *TimestampRules) GetConst() *timestamppb.Timestamp { if x != nil { return x.Const } return nil } func (x *TimestampRules) GetLt() *timestamppb.Timestamp { if x != nil { return x.Lt } return nil } func (x *TimestampRules) GetLte() *timestamppb.Timestamp { if x != nil { return x.Lte } return nil } func (x *TimestampRules) GetGt() *timestamppb.Timestamp { if x != nil { return x.Gt } return nil } func (x *TimestampRules) GetGte() *timestamppb.Timestamp { if x != nil { return x.Gte } return nil } func (x *TimestampRules) GetLtNow() bool { if x != nil && x.LtNow != nil { return *x.LtNow } return false } func (x *TimestampRules) GetGtNow() bool { if x != nil && x.GtNow != nil { return *x.GtNow } return false } func (x *TimestampRules) GetWithin() *durationpb.Duration { if x != nil { return x.Within } return nil } var file_validate_validate_proto_extTypes = []protoimpl.ExtensionInfo{ { ExtendedType: (*descriptorpb.MessageOptions)(nil), ExtensionType: (*bool)(nil), Field: 1071, Name: "validate.disabled", Tag: "varint,1071,opt,name=disabled", Filename: "validate/validate.proto", }, { ExtendedType: (*descriptorpb.MessageOptions)(nil), ExtensionType: (*bool)(nil), Field: 1072, Name: "validate.ignored", Tag: "varint,1072,opt,name=ignored", Filename: "validate/validate.proto", }, { ExtendedType: (*descriptorpb.OneofOptions)(nil), ExtensionType: (*bool)(nil), Field: 1071, Name: "validate.required", Tag: "varint,1071,opt,name=required", Filename: "validate/validate.proto", }, { ExtendedType: (*descriptorpb.FieldOptions)(nil), ExtensionType: (*FieldRules)(nil), Field: 1071, Name: "validate.rules", Tag: "bytes,1071,opt,name=rules", Filename: "validate/validate.proto", }, } // Extension fields to descriptorpb.MessageOptions. var ( // Disabled nullifies any validation rules for this message, including any // message fields associated with it that do support validation. // // optional bool disabled = 1071; E_Disabled = &file_validate_validate_proto_extTypes[0] // Ignore skips generation of validation methods for this message. // // optional bool ignored = 1072; E_Ignored = &file_validate_validate_proto_extTypes[1] ) // Extension fields to descriptorpb.OneofOptions. var ( // Required ensures that exactly one the field options in a oneof is set; // validation fails if no fields in the oneof are set. // // optional bool required = 1071; E_Required = &file_validate_validate_proto_extTypes[2] ) // Extension fields to descriptorpb.FieldOptions. var ( // Rules specify the validations to be performed on this field. By default, // no validation is performed against a field. // // optional validate.FieldRules rules = 1071; E_Rules = &file_validate_validate_proto_extTypes[3] ) var File_validate_validate_proto protoreflect.FileDescriptor var file_validate_validate_proto_rawDesc = []byte{ 0x0a, 0x17, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc8, 0x08, 0x0a, 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x05, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x05, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x06, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x12, 0x2c, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x2c, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x2f, 0x0a, 0x06, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x06, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x2f, 0x0a, 0x06, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x06, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x06, 0x73, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x06, 0x73, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x32, 0x0a, 0x07, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x07, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x12, 0x32, 0x0a, 0x07, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x07, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x12, 0x35, 0x0a, 0x08, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x08, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x12, 0x35, 0x0a, 0x08, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x08, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x12, 0x29, 0x0a, 0x04, 0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x04, 0x62, 0x6f, 0x6f, 0x6c, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x2c, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x04, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x04, 0x65, 0x6e, 0x75, 0x6d, 0x12, 0x35, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x03, 0x6d, 0x61, 0x70, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x61, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x03, 0x6d, 0x61, 0x70, 0x12, 0x26, 0x0a, 0x03, 0x61, 0x6e, 0x79, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x03, 0x61, 0x6e, 0x79, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x48, 0x00, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xb0, 0x01, 0x0a, 0x0a, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x02, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x02, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x02, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x02, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb1, 0x01, 0x0a, 0x0b, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x01, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x01, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb0, 0x01, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x05, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x05, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb0, 0x01, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x03, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x03, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb1, 0x01, 0x0a, 0x0b, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb1, 0x01, 0x0a, 0x0b, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x04, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x04, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb1, 0x01, 0x0a, 0x0b, 0x53, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x11, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x11, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x11, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x11, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x11, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x11, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb1, 0x01, 0x0a, 0x0b, 0x53, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x12, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x12, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x12, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x12, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x12, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x12, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x12, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb2, 0x01, 0x0a, 0x0c, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x07, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x07, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x07, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x07, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x07, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x07, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x07, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb2, 0x01, 0x0a, 0x0c, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x06, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x06, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x06, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x06, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x06, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x06, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x06, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb3, 0x01, 0x0a, 0x0d, 0x53, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0f, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0f, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xb3, 0x01, 0x0a, 0x0d, 0x53, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x10, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x10, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x10, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x10, 0x52, 0x02, 0x67, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x10, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x10, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x10, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x21, 0x0a, 0x09, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x22, 0xd4, 0x05, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x65, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6c, 0x65, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x69, 0x6e, 0x4c, 0x65, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x4c, 0x65, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x65, 0x6e, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6c, 0x65, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6e, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x69, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x6f, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x6f, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1c, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x02, 0x69, 0x70, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x36, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x36, 0x12, 0x12, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x19, 0x0a, 0x07, 0x75, 0x72, 0x69, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x06, 0x75, 0x72, 0x69, 0x52, 0x65, 0x66, 0x12, 0x1a, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x40, 0x0a, 0x10, 0x77, 0x65, 0x6c, 0x6c, 0x5f, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x48, 0x00, 0x52, 0x0e, 0x77, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x1c, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x18, 0x19, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x0c, 0x0a, 0x0a, 0x77, 0x65, 0x6c, 0x6c, 0x5f, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x22, 0xe2, 0x02, 0x0a, 0x0a, 0x42, 0x79, 0x74, 0x65, 0x73, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x65, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6c, 0x65, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x69, 0x6e, 0x4c, 0x65, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x4c, 0x65, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x12, 0x10, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x02, 0x69, 0x70, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x36, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x36, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x0c, 0x0a, 0x0a, 0x77, 0x65, 0x6c, 0x6c, 0x5f, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x22, 0x6b, 0x0a, 0x09, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x05, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x05, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x22, 0x3e, 0x0a, 0x0c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6b, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x6b, 0x69, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x69, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xdc, 0x01, 0x0a, 0x08, 0x4d, 0x61, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x69, 0x6e, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x5f, 0x73, 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, 0x6f, 0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x2c, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x4d, 0x0a, 0x08, 0x41, 0x6e, 0x79, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x22, 0xe9, 0x02, 0x0a, 0x0d, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x2f, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x29, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x67, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x29, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x30, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x49, 0x6e, 0x22, 0xf3, 0x02, 0x0a, 0x0e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x30, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x02, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x02, 0x6c, 0x74, 0x12, 0x2c, 0x0a, 0x03, 0x6c, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x6c, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x02, 0x67, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x02, 0x67, 0x74, 0x12, 0x2c, 0x0a, 0x03, 0x67, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x67, 0x74, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x6c, 0x74, 0x5f, 0x6e, 0x6f, 0x77, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x6c, 0x74, 0x4e, 0x6f, 0x77, 0x12, 0x15, 0x0a, 0x06, 0x67, 0x74, 0x5f, 0x6e, 0x6f, 0x77, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x67, 0x74, 0x4e, 0x6f, 0x77, 0x12, 0x31, 0x0a, 0x06, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x2a, 0x46, 0x0a, 0x0a, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x48, 0x54, 0x54, 0x50, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x48, 0x54, 0x54, 0x50, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x02, 0x3a, 0x3c, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xaf, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x3a, 0x3a, 0x0a, 0x07, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xb0, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x3a, 0x3a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xaf, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x3a, 0x4a, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xaf, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x42, 0x50, 0x0a, 0x1a, 0x69, 0x6f, 0x2e, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x70, 0x67, 0x76, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, } var ( file_validate_validate_proto_rawDescOnce sync.Once file_validate_validate_proto_rawDescData = file_validate_validate_proto_rawDesc ) func file_validate_validate_proto_rawDescGZIP() []byte { file_validate_validate_proto_rawDescOnce.Do(func() { file_validate_validate_proto_rawDescData = protoimpl.X.CompressGZIP(file_validate_validate_proto_rawDescData) }) return file_validate_validate_proto_rawDescData } var file_validate_validate_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_validate_validate_proto_msgTypes = make([]protoimpl.MessageInfo, 23) var file_validate_validate_proto_goTypes = []interface{}{ (KnownRegex)(0), // 0: validate.KnownRegex (*FieldRules)(nil), // 1: validate.FieldRules (*FloatRules)(nil), // 2: validate.FloatRules (*DoubleRules)(nil), // 3: validate.DoubleRules (*Int32Rules)(nil), // 4: validate.Int32Rules (*Int64Rules)(nil), // 5: validate.Int64Rules (*UInt32Rules)(nil), // 6: validate.UInt32Rules (*UInt64Rules)(nil), // 7: validate.UInt64Rules (*SInt32Rules)(nil), // 8: validate.SInt32Rules (*SInt64Rules)(nil), // 9: validate.SInt64Rules (*Fixed32Rules)(nil), // 10: validate.Fixed32Rules (*Fixed64Rules)(nil), // 11: validate.Fixed64Rules (*SFixed32Rules)(nil), // 12: validate.SFixed32Rules (*SFixed64Rules)(nil), // 13: validate.SFixed64Rules (*BoolRules)(nil), // 14: validate.BoolRules (*StringRules)(nil), // 15: validate.StringRules (*BytesRules)(nil), // 16: validate.BytesRules (*EnumRules)(nil), // 17: validate.EnumRules (*MessageRules)(nil), // 18: validate.MessageRules (*RepeatedRules)(nil), // 19: validate.RepeatedRules (*MapRules)(nil), // 20: validate.MapRules (*AnyRules)(nil), // 21: validate.AnyRules (*DurationRules)(nil), // 22: validate.DurationRules (*TimestampRules)(nil), // 23: validate.TimestampRules (*durationpb.Duration)(nil), // 24: google.protobuf.Duration (*timestamppb.Timestamp)(nil), // 25: google.protobuf.Timestamp (*descriptorpb.MessageOptions)(nil), // 26: google.protobuf.MessageOptions (*descriptorpb.OneofOptions)(nil), // 27: google.protobuf.OneofOptions (*descriptorpb.FieldOptions)(nil), // 28: google.protobuf.FieldOptions } var file_validate_validate_proto_depIdxs = []int32{ 18, // 0: validate.FieldRules.message:type_name -> validate.MessageRules 2, // 1: validate.FieldRules.float:type_name -> validate.FloatRules 3, // 2: validate.FieldRules.double:type_name -> validate.DoubleRules 4, // 3: validate.FieldRules.int32:type_name -> validate.Int32Rules 5, // 4: validate.FieldRules.int64:type_name -> validate.Int64Rules 6, // 5: validate.FieldRules.uint32:type_name -> validate.UInt32Rules 7, // 6: validate.FieldRules.uint64:type_name -> validate.UInt64Rules 8, // 7: validate.FieldRules.sint32:type_name -> validate.SInt32Rules 9, // 8: validate.FieldRules.sint64:type_name -> validate.SInt64Rules 10, // 9: validate.FieldRules.fixed32:type_name -> validate.Fixed32Rules 11, // 10: validate.FieldRules.fixed64:type_name -> validate.Fixed64Rules 12, // 11: validate.FieldRules.sfixed32:type_name -> validate.SFixed32Rules 13, // 12: validate.FieldRules.sfixed64:type_name -> validate.SFixed64Rules 14, // 13: validate.FieldRules.bool:type_name -> validate.BoolRules 15, // 14: validate.FieldRules.string:type_name -> validate.StringRules 16, // 15: validate.FieldRules.bytes:type_name -> validate.BytesRules 17, // 16: validate.FieldRules.enum:type_name -> validate.EnumRules 19, // 17: validate.FieldRules.repeated:type_name -> validate.RepeatedRules 20, // 18: validate.FieldRules.map:type_name -> validate.MapRules 21, // 19: validate.FieldRules.any:type_name -> validate.AnyRules 22, // 20: validate.FieldRules.duration:type_name -> validate.DurationRules 23, // 21: validate.FieldRules.timestamp:type_name -> validate.TimestampRules 0, // 22: validate.StringRules.well_known_regex:type_name -> validate.KnownRegex 1, // 23: validate.RepeatedRules.items:type_name -> validate.FieldRules 1, // 24: validate.MapRules.keys:type_name -> validate.FieldRules 1, // 25: validate.MapRules.values:type_name -> validate.FieldRules 24, // 26: validate.DurationRules.const:type_name -> google.protobuf.Duration 24, // 27: validate.DurationRules.lt:type_name -> google.protobuf.Duration 24, // 28: validate.DurationRules.lte:type_name -> google.protobuf.Duration 24, // 29: validate.DurationRules.gt:type_name -> google.protobuf.Duration 24, // 30: validate.DurationRules.gte:type_name -> google.protobuf.Duration 24, // 31: validate.DurationRules.in:type_name -> google.protobuf.Duration 24, // 32: validate.DurationRules.not_in:type_name -> google.protobuf.Duration 25, // 33: validate.TimestampRules.const:type_name -> google.protobuf.Timestamp 25, // 34: validate.TimestampRules.lt:type_name -> google.protobuf.Timestamp 25, // 35: validate.TimestampRules.lte:type_name -> google.protobuf.Timestamp 25, // 36: validate.TimestampRules.gt:type_name -> google.protobuf.Timestamp 25, // 37: validate.TimestampRules.gte:type_name -> google.protobuf.Timestamp 24, // 38: validate.TimestampRules.within:type_name -> google.protobuf.Duration 26, // 39: validate.disabled:extendee -> google.protobuf.MessageOptions 26, // 40: validate.ignored:extendee -> google.protobuf.MessageOptions 27, // 41: validate.required:extendee -> google.protobuf.OneofOptions 28, // 42: validate.rules:extendee -> google.protobuf.FieldOptions 1, // 43: validate.rules:type_name -> validate.FieldRules 44, // [44:44] is the sub-list for method output_type 44, // [44:44] is the sub-list for method input_type 43, // [43:44] is the sub-list for extension type_name 39, // [39:43] is the sub-list for extension extendee 0, // [0:39] is the sub-list for field type_name } func init() { file_validate_validate_proto_init() } func file_validate_validate_proto_init() { if File_validate_validate_proto != nil { return } if !protoimpl.UnsafeEnabled { file_validate_validate_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FieldRules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FloatRules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DoubleRules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Int32Rules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Int64Rules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UInt32Rules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UInt64Rules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SInt32Rules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SInt64Rules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Fixed32Rules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Fixed64Rules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SFixed32Rules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SFixed64Rules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BoolRules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StringRules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BytesRules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnumRules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MessageRules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RepeatedRules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MapRules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AnyRules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DurationRules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_validate_validate_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TimestampRules); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } file_validate_validate_proto_msgTypes[0].OneofWrappers = []interface{}{ (*FieldRules_Float)(nil), (*FieldRules_Double)(nil), (*FieldRules_Int32)(nil), (*FieldRules_Int64)(nil), (*FieldRules_Uint32)(nil), (*FieldRules_Uint64)(nil), (*FieldRules_Sint32)(nil), (*FieldRules_Sint64)(nil), (*FieldRules_Fixed32)(nil), (*FieldRules_Fixed64)(nil), (*FieldRules_Sfixed32)(nil), (*FieldRules_Sfixed64)(nil), (*FieldRules_Bool)(nil), (*FieldRules_String_)(nil), (*FieldRules_Bytes)(nil), (*FieldRules_Enum)(nil), (*FieldRules_Repeated)(nil), (*FieldRules_Map)(nil), (*FieldRules_Any)(nil), (*FieldRules_Duration)(nil), (*FieldRules_Timestamp)(nil), } file_validate_validate_proto_msgTypes[14].OneofWrappers = []interface{}{ (*StringRules_Email)(nil), (*StringRules_Hostname)(nil), (*StringRules_Ip)(nil), (*StringRules_Ipv4)(nil), (*StringRules_Ipv6)(nil), (*StringRules_Uri)(nil), (*StringRules_UriRef)(nil), (*StringRules_Address)(nil), (*StringRules_Uuid)(nil), (*StringRules_WellKnownRegex)(nil), } file_validate_validate_proto_msgTypes[15].OneofWrappers = []interface{}{ (*BytesRules_Ip)(nil), (*BytesRules_Ipv4)(nil), (*BytesRules_Ipv6)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_validate_validate_proto_rawDesc, NumEnums: 1, NumMessages: 23, NumExtensions: 4, NumServices: 0, }, GoTypes: file_validate_validate_proto_goTypes, DependencyIndexes: file_validate_validate_proto_depIdxs, EnumInfos: file_validate_validate_proto_enumTypes, MessageInfos: file_validate_validate_proto_msgTypes, ExtensionInfos: file_validate_validate_proto_extTypes, }.Build() File_validate_validate_proto = out.File file_validate_validate_proto_rawDesc = nil file_validate_validate_proto_goTypes = nil file_validate_validate_proto_depIdxs = nil } protoc-gen-validate-1.0.2/validate/validate.proto000066400000000000000000000750221444536353100220430ustar00rootroot00000000000000syntax = "proto2"; package validate; option go_package = "github.com/envoyproxy/protoc-gen-validate/validate"; option java_package = "io.envoyproxy.pgv.validate"; import "google/protobuf/descriptor.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; // Validation rules applied at the message level extend google.protobuf.MessageOptions { // Disabled nullifies any validation rules for this message, including any // message fields associated with it that do support validation. optional bool disabled = 1071; // Ignore skips generation of validation methods for this message. optional bool ignored = 1072; } // Validation rules applied at the oneof level extend google.protobuf.OneofOptions { // Required ensures that exactly one the field options in a oneof is set; // validation fails if no fields in the oneof are set. optional bool required = 1071; } // Validation rules applied at the field level extend google.protobuf.FieldOptions { // Rules specify the validations to be performed on this field. By default, // no validation is performed against a field. optional FieldRules rules = 1071; } // FieldRules encapsulates the rules for each type of field. Depending on the // field, the correct set should be used to ensure proper validations. message FieldRules { optional MessageRules message = 17; oneof type { // Scalar Field Types FloatRules float = 1; DoubleRules double = 2; Int32Rules int32 = 3; Int64Rules int64 = 4; UInt32Rules uint32 = 5; UInt64Rules uint64 = 6; SInt32Rules sint32 = 7; SInt64Rules sint64 = 8; Fixed32Rules fixed32 = 9; Fixed64Rules fixed64 = 10; SFixed32Rules sfixed32 = 11; SFixed64Rules sfixed64 = 12; BoolRules bool = 13; StringRules string = 14; BytesRules bytes = 15; // Complex Field Types EnumRules enum = 16; RepeatedRules repeated = 18; MapRules map = 19; // Well-Known Field Types AnyRules any = 20; DurationRules duration = 21; TimestampRules timestamp = 22; } } // FloatRules describes the constraints applied to `float` values message FloatRules { // Const specifies that this field must be exactly the specified value optional float const = 1; // Lt specifies that this field must be less than the specified value, // exclusive optional float lt = 2; // Lte specifies that this field must be less than or equal to the // specified value, inclusive optional float lte = 3; // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. optional float gt = 4; // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. optional float gte = 5; // In specifies that this field must be equal to one of the specified // values repeated float in = 6; // NotIn specifies that this field cannot be equal to one of the specified // values repeated float not_in = 7; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 8; } // DoubleRules describes the constraints applied to `double` values message DoubleRules { // Const specifies that this field must be exactly the specified value optional double const = 1; // Lt specifies that this field must be less than the specified value, // exclusive optional double lt = 2; // Lte specifies that this field must be less than or equal to the // specified value, inclusive optional double lte = 3; // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. optional double gt = 4; // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. optional double gte = 5; // In specifies that this field must be equal to one of the specified // values repeated double in = 6; // NotIn specifies that this field cannot be equal to one of the specified // values repeated double not_in = 7; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 8; } // Int32Rules describes the constraints applied to `int32` values message Int32Rules { // Const specifies that this field must be exactly the specified value optional int32 const = 1; // Lt specifies that this field must be less than the specified value, // exclusive optional int32 lt = 2; // Lte specifies that this field must be less than or equal to the // specified value, inclusive optional int32 lte = 3; // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. optional int32 gt = 4; // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. optional int32 gte = 5; // In specifies that this field must be equal to one of the specified // values repeated int32 in = 6; // NotIn specifies that this field cannot be equal to one of the specified // values repeated int32 not_in = 7; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 8; } // Int64Rules describes the constraints applied to `int64` values message Int64Rules { // Const specifies that this field must be exactly the specified value optional int64 const = 1; // Lt specifies that this field must be less than the specified value, // exclusive optional int64 lt = 2; // Lte specifies that this field must be less than or equal to the // specified value, inclusive optional int64 lte = 3; // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. optional int64 gt = 4; // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. optional int64 gte = 5; // In specifies that this field must be equal to one of the specified // values repeated int64 in = 6; // NotIn specifies that this field cannot be equal to one of the specified // values repeated int64 not_in = 7; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 8; } // UInt32Rules describes the constraints applied to `uint32` values message UInt32Rules { // Const specifies that this field must be exactly the specified value optional uint32 const = 1; // Lt specifies that this field must be less than the specified value, // exclusive optional uint32 lt = 2; // Lte specifies that this field must be less than or equal to the // specified value, inclusive optional uint32 lte = 3; // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. optional uint32 gt = 4; // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. optional uint32 gte = 5; // In specifies that this field must be equal to one of the specified // values repeated uint32 in = 6; // NotIn specifies that this field cannot be equal to one of the specified // values repeated uint32 not_in = 7; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 8; } // UInt64Rules describes the constraints applied to `uint64` values message UInt64Rules { // Const specifies that this field must be exactly the specified value optional uint64 const = 1; // Lt specifies that this field must be less than the specified value, // exclusive optional uint64 lt = 2; // Lte specifies that this field must be less than or equal to the // specified value, inclusive optional uint64 lte = 3; // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. optional uint64 gt = 4; // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. optional uint64 gte = 5; // In specifies that this field must be equal to one of the specified // values repeated uint64 in = 6; // NotIn specifies that this field cannot be equal to one of the specified // values repeated uint64 not_in = 7; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 8; } // SInt32Rules describes the constraints applied to `sint32` values message SInt32Rules { // Const specifies that this field must be exactly the specified value optional sint32 const = 1; // Lt specifies that this field must be less than the specified value, // exclusive optional sint32 lt = 2; // Lte specifies that this field must be less than or equal to the // specified value, inclusive optional sint32 lte = 3; // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. optional sint32 gt = 4; // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. optional sint32 gte = 5; // In specifies that this field must be equal to one of the specified // values repeated sint32 in = 6; // NotIn specifies that this field cannot be equal to one of the specified // values repeated sint32 not_in = 7; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 8; } // SInt64Rules describes the constraints applied to `sint64` values message SInt64Rules { // Const specifies that this field must be exactly the specified value optional sint64 const = 1; // Lt specifies that this field must be less than the specified value, // exclusive optional sint64 lt = 2; // Lte specifies that this field must be less than or equal to the // specified value, inclusive optional sint64 lte = 3; // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. optional sint64 gt = 4; // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. optional sint64 gte = 5; // In specifies that this field must be equal to one of the specified // values repeated sint64 in = 6; // NotIn specifies that this field cannot be equal to one of the specified // values repeated sint64 not_in = 7; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 8; } // Fixed32Rules describes the constraints applied to `fixed32` values message Fixed32Rules { // Const specifies that this field must be exactly the specified value optional fixed32 const = 1; // Lt specifies that this field must be less than the specified value, // exclusive optional fixed32 lt = 2; // Lte specifies that this field must be less than or equal to the // specified value, inclusive optional fixed32 lte = 3; // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. optional fixed32 gt = 4; // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. optional fixed32 gte = 5; // In specifies that this field must be equal to one of the specified // values repeated fixed32 in = 6; // NotIn specifies that this field cannot be equal to one of the specified // values repeated fixed32 not_in = 7; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 8; } // Fixed64Rules describes the constraints applied to `fixed64` values message Fixed64Rules { // Const specifies that this field must be exactly the specified value optional fixed64 const = 1; // Lt specifies that this field must be less than the specified value, // exclusive optional fixed64 lt = 2; // Lte specifies that this field must be less than or equal to the // specified value, inclusive optional fixed64 lte = 3; // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. optional fixed64 gt = 4; // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. optional fixed64 gte = 5; // In specifies that this field must be equal to one of the specified // values repeated fixed64 in = 6; // NotIn specifies that this field cannot be equal to one of the specified // values repeated fixed64 not_in = 7; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 8; } // SFixed32Rules describes the constraints applied to `sfixed32` values message SFixed32Rules { // Const specifies that this field must be exactly the specified value optional sfixed32 const = 1; // Lt specifies that this field must be less than the specified value, // exclusive optional sfixed32 lt = 2; // Lte specifies that this field must be less than or equal to the // specified value, inclusive optional sfixed32 lte = 3; // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. optional sfixed32 gt = 4; // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. optional sfixed32 gte = 5; // In specifies that this field must be equal to one of the specified // values repeated sfixed32 in = 6; // NotIn specifies that this field cannot be equal to one of the specified // values repeated sfixed32 not_in = 7; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 8; } // SFixed64Rules describes the constraints applied to `sfixed64` values message SFixed64Rules { // Const specifies that this field must be exactly the specified value optional sfixed64 const = 1; // Lt specifies that this field must be less than the specified value, // exclusive optional sfixed64 lt = 2; // Lte specifies that this field must be less than or equal to the // specified value, inclusive optional sfixed64 lte = 3; // Gt specifies that this field must be greater than the specified value, // exclusive. If the value of Gt is larger than a specified Lt or Lte, the // range is reversed. optional sfixed64 gt = 4; // Gte specifies that this field must be greater than or equal to the // specified value, inclusive. If the value of Gte is larger than a // specified Lt or Lte, the range is reversed. optional sfixed64 gte = 5; // In specifies that this field must be equal to one of the specified // values repeated sfixed64 in = 6; // NotIn specifies that this field cannot be equal to one of the specified // values repeated sfixed64 not_in = 7; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 8; } // BoolRules describes the constraints applied to `bool` values message BoolRules { // Const specifies that this field must be exactly the specified value optional bool const = 1; } // StringRules describe the constraints applied to `string` values message StringRules { // Const specifies that this field must be exactly the specified value optional string const = 1; // Len specifies that this field must be the specified number of // characters (Unicode code points). Note that the number of // characters may differ from the number of bytes in the string. optional uint64 len = 19; // MinLen specifies that this field must be the specified number of // characters (Unicode code points) at a minimum. Note that the number of // characters may differ from the number of bytes in the string. optional uint64 min_len = 2; // MaxLen specifies that this field must be the specified number of // characters (Unicode code points) at a maximum. Note that the number of // characters may differ from the number of bytes in the string. optional uint64 max_len = 3; // LenBytes specifies that this field must be the specified number of bytes optional uint64 len_bytes = 20; // MinBytes specifies that this field must be the specified number of bytes // at a minimum optional uint64 min_bytes = 4; // MaxBytes specifies that this field must be the specified number of bytes // at a maximum optional uint64 max_bytes = 5; // Pattern specifes that this field must match against the specified // regular expression (RE2 syntax). The included expression should elide // any delimiters. optional string pattern = 6; // Prefix specifies that this field must have the specified substring at // the beginning of the string. optional string prefix = 7; // Suffix specifies that this field must have the specified substring at // the end of the string. optional string suffix = 8; // Contains specifies that this field must have the specified substring // anywhere in the string. optional string contains = 9; // NotContains specifies that this field cannot have the specified substring // anywhere in the string. optional string not_contains = 23; // In specifies that this field must be equal to one of the specified // values repeated string in = 10; // NotIn specifies that this field cannot be equal to one of the specified // values repeated string not_in = 11; // WellKnown rules provide advanced constraints against common string // patterns oneof well_known { // Email specifies that the field must be a valid email address as // defined by RFC 5322 bool email = 12; // Hostname specifies that the field must be a valid hostname as // defined by RFC 1034. This constraint does not support // internationalized domain names (IDNs). bool hostname = 13; // Ip specifies that the field must be a valid IP (v4 or v6) address. // Valid IPv6 addresses should not include surrounding square brackets. bool ip = 14; // Ipv4 specifies that the field must be a valid IPv4 address. bool ipv4 = 15; // Ipv6 specifies that the field must be a valid IPv6 address. Valid // IPv6 addresses should not include surrounding square brackets. bool ipv6 = 16; // Uri specifies that the field must be a valid, absolute URI as defined // by RFC 3986 bool uri = 17; // UriRef specifies that the field must be a valid URI as defined by RFC // 3986 and may be relative or absolute. bool uri_ref = 18; // Address specifies that the field must be either a valid hostname as // defined by RFC 1034 (which does not support internationalized domain // names or IDNs), or it can be a valid IP (v4 or v6). bool address = 21; // Uuid specifies that the field must be a valid UUID as defined by // RFC 4122 bool uuid = 22; // WellKnownRegex specifies a common well known pattern defined as a regex. KnownRegex well_known_regex = 24; } // This applies to regexes HTTP_HEADER_NAME and HTTP_HEADER_VALUE to enable // strict header validation. // By default, this is true, and HTTP header validations are RFC-compliant. // Setting to false will enable a looser validations that only disallows // \r\n\0 characters, which can be used to bypass header matching rules. optional bool strict = 25 [default = true]; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 26; } // WellKnownRegex contain some well-known patterns. enum KnownRegex { UNKNOWN = 0; // HTTP header name as defined by RFC 7230. HTTP_HEADER_NAME = 1; // HTTP header value as defined by RFC 7230. HTTP_HEADER_VALUE = 2; } // BytesRules describe the constraints applied to `bytes` values message BytesRules { // Const specifies that this field must be exactly the specified value optional bytes const = 1; // Len specifies that this field must be the specified number of bytes optional uint64 len = 13; // MinLen specifies that this field must be the specified number of bytes // at a minimum optional uint64 min_len = 2; // MaxLen specifies that this field must be the specified number of bytes // at a maximum optional uint64 max_len = 3; // Pattern specifes that this field must match against the specified // regular expression (RE2 syntax). The included expression should elide // any delimiters. optional string pattern = 4; // Prefix specifies that this field must have the specified bytes at the // beginning of the string. optional bytes prefix = 5; // Suffix specifies that this field must have the specified bytes at the // end of the string. optional bytes suffix = 6; // Contains specifies that this field must have the specified bytes // anywhere in the string. optional bytes contains = 7; // In specifies that this field must be equal to one of the specified // values repeated bytes in = 8; // NotIn specifies that this field cannot be equal to one of the specified // values repeated bytes not_in = 9; // WellKnown rules provide advanced constraints against common byte // patterns oneof well_known { // Ip specifies that the field must be a valid IP (v4 or v6) address in // byte format bool ip = 10; // Ipv4 specifies that the field must be a valid IPv4 address in byte // format bool ipv4 = 11; // Ipv6 specifies that the field must be a valid IPv6 address in byte // format bool ipv6 = 12; } // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 14; } // EnumRules describe the constraints applied to enum values message EnumRules { // Const specifies that this field must be exactly the specified value optional int32 const = 1; // DefinedOnly specifies that this field must be only one of the defined // values for this enum, failing on any undefined value. optional bool defined_only = 2; // In specifies that this field must be equal to one of the specified // values repeated int32 in = 3; // NotIn specifies that this field cannot be equal to one of the specified // values repeated int32 not_in = 4; } // MessageRules describe the constraints applied to embedded message values. // For message-type fields, validation is performed recursively. message MessageRules { // Skip specifies that the validation rules of this field should not be // evaluated optional bool skip = 1; // Required specifies that this field must be set optional bool required = 2; } // RepeatedRules describe the constraints applied to `repeated` values message RepeatedRules { // MinItems specifies that this field must have the specified number of // items at a minimum optional uint64 min_items = 1; // MaxItems specifies that this field must have the specified number of // items at a maximum optional uint64 max_items = 2; // Unique specifies that all elements in this field must be unique. This // contraint is only applicable to scalar and enum types (messages are not // supported). optional bool unique = 3; // Items specifies the contraints to be applied to each item in the field. // Repeated message fields will still execute validation against each item // unless skip is specified here. optional FieldRules items = 4; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 5; } // MapRules describe the constraints applied to `map` values message MapRules { // MinPairs specifies that this field must have the specified number of // KVs at a minimum optional uint64 min_pairs = 1; // MaxPairs specifies that this field must have the specified number of // KVs at a maximum optional uint64 max_pairs = 2; // NoSparse specifies values in this field cannot be unset. This only // applies to map's with message value types. optional bool no_sparse = 3; // Keys specifies the constraints to be applied to each key in the field. optional FieldRules keys = 4; // Values specifies the constraints to be applied to the value of each key // in the field. Message values will still have their validations evaluated // unless skip is specified here. optional FieldRules values = 5; // IgnoreEmpty specifies that the validation rules of this field should be // evaluated only if the field is not empty optional bool ignore_empty = 6; } // AnyRules describe constraints applied exclusively to the // `google.protobuf.Any` well-known type message AnyRules { // Required specifies that this field must be set optional bool required = 1; // In specifies that this field's `type_url` must be equal to one of the // specified values. repeated string in = 2; // NotIn specifies that this field's `type_url` must not be equal to any of // the specified values. repeated string not_in = 3; } // DurationRules describe the constraints applied exclusively to the // `google.protobuf.Duration` well-known type message DurationRules { // Required specifies that this field must be set optional bool required = 1; // Const specifies that this field must be exactly the specified value optional google.protobuf.Duration const = 2; // Lt specifies that this field must be less than the specified value, // exclusive optional google.protobuf.Duration lt = 3; // Lt specifies that this field must be less than the specified value, // inclusive optional google.protobuf.Duration lte = 4; // Gt specifies that this field must be greater than the specified value, // exclusive optional google.protobuf.Duration gt = 5; // Gte specifies that this field must be greater than the specified value, // inclusive optional google.protobuf.Duration gte = 6; // In specifies that this field must be equal to one of the specified // values repeated google.protobuf.Duration in = 7; // NotIn specifies that this field cannot be equal to one of the specified // values repeated google.protobuf.Duration not_in = 8; } // TimestampRules describe the constraints applied exclusively to the // `google.protobuf.Timestamp` well-known type message TimestampRules { // Required specifies that this field must be set optional bool required = 1; // Const specifies that this field must be exactly the specified value optional google.protobuf.Timestamp const = 2; // Lt specifies that this field must be less than the specified value, // exclusive optional google.protobuf.Timestamp lt = 3; // Lte specifies that this field must be less than the specified value, // inclusive optional google.protobuf.Timestamp lte = 4; // Gt specifies that this field must be greater than the specified value, // exclusive optional google.protobuf.Timestamp gt = 5; // Gte specifies that this field must be greater than the specified value, // inclusive optional google.protobuf.Timestamp gte = 6; // LtNow specifies that this must be less than the current time. LtNow // can only be used with the Within rule. optional bool lt_now = 7; // GtNow specifies that this must be greater than the current time. GtNow // can only be used with the Within rule. optional bool gt_now = 8; // Within specifies that this field must be within this duration of the // current time. This constraint can be used alone or with the LtNow and // GtNow rules. optional google.protobuf.Duration within = 9; } protoc-gen-validate-1.0.2/windows/000077500000000000000000000000001444536353100170605ustar00rootroot00000000000000protoc-gen-validate-1.0.2/windows/bazel.rc000066400000000000000000000000311444536353100204750ustar00rootroot00000000000000build --verbose_failures protoc-gen-validate-1.0.2/windows/ci.ps1000066400000000000000000000003471444536353100201040ustar00rootroot00000000000000$ErrorActionPreference = "Stop"; trap { $host.SetShouldExit(1) } #bazel-harness # runs the test harness via bazel bazel "--output_base=c:\_pgv" "--bazelrc=windows\bazel.rc" run //tests/harness/executor:executor exit $LASTEXITCODE