pax_global_header 0000666 0000000 0000000 00000000064 14445363531 0014522 g ustar 00root root 0000000 0000000 52 comment=fab737efbb4b4d03e7c771393708f75594b121e4
protoc-gen-validate-1.0.2/ 0000775 0000000 0000000 00000000000 14445363531 0015366 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/.bazelversion 0000664 0000000 0000000 00000000006 14445363531 0020066 0 ustar 00root root 0000000 0000000 6.2.0
protoc-gen-validate-1.0.2/.clang-format 0000775 0000000 0000000 00000000431 14445363531 0017742 0 ustar 00root root 0000000 0000000 ---
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/.dockerignore 0000664 0000000 0000000 00000000031 14445363531 0020034 0 ustar 00root root 0000000 0000000 .git/
.idea/
.bin/
dist/
protoc-gen-validate-1.0.2/.github/ 0000775 0000000 0000000 00000000000 14445363531 0016726 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/.github/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000012535 14445363531 0021533 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 14445363531 0020366 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/.github/actions/github-tag-action/ 0000775 0000000 0000000 00000000000 14445363531 0023674 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/.github/actions/github-tag-action/entrypoint.sh 0000775 0000000 0000000 00000014365 14445363531 0026457 0 ustar 00root root 0000000 0000000 #!/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.svg 0000664 0000000 0000000 00000001151 14445363531 0021157 0 ustar 00root root 0000000 0000000
protoc-gen-validate-1.0.2/.github/dependabot.yml 0000664 0000000 0000000 00000000520 14445363531 0021553 0 ustar 00root root 0000000 0000000 version: 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.yml 0000664 0000000 0000000 00000001352 14445363531 0020562 0 ustar 00root root 0000000 0000000 # 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: false protoc-gen-validate-1.0.2/.github/workflows/ 0000775 0000000 0000000 00000000000 14445363531 0020763 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/.github/workflows/ci.yaml 0000664 0000000 0000000 00000003063 14445363531 0022244 0 ustar 00root root 0000000 0000000 name: 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.yaml 0000664 0000000 0000000 00000000465 14445363531 0026430 0 ustar 00root root 0000000 0000000 name: 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.yaml 0000664 0000000 0000000 00000001514 14445363531 0024000 0 ustar 00root root 0000000 0000000 # 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.yaml 0000664 0000000 0000000 00000001271 14445363531 0024053 0 ustar 00root root 0000000 0000000 # 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.yaml 0000664 0000000 0000000 00000005727 14445363531 0024262 0 ustar 00root root 0000000 0000000 # 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.yaml 0000664 0000000 0000000 00000000412 14445363531 0026275 0 ustar 00root root 0000000 0000000 name: 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.yaml 0000664 0000000 0000000 00000001144 14445363531 0023407 0 ustar 00root root 0000000 0000000 name: 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.yaml 0000664 0000000 0000000 00000001547 14445363531 0024570 0 ustar 00root root 0000000 0000000 name: 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.yaml 0000664 0000000 0000000 00000002325 14445363531 0024277 0 ustar 00root root 0000000 0000000 name: 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/.gitignore 0000664 0000000 0000000 00000002415 14445363531 0017360 0 ustar 00root root 0000000 0000000 bazel-*
**/.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.yaml 0000664 0000000 0000000 00000003625 14445363531 0020466 0 ustar 00root root 0000000 0000000 builds:
- 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.bazel 0000664 0000000 0000000 00000001642 14445363531 0017247 0 ustar 00root root 0000000 0000000 load("@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/Dockerfile 0000664 0000000 0000000 00000004252 14445363531 0017363 0 ustar 00root root 0000000 0000000 FROM 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/LICENSE 0000664 0000000 0000000 00000026136 14445363531 0016403 0 ustar 00root root 0000000 0000000
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/Makefile 0000664 0000000 0000000 00000017163 14445363531 0017036 0 ustar 00root root 0000000 0000000 empty :=
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.mk 0000664 0000000 0000000 00000006762 14445363531 0016650 0 ustar 00root root 0000000 0000000 # 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.md 0000664 0000000 0000000 00000100416 14445363531 0016647 0 ustar 00root root 0000000 0000000 # [][buf] protoc-gen-validate (PGV)



**_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-validatepgv-java-stub${pgv.version}kr.motd.mavenos-maven-plugin1.4.1.Finalorg.xolstice.maven.pluginsprotobuf-maven-plugin0.6.1
com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
protoc-java-pgvcompile-customlang=javajava-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.mk 0000664 0000000 0000000 00000000401 14445363531 0017012 0 ustar 00root root 0000000 0000000 # 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/WORKSPACE 0000664 0000000 0000000 00000000531 14445363531 0016646 0 ustar 00root root 0000000 0000000 workspace(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/ 0000775 0000000 0000000 00000000000 14445363531 0016463 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/bazel/BUILD 0000664 0000000 0000000 00000000467 14445363531 0017254 0 ustar 00root root 0000000 0000000 load("@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.bzl 0000664 0000000 0000000 00000002243 14445363531 0023070 0 ustar 00root root 0000000 0000000 load("@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/ 0000775 0000000 0000000 00000000000 14445363531 0017070 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/bazel/go/BUILD 0000664 0000000 0000000 00000001557 14445363531 0017662 0 ustar 00root root 0000000 0000000 """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.bzl 0000664 0000000 0000000 00000004057 14445363531 0022745 0 ustar 00root root 0000000 0000000 load("@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.bzl 0000664 0000000 0000000 00000021074 14445363531 0021040 0 ustar 00root root 0000000 0000000 load("@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.bzl 0000664 0000000 0000000 00000014117 14445363531 0021727 0 ustar 00root root 0000000 0000000 load("@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/ 0000775 0000000 0000000 00000000000 14445363531 0016131 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/cmd/protoc-gen-validate-cpp/ 0000775 0000000 0000000 00000000000 14445363531 0022555 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/cmd/protoc-gen-validate-cpp/BUILD 0000664 0000000 0000000 00000001746 14445363531 0023347 0 ustar 00root root 0000000 0000000 load("@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.go 0000664 0000000 0000000 00000000614 14445363531 0024031 0 ustar 00root root 0000000 0000000 package 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/ 0000775 0000000 0000000 00000000000 14445363531 0022400 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/cmd/protoc-gen-validate-go/BUILD 0000664 0000000 0000000 00000001741 14445363531 0023165 0 ustar 00root root 0000000 0000000 load("@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.go 0000664 0000000 0000000 00000000750 14445363531 0023655 0 ustar 00root root 0000000 0000000 package 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/ 0000775 0000000 0000000 00000000000 14445363531 0022714 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/cmd/protoc-gen-validate-java/BUILD 0000664 0000000 0000000 00000001753 14445363531 0023504 0 ustar 00root root 0000000 0000000 load("@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.go 0000664 0000000 0000000 00000000616 14445363531 0024172 0 ustar 00root root 0000000 0000000 package 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.bzl 0000664 0000000 0000000 00000042123 14445363531 0020527 0 ustar 00root root 0000000 0000000 load("@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/ 0000775 0000000 0000000 00000000000 14445363531 0021015 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/example-workspace/.bazelrc 0000664 0000000 0000000 00000000064 14445363531 0022440 0 ustar 00root root 0000000 0000000 build --incompatible_use_cc_configure_from_rules_cc
protoc-gen-validate-1.0.2/example-workspace/BUILD 0000664 0000000 0000000 00000003544 14445363531 0021605 0 ustar 00root root 0000000 0000000 # 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/WORKSPACE 0000664 0000000 0000000 00000001751 14445363531 0022302 0 ustar 00root root 0000000 0000000 # 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.bzl 0000664 0000000 0000000 00000042123 14445363531 0024156 0 ustar 00root root 0000000 0000000 load("@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.cc 0000664 0000000 0000000 00000003372 14445363531 0022764 0 ustar 00root root 0000000 0000000 #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.py 0000664 0000000 0000000 00000003120 14445363531 0023016 0 ustar 00root root 0000000 0000000 import 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.sh 0000775 0000000 0000000 00000000171 14445363531 0024045 0 ustar 00root root 0000000 0000000 #!/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/ 0000775 0000000 0000000 00000000000 14445363531 0021600 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/example-workspace/foo/BUILD 0000664 0000000 0000000 00000001756 14445363531 0022373 0 ustar 00root root 0000000 0000000 load("@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.proto 0000664 0000000 0000000 00000000410 14445363531 0023424 0 ustar 00root root 0000000 0000000 syntax = "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.cc 0000664 0000000 0000000 00000000642 14445363531 0024371 0 ustar 00root root 0000000 0000000 #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/ 0000775 0000000 0000000 00000000000 14445363531 0026326 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/example-workspace/foo/subdir_without_package/baz.proto 0000664 0000000 0000000 00000000237 14445363531 0030171 0 ustar 00root root 0000000 0000000 syntax = "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.textproto 0000664 0000000 0000000 00000000167 14445363531 0024441 0 ustar 00root root 0000000 0000000 # 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.textproto 0000664 0000000 0000000 00000000166 14445363531 0024111 0 ustar 00root root 0000000 0000000 # 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.mod 0000664 0000000 0000000 00000001007 14445363531 0016472 0 ustar 00root root 0000000 0000000 module 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.sum 0000664 0000000 0000000 00000011772 14445363531 0016531 0 ustar 00root root 0000000 0000000 github.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/ 0000775 0000000 0000000 00000000000 14445363531 0016307 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/RELEASING.md 0000664 0000000 0000000 00000002632 14445363531 0020145 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 14445363531 0021061 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-artifacts/pom.xml 0000664 0000000 0000000 00000025441 14445363531 0022404 0 ustar 00root root 0000000 0000000
pgv-javabuild.buf.protoc-gen-validateVERSION4.0.0protoc-gen-validatepomPGV-Java Protoc Pluginsorg.codehaus.mojoexec-maven-plugin3.1.0osx-x86_64execcompilegobuild-o${project.build.directory}/protoc-gen-validate-${project.version}-osx-x86_64.exe../..darwinamd64osx-aarch_64execcompilegobuild-o${project.build.directory}/protoc-gen-validate-${project.version}-osx-aarch_64.exe../..darwinarm64linux_x86_32execcompilegobuild-o${project.build.directory}/protoc-gen-validate-${project.version}-linux-x86_32.exe../..linux386linux_x86_64execcompilegobuild-o${project.build.directory}/protoc-gen-validate-${project.version}-linux-x86_64.exe../..linuxamd64windows_x86_32execcompilegobuild-o${project.build.directory}/protoc-gen-validate-${project.version}-windows-x86_32.exe../..windows386windows_x86_64execcompilegobuild-o${project.build.directory}/protoc-gen-validate-${project.version}-windows-x86_64.exe../..windowsamd64linux-aarch_64execcompilegobuild-o${project.build.directory}/protoc-gen-validate-${project.version}-linux-aarch_64.exe../..linuxarm64org.codehaus.mojobuild-helper-maven-plugin3.4.0attach-artifactsattach-artifact${project.build.directory}/protoc-gen-validate-${project.version}-osx-x86_64.exeexeosx-x86_64${project.build.directory}/protoc-gen-validate-${project.version}-osx-aarch_64.exeexeosx-aarch_64${project.build.directory}/protoc-gen-validate-${project.version}-linux-aarch_64.exeexelinux-aarch_64${project.build.directory}/protoc-gen-validate-${project.version}-linux-x86_32.exeexelinux-x86_32${project.build.directory}/protoc-gen-validate-${project.version}-linux-x86_64.exeexelinux-x86_64${project.build.directory}/protoc-gen-validate-${project.version}-windows-x86_32.exeexewindows-x86_32${project.build.directory}/protoc-gen-validate-${project.version}-windows-x86_64.exeexewindows-x86_64
protoc-gen-validate-1.0.2/java/pgv-java-grpc/ 0000775 0000000 0000000 00000000000 14445363531 0020753 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/pom.xml 0000664 0000000 0000000 00000011726 14445363531 0022277 0 ustar 00root root 0000000 0000000
pgv-javabuild.buf.protoc-gen-validateVERSION4.0.0pgv-java-grpcPGV-Java gRPC Interceptorsio.grpcgrpc-bom${grpc.version}pomimportcom.google.api.grpcproto-google-common-protos${proto-google-common-protos.version}io.grpcgrpc-coreio.grpcgrpc-testingtestio.grpcgrpc-protobufio.grpcgrpc-stubtestjavax.annotationjavax.annotation-api1.3.2testbuild.buf.protoc-gen-validateprotoc-gen-validate${project.version}pomtestbuild.buf.protoc-gen-validatepgv-java-stub${project.version}kr.motd.mavenos-maven-plugin1.7.1org.xolstice.maven.pluginsprotobuf-maven-plugin${protobuf.maven.plugin.version}com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}grpc-javaio.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}test-compiletest-compile-customprotoc-java-pgvtest-compile-customlang=javajava-pgvbuild.buf.protoc-gen-validate:protoc-gen-validate:${project.version}:exe:${os.detected.classifier}org.jacocojacoco-maven-plugin0.8.10prepare-agentreportprepare-packagereport
protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/ 0000775 0000000 0000000 00000000000 14445363531 0021542 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/ 0000775 0000000 0000000 00000000000 14445363531 0022466 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/ 0000775 0000000 0000000 00000000000 14445363531 0023407 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/ 0000775 0000000 0000000 00000000000 14445363531 0024016 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/envoyproxy/ 0000775 0000000 0000000 00000000000 14445363531 0026260 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/envoyproxy/pgv/ 0000775 0000000 0000000 00000000000 14445363531 0027054 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/envoyproxy/pgv/grpc/ 0000775 0000000 0000000 00000000000 14445363531 0030007 5 ustar 00root root 0000000 0000000 ValidatingClientInterceptor.java 0000664 0000000 0000000 00000002343 14445363531 0036235 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/envoyproxy/pgv/grpc package 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.java 0000664 0000000 0000000 00000003333 14445363531 0036265 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/envoyproxy/pgv/grpc package 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.java 0000664 0000000 0000000 00000003001 14445363531 0034721 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/main/java/io/envoyproxy/pgv/grpc package 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/ 0000775 0000000 0000000 00000000000 14445363531 0022521 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/ 0000775 0000000 0000000 00000000000 14445363531 0023442 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/io/ 0000775 0000000 0000000 00000000000 14445363531 0024051 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/io/envoyproxy/ 0000775 0000000 0000000 00000000000 14445363531 0026313 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/io/envoyproxy/pgv/ 0000775 0000000 0000000 00000000000 14445363531 0027107 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/io/envoyproxy/pgv/grpc/ 0000775 0000000 0000000 00000000000 14445363531 0030042 5 ustar 00root root 0000000 0000000 ValidatingClientInterceptorTest.java 0000664 0000000 0000000 00000014002 14445363531 0037123 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/io/envoyproxy/pgv/grpc package 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.java 0000664 0000000 0000000 00000012241 14445363531 0037156 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/java/io/envoyproxy/pgv/grpc package 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/ 0000775 0000000 0000000 00000000000 14445363531 0023664 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-grpc/src/test/proto/BUILD.bazel 0000664 0000000 0000000 00000002300 14445363531 0025535 0 ustar 00root root 0000000 0000000 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")
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.proto 0000664 0000000 0000000 00000000550 14445363531 0026201 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000000703 14445363531 0026054 0 ustar 00root root 0000000 0000000 syntax = "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/ 0000775 0000000 0000000 00000000000 14445363531 0020775 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/pom.xml 0000664 0000000 0000000 00000012451 14445363531 0022315 0 ustar 00root root 0000000 0000000
pgv-javabuild.buf.protoc-gen-validateVERSION4.0.0pgv-java-stubPGV-Java Stubscom.google.re2jre2j${re2j.version}commons-validatorcommons-validator${commons.validator.version}**com.google.protobufprotobuf-java${google.protobuf.version}com.google.protobufprotobuf-java-util${google.protobuf.version}build.buf.protoc-gen-validateprotoc-gen-validate${project.version}pomtest../..validate/validate.protokr.motd.mavenos-maven-plugin1.7.1org.xolstice.maven.pluginsprotobuf-maven-plugin${protobuf.maven.plugin.version}com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}protoc-java-pgvcompile../../validate/*.protoprotoc-javatest-compiletest-protoc-java-pgvtest-compile-customlang=javajava-pgvbuild.buf.protoc-gen-validate:protoc-gen-validate:${project.version}:exe:${os.detected.classifier}org.jacocojacoco-maven-plugin0.8.10prepare-agentreportprepare-packagereport
protoc-gen-validate-1.0.2/java/pgv-java-stub/src/ 0000775 0000000 0000000 00000000000 14445363531 0021564 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/ 0000775 0000000 0000000 00000000000 14445363531 0022510 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/ 0000775 0000000 0000000 00000000000 14445363531 0023431 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/ 0000775 0000000 0000000 00000000000 14445363531 0024040 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/ 0000775 0000000 0000000 00000000000 14445363531 0026302 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/ 0000775 0000000 0000000 00000000000 14445363531 0027076 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv/BUILD 0000664 0000000 0000000 00000000601 14445363531 0027655 0 ustar 00root root 0000000 0000000 load("@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.java 0000664 0000000 0000000 00000006414 14445363531 0033047 0 ustar 00root root 0000000 0000000 package 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.java 0000664 0000000 0000000 00000001522 14445363531 0033766 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000010053 14445363531 0034146 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv package 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.java0000664 0000000 0000000 00000000676 14445363531 0033556 0 ustar 00root root 0000000 0000000 package 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.java 0000664 0000000 0000000 00000001013 14445363531 0032653 0 ustar 00root root 0000000 0000000 package 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.java 0000664 0000000 0000000 00000002750 14445363531 0034305 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000002506 14445363531 0032474 0 ustar 00root root 0000000 0000000 package 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.java 0000664 0000000 0000000 00000004043 14445363531 0034611 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv package 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.java0000664 0000000 0000000 00000002767 14445363531 0033521 0 ustar 00root root 0000000 0000000 package 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.java0000664 0000000 0000000 00000000720 14445363531 0033533 0 ustar 00root root 0000000 0000000 package 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.java 0000664 0000000 0000000 00000026373 14445363531 0033235 0 ustar 00root root 0000000 0000000 package 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.java 0000664 0000000 0000000 00000003051 14445363531 0033637 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000000466 14445363531 0034355 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000001172 14445363531 0033634 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/main/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000002114 14445363531 0031664 0 ustar 00root root 0000000 0000000 package 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.java 0000664 0000000 0000000 00000001123 14445363531 0032505 0 ustar 00root root 0000000 0000000 package 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.java 0000664 0000000 0000000 00000002120 14445363531 0032651 0 ustar 00root root 0000000 0000000 package 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/ 0000775 0000000 0000000 00000000000 14445363531 0022543 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/ 0000775 0000000 0000000 00000000000 14445363531 0023464 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/ 0000775 0000000 0000000 00000000000 14445363531 0024073 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/ 0000775 0000000 0000000 00000000000 14445363531 0026335 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv/ 0000775 0000000 0000000 00000000000 14445363531 0027131 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv/AnyValidationTest.java 0000664 0000000 0000000 00000002251 14445363531 0033376 0 ustar 00root root 0000000 0000000 package 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.java 0000664 0000000 0000000 00000000641 14445363531 0032127 0 ustar 00root root 0000000 0000000 package 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.java 0000664 0000000 0000000 00000013006 14445363531 0033656 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000001453 14445363531 0034664 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000014042 14445363531 0035043 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000001247 14445363531 0034365 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000007043 14445363531 0034361 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv package 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.java0000664 0000000 0000000 00000002576 14445363531 0033565 0 ustar 00root root 0000000 0000000 package 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.java 0000664 0000000 0000000 00000003100 14445363531 0035166 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000002346 14445363531 0033371 0 ustar 00root root 0000000 0000000 package 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.java 0000664 0000000 0000000 00000005012 14445363531 0035501 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000002437 14445363531 0034327 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000000763 14445363531 0034356 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000026027 14445363531 0034045 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv package 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.java 0000664 0000000 0000000 00000007324 14445363531 0034541 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/java/io/envoyproxy/pgv package 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/ 0000775 0000000 0000000 00000000000 14445363531 0023706 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-stub/src/test/proto/BUILD.bazel 0000664 0000000 0000000 00000001112 14445363531 0025557 0 ustar 00root root 0000000 0000000 load("@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.proto 0000664 0000000 0000000 00000000440 14445363531 0026522 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000000231 14445363531 0025733 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000000727 14445363531 0027753 0 ustar 00root root 0000000 0000000 syntax = "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/ 0000775 0000000 0000000 00000000000 14445363531 0022152 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/pom.xml 0000664 0000000 0000000 00000013573 14445363531 0023500 0 ustar 00root root 0000000 0000000
pgv-javabuild.buf.protoc-gen-validateVERSION4.0.0pgv-java-validationPGV-Java Validation Harnesstruebuild.buf.protoc-gen-validatepgv-java-stub${project.version}com.google.protobufprotobuf-java${google.protobuf.version}build.buf.protoc-gen-validateprotoc-gen-validate${project.version}pomkr.motd.mavenos-maven-plugin1.7.1org.xolstice.maven.pluginsprotobuf-maven-plugin${protobuf.maven.plugin.version}com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}protoc-javacompile../../tests/harness/harness.prototests/harness/cases/*.prototests/harness/cases/other_package/*.prototests/harness/cases/yet_another_package/*.prototests/harness/cases/sort/*.protoprotoc-java-pgvcompile-custom../../lang=javatests/harness/cases/*.prototests/harness/cases/other_package/*.prototests/harness/cases/yet_another_package/*.protojava-pgvbuild.buf.protoc-gen-validate:protoc-gen-validate:${project.version}:exe:${os.detected.classifier}org.apache.maven.pluginsmaven-shade-plugin3.5.0packageshadejava-harnessio.envoyproxy.pgv.validation.JavaHarnessorg.jacocojacoco-maven-plugin0.8.10prepare-agentreportprepare-packagereport
protoc-gen-validate-1.0.2/java/pgv-java-validation/src/ 0000775 0000000 0000000 00000000000 14445363531 0022741 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/ 0000775 0000000 0000000 00000000000 14445363531 0023665 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/ 0000775 0000000 0000000 00000000000 14445363531 0024606 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/ 0000775 0000000 0000000 00000000000 14445363531 0025215 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/envoyproxy/ 0000775 0000000 0000000 00000000000 14445363531 0027457 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/envoyproxy/pgv/ 0000775 0000000 0000000 00000000000 14445363531 0030253 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/envoyproxy/pgv/BUILD 0000664 0000000 0000000 00000000334 14445363531 0031035 0 ustar 00root root 0000000 0000000 load("@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/ 0000775 0000000 0000000 00000000000 14445363531 0032405 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/envoyproxy/pgv/validation/BUILD 0000664 0000000 0000000 00000001635 14445363531 0033174 0 ustar 00root root 0000000 0000000 load("@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.java 0000664 0000000 0000000 00000006633 14445363531 0035406 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/envoyproxy/pgv/validation package 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.java 0000664 0000000 0000000 00000020623 14445363531 0035577 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/main/java/io/envoyproxy/pgv/validation package 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/ 0000775 0000000 0000000 00000000000 14445363531 0023720 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/test/java/ 0000775 0000000 0000000 00000000000 14445363531 0024641 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/test/java/io/ 0000775 0000000 0000000 00000000000 14445363531 0025250 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/test/java/io/envoyproxy/ 0000775 0000000 0000000 00000000000 14445363531 0027512 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/test/java/io/envoyproxy/pgv/ 0000775 0000000 0000000 00000000000 14445363531 0030306 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/test/java/io/envoyproxy/pgv/validation/ 0000775 0000000 0000000 00000000000 14445363531 0032440 5 ustar 00root root 0000000 0000000 ProtoTypeMapTest.java 0000664 0000000 0000000 00000002764 14445363531 0036500 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-java-validation/src/test/java/io/envoyproxy/pgv/validation package 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/ 0000775 0000000 0000000 00000000000 14445363531 0023162 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/java/pgv-test-coverage-report/pom.xml 0000664 0000000 0000000 00000004336 14445363531 0024505 0 ustar 00root root 0000000 0000000
pgv-javabuild.buf.protoc-gen-validateVERSION4.0.0pgv-test-coverage-reportPGV-Java Code Coverage Reportbuild.buf.protoc-gen-validateprotoc-gen-validate${project.version}pomtestbuild.buf.protoc-gen-validatepgv-java-stub${project.version}build.buf.protoc-gen-validatepgv-java-grpc${project.version}build.buf.protoc-gen-validatepgv-java-validation${project.version}org.jacocojacoco-maven-plugin0.8.10prepare-agentreportprepare-packagereport-aggregate
protoc-gen-validate-1.0.2/java/pom.xml 0000664 0000000 0000000 00000020212 14445363531 0017621 0 ustar 00root root 0000000 0000000
4.0.0build.buf.protoc-gen-validatepgv-javaVERSIONpgv-java-stubpgv-java-validationpgv-java-grpcpgv-artifactspgv-test-coverage-reportpomPGV-Java ParentProtoc plugin to generate protobuf message validators.https://github.com/envoyproxy/protoc-gen-validateThe Apache Software License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0.txtrepoelliotmjacksonElliot Jacksonejackson@buf.buildUTF-83.22.23.23.30.6.11.71.71.56.04.13.23.24.281.82.21.0junitjunit${junit.version}testorg.assertjassertj-core${assertj.version}testorg.apache.maven.pluginsmaven-compiler-plugin3.11.0${java.release}${java.version}${java.version}-Xlint:uncheckedorg.apache.maven.pluginsmaven-surefire-plugin3.1.2falseorg.apache.maven.pluginsmaven-javadoc-plugin3.5.0falsetrueaccessibility,html,reference,syntaxtruefalse8attach-javadocsjarorg.apache.maven.pluginsmaven-source-plugin3.3.0attach-sourcesjarciorg.apache.maven.pluginsmaven-release-plugin3.0.1truev@{project.version}-javajava release: java/pom.xmlorg.codehaus.mojoversions-maven-plugin2.16.0org.sonatype.pluginsnexus-staging-maven-plugin1.6.13truesonatype-nexus-staginghttps://s01.oss.sonatype.org/truesigningorg.apache.maven.pluginsmaven-gpg-plugin3.1.0sign-artifactsverifysign--pinentry-modeloopbackhttps://github.com/bufbuild/protoc-gen-validatescm:git:git@github.com:bufbuild/protoc-gen-validate.gitscm:git:git@github.com:bufbuild/protoc-gen-validate.gitHEADsonatype-nexus-snapshotshttps://s01.oss.sonatype.org/content/repositories/snapshots
protoc-gen-validate-1.0.2/java/settings.xml 0000664 0000000 0000000 00000003540 14445363531 0020673 0 ustar 00root root 0000000 0000000 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}cisonatype-staginghttps://s01.oss.sonatype.org/service/local/staging/deploy/maven2/defaulttruesigninggpg${env.GPG_KEY_NAME}${env.GPG_PASSPHRASE}cisigning
protoc-gen-validate-1.0.2/main.go 0000664 0000000 0000000 00000000731 14445363531 0016642 0 ustar 00root root 0000000 0000000 package 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/ 0000775 0000000 0000000 00000000000 14445363531 0016653 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/module/BUILD 0000664 0000000 0000000 00000001645 14445363531 0017443 0 ustar 00root root 0000000 0000000 load("@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.go 0000664 0000000 0000000 00000033517 14445363531 0020617 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000005104 14445363531 0020773 0 ustar 00root root 0000000 0000000 package 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/ 0000775 0000000 0000000 00000000000 14445363531 0016707 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/python/BUILD 0000664 0000000 0000000 00000000475 14445363531 0017477 0 ustar 00root root 0000000 0000000 load("@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.md 0000664 0000000 0000000 00000002222 14445363531 0020164 0 ustar 00root root 0000000 0000000 # 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.md protoc-gen-validate-1.0.2/python/protoc_gen_validate/ 0000775 0000000 0000000 00000000000 14445363531 0022717 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/python/protoc_gen_validate/__init__.py 0000664 0000000 0000000 00000000000 14445363531 0025016 0 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/python/protoc_gen_validate/validator.py 0000664 0000000 0000000 00000142157 14445363531 0025270 0 ustar 00root root 0000000 0000000 import 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.toml 0000664 0000000 0000000 00000000247 14445363531 0021626 0 ustar 00root root 0000000 0000000 [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.in 0000664 0000000 0000000 00000000352 14445363531 0021762 0 ustar 00root root 0000000 0000000 # 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.cfg 0000664 0000000 0000000 00000001513 14445363531 0020530 0 ustar 00root root 0000000 0000000 [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.txt 0000664 0000000 0000000 00000000464 14445363531 0020656 0 ustar 00root root 0000000 0000000 # 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.md 0000664 0000000 0000000 00000010167 14445363531 0021116 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 14445363531 0017364 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/templates/BUILD.bazel 0000664 0000000 0000000 00000001420 14445363531 0021237 0 ustar 00root root 0000000 0000000 load("@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/ 0000775 0000000 0000000 00000000000 14445363531 0017751 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/templates/cc/BUILD.bazel 0000664 0000000 0000000 00000002300 14445363531 0021622 0 ustar 00root root 0000000 0000000 load("@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.go 0000664 0000000 0000000 00000001040 14445363531 0021062 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000005567 14445363531 0021443 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000477 14445363531 0021436 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000006410 14445363531 0022126 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000671 14445363531 0021250 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000003367 14445363531 0021230 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001415 14445363531 0020707 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000003142 14445363531 0021434 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000004133 14445363531 0021253 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000002651 14445363531 0021061 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001044 14445363531 0021723 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000012523 14445363531 0021071 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000225 14445363531 0021236 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000342 14445363531 0021076 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000027333 14445363531 0022134 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000004017 14445363531 0022073 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000012701 14445363531 0021607 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000007405 14445363531 0022311 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000444 14445363531 0021762 0 ustar 00root root 0000000 0000000 package 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/ 0000775 0000000 0000000 00000000000 14445363531 0020466 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/templates/ccnop/BUILD.bazel 0000664 0000000 0000000 00000000751 14445363531 0022347 0 ustar 00root root 0000000 0000000 load("@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.go 0000664 0000000 0000000 00000001475 14445363531 0021743 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000662 14445363531 0022645 0 ustar 00root root 0000000 0000000 package 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/ 0000775 0000000 0000000 00000000000 14445363531 0017771 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/templates/go/BUILD.bazel 0000664 0000000 0000000 00000001336 14445363531 0021652 0 ustar 00root root 0000000 0000000 load("@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.go 0000664 0000000 0000000 00000000721 14445363531 0022145 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000002130 14445363531 0021233 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001772 14445363531 0021753 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000770 14445363531 0022150 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000327 14445363531 0022142 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000734 14445363531 0022327 0 ustar 00root root 0000000 0000000 package 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/ 0000775 0000000 0000000 00000000000 14445363531 0021160 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/templates/goshared/BUILD.bazel 0000664 0000000 0000000 00000002257 14445363531 0023044 0 ustar 00root root 0000000 0000000 load("@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.go 0000664 0000000 0000000 00000001105 14445363531 0022273 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000007062 14445363531 0022642 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000605 14445363531 0022636 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000007370 14445363531 0023343 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000602 14445363531 0022451 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001343 14445363531 0022116 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000003107 14445363531 0022644 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000005735 14445363531 0022473 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000004010 14445363531 0022257 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000020145 14445363531 0022277 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000233 14445363531 0022444 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000351 14445363531 0022305 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000024163 14445363531 0023341 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000004016 14445363531 0023301 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000014027 14445363531 0023021 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000011260 14445363531 0023512 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000526 14445363531 0023172 0 ustar 00root root 0000000 0000000 package 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/ 0000775 0000000 0000000 00000000000 14445363531 0020305 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/templates/java/BUILD.bazel 0000664 0000000 0000000 00000002326 14445363531 0022166 0 ustar 00root root 0000000 0000000 load("@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.go 0000664 0000000 0000000 00000001533 14445363531 0021425 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000332 14445363531 0021565 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000006521 14445363531 0021766 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000006215 14445363531 0022465 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000002323 14445363531 0021600 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000002350 14445363531 0021553 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000002264 14445363531 0021415 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000574 14445363531 0022266 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000002026 14445363531 0021422 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000124 14445363531 0021570 0 ustar 00root root 0000000 0000000 package java
const noneTpl = `// no validation rules for {{ simpleName .Field }}
`
protoc-gen-validate-1.0.2/templates/java/num.go 0000664 0000000 0000000 00000006124 14445363531 0021436 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000652 14445363531 0021745 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000035407 14445363531 0022471 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001475 14445363531 0022434 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000512 14445363531 0022452 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000010014 14445363531 0022136 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000006446 14445363531 0022651 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000104 14445363531 0023475 0 ustar 00root root 0000000 0000000 package java
const notImplementedTpl = `/* NOT YET IMPLEMENTED */`
protoc-gen-validate-1.0.2/templates/java/wrapper.go 0000664 0000000 0000000 00000000607 14445363531 0022317 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000003170 14445363531 0020475 0 ustar 00root root 0000000 0000000 package 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/ 0000775 0000000 0000000 00000000000 14445363531 0020632 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/templates/shared/BUILD.bazel 0000664 0000000 0000000 00000001442 14445363531 0022511 0 ustar 00root root 0000000 0000000 load("@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.go 0000664 0000000 0000000 00000012227 14445363531 0022651 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001303 14445363531 0022725 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000002015 14445363531 0022306 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000735 14445363531 0023176 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000740 14445363531 0023314 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000003443 14445363531 0023344 0 ustar 00root root 0000000 0000000 package 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/ 0000775 0000000 0000000 00000000000 14445363531 0016530 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/generation/ 0000775 0000000 0000000 00000000000 14445363531 0020663 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/generation/multi_file_java_test/ 0000775 0000000 0000000 00000000000 14445363531 0025054 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/generation/multi_file_java_test/BUILD 0000664 0000000 0000000 00000001222 14445363531 0025633 0 ustar 00root root 0000000 0000000 load("@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.md 0000664 0000000 0000000 00000000403 14445363531 0026330 0 ustar 00root root 0000000 0000000 # 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.cc 0000664 0000000 0000000 00000000305 14445363531 0026305 0 ustar 00root root 0000000 0000000 #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.proto 0000664 0000000 0000000 00000000306 14445363531 0027117 0 ustar 00root root 0000000 0000000 syntax = "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.mod 0000664 0000000 0000000 00000000412 14445363531 0017633 0 ustar 00root root 0000000 0000000 module 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.sum 0000664 0000000 0000000 00000010331 14445363531 0017661 0 ustar 00root root 0000000 0000000 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/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/ 0000775 0000000 0000000 00000000000 14445363531 0020173 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/harness/BUILD 0000664 0000000 0000000 00000002537 14445363531 0020764 0 ustar 00root root 0000000 0000000 load("@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/ 0000775 0000000 0000000 00000000000 14445363531 0021271 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/harness/cases/.gitignore 0000664 0000000 0000000 00000000017 14445363531 0023257 0 ustar 00root root 0000000 0000000 *.pb.cc
*.pb.h
protoc-gen-validate-1.0.2/tests/harness/cases/BUILD 0000664 0000000 0000000 00000007363 14445363531 0022064 0 ustar 00root root 0000000 0000000 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(
"//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.proto 0000664 0000000 0000000 00000000570 14445363531 0023313 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000003137 14445363531 0023510 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000005634 14445363531 0023515 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000000261 14445363531 0026023 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000004055 14445363531 0025033 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000003553 14445363531 0023324 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000002341 14445363531 0024165 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000031672 14445363531 0024042 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000002164 14445363531 0023652 0 ustar 00root root 0000000 0000000 syntax = "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/ 0000775 0000000 0000000 00000000000 14445363531 0024065 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/harness/cases/other_package/BUILD 0000664 0000000 0000000 00000004151 14445363531 0024650 0 ustar 00root root 0000000 0000000 load("@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.proto 0000664 0000000 0000000 00000001017 14445363531 0026225 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000006102 14445363531 0024146 0 ustar 00root root 0000000 0000000 syntax = "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/ 0000775 0000000 0000000 00000000000 14445363531 0022260 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/harness/cases/sort/BUILD 0000664 0000000 0000000 00000004056 14445363531 0023047 0 ustar 00root root 0000000 0000000 load("@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.proto 0000664 0000000 0000000 00000000341 14445363531 0024332 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000006531 14445363531 0024054 0 ustar 00root root 0000000 0000000 syntax = "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/ 0000775 0000000 0000000 00000000000 14445363531 0024007 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/harness/cases/subdirectory/in_subdirectory.proto 0000664 0000000 0000000 00000000262 14445363531 0030300 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000001164 14445363531 0024034 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000004013 14445363531 0025066 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000000751 14445363531 0024530 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000004045 14445363531 0025251 0 ustar 00root root 0000000 0000000 syntax = "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.proto 0000664 0000000 0000000 00000003336 14445363531 0025113 0 ustar 00root root 0000000 0000000 syntax = "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/ 0000775 0000000 0000000 00000000000 14445363531 0025265 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/harness/cases/yet_another_package/BUILD 0000664 0000000 0000000 00000004223 14445363531 0026050 0 ustar 00root root 0000000 0000000 load("@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.proto 0000664 0000000 0000000 00000000723 14445363531 0027430 0 ustar 00root root 0000000 0000000 syntax = "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/ 0000775 0000000 0000000 00000000000 14445363531 0020560 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/harness/cc/BUILD 0000664 0000000 0000000 00000004304 14445363531 0021343 0 ustar 00root root 0000000 0000000 load("@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.cc 0000664 0000000 0000000 00000002365 14445363531 0023336 0 ustar 00root root 0000000 0000000 #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.cc 0000664 0000000 0000000 00000002432 14445363531 0023542 0 ustar 00root root 0000000 0000000 #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.cc 0000664 0000000 0000000 00000014374 14445363531 0022543 0 ustar 00root root 0000000 0000000 #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.proto 0000664 0000000 0000000 00000000076 14445363531 0022771 0 ustar 00root root 0000000 0000000 syntax = "proto3";
package tests.harness.cc;
message Foo {}
protoc-gen-validate-1.0.2/tests/harness/cc/polymorphic_test.cc 0000664 0000000 0000000 00000001055 14445363531 0024474 0 ustar 00root root 0000000 0000000 #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/ 0000775 0000000 0000000 00000000000 14445363531 0022031 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/harness/executor/BUILD 0000664 0000000 0000000 00000004234 14445363531 0022616 0 ustar 00root root 0000000 0000000 load("@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.go 0000664 0000000 0000000 00000257635 14445363531 0023500 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000005323 14445363531 0024221 0 ustar 00root root 0000000 0000000 package 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.sh 0000775 0000000 0000000 00000000100 14445363531 0025254 0 ustar 00root root 0000000 0000000 #!/bin/bash
#
set -x
EXECUTOR_BIN=$1
shift
$EXECUTOR_BIN "$@"
protoc-gen-validate-1.0.2/tests/harness/executor/harness.go 0000664 0000000 0000000 00000005424 14445363531 0024030 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000005305 14445363531 0023674 0 ustar 00root root 0000000 0000000 package 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/ 0000775 0000000 0000000 00000000000 14445363531 0020600 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/harness/go/main/ 0000775 0000000 0000000 00000000000 14445363531 0021524 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/harness/go/main/BUILD 0000664 0000000 0000000 00000002474 14445363531 0022315 0 ustar 00root root 0000000 0000000 load("@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.go 0000664 0000000 0000000 00000006373 14445363531 0023527 0 ustar 00root root 0000000 0000000 package 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.proto 0000664 0000000 0000000 00000000615 14445363531 0022725 0 ustar 00root root 0000000 0000000 syntax = "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/ 0000775 0000000 0000000 00000000000 14445363531 0021114 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/harness/java/BUILD 0000664 0000000 0000000 00000000512 14445363531 0021674 0 ustar 00root root 0000000 0000000 load("@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/ 0000775 0000000 0000000 00000000000 14445363531 0021514 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tests/harness/python/BUILD 0000664 0000000 0000000 00000001476 14445363531 0022306 0 ustar 00root root 0000000 0000000 load("@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.py 0000664 0000000 0000000 00000005051 14445363531 0023532 0 ustar 00root root 0000000 0000000 import 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.py 0000775 0000000 0000000 00000002331 14445363531 0025652 0 ustar 00root root 0000000 0000000 import 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.go 0000664 0000000 0000000 00000000346 14445363531 0017060 0 ustar 00root root 0000000 0000000 //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/ 0000775 0000000 0000000 00000000000 14445363531 0016526 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tools/build/ 0000775 0000000 0000000 00000000000 14445363531 0017625 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/tools/build/Env.mk 0000664 0000000 0000000 00000000404 14445363531 0020704 0 ustar 00root root 0000000 0000000 # 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.mk 0000664 0000000 0000000 00000002525 14445363531 0021052 0 ustar 00root root 0000000 0000000 # 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.mk 0000664 0000000 0000000 00000002025 14445363531 0022112 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 14445363531 0017157 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/validate/BUILD 0000664 0000000 0000000 00000003566 14445363531 0017753 0 ustar 00root root 0000000 0000000 load("@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.h 0000664 0000000 0000000 00000012646 14445363531 0021132 0 ustar 00root root 0000000 0000000 #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.go 0000664 0000000 0000000 00000426767 14445363531 0021725 0 ustar 00root root 0000000 0000000 // 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.proto 0000664 0000000 0000000 00000075022 14445363531 0022043 0 ustar 00root root 0000000 0000000 syntax = "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/ 0000775 0000000 0000000 00000000000 14445363531 0017060 5 ustar 00root root 0000000 0000000 protoc-gen-validate-1.0.2/windows/bazel.rc 0000664 0000000 0000000 00000000031 14445363531 0020475 0 ustar 00root root 0000000 0000000 build --verbose_failures
protoc-gen-validate-1.0.2/windows/ci.ps1 0000664 0000000 0000000 00000000347 14445363531 0020104 0 ustar 00root root 0000000 0000000 $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