///|
priv enum BindingLocation {
Label
Query(String)
QueryParams
Header(String)
Payload
PrefixHeaders
ResponseCode
Document
} derive(Eq)
///|
priv struct Binding {
shape : @smithy.Shape
location : BindingLocation
}
///|
fn Context::bindings(
self : Context,
container : @smithy.ShapeId,
response : Bool,
) -> Array[Binding] {
self
.members(container)
.map(shape => {
let location = if trait_string(shape, "smithy.api#httpHeader") is Some(name) {
Header(name)
} else if shape.trait_value("smithy.api#httpPayload") is Some(_) {
Payload
} else if shape.trait_value("smithy.api#httpPrefixHeaders") is Some(_) {
PrefixHeaders
} else if response &&
shape.trait_value("smithy.api#httpResponseCode") is Some(_) {
ResponseCode
} else if !response && shape.trait_value("smithy.api#httpLabel") is Some(_) {
Label
} else if !response &&
trait_string(shape, "smithy.api#httpQuery") is Some(name) {
Query(name)
} else if !response &&
shape.trait_value("smithy.api#httpQueryParams") is Some(_) {
QueryParams
} else {
Document
}
{ shape, location, }
})
}
///|
fn string_schema(schema : Json, format : String?) -> Json {
let out = copy_fields(schema)
for
key in [
"$ref", "maximum", "minimum", "exclusiveMaximum", "exclusiveMinimum", "multipleOf",
"items", "properties", "required", "propertyNames", "oneOf", "anyOf", "not",
"minProperties", "maxProperties", "minItems", "maxItems", "format",
] {
ignore(out.remove(key))
}
out["type"] = Json::string("string")
if format is Some(value) {
out["format"] = Json::string(value)
}
Json::object(out)
}
///|
fn Context::parameter_schema(
self : Context,
shape : @smithy.Shape,
header : Bool,
) -> Json raise OpenApiError {
let schema = self.member_schema(shape)
let target = self.target(shape)
match target.body {
@smithy.Simple(Timestamp) if shape.trait_value("smithy.api#timestampFormat")
is None =>
string_schema(schema, if header { None } else { Some("date-time") })
@smithy.Simple(String) if header &&
target.trait_value("smithy.api#mediaType") is Some(_) =>
string_schema(schema, Some("byte"))
@smithy.List(item) => {
let out = copy_fields(schema)
if self.model.shapes.get(item) is Some(item_shape) {
ignore(out.remove("$ref"))
out["type"] = Json::string("array")
out["items"] = self.parameter_schema(item_shape, header)
}
Json::object(out)
}
_ => schema
}
}
///|
fn Context::parameter(
self : Context,
binding : Binding,
name : String,
location : String,
response : Bool,
) -> Json raise OpenApiError {
let out : Map[String, Json] = Map([])
let shape = binding.shape
let target = self.target(shape)
if !response {
out["name"] = Json::string(name)
out["in"] = Json::string(location)
}
if shape.trait_value("smithy.api#required") is Some(_) {
out["required"] = Json::boolean(true)
}
let description = match trait_string(shape, "smithy.api#documentation") {
Some(value) => Some(value)
None => trait_string(target, "smithy.api#documentation")
}
if description is Some(value) {
out["description"] = Json::string(value)
}
out["schema"] = self.parameter_schema(shape, location == "header")
if binding.location is Query(_) && target.body is @smithy.List(_) {
out["style"] = Json::string("form")
out["explode"] = Json::boolean(true)
}
if binding.location == QueryParams {
out["style"] = Json::string("form")
if target.body is @smithy.Map(value~, ..) &&
self.model.shapes.get(value) is Some(value_member) &&
self.target(value_member).body is @smithy.List(_) {
out["explode"] = Json::boolean(true)
}
}
Json::object(out)
}
///|
fn Context::parameter_with_examples(
self : Context,
operation : @smithy.Shape,
binding : Binding,
name : String,
location : String,
) -> Json raise OpenApiError {
let parameter = copy_fields(self.parameter(binding, name, location, false))
let examples = self.binding_examples(operation, binding, RequestExample)
if !examples.is_empty() {
parameter["examples"] = Json::object(examples)
}
Json::object(parameter)
}
///|
fn Context::payload_content(
self : Context,
binding : Binding,
synthesized_name : String,
) -> Json raise OpenApiError {
let target = self.target(binding.shape)
let mut schema = self.member_schema(binding.shape)
let media_type = match trait_string(target, "smithy.api#mediaType") {
Some(value) => value
None =>
match target.body {
@smithy.Simple(Blob) => "application/octet-stream"
@smithy.Simple(String) => "text/plain"
@smithy.Union(_) if target.trait_value("smithy.api#streaming")
is Some(_) => "application/vnd.amazon.eventstream"
_ => self.config.json_content_type
}
}
if fields(schema).get("$ref") is None {
schema = self.add_schema(synthesized_name, schema)
}
let content : Map[String, Json] = Map([])
content[media_type] = Json::object({ "schema": schema })
Json::object(content)
}