cwist
Modern C web framework with libttak runtime
Loading...
Searching...
No Matches
bind.h File Reference

Declarative Schema Validation and Type-Safe Binding for CWIST. More...

#include <cwist/net/http/http.h>
#include <cwist/core/sstring/sstring.h>
#include <cwist/core/utils/json_builder.h>
#include <cjson/cJSON.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <regex.h>
Include dependency graph for bind.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  cwist_bind_rule
 Single validation rule attached to a field. More...
 
struct  cwist_bind_field
 Per-field binding descriptor. More...
 
struct  cwist_bind_schema
 Complete schema descriptor for a struct. More...
 
struct  cwist_bind_error
 A single bind/validation failure. More...
 
struct  cwist_bind_result
 Result of a bind operation. More...
 

Macros

#define CWIST_BIND_MAX_ERRORS   32
 
#define CWIST_BIND_MSG_MAX   256
 
#define CWIST_BIND_KEY_MAX   64
 
#define CWIST_BIND_TYPEOF(x)
 Internal helper that resolves the cwist_bind_field_type_t for a C expression.
 
#define CWIST_BIND_OFFSET(st, m)   offsetof(st, m)
 Compute the byte offset of a member inside a struct type.
 
#define CWIST_BIND_SIZEOF(st, m)   sizeof(((st *)0)->m)
 Compute the size of a struct member.
 
#define CWIST_BIND_RULES(name, ...)    static const cwist_bind_rule_t name[] = {__VA_ARGS__, {-1, {0}, NULL}}
 Declare a static rule array suitable for use with CWIST_BIND_FIELD.
 
#define CWIST_BIND_FIELD(StructType, MemberName, JsonKey, RulesArray)
 Helper to declare a field descriptor with automatic type inference.
 
#define CWIST_BIND_SCHEMA(StructType, FieldArray)
 Build a schema descriptor from an array of field descriptors.
 
#define CWIST_RULE_REQUIRED()
 
#define CWIST_RULE_MIN_LEN(n)
 
#define CWIST_RULE_MAX_LEN(n)
 
#define CWIST_RULE_MIN_VAL(v)
 
#define CWIST_RULE_MAX_VAL(v)
 
#define CWIST_RULE_REGEX(pat)
 
#define CWIST_RULE_EMAIL()
 
#define CWIST_RULE_CUSTOM(fn_ptr, ctx_ptr)
 

Typedefs

typedef enum cwist_bind_rule_type cwist_bind_rule_type_t
 Supported validation constraint types.
 
typedef struct cwist_bind_rule cwist_bind_rule_t
 Single validation rule attached to a field.
 
typedef enum cwist_bind_field_type cwist_bind_field_type_t
 Logical type of a bind target field.
 
typedef struct cwist_bind_field cwist_bind_field_t
 Per-field binding descriptor.
 
typedef struct cwist_bind_schema cwist_bind_schema_t
 Complete schema descriptor for a struct.
 
typedef struct cwist_bind_error cwist_bind_error_t
 A single bind/validation failure.
 
typedef struct cwist_bind_result cwist_bind_result_t
 Result of a bind operation.
 

Enumerations

enum  cwist_bind_rule_type {
  CWIST_BIND_RULE_REQUIRED , CWIST_BIND_RULE_MIN_LEN , CWIST_BIND_RULE_MAX_LEN , CWIST_BIND_RULE_MIN_VAL ,
  CWIST_BIND_RULE_MAX_VAL , CWIST_BIND_RULE_REGEX , CWIST_BIND_RULE_EMAIL , CWIST_BIND_RULE_CUSTOM
}
 Supported validation constraint types. More...
 
enum  cwist_bind_field_type {
  CWIST_BIND_BOOL , CWIST_BIND_INT , CWIST_BIND_UINT , CWIST_BIND_FLOAT ,
  CWIST_BIND_DOUBLE , CWIST_BIND_STRING , CWIST_BIND_SSTRING , CWIST_BIND_JSON_OBJECT
}
 Logical type of a bind target field. More...
 

Functions

