Packages
oaspec
0.66.0
0.68.0
0.67.0
0.66.0
0.65.0
0.64.0
0.63.0
0.62.0
0.61.0
0.60.0
0.59.0
0.58.1
0.58.0
0.57.0
0.56.0
0.55.0
0.54.0
0.53.0
0.52.0
0.51.0
0.50.0
0.49.0
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.43.0
0.42.0
0.41.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.0
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.0
0.7.0
0.6.3
0.6.1
0.6.0
0.5.0
0.4.0
0.3.0
0.1.3
Generate Gleam code from OpenAPI 3.x specifications
Current section
Files
Jump to
Current section
Files
src/oaspec/internal/codegen/codec_helpers.gleam
//// Helpers shared between `encoders.gleam` and `decoders.gleam`.
////
//// Issue #402: prior to extraction these four helpers were duplicated
//// in both modules, with the doc comment on `encoders.gleam` flagging
//// the duplication as a follow-up to #212. The bodies were
//// byte-identical (modulo function names for the bare-Option pair), so
//// keeping them in lock-step manually was a maintenance trap. This
//// module owns the canonical implementations now.
import gleam/string
import oaspec/internal/codegen/context.{type Context}
import oaspec/internal/codegen/schema_dispatch
import oaspec/internal/openapi/schema.{
type SchemaRef, ArraySchema, BooleanSchema, Inline, IntegerSchema,
NumberSchema, StringSchema,
}
/// Escape a spec-derived string so it can be safely interpolated
/// inside a generated Gleam string literal (e.g. `json.string("...")`).
/// Constant property values from issue #309 land here — practical
/// values are simple identifiers (`text`, `media`, …) but a spec
/// could in principle declare an enum value containing `"` or `\`.
pub fn escape_for_string_literal(value: String) -> String {
value
|> string.replace(each: "\\", with: "\\\\")
|> string.replace(each: "\"", with: "\\\"")
}
/// Get element at index from a list, or return a default.
pub fn list_at_or(lst: List(String), idx: Int, default: String) -> String {
case lst, idx {
[], _ -> default
[head, ..], 0 -> head
[_, ..rest], n -> list_at_or(rest, n - 1, default)
}
}
/// Convert a SchemaRef to a qualified Gleam type string (with `types.`
/// prefix for component refs). `_ctx` is currently unused but kept on
/// the signature so future ref-resolving variants don't change the
/// caller surface.
pub fn qualified_schema_ref_type(ref: SchemaRef, _ctx: Context) -> String {
case ref {
Inline(schema) -> schema_dispatch.schema_type(schema)
_ -> schema_dispatch.schema_ref_qualified_type(ref)
}
}
/// Issue #387: True when the top-level codec for this schema would
/// emit a bare `Option(...)` wrapper at the surface (decoder declares
/// `decode.Decoder(Option(...))`, encoder takes a bare `Option(...)`
/// parameter). Only primitive / array component schemas with
/// `nullable: true` reach this shape; object / allOf / oneOf / anyOf /
/// enum schemas wrap optionality through `decode.optional` /
/// `json.nullable` inside their bodies and never declare `Option(...)`
/// as the outer type.
pub fn schema_ref_has_bare_option_type(ref: SchemaRef) -> Bool {
case ref {
Inline(StringSchema(metadata:, enum_values: [], ..)) -> metadata.nullable
Inline(IntegerSchema(metadata:, ..)) -> metadata.nullable
Inline(NumberSchema(metadata:, ..)) -> metadata.nullable
Inline(BooleanSchema(metadata:)) -> metadata.nullable
Inline(ArraySchema(metadata:, ..)) -> metadata.nullable
_ -> False
}
}