General Structure
Love it or hate it, ngen uses TOML as its configuration language. ngen requires a reference to a singular, well-formed configuration file to run.
This chapter goes in-depth about what this config file looks like, explaining what makes a config file “well-formed” and what to avoid.
ngen does not assume a particular ordering of configuration file sections.
Header
version = 1
The “header” section of an ngen file is currently very simple, requiring a field version,
which holds an integer value from 0 to 255 (inclusive).
This field currently does not serve any purpose other than future proofing. Its intended purpose is to be able to facilitate programmatic distinction between configuration file versions, should this be needed in the future.
general
Every ngen configuration file must contain a section [general], formatted as such:
[general]
# May be empty; array of conversion rules
convert = []
# Boolean value; whether the rules in the `convert` array are
# being considered when generating type mappings
enabled = true
# String, valid path; Where the auto-generated code should be placed.
output = "./example/src/auto_gen/matrix_v113.rs"
Fallback Behavior
Read the chapter “Priority Resolution” in “Route Matching” to learn more.
output
The path in the output directory must be readable and writable by the operating system user
executing ngen. Both absolute and relative paths are allowed. The file that is being
pointed to in the path will be replaced entirely with the auto-generated code generated
by ngen.
For more information on what happens to this file and parent mod.rs files, see
the “Generating Code” chapter.
Custom Rulesets
In addition to the general ruleset, an unlimited amount of custom rulesets may be present in
the configuration file. Custom rulesets allow you to apply different conversion rules to specific
groups of API routes based on regex pattern matching.
Custom rulesets are formatted as such:
[admin_api] # String, unique per config file; Name of custom ruleset
include_routes = [] # Array of String; Regex patterns of route paths to include in this ruleset
exclude_routes = [] # Array of String; Regex patterns of route paths to exclude from this ruleset
convert = [] # Array of Object; Conversion rules to apply to all matched routes
Route Matching
Custom rulesets use regex patterns to determine which OpenAPI routes they should apply to:
include_routes: Array of regex patterns. If any pattern matches a route path, that route is included in this ruleset (unless explicitly excluded).exclude_routes: Array of regex patterns. If any pattern matches a route path, that route is excluded from this ruleset, even if it matches an include pattern.
Exclude patterns take precedence over include patterns.
Example
[matrix_client_v1]
include_routes = ['^/_matrix/client/v1/.*$'] # Include all Matrix client v1 routes
exclude_routes = ['^/_matrix/client/v1/admin/.*$'] # But exclude admin routes
convert = [
{ from = "roomId", to = "RoomId" },
{ from = "userId", to = "UserId" }
]
[admin_api]
include_routes = [
'^/admin/.*$', # All admin routes
'specific/route/\{id\}/actions' # Plus this specific route
]
exclude_routes = ['^/admin/health$'] # Except health check
convert = [
{ from = "adminId", to = "AdminUserId" }
]
Priority and Fallback Behavior
Rulesets have priority based on their specificity and definition order:
- Custom rulesets are processed first, in the order they appear in the configuration file
- General ruleset acts as a fallback for routes not matched by any custom ruleset
- Rule inheritance: If the general ruleset is enabled, its rules are merged into custom rulesets, but custom ruleset rules take precedence
Priority Example
[general]
convert = [
{ from = "userId", to = "String" }, # Fallback mapping
{ from = "roomId", to = "String" } # Fallback mapping
]
enabled = true
[matrix_client_v1]
include_routes = ['^/_matrix/client/v1/.*$']
convert = [
{ from = "roomId", to = "RoomId" } # Overrides general ruleset for roomId
# userId inherits from general ruleset (maps to "String")
]
Best Practices
- Order matters: Define more specific rulesets before general ones
- Use descriptive names: Ruleset names should clearly indicate their purpose
- Test regex patterns: Ensure your include/exclude patterns match the intended routes. You can use https://regex101.com/ to help with this. Don’t forget to set the regex engine flavor to “Rust”!