bool cwist_app_req_bind_json (cwist_http_request *req, const cwist_bind_schema_t *schema, void *out, cwist_bind_result_t *result)
 Bind a JSON payload to a user struct according to a schema.
 
bool cwist_app_req_bind_form (cwist_http_request *req, const cwist_bind_schema_t *schema, void *out, cwist_bind_result_t *result)
 Bind URL-encoded form data to a user struct.
 
void cwist_bind_write_error_response (cwist_http_response *res, const cwist_bind_result_t *result)
 Populate a response with 400 Bad Request and a JSON error payload.
 
bool cwist_app_req_bind_json_or_400 (cwist_http_request *req, cwist_http_response *res, const cwist_bind_schema_t *schema, void *out)
 Convenience wrapper: bind JSON and auto-respond 400 on failure.
 

Detailed Description

Declarative Schema Validation and Type-Safe Binding for CWIST.

Provides a _Generic-driven dispatch layer that maps JSON/Form payloads directly into user-defined C structures with zero-copy semantics where possible. Validation rules (REQUIRED, MIN/MAX, REGEX, EMAIL) are evaluated at bind-time and automatically produce 400 Bad Request responses with descriptive JSON error payloads on failure.

Definition in file bind.h.

Macro Definition Documentation

◆ CWIST_BIND_FIELD

#define CWIST_BIND_FIELD (   StructType,
  MemberName,
  JsonKey,
  RulesArray 
)
Value:
{.json_key = (JsonKey), \
.target_type = CWIST_BIND_TYPEOF(((StructType *)0)->MemberName), \
.target_offset = CWIST_BIND_OFFSET(StructType, MemberName), \
.rules = (RulesArray)}
#define CWIST_BIND_SIZEOF(st, m)
Compute the size of a struct member.
Definition bind.h:213
#define CWIST_BIND_TYPEOF(x)
Internal helper that resolves the cwist_bind_field_type_t for a C expression.
Definition bind.h:187
#define CWIST_BIND_OFFSET(st, m)
Compute the byte offset of a member inside a struct type.
Definition bind.h:208
size_t cap
Definition otel.c:56

Helper to declare a field descriptor with automatic type inference.

Parameters
StructTypeThe C struct type being bound (e.g., struct user).
MemberNameThe member name inside the struct (e.g., email).
JsonKeyThe JSON key that maps to this member.
RulesArrayA cwist_bind_rule_t array created with CWIST_BIND_RULES.

Example:

typedef struct { char email[128]; int age; } user_t;
static const cwist_bind_field_t user_fields[] = {
};
#define CWIST_BIND_FIELD(StructType, MemberName, JsonKey, RulesArray)
Helper to declare a field descriptor with automatic type inference.
Definition bind.h:253
#define CWIST_RULE_MIN_VAL(v)
Definition bind.h:288
#define CWIST_RULE_MAX_VAL(v)
Definition bind.h:293
#define CWIST_BIND_RULES(name,...)
Declare a static rule array suitable for use with CWIST_BIND_FIELD.
Definition bind.h:228
#define CWIST_RULE_EMAIL()
Definition bind.h:303
#define CWIST_RULE_REQUIRED()
Definition bind.h:273
Per-field binding descriptor.
Definition bind.h:74

Definition at line 253 of file bind.h.

◆ CWIST_BIND_KEY_MAX

#define CWIST_BIND_KEY_MAX   64

Definition at line 96 of file bind.h.

◆ CWIST_BIND_MAX_ERRORS

#define CWIST_BIND_MAX_ERRORS   32

Definition at line 94 of file bind.h.

◆ CWIST_BIND_MSG_MAX

#define CWIST_BIND_MSG_MAX   256

Definition at line 95 of file bind.h.

◆ CWIST_BIND_OFFSET

#define CWIST_BIND_OFFSET (   st,
  m 
)    offsetof(st, m)

Compute the byte offset of a member inside a struct type.

Definition at line 208 of file bind.h.

◆ CWIST_BIND_RULES

#define CWIST_BIND_RULES (   name,
  ... 
)     static const cwist_bind_rule_t name[] = {__VA_ARGS__, {-1, {0}, NULL}}

