protocheck-build 0.1.10

⚙️ Build-time entrypoint for protocheck
docs.rs failed to build protocheck-build-0.1.10
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: protocheck-build-0.1.11

⚒️ Protocheck-build

This is the build-time entrypoint for protocheck.

➡️ Getting started

To get started, you need to use [protocheck-build] as a build dependency in your crate, which will use protocheck-proc-macro to add all the validation logic to your structs. The setup will look more or less like this (this is taken directly from the tests crate)

// In your build.rs file
use prost_build::Config;
use protocheck_build::{compile_protos_with_validators, get_proto_files_recursive};
use std::{
  env,
  path::PathBuf
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
  println!("cargo:rerun-if-changed=proto/");

  let out_dir = env::var("OUT_DIR")
    .map(PathBuf::from)
    .unwrap_or(env::temp_dir());

  let descriptor_path = out_dir.join("file_descriptor_set.bin");

  let proto_include_paths = &["proto"];

  // Use the helper to get all proto files recursively in a directory
  let proto_files = get_proto_files_recursive("proto")?;

  let mut config = Config::new();
  config
    .file_descriptor_set_path(&descriptor_path)
    // Enable the use of bytes::Bytes for `bytes` fields
    .bytes(["."])
    .out_dir(&out_dir);

  // Call the build helper
  compile_protos_with_validators(&mut config, &proto_files, proto_include_paths, &["myapp.v1"])?;

  // Compile protos
  config.compile_protos(&proto_files, proto_include_paths)?;

  // Set the env for the file descriptor location
  println!(
    "cargo:rustc-env=PROTO_DESCRIPTOR_SET={}",
    descriptor_path.display()
  );

  Ok(())
}

compile_protos_with_validators takes these arguments:

  1. The config struct.
  2. The proto files and include paths being used by the config.
  3. The list of packages to apply validators to. If a given message contains Cel validation or is validated as a field by another message, its package name must be included in this list.

The function will then:

  1. Compile your protos to create an intermediary descriptor
  2. Iterate its messages, and use the information extracted from them to add the derives and attributes to the actual config that are needed by protocheck-proc-macro to add the validation logic.
  3. Add the derive macros used by protocheck
  4. Use proto_types as the source for the well known types and the protovalidate types (it is re-exported by protocheck, so there is no need to add it as a dependency).

🍸 Tonic example

When using tonic-prost-build, the workflow is almost identical, except that we pass the config to compile_with_config:

  let mut config = Config::new();
  config
    .file_descriptor_set_path(&descriptor_path)
    .bytes(["."])
    .out_dir(&out_dir);

  // Call the build helper
  compile_protos_with_validators(&mut config, &proto_files, &["proto".to_string()], &["myapp.v1"])?;

  // Compile protos
  tonic_prost_build::configure()
    // We pass the config here
    .compile_with_config(config, &proto_files, &["proto".to_string()])?;
}