Declare a static rule array suitable for use with CWIST_BIND_FIELD.

Parameters
nameC identifier for the array.
...cwist_bind_rule_t initialiser list.

Example:

Definition at line 228 of file bind.h.

◆ CWIST_BIND_SCHEMA

#define CWIST_BIND_SCHEMA (   StructType,
  FieldArray 
)
Value:
.fields = (FieldArray), .field_count = sizeof(FieldArray) / sizeof((FieldArray)[0]), \
.struct_size = sizeof(StructType) \
}
struct cwist_bind_schema cwist_bind_schema_t
Complete schema descriptor for a struct.

Build a schema descriptor from an array of field descriptors.

Definition at line 263 of file bind.h.

◆ CWIST_BIND_SIZEOF

#define CWIST_BIND_SIZEOF (   st,
  m 
)    sizeof(((st *)0)->m)

Compute the size of a struct member.

Definition at line 213 of file bind.h.

◆ CWIST_BIND_TYPEOF

#define CWIST_BIND_TYPEOF (   x)
Value:
_Generic((x), \
bool: CWIST_BIND_BOOL, \
@ CWIST_BIND_DOUBLE
Definition bind.h:67
@ CWIST_BIND_JSON_OBJECT
cJSON * (ownership transferred to caller).
Definition bind.h:70
@ CWIST_BIND_INT
Definition bind.h:64
@ CWIST_BIND_UINT
Definition bind.h:65
@ CWIST_BIND_FLOAT
Definition bind.h:66
@ CWIST_BIND_STRING
Null-terminated C string (copied).
Definition bind.h:68
@ CWIST_BIND_BOOL
Definition bind.h:63
@ CWIST_BIND_SSTRING
cwist_sstring target.
Definition bind.h:69

Internal helper that resolves the cwist_bind_field_type_t for a C expression.

Uses C11 _Generic to map common C types to the binding enum. This is the core mechanism that makes the macro API type-safe.

Definition at line 187 of file bind.h.

◆ CWIST_RULE_CUSTOM

#define CWIST_RULE_CUSTOM (   fn_ptr,
  ctx_ptr 
)
Value:
CWIST_BIND_RULE_CUSTOM, {.custom = {.fn = (fn_ptr), .ctx = (ctx_ptr)}}, NULL \
}
struct cwist_bind_rule cwist_bind_rule_t
Single validation rule attached to a field.
@ CWIST_BIND_RULE_CUSTOM
User-supplied predicate.
Definition bind.h:41

Definition at line 308 of file bind.h.

◆ CWIST_RULE_EMAIL

#define CWIST_RULE_EMAIL ( )
Value:
}
@ CWIST_BIND_RULE_EMAIL
Must conform to RFC 5322 simplified email shape.
Definition bind.h:40

Definition at line 303 of file bind.h.

◆ CWIST_RULE_MAX_LEN

#define CWIST_RULE_MAX_LEN (   n)
Value:
CWIST_BIND_RULE_MAX_LEN, {.max_len = (n)}, NULL \
}
@ CWIST_BIND_RULE_MAX_LEN
Maximum string length.
Definition bind.h:36

Definition at line 283 of file bind.h.

◆ CWIST_RULE_MAX_VAL

#define CWIST_RULE_MAX_VAL (   v)
Value:
CWIST_BIND_RULE_MAX_VAL, {.max_val = (v)}, NULL \
}
@ CWIST_BIND_RULE_MAX_VAL
Maximum numeric value.
Definition bind.h:38

Definition at line 293 of file bind.h.

◆ CWIST_RULE_MIN_LEN

#define CWIST_RULE_MIN_LEN (   n)
Value:
CWIST_BIND_RULE_MIN_LEN, {.min_len = (n)}, NULL \
}
@ CWIST_BIND_RULE_MIN_LEN
Minimum string length.
Definition bind.h:35

Definition at line 278 of file bind.h.

◆ CWIST_RULE_MIN_VAL

#define CWIST_RULE_MIN_VAL (   v)
Value:
CWIST_BIND_RULE_MIN_VAL, {.min_val = (v)}, NULL \
}
@ CWIST_BIND_RULE_MIN_VAL
Minimum numeric value.
Definition bind.h:37

Definition at line 288 of file bind.h.

◆ CWIST_RULE_REGEX

#define CWIST_RULE_REGEX (   pat)
Value:
CWIST_BIND_RULE_REGEX, {.pattern = (pat)}, NULL \
}
@ CWIST_BIND_RULE_REGEX
Must match POSIX extended regular expression.
Definition bind.h:39

Definition at line 298 of file bind.h.

◆ CWIST_RULE_REQUIRED

#define CWIST_RULE_REQUIRED ( )
Value:
}
@ CWIST_BIND_RULE_REQUIRED
Field must be present and non-empty.
Definition bind.h:34

Definition at line 273 of file bind.h.

Typedef Documentation

◆ cwist_bind_error_t

A single bind/validation failure.

◆ cwist_bind_field_t

Per-field binding descriptor.

◆ cwist_bind_field_type_t

Logical type of a bind target field.

◆ cwist_bind_result_t

Result of a bind operation.

◆ cwist_bind_rule_t

Single validation rule attached to a field.

◆ cwist_bind_rule_type_t

Supported validation constraint types.

◆ cwist_bind_schema_t

Complete schema descriptor for a struct.

Enumeration Type Documentation

◆ cwist_bind_field_type

Logical type of a bind target field.

Enumerator
CWIST_BIND_BOOL 
CWIST_BIND_INT 
CWIST_BIND_UINT 
CWIST_BIND_FLOAT 
CWIST_BIND_DOUBLE 
CWIST_BIND_STRING 

Null-terminated C string (copied).

CWIST_BIND_SSTRING 

cwist_sstring target.

CWIST_BIND_JSON_OBJECT 

cJSON * (ownership transferred to caller).

Definition at line 62 of file bind.h.

◆ cwist_bind_rule_type

Supported validation constraint types.

Enumerator
CWIST_BIND_RULE_REQUIRED 

Field must be present and non-empty.

CWIST_BIND_RULE_MIN_LEN 

Minimum string length.

CWIST_BIND_RULE_MAX_LEN 

Maximum string length.

CWIST_BIND_RULE_MIN_VAL 

Minimum numeric value.

CWIST_BIND_RULE_MAX_VAL 

Maximum numeric value.

CWIST_BIND_RULE_REGEX 

Must match POSIX extended regular expression.

CWIST_BIND_RULE_EMAIL 

Must conform to RFC 5322 simplified email shape.

CWIST_BIND_RULE_CUSTOM 

User-supplied predicate.

Definition at line 33 of file bind.h.

Function Documentation

◆ cwist_app_req_bind_form()

bool cwist_app_req_bind_form ( cwist_http_request *  req,
const cwist_bind_schema_t *  schema,
void *  out,
cwist_bind_result_t *  result 
)

Bind URL-encoded form data to a user struct.

Operates on req->body treating it as application/x-www-form-urlencoded.

Parameters
reqHTTP request whose body contains the form payload.
schemaBind schema describing the target struct layout.
outPointer to the user struct to populate.
result[out] Detailed validation result.
Returns
true when every field passes validation and the struct is filled.

Bind URL-encoded form data to a user struct.

Uses a simple key=value scan of the body without URL unescaping; values are bounded to an internal buffer before validation.

Parameters
reqHTTP request whose body contains form text; may be NULL.
schemaDeclarative field schema; must not be NULL.
outDestination struct; must not be NULL.
resultAccumulator for validation errors; reset at start.
Returns
true when every field passed validation, false otherwise.
Return values
trueResult is valid and out is fully written.
falseresult contains one or more field errors.

Definition at line 446 of file bind.c.

References cwist_http_request::body, cap, and cwist_sstring::data.

◆ cwist_app_req_bind_json()

bool cwist_app_req_bind_json ( cwist_http_request *  req,
const cwist_bind_schema_t *  schema,
void *  out,
cwist_bind_result_t *  result 
)

Bind a JSON payload to a user struct according to a schema.

The JSON body of req is parsed once and then each field in schema is extracted, validated, and written into out at the specified offset.

On validation failure the function returns false and populates result with per-field error messages. The caller can then pass result to cwist_bind_write_error_response() to emit a 400 response.

Parameters
reqHTTP request whose body contains the JSON payload.
schemaBind schema describing the target struct layout.
outPointer to the user struct to populate.
result[out] Detailed validation result.
Returns
true when every field passes validation and the struct is filled.

Bind a JSON payload to a user struct according to a schema.

Each schema field is looked up in the parsed JSON body, validated against its rules, and converted into the struct field at f->target_offset. The output struct is written even for fields with no matching key (zero values are written for missing fields).

Parameters
reqHTTP request whose body contains JSON text; may be NULL.
schemaDeclarative field schema; must not be NULL.
outDestination struct; must not be NULL.
resultAccumulator for validation errors; reset at start.
Returns
true when every field passed validation, false otherwise.
Return values
trueResult is valid and out is fully written.
falseresult contains one or more field errors.

Definition at line 426 of file bind.c.

References cwist_http_request::body, cap, and cwist_sstring::data.

Referenced by cwist_app_req_bind_json_or_400().

◆ cwist_app_req_bind_json_or_400()

bool cwist_app_req_bind_json_or_400 ( cwist_http_request *  req,
cwist_http_response *  res,
const cwist_bind_schema_t *  schema,
void *  out 
)

Convenience wrapper: bind JSON and auto-respond 400 on failure.

If binding succeeds, the function returns true and out is filled. If binding fails, the function automatically sets res to 400 Bad Request with a JSON error body and returns false.

Parameters
reqHTTP request.
resHTTP response (may be mutated on failure).
schemaBind schema.
outPointer to the user struct to populate.
Returns
true on success; false when res has been prepped with 400 errors.

Convenience wrapper: bind JSON and auto-respond 400 on failure.

Convenience wrapper around cwist_app_req_bind_json() and cwist_bind_write_error_response() for handlers that want automatic error replies.

Parameters
reqHTTP request whose body contains JSON text; may be NULL.
resResponse receiving the error payload when binding fails.
schemaDeclarative field schema; must not be NULL.
outDestination struct; must not be NULL.
Returns
true when binding succeeded; false when an error response was written.
Return values
trueout is fully written, res untouched.
falseA 400 error response was written to res.

Definition at line 502 of file bind.c.

References cwist_app_req_bind_json(), and cwist_bind_write_error_response().

◆ cwist_bind_write_error_response()

void cwist_bind_write_error_response ( cwist_http_response *  res,
const cwist_bind_result_t *  result 
)

Populate a response with 400 Bad Request and a JSON error payload.

The payload follows the shape:

{"success":false,"errors":[{"field":"name","message":"..."},...]}
Parameters
resResponse object to populate.
resultValidation result produced by a failed bind call.

Populate a response with 400 Bad Request and a JSON error payload.

Serializes the accumulated field errors as a JSON object { "success": false, "errors": [ { "field", "message" }, ... ] }, sets the response status and Content-Type, and takes ownership of freeing the temporary JSON builder.

Parameters
resResponse to fill in; ignored when NULL.
resultBind result containing the errors; ignored when NULL.

Definition at line 463 of file bind.c.

References cwist_http_response::body, cap, CWIST_HTTP_BAD_REQUEST, cwist_http_header_add(), cwist_json_add_bool(), cwist_json_add_string(), cwist_json_begin_array(), cwist_json_begin_object(), cwist_json_builder_create(), cwist_json_builder_destroy(), cwist_json_end_array(), cwist_json_end_object(), cwist_json_get_raw(), cwist_sstring_assign(), cwist_bind_result::error_count, cwist_bind_result::errors, cwist_http_response::headers, cwist_bind_error::key, cwist_bind_error::message, cwist_http_response::status_code, and cwist_http_response::status_text.

Referenced by cwist_app_req_bind_json_or_400().