Skip to main content

src/aws/services/dynamodb.gleam

//// Generated from com.amazonaws.dynamodb#DynamoDB_20120810 (awsJson1_0).
//// DO NOT EDIT. Re-generate via the codegen subproject.

import aws/config
import aws/endpoints
import aws/internal/client/runtime
import aws/internal/codec/json_float
import aws/internal/codec/json_timestamp
import aws/internal/credentials_cache
import aws/pagination
import aws/region
import aws/waiter
import gleam/bit_array
import gleam/dict
import gleam/dynamic/decode
import gleam/int
import gleam/json
import gleam/list
import gleam/option
import gleam/result

pub opaque type Client {
  Client(config: runtime.ClientConfig, cache: credentials_cache.Cache)
}

/// Smithy endpoint rule set for this service, lifted verbatim from
/// the source model. Parsed once in `new_with` and attached to every
/// Client via `runtime.with_endpoint_rule_set`.
const endpoint_rule_set_json: String = "{\"parameters\":{\"AccountId\":{\"builtIn\":\"AWS::Auth::AccountId\",\"documentation\":\"The AWS AccountId used for the request.\",\"required\":false,\"type\":\"string\"},\"AccountIdEndpointMode\":{\"builtIn\":\"AWS::Auth::AccountIdEndpointMode\",\"documentation\":\"The AccountId Endpoint Mode.\",\"required\":false,\"type\":\"string\"},\"Endpoint\":{\"builtIn\":\"SDK::Endpoint\",\"documentation\":\"Override the endpoint used to send this request\",\"required\":false,\"type\":\"string\"},\"Region\":{\"builtIn\":\"AWS::Region\",\"documentation\":\"The AWS region used to dispatch the request.\",\"required\":false,\"type\":\"string\"},\"ResourceArn\":{\"documentation\":\"ResourceArn containing arn of resource\",\"required\":false,\"type\":\"string\"},\"ResourceArnList\":{\"documentation\":\"ResourceArnList containing list of resource arns\",\"required\":false,\"type\":\"stringArray\"},\"UseDualStack\":{\"builtIn\":\"AWS::UseDualStack\",\"default\":false,\"documentation\":\"When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.\",\"required\":true,\"type\":\"boolean\"},\"UseFIPS\":{\"builtIn\":\"AWS::UseFIPS\",\"default\":false,\"documentation\":\"When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.\",\"required\":true,\"type\":\"boolean\"}},\"rules\":[{\"conditions\":[{\"argv\":[{\"ref\":\"Endpoint\"}],\"fn\":\"isSet\"},{\"argv\":[{\"ref\":\"Region\"}],\"fn\":\"isSet\"},{\"argv\":[{\"ref\":\"Region\"}],\"assign\":\"PartitionResult\",\"fn\":\"aws.partition\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"ref\":\"UseFIPS\"},true],\"fn\":\"booleanEquals\"}],\"error\":\"Invalid Configuration: FIPS and custom endpoint are not supported\",\"type\":\"error\"},{\"conditions\":[{\"argv\":[{\"ref\":\"UseDualStack\"},true],\"fn\":\"booleanEquals\"}],\"error\":\"Invalid Configuration: Dualstack and custom endpoint are not supported\",\"type\":\"error\"},{\"conditions\":[{\"argv\":[{\"ref\":\"Endpoint\"},\"https://dynamodb.{Region}.{PartitionResult#dualStackDnsSuffix}\"],\"fn\":\"stringEquals\"}],\"error\":\"Endpoint override is not supported for dual-stack endpoints. Please enable dual-stack functionality by enabling the configuration. For more details, see: https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoints.html\",\"type\":\"error\"},{\"conditions\":[],\"endpoint\":{\"headers\":{},\"properties\":{},\"url\":\"{Endpoint}\"},\"type\":\"endpoint\"}],\"type\":\"tree\"},{\"conditions\":[{\"argv\":[{\"ref\":\"Endpoint\"}],\"fn\":\"isSet\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"ref\":\"UseFIPS\"},true],\"fn\":\"booleanEquals\"}],\"error\":\"Invalid Configuration: FIPS and custom endpoint are not supported\",\"type\":\"error\"},{\"conditions\":[{\"argv\":[{\"ref\":\"UseDualStack\"},true],\"fn\":\"booleanEquals\"}],\"error\":\"Invalid Configuration: Dualstack and custom endpoint are not supported\",\"type\":\"error\"},{\"conditions\":[],\"endpoint\":{\"headers\":{},\"properties\":{},\"url\":\"{Endpoint}\"},\"type\":\"endpoint\"}],\"type\":\"tree\"},{\"conditions\":[{\"argv\":[{\"ref\":\"Region\"}],\"fn\":\"isSet\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"ref\":\"Region\"}],\"assign\":\"PartitionResult\",\"fn\":\"aws.partition\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"ref\":\"Region\"},\"local\"],\"fn\":\"stringEquals\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"ref\":\"UseFIPS\"},true],\"fn\":\"booleanEquals\"}],\"error\":\"Invalid Configuration: FIPS and local endpoint are not supported\",\"type\":\"error\"},{\"conditions\":[{\"argv\":[{\"ref\":\"UseDualStack\"},true],\"fn\":\"booleanEquals\"}],\"error\":\"Invalid Configuration: Dualstack and local endpoint are not supported\",\"type\":\"error\"},{\"conditions\":[],\"endpoint\":{\"headers\":{},\"properties\":{\"authSchemes\":[{\"name\":\"sigv4\",\"signingName\":\"dynamodb\",\"signingRegion\":\"us-east-1\"}]},\"url\":\"http://localhost:8000\"},\"type\":\"endpoint\"}],\"type\":\"tree\"},{\"conditions\":[{\"argv\":[{\"ref\":\"UseFIPS\"},true],\"fn\":\"booleanEquals\"},{\"argv\":[{\"ref\":\"UseDualStack\"},true],\"fn\":\"booleanEquals\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"argv\":[{\"ref\":\"PartitionResult\"},\"supportsFIPS\"],\"fn\":\"getAttr\"},true],\"fn\":\"booleanEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"PartitionResult\"},\"supportsDualStack\"],\"fn\":\"getAttr\"},true],\"fn\":\"booleanEquals\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"}],\"fn\":\"isSet\"},{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"},\"required\"],\"fn\":\"stringEquals\"}],\"rules\":[{\"conditions\":[],\"error\":\"Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[],\"endpoint\":{\"headers\":{},\"properties\":{},\"url\":\"https://dynamodb-fips.{Region}.{PartitionResult#dualStackDnsSuffix}\"},\"type\":\"endpoint\"}],\"type\":\"tree\"},{\"conditions\":[],\"error\":\"FIPS and DualStack are enabled, but this partition does not support one or both\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[{\"argv\":[{\"ref\":\"UseFIPS\"},true],\"fn\":\"booleanEquals\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"argv\":[{\"ref\":\"PartitionResult\"},\"supportsFIPS\"],\"fn\":\"getAttr\"},true],\"fn\":\"booleanEquals\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"argv\":[{\"ref\":\"PartitionResult\"},\"name\"],\"fn\":\"getAttr\"},\"aws-us-gov\"],\"fn\":\"stringEquals\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"}],\"fn\":\"isSet\"},{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"},\"required\"],\"fn\":\"stringEquals\"}],\"rules\":[{\"conditions\":[],\"error\":\"Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[],\"endpoint\":{\"headers\":{},\"properties\":{},\"url\":\"https://dynamodb.{Region}.{PartitionResult#dnsSuffix}\"},\"type\":\"endpoint\"}],\"type\":\"tree\"},{\"conditions\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"}],\"fn\":\"isSet\"},{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"},\"required\"],\"fn\":\"stringEquals\"}],\"rules\":[{\"conditions\":[],\"error\":\"Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[],\"endpoint\":{\"headers\":{},\"properties\":{},\"url\":\"https://dynamodb-fips.{Region}.{PartitionResult#dnsSuffix}\"},\"type\":\"endpoint\"}],\"type\":\"tree\"},{\"conditions\":[],\"error\":\"FIPS is enabled but this partition does not support FIPS\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[{\"argv\":[{\"ref\":\"UseDualStack\"},true],\"fn\":\"booleanEquals\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"argv\":[{\"ref\":\"PartitionResult\"},\"supportsDualStack\"],\"fn\":\"getAttr\"},true],\"fn\":\"booleanEquals\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"}],\"fn\":\"isSet\"},{\"argv\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"},\"disabled\"],\"fn\":\"stringEquals\"}],\"fn\":\"not\"},{\"argv\":[{\"argv\":[{\"ref\":\"PartitionResult\"},\"name\"],\"fn\":\"getAttr\"},\"aws\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"UseFIPS\"},true],\"fn\":\"booleanEquals\"}],\"fn\":\"not\"},{\"argv\":[{\"ref\":\"ResourceArn\"}],\"fn\":\"isSet\"},{\"argv\":[{\"ref\":\"ResourceArn\"}],\"assign\":\"ParsedArn\",\"fn\":\"aws.parseArn\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"service\"],\"fn\":\"getAttr\"},\"dynamodb\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"region\"],\"fn\":\"getAttr\"},false],\"fn\":\"isValidHostLabel\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"region\"],\"fn\":\"getAttr\"},\"{Region}\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"accountId\"],\"fn\":\"getAttr\"},false],\"fn\":\"isValidHostLabel\"}],\"endpoint\":{\"headers\":{},\"properties\":{\"metricValues\":[\"O\"]},\"url\":\"https://{ParsedArn#accountId}.ddb.{Region}.{PartitionResult#dualStackDnsSuffix}\"},\"type\":\"endpoint\"},{\"conditions\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"}],\"fn\":\"isSet\"},{\"argv\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"},\"disabled\"],\"fn\":\"stringEquals\"}],\"fn\":\"not\"},{\"argv\":[{\"argv\":[{\"ref\":\"PartitionResult\"},\"name\"],\"fn\":\"getAttr\"},\"aws\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"UseFIPS\"},true],\"fn\":\"booleanEquals\"}],\"fn\":\"not\"},{\"argv\":[{\"ref\":\"ResourceArnList\"}],\"fn\":\"isSet\"},{\"argv\":[{\"ref\":\"ResourceArnList\"},\"[0]\"],\"assign\":\"FirstArn\",\"fn\":\"getAttr\"},{\"argv\":[{\"ref\":\"FirstArn\"}],\"assign\":\"ParsedArn\",\"fn\":\"aws.parseArn\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"service\"],\"fn\":\"getAttr\"},\"dynamodb\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"region\"],\"fn\":\"getAttr\"},false],\"fn\":\"isValidHostLabel\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"region\"],\"fn\":\"getAttr\"},\"{Region}\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"accountId\"],\"fn\":\"getAttr\"},false],\"fn\":\"isValidHostLabel\"}],\"endpoint\":{\"headers\":{},\"properties\":{\"metricValues\":[\"O\"]},\"url\":\"https://{ParsedArn#accountId}.ddb.{Region}.{PartitionResult#dualStackDnsSuffix}\"},\"type\":\"endpoint\"},{\"conditions\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"}],\"fn\":\"isSet\"},{\"argv\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"},\"disabled\"],\"fn\":\"stringEquals\"}],\"fn\":\"not\"},{\"argv\":[{\"argv\":[{\"ref\":\"PartitionResult\"},\"name\"],\"fn\":\"getAttr\"},\"aws\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"UseFIPS\"},true],\"fn\":\"booleanEquals\"}],\"fn\":\"not\"},{\"argv\":[{\"ref\":\"AccountId\"}],\"fn\":\"isSet\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"ref\":\"AccountId\"},false],\"fn\":\"isValidHostLabel\"}],\"rules\":[{\"conditions\":[],\"endpoint\":{\"headers\":{},\"properties\":{\"metricValues\":[\"O\"]},\"url\":\"https://{AccountId}.ddb.{Region}.{PartitionResult#dualStackDnsSuffix}\"},\"type\":\"endpoint\"}],\"type\":\"tree\"},{\"conditions\":[],\"error\":\"Credentials-sourced account ID parameter is invalid\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"}],\"fn\":\"isSet\"},{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"},\"required\"],\"fn\":\"stringEquals\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"argv\":[{\"ref\":\"UseFIPS\"},true],\"fn\":\"booleanEquals\"}],\"fn\":\"not\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"argv\":[{\"ref\":\"PartitionResult\"},\"name\"],\"fn\":\"getAttr\"},\"aws\"],\"fn\":\"stringEquals\"}],\"rules\":[{\"conditions\":[],\"error\":\"AccountIdEndpointMode is required but no AccountID was provided or able to be loaded\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[],\"error\":\"Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[],\"error\":\"Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[],\"endpoint\":{\"headers\":{},\"properties\":{},\"url\":\"https://dynamodb.{Region}.{PartitionResult#dualStackDnsSuffix}\"},\"type\":\"endpoint\"}],\"type\":\"tree\"},{\"conditions\":[],\"error\":\"DualStack is enabled but this partition does not support DualStack\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"}],\"fn\":\"isSet\"},{\"argv\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"},\"disabled\"],\"fn\":\"stringEquals\"}],\"fn\":\"not\"},{\"argv\":[{\"argv\":[{\"ref\":\"PartitionResult\"},\"name\"],\"fn\":\"getAttr\"},\"aws\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"UseFIPS\"},true],\"fn\":\"booleanEquals\"}],\"fn\":\"not\"},{\"argv\":[{\"ref\":\"ResourceArn\"}],\"fn\":\"isSet\"},{\"argv\":[{\"ref\":\"ResourceArn\"}],\"assign\":\"ParsedArn\",\"fn\":\"aws.parseArn\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"service\"],\"fn\":\"getAttr\"},\"dynamodb\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"region\"],\"fn\":\"getAttr\"},false],\"fn\":\"isValidHostLabel\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"region\"],\"fn\":\"getAttr\"},\"{Region}\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"accountId\"],\"fn\":\"getAttr\"},false],\"fn\":\"isValidHostLabel\"}],\"endpoint\":{\"headers\":{},\"properties\":{\"metricValues\":[\"O\"]},\"url\":\"https://{ParsedArn#accountId}.ddb.{Region}.{PartitionResult#dnsSuffix}\"},\"type\":\"endpoint\"},{\"conditions\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"}],\"fn\":\"isSet\"},{\"argv\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"},\"disabled\"],\"fn\":\"stringEquals\"}],\"fn\":\"not\"},{\"argv\":[{\"argv\":[{\"ref\":\"PartitionResult\"},\"name\"],\"fn\":\"getAttr\"},\"aws\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"UseFIPS\"},true],\"fn\":\"booleanEquals\"}],\"fn\":\"not\"},{\"argv\":[{\"ref\":\"ResourceArnList\"}],\"fn\":\"isSet\"},{\"argv\":[{\"ref\":\"ResourceArnList\"},\"[0]\"],\"assign\":\"FirstArn\",\"fn\":\"getAttr\"},{\"argv\":[{\"ref\":\"FirstArn\"}],\"assign\":\"ParsedArn\",\"fn\":\"aws.parseArn\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"service\"],\"fn\":\"getAttr\"},\"dynamodb\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"region\"],\"fn\":\"getAttr\"},false],\"fn\":\"isValidHostLabel\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"region\"],\"fn\":\"getAttr\"},\"{Region}\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"ParsedArn\"},\"accountId\"],\"fn\":\"getAttr\"},false],\"fn\":\"isValidHostLabel\"}],\"endpoint\":{\"headers\":{},\"properties\":{\"metricValues\":[\"O\"]},\"url\":\"https://{ParsedArn#accountId}.ddb.{Region}.{PartitionResult#dnsSuffix}\"},\"type\":\"endpoint\"},{\"conditions\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"}],\"fn\":\"isSet\"},{\"argv\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"},\"disabled\"],\"fn\":\"stringEquals\"}],\"fn\":\"not\"},{\"argv\":[{\"argv\":[{\"ref\":\"PartitionResult\"},\"name\"],\"fn\":\"getAttr\"},\"aws\"],\"fn\":\"stringEquals\"},{\"argv\":[{\"argv\":[{\"ref\":\"UseFIPS\"},true],\"fn\":\"booleanEquals\"}],\"fn\":\"not\"},{\"argv\":[{\"ref\":\"AccountId\"}],\"fn\":\"isSet\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"ref\":\"AccountId\"},false],\"fn\":\"isValidHostLabel\"}],\"rules\":[{\"conditions\":[],\"endpoint\":{\"headers\":{},\"properties\":{\"metricValues\":[\"O\"]},\"url\":\"https://{AccountId}.ddb.{Region}.{PartitionResult#dnsSuffix}\"},\"type\":\"endpoint\"}],\"type\":\"tree\"},{\"conditions\":[],\"error\":\"Credentials-sourced account ID parameter is invalid\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"}],\"fn\":\"isSet\"},{\"argv\":[{\"ref\":\"AccountIdEndpointMode\"},\"required\"],\"fn\":\"stringEquals\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"argv\":[{\"ref\":\"UseFIPS\"},true],\"fn\":\"booleanEquals\"}],\"fn\":\"not\"}],\"rules\":[{\"conditions\":[{\"argv\":[{\"argv\":[{\"ref\":\"PartitionResult\"},\"name\"],\"fn\":\"getAttr\"},\"aws\"],\"fn\":\"stringEquals\"}],\"rules\":[{\"conditions\":[],\"error\":\"AccountIdEndpointMode is required but no AccountID was provided or able to be loaded\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[],\"error\":\"Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[],\"error\":\"Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported\",\"type\":\"error\"}],\"type\":\"tree\"},{\"conditions\":[],\"endpoint\":{\"headers\":{},\"properties\":{},\"url\":\"https://dynamodb.{Region}.{PartitionResult#dnsSuffix}\"},\"type\":\"endpoint\"}],\"type\":\"tree\"}],\"type\":\"tree\"},{\"conditions\":[],\"error\":\"Invalid Configuration: Missing Region\",\"type\":\"error\"}],\"version\":\"1.0\"}"

/// AWS endpoint-rule-set parameters for this service. Each `Some` value
/// feeds endpoint resolution; `None` keeps the rule set's own default.
/// Start from `default_endpoint_params()` and override what you need.
pub type EndpointParams {
  EndpointParams(
    account_id: option.Option(String),
    account_id_endpoint_mode: option.Option(String),
    use_dual_stack: option.Option(Bool),
    use_fips: option.Option(Bool),
  )
}

/// The all-default `EndpointParams`: every parameter left to the rule
/// set's default. Spread it and override only the params you need.
pub fn default_endpoint_params() -> EndpointParams {
  EndpointParams(
    account_id: option.None,
    account_id_endpoint_mode: option.None,
    use_dual_stack: option.None,
    use_fips: option.None,
  )
}

/// Build a Client with everything resolved automatically: the region
/// from the standard AWS sources (`AWS_REGION`, `AWS_DEFAULT_REGION`,
/// `~/.aws/config`) and credentials from the default chain. Zero
/// config — the path you want in Lambda / ECS / EC2, where the
/// environment always supplies a region. `Error(_)` only when no
/// source provides one; pass explicit settings via `new_with` then.
pub fn new() -> Result(Client, region.ResolveError) {
  new_with(config.default_settings(), default_endpoint_params())
}

/// Build a Client from explicit customer `config.Settings` and this
/// service's AWS `EndpointParams`. Start each from its defaults
/// (`config.default_settings()` / `default_endpoint_params()`) and
/// override only the fields you need. Region auto-resolves when
/// `settings.region` is `None` — the only failure path; credentials
/// resolve lazily on the first request.
pub fn new_with(
  settings: config.Settings,
  endpoint_params: EndpointParams,
) -> Result(Client, region.ResolveError) {
  use cfg <- result.map(config.resolve(
    settings,
    endpoint_prefix: "dynamodb",
    signing_name: "dynamodb",
  ))
  let assert Ok(rule_set) = endpoints.parse_rule_set(endpoint_rule_set_json)
  let cfg = runtime.with_endpoint_rule_set(cfg, rule_set)
  let cfg = case endpoint_params.account_id {
    option.Some(value) ->
      runtime.with_endpoint_param(cfg, "AccountId", endpoints.StringVal(value))
    option.None -> cfg
  }
  let cfg = case endpoint_params.account_id_endpoint_mode {
    option.Some(value) ->
      runtime.with_endpoint_param(
        cfg,
        "AccountIdEndpointMode",
        endpoints.StringVal(value),
      )
    option.None -> cfg
  }
  let cfg = case endpoint_params.use_dual_stack {
    option.Some(value) ->
      runtime.with_endpoint_param(cfg, "UseDualStack", endpoints.BoolVal(value))
    option.None -> cfg
  }
  let cfg = case endpoint_params.use_fips {
    option.Some(value) ->
      runtime.with_endpoint_param(cfg, "UseFIPS", endpoints.BoolVal(value))
    option.None -> cfg
  }
  let assert Ok(cache) = credentials_cache.start_default(cfg.provider)
  let cfg =
    runtime.with_credentials_provider(cfg, credentials_cache.as_provider(cache))
  Client(config: cfg, cache: cache)
}

/// Read the underlying `runtime.ClientConfig` out of an existing
/// `Client`. Use this when you want to dispatch a request through
/// `runtime.invoke` / `runtime.invoke_streaming` directly — e.g. to
/// build a service-specific streaming wrapper around a `@streaming`
/// output operation that the per-op codegen hasn't surfaced yet.
/// The returned config is a value (Gleam records are immutable);
/// callers cannot mutate the Client through it.
pub fn client_config(client: Client) -> runtime.ClientConfig {
  client.config
}

/// Release the per-Client credentials cache actor. Call this when a
/// Client value is no longer needed — long-running processes that
/// build many Clients (tests, scripts, multi-tenant servers) will
/// otherwise accumulate one BEAM process per construction. Fire-and-
/// forget; safe to call multiple times. For tests or graceful
/// shutdown that must observe the actor's exit, use `shutdown_sync`.
pub fn shutdown(client: Client) -> Nil {
  credentials_cache.shutdown(client.cache)
}

/// Like `shutdown` but blocks until the credentials cache actor has
/// actually exited (or `timeout_ms` elapses). `Ok(Nil)` indicates a
/// clean exit; `Error(Nil)` indicates the timeout fired and the
/// actor was still alive when the caller gave up.
pub fn shutdown_sync(
  client: Client,
  timeout_ms timeout_ms: Int,
) -> Result(Nil, Nil) {
  credentials_cache.shutdown_sync(client.cache, timeout_ms)
}

pub type BatchExecuteStatementInput {
  BatchExecuteStatementInput(
    return_consumed_capacity: option.Option(ReturnConsumedCapacity),
    statements: List(BatchStatementRequest),
  )
}

pub fn batch_execute_statement_input_default(
  statements statements: List(BatchStatementRequest),
) -> BatchExecuteStatementInput {
  BatchExecuteStatementInput(
    return_consumed_capacity: option.None,
    statements: statements,
  )
}

pub fn encode_batch_execute_statement_input_struct(
  input: BatchExecuteStatementInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.statements
    [
      #(
        "Statements",
        fn(xs) { json.array(xs, encode_batch_statement_request_struct) }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn encode_batch_execute_statement_input_struct_top(
  input: BatchExecuteStatementInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.statements
    [
      #(
        "Statements",
        fn(xs) { json.array(xs, encode_batch_statement_request_struct) }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn decode_batch_execute_statement_input_struct() -> decode.Decoder(
  BatchExecuteStatementInput,
) {
  use <- decode.recursive
  use return_consumed_capacity <- decode.optional_field(
    "ReturnConsumedCapacity",
    option.None,
    decode.optional(decode_return_consumed_capacity_enum()),
  )
  use statements <- decode.field(
    "Statements",
    decode.list(decode_batch_statement_request_struct()),
  )
  decode.success(BatchExecuteStatementInput(
    return_consumed_capacity: return_consumed_capacity,
    statements: statements,
  ))
}

pub type ReturnConsumedCapacity {
  ReturnConsumedCapacityIndexes
  ReturnConsumedCapacityNone
  ReturnConsumedCapacityTotal
}

pub fn encode_return_consumed_capacity_enum(
  v: ReturnConsumedCapacity,
) -> json.Json {
  case v {
    ReturnConsumedCapacityIndexes -> json.string("INDEXES")
    ReturnConsumedCapacityNone -> json.string("NONE")
    ReturnConsumedCapacityTotal -> json.string("TOTAL")
  }
}

pub fn decode_return_consumed_capacity_enum() -> decode.Decoder(
  ReturnConsumedCapacity,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "INDEXES" -> decode.success(ReturnConsumedCapacityIndexes)
      "NONE" -> decode.success(ReturnConsumedCapacityNone)
      "TOTAL" -> decode.success(ReturnConsumedCapacityTotal)
      _ -> decode.failure(ReturnConsumedCapacityIndexes, "unknown enum value")
    }
  })
}

pub type BatchStatementRequest {
  BatchStatementRequest(
    consistent_read: option.Option(Bool),
    parameters: option.Option(List(AttributeValue)),
    return_values_on_condition_check_failure: option.Option(
      ReturnValuesOnConditionCheckFailure,
    ),
    statement: String,
  )
}

pub fn batch_statement_request_default(
  statement statement: String,
) -> BatchStatementRequest {
  BatchStatementRequest(
    consistent_read: option.None,
    parameters: option.None,
    return_values_on_condition_check_failure: option.None,
    statement: statement,
  )
}

pub fn encode_batch_statement_request_struct(
  input: BatchStatementRequest,
) -> json.Json {
  let pairs = []
  let pairs = case input.consistent_read {
    option.Some(v) -> [#("ConsistentRead", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.parameters {
    option.Some(v) -> [
      #(
        "Parameters",
        fn(xs) { json.array(xs, encode_attribute_value_union) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.statement
    [#("Statement", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_batch_statement_request_struct_top(
  input: BatchStatementRequest,
) -> json.Json {
  let pairs = []
  let pairs = case input.consistent_read {
    option.Some(v) -> [#("ConsistentRead", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.parameters {
    option.Some(v) -> [
      #(
        "Parameters",
        fn(xs) { json.array(xs, encode_attribute_value_union) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.statement
    [#("Statement", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_batch_statement_request_struct() -> decode.Decoder(
  BatchStatementRequest,
) {
  use <- decode.recursive
  use consistent_read <- decode.optional_field(
    "ConsistentRead",
    option.None,
    decode.optional(decode.bool),
  )
  use parameters <- decode.optional_field(
    "Parameters",
    option.None,
    decode.optional(decode.list(decode_attribute_value_union())),
  )
  use return_values_on_condition_check_failure <- decode.optional_field(
    "ReturnValuesOnConditionCheckFailure",
    option.None,
    decode.optional(decode_return_values_on_condition_check_failure_enum()),
  )
  use statement <- decode.field("Statement", decode.string)
  decode.success(BatchStatementRequest(
    consistent_read: consistent_read,
    parameters: parameters,
    return_values_on_condition_check_failure: return_values_on_condition_check_failure,
    statement: statement,
  ))
}

pub type AttributeValue {
  AttributeValueB(BitArray)
  AttributeValueBOOL(Bool)
  AttributeValueBS(List(BitArray))
  AttributeValueL(List(AttributeValue))
  AttributeValueM(dict.Dict(String, AttributeValue))
  AttributeValueN(String)
  AttributeValueNS(List(String))
  AttributeValueNULL(Bool)
  AttributeValueS(String)
  AttributeValueSS(List(String))
}

pub fn encode_attribute_value_union(v: AttributeValue) -> json.Json {
  case v {
    AttributeValueB(x) ->
      json.object([
        #("B", fn(b) { json.string(bit_array.base64_encode(b, True)) }(x)),
      ])
    AttributeValueBOOL(x) -> json.object([#("BOOL", json.bool(x))])
    AttributeValueBS(x) ->
      json.object([
        #(
          "BS",
          fn(xs) {
            json.array(xs, fn(b) {
              json.string(bit_array.base64_encode(b, True))
            })
          }(x),
        ),
      ])
    AttributeValueL(x) ->
      json.object([
        #("L", fn(xs) { json.array(xs, encode_attribute_value_union) }(x)),
      ])
    AttributeValueM(x) ->
      json.object([
        #(
          "M",
          fn(d) {
            json.object(
              dict.to_list(d)
              |> list.map(fn(pair) {
                #(pair.0, encode_attribute_value_union(pair.1))
              }),
            )
          }(x),
        ),
      ])
    AttributeValueN(x) -> json.object([#("N", json.string(x))])
    AttributeValueNS(x) ->
      json.object([#("NS", fn(xs) { json.array(xs, json.string) }(x))])
    AttributeValueNULL(x) -> json.object([#("NULL", json.bool(x))])
    AttributeValueS(x) -> json.object([#("S", json.string(x))])
    AttributeValueSS(x) ->
      json.object([#("SS", fn(xs) { json.array(xs, json.string) }(x))])
  }
}

pub fn decode_attribute_value_union() -> decode.Decoder(AttributeValue) {
  use <- decode.recursive
  decode.one_of(
    decode.field(
      "B",
      decode.then(decode.string, fn(s) {
        decode.success(bit_array.from_string(s))
      }),
      fn(x) { decode.success(AttributeValueB(x)) },
    ),
    [
      decode.field("BOOL", decode.bool, fn(x) {
        decode.success(AttributeValueBOOL(x))
      }),
      decode.field(
        "BS",
        decode.list(
          decode.then(decode.string, fn(s) {
            decode.success(bit_array.from_string(s))
          }),
        ),
        fn(x) { decode.success(AttributeValueBS(x)) },
      ),
      decode.field("L", decode.list(decode_attribute_value_union()), fn(x) {
        decode.success(AttributeValueL(x))
      }),
      decode.field(
        "M",
        decode.dict(decode.string, decode_attribute_value_union()),
        fn(x) { decode.success(AttributeValueM(x)) },
      ),
      decode.field("N", decode.string, fn(x) {
        decode.success(AttributeValueN(x))
      }),
      decode.field("NS", decode.list(decode.string), fn(x) {
        decode.success(AttributeValueNS(x))
      }),
      decode.field("NULL", decode.bool, fn(x) {
        decode.success(AttributeValueNULL(x))
      }),
      decode.field("S", decode.string, fn(x) {
        decode.success(AttributeValueS(x))
      }),
      decode.field("SS", decode.list(decode.string), fn(x) {
        decode.success(AttributeValueSS(x))
      }),
    ],
  )
}

pub type ReturnValuesOnConditionCheckFailure {
  ReturnValuesOnConditionCheckFailureAllOld
  ReturnValuesOnConditionCheckFailureNone
}

pub fn encode_return_values_on_condition_check_failure_enum(
  v: ReturnValuesOnConditionCheckFailure,
) -> json.Json {
  case v {
    ReturnValuesOnConditionCheckFailureAllOld -> json.string("ALL_OLD")
    ReturnValuesOnConditionCheckFailureNone -> json.string("NONE")
  }
}

pub fn decode_return_values_on_condition_check_failure_enum() -> decode.Decoder(
  ReturnValuesOnConditionCheckFailure,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "ALL_OLD" -> decode.success(ReturnValuesOnConditionCheckFailureAllOld)
      "NONE" -> decode.success(ReturnValuesOnConditionCheckFailureNone)
      _ ->
        decode.failure(
          ReturnValuesOnConditionCheckFailureAllOld,
          "unknown enum value",
        )
    }
  })
}

pub type BatchExecuteStatementOutput {
  BatchExecuteStatementOutput(
    consumed_capacity: option.Option(List(ConsumedCapacity)),
    responses: option.Option(List(BatchStatementResponse)),
  )
}

pub fn batch_execute_statement_output_default() -> BatchExecuteStatementOutput {
  BatchExecuteStatementOutput(
    consumed_capacity: option.None,
    responses: option.None,
  )
}

pub fn encode_batch_execute_statement_output_struct(
  input: BatchExecuteStatementOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #(
        "ConsumedCapacity",
        fn(xs) { json.array(xs, encode_consumed_capacity_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.responses {
    option.Some(v) -> [
      #(
        "Responses",
        fn(xs) { json.array(xs, encode_batch_statement_response_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_batch_execute_statement_output_struct_top(
  input: BatchExecuteStatementOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #(
        "ConsumedCapacity",
        fn(xs) { json.array(xs, encode_consumed_capacity_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.responses {
    option.Some(v) -> [
      #(
        "Responses",
        fn(xs) { json.array(xs, encode_batch_statement_response_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_batch_execute_statement_output_struct() -> decode.Decoder(
  BatchExecuteStatementOutput,
) {
  use <- decode.recursive
  use consumed_capacity <- decode.optional_field(
    "ConsumedCapacity",
    option.None,
    decode.optional(decode.list(decode_consumed_capacity_struct())),
  )
  use responses <- decode.optional_field(
    "Responses",
    option.None,
    decode.optional(decode.list(decode_batch_statement_response_struct())),
  )
  decode.success(BatchExecuteStatementOutput(
    consumed_capacity: consumed_capacity,
    responses: responses,
  ))
}

pub type ConsumedCapacity {
  ConsumedCapacity(
    capacity_units: option.Option(json_float.SmithyFloat),
    global_secondary_indexes: option.Option(dict.Dict(String, Capacity)),
    local_secondary_indexes: option.Option(dict.Dict(String, Capacity)),
    read_capacity_units: option.Option(json_float.SmithyFloat),
    table: option.Option(Capacity),
    table_name: option.Option(String),
    write_capacity_units: option.Option(json_float.SmithyFloat),
  )
}

pub fn consumed_capacity_default() -> ConsumedCapacity {
  ConsumedCapacity(
    capacity_units: option.None,
    global_secondary_indexes: option.None,
    local_secondary_indexes: option.None,
    read_capacity_units: option.None,
    table: option.None,
    table_name: option.None,
    write_capacity_units: option.None,
  )
}

pub fn encode_consumed_capacity_struct(input: ConsumedCapacity) -> json.Json {
  let pairs = []
  let pairs = case input.capacity_units {
    option.Some(v) -> [#("CapacityUnits", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, encode_capacity_struct(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.local_secondary_indexes {
    option.Some(v) -> [
      #(
        "LocalSecondaryIndexes",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, encode_capacity_struct(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.read_capacity_units {
    option.Some(v) -> [#("ReadCapacityUnits", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table {
    option.Some(v) -> [#("Table", encode_capacity_struct(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.write_capacity_units {
    option.Some(v) -> [#("WriteCapacityUnits", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_consumed_capacity_struct_top(
  input: ConsumedCapacity,
) -> json.Json {
  let pairs = []
  let pairs = case input.capacity_units {
    option.Some(v) -> [#("CapacityUnits", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, encode_capacity_struct(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.local_secondary_indexes {
    option.Some(v) -> [
      #(
        "LocalSecondaryIndexes",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, encode_capacity_struct(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.read_capacity_units {
    option.Some(v) -> [#("ReadCapacityUnits", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table {
    option.Some(v) -> [#("Table", encode_capacity_struct(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.write_capacity_units {
    option.Some(v) -> [#("WriteCapacityUnits", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_consumed_capacity_struct() -> decode.Decoder(ConsumedCapacity) {
  use <- decode.recursive
  use capacity_units <- decode.optional_field(
    "CapacityUnits",
    option.None,
    decode.optional(json_float.decoder()),
  )
  use global_secondary_indexes <- decode.optional_field(
    "GlobalSecondaryIndexes",
    option.None,
    decode.optional(decode.dict(decode.string, decode_capacity_struct())),
  )
  use local_secondary_indexes <- decode.optional_field(
    "LocalSecondaryIndexes",
    option.None,
    decode.optional(decode.dict(decode.string, decode_capacity_struct())),
  )
  use read_capacity_units <- decode.optional_field(
    "ReadCapacityUnits",
    option.None,
    decode.optional(json_float.decoder()),
  )
  use table <- decode.optional_field(
    "Table",
    option.None,
    decode.optional(decode_capacity_struct()),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  use write_capacity_units <- decode.optional_field(
    "WriteCapacityUnits",
    option.None,
    decode.optional(json_float.decoder()),
  )
  decode.success(ConsumedCapacity(
    capacity_units: capacity_units,
    global_secondary_indexes: global_secondary_indexes,
    local_secondary_indexes: local_secondary_indexes,
    read_capacity_units: read_capacity_units,
    table: table,
    table_name: table_name,
    write_capacity_units: write_capacity_units,
  ))
}

pub type Capacity {
  Capacity(
    capacity_units: option.Option(json_float.SmithyFloat),
    read_capacity_units: option.Option(json_float.SmithyFloat),
    write_capacity_units: option.Option(json_float.SmithyFloat),
  )
}

pub fn capacity_default() -> Capacity {
  Capacity(
    capacity_units: option.None,
    read_capacity_units: option.None,
    write_capacity_units: option.None,
  )
}

pub fn encode_capacity_struct(input: Capacity) -> json.Json {
  let pairs = []
  let pairs = case input.capacity_units {
    option.Some(v) -> [#("CapacityUnits", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.read_capacity_units {
    option.Some(v) -> [#("ReadCapacityUnits", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.write_capacity_units {
    option.Some(v) -> [#("WriteCapacityUnits", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_capacity_struct_top(input: Capacity) -> json.Json {
  let pairs = []
  let pairs = case input.capacity_units {
    option.Some(v) -> [#("CapacityUnits", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.read_capacity_units {
    option.Some(v) -> [#("ReadCapacityUnits", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.write_capacity_units {
    option.Some(v) -> [#("WriteCapacityUnits", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_capacity_struct() -> decode.Decoder(Capacity) {
  use <- decode.recursive
  use capacity_units <- decode.optional_field(
    "CapacityUnits",
    option.None,
    decode.optional(json_float.decoder()),
  )
  use read_capacity_units <- decode.optional_field(
    "ReadCapacityUnits",
    option.None,
    decode.optional(json_float.decoder()),
  )
  use write_capacity_units <- decode.optional_field(
    "WriteCapacityUnits",
    option.None,
    decode.optional(json_float.decoder()),
  )
  decode.success(Capacity(
    capacity_units: capacity_units,
    read_capacity_units: read_capacity_units,
    write_capacity_units: write_capacity_units,
  ))
}

pub type BatchStatementResponse {
  BatchStatementResponse(
    error: option.Option(BatchStatementError),
    item: option.Option(dict.Dict(String, AttributeValue)),
    table_name: option.Option(String),
  )
}

pub fn batch_statement_response_default() -> BatchStatementResponse {
  BatchStatementResponse(
    error: option.None,
    item: option.None,
    table_name: option.None,
  )
}

pub fn encode_batch_statement_response_struct(
  input: BatchStatementResponse,
) -> json.Json {
  let pairs = []
  let pairs = case input.error {
    option.Some(v) -> [
      #("Error", encode_batch_statement_error_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item {
    option.Some(v) -> [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_batch_statement_response_struct_top(
  input: BatchStatementResponse,
) -> json.Json {
  let pairs = []
  let pairs = case input.error {
    option.Some(v) -> [
      #("Error", encode_batch_statement_error_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item {
    option.Some(v) -> [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_batch_statement_response_struct() -> decode.Decoder(
  BatchStatementResponse,
) {
  use <- decode.recursive
  use error <- decode.optional_field(
    "Error",
    option.None,
    decode.optional(decode_batch_statement_error_struct()),
  )
  use item <- decode.optional_field(
    "Item",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(BatchStatementResponse(
    error: error,
    item: item,
    table_name: table_name,
  ))
}

pub type BatchStatementError {
  BatchStatementError(
    code: option.Option(BatchStatementErrorCodeEnum),
    item: option.Option(dict.Dict(String, AttributeValue)),
    message: option.Option(String),
  )
}

pub fn batch_statement_error_default() -> BatchStatementError {
  BatchStatementError(
    code: option.None,
    item: option.None,
    message: option.None,
  )
}

pub fn encode_batch_statement_error_struct(
  input: BatchStatementError,
) -> json.Json {
  let pairs = []
  let pairs = case input.code {
    option.Some(v) -> [
      #("Code", encode_batch_statement_error_code_enum_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item {
    option.Some(v) -> [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.message {
    option.Some(v) -> [#("Message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_batch_statement_error_struct_top(
  input: BatchStatementError,
) -> json.Json {
  let pairs = []
  let pairs = case input.code {
    option.Some(v) -> [
      #("Code", encode_batch_statement_error_code_enum_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item {
    option.Some(v) -> [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.message {
    option.Some(v) -> [#("Message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_batch_statement_error_struct() -> decode.Decoder(
  BatchStatementError,
) {
  use <- decode.recursive
  use code <- decode.optional_field(
    "Code",
    option.None,
    decode.optional(decode_batch_statement_error_code_enum_enum()),
  )
  use item <- decode.optional_field(
    "Item",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use message <- decode.optional_field(
    "Message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(BatchStatementError(code: code, item: item, message: message))
}

pub type BatchStatementErrorCodeEnum {
  BatchStatementErrorCodeEnumAccessdenied
  BatchStatementErrorCodeEnumConditionalcheckfailed
  BatchStatementErrorCodeEnumDuplicateitem
  BatchStatementErrorCodeEnumInternalservererror
  BatchStatementErrorCodeEnumItemcollectionsizelimitexceeded
  BatchStatementErrorCodeEnumProvisionedthroughputexceeded
  BatchStatementErrorCodeEnumRequestlimitexceeded
  BatchStatementErrorCodeEnumResourcenotfound
  BatchStatementErrorCodeEnumThrottlingerror
  BatchStatementErrorCodeEnumTransactionconflict
  BatchStatementErrorCodeEnumValidationerror
}

pub fn encode_batch_statement_error_code_enum_enum(
  v: BatchStatementErrorCodeEnum,
) -> json.Json {
  case v {
    BatchStatementErrorCodeEnumAccessdenied -> json.string("AccessDenied")
    BatchStatementErrorCodeEnumConditionalcheckfailed ->
      json.string("ConditionalCheckFailed")
    BatchStatementErrorCodeEnumDuplicateitem -> json.string("DuplicateItem")
    BatchStatementErrorCodeEnumInternalservererror ->
      json.string("InternalServerError")
    BatchStatementErrorCodeEnumItemcollectionsizelimitexceeded ->
      json.string("ItemCollectionSizeLimitExceeded")
    BatchStatementErrorCodeEnumProvisionedthroughputexceeded ->
      json.string("ProvisionedThroughputExceeded")
    BatchStatementErrorCodeEnumRequestlimitexceeded ->
      json.string("RequestLimitExceeded")
    BatchStatementErrorCodeEnumResourcenotfound ->
      json.string("ResourceNotFound")
    BatchStatementErrorCodeEnumThrottlingerror -> json.string("ThrottlingError")
    BatchStatementErrorCodeEnumTransactionconflict ->
      json.string("TransactionConflict")
    BatchStatementErrorCodeEnumValidationerror -> json.string("ValidationError")
  }
}

pub fn decode_batch_statement_error_code_enum_enum() -> decode.Decoder(
  BatchStatementErrorCodeEnum,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "AccessDenied" -> decode.success(BatchStatementErrorCodeEnumAccessdenied)
      "ConditionalCheckFailed" ->
        decode.success(BatchStatementErrorCodeEnumConditionalcheckfailed)
      "DuplicateItem" ->
        decode.success(BatchStatementErrorCodeEnumDuplicateitem)
      "InternalServerError" ->
        decode.success(BatchStatementErrorCodeEnumInternalservererror)
      "ItemCollectionSizeLimitExceeded" ->
        decode.success(
          BatchStatementErrorCodeEnumItemcollectionsizelimitexceeded,
        )
      "ProvisionedThroughputExceeded" ->
        decode.success(BatchStatementErrorCodeEnumProvisionedthroughputexceeded)
      "RequestLimitExceeded" ->
        decode.success(BatchStatementErrorCodeEnumRequestlimitexceeded)
      "ResourceNotFound" ->
        decode.success(BatchStatementErrorCodeEnumResourcenotfound)
      "ThrottlingError" ->
        decode.success(BatchStatementErrorCodeEnumThrottlingerror)
      "TransactionConflict" ->
        decode.success(BatchStatementErrorCodeEnumTransactionconflict)
      "ValidationError" ->
        decode.success(BatchStatementErrorCodeEnumValidationerror)
      _ ->
        decode.failure(
          BatchStatementErrorCodeEnumAccessdenied,
          "unknown enum value",
        )
    }
  })
}

pub type InternalServerError {
  InternalServerError(message: option.Option(String))
}

pub fn internal_server_error_default() -> InternalServerError {
  InternalServerError(message: option.None)
}

pub fn encode_internal_server_error_struct(
  input: InternalServerError,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_internal_server_error_struct_top(
  input: InternalServerError,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_internal_server_error_struct() -> decode.Decoder(
  InternalServerError,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(InternalServerError(message: message))
}

pub type RequestLimitExceeded {
  RequestLimitExceeded(
    throttling_reasons: option.Option(List(ThrottlingReason)),
    message: option.Option(String),
  )
}

pub fn request_limit_exceeded_default() -> RequestLimitExceeded {
  RequestLimitExceeded(throttling_reasons: option.None, message: option.None)
}

pub fn encode_request_limit_exceeded_struct(
  input: RequestLimitExceeded,
) -> json.Json {
  let pairs = []
  let pairs = case input.throttling_reasons {
    option.Some(v) -> [
      #(
        "ThrottlingReasons",
        fn(xs) { json.array(xs, encode_throttling_reason_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_request_limit_exceeded_struct_top(
  input: RequestLimitExceeded,
) -> json.Json {
  let pairs = []
  let pairs = case input.throttling_reasons {
    option.Some(v) -> [
      #(
        "ThrottlingReasons",
        fn(xs) { json.array(xs, encode_throttling_reason_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_request_limit_exceeded_struct() -> decode.Decoder(
  RequestLimitExceeded,
) {
  use <- decode.recursive
  use throttling_reasons <- decode.optional_field(
    "ThrottlingReasons",
    option.None,
    decode.optional(decode.list(decode_throttling_reason_struct())),
  )
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(RequestLimitExceeded(
    throttling_reasons: throttling_reasons,
    message: message,
  ))
}

pub type ThrottlingReason {
  ThrottlingReason(
    reason: option.Option(String),
    resource: option.Option(String),
  )
}

pub fn throttling_reason_default() -> ThrottlingReason {
  ThrottlingReason(reason: option.None, resource: option.None)
}

pub fn encode_throttling_reason_struct(input: ThrottlingReason) -> json.Json {
  let pairs = []
  let pairs = case input.reason {
    option.Some(v) -> [#("reason", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.resource {
    option.Some(v) -> [#("resource", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_throttling_reason_struct_top(
  input: ThrottlingReason,
) -> json.Json {
  let pairs = []
  let pairs = case input.reason {
    option.Some(v) -> [#("reason", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.resource {
    option.Some(v) -> [#("resource", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_throttling_reason_struct() -> decode.Decoder(ThrottlingReason) {
  use <- decode.recursive
  use reason <- decode.optional_field(
    "reason",
    option.None,
    decode.optional(decode.string),
  )
  use resource <- decode.optional_field(
    "resource",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ThrottlingReason(reason: reason, resource: resource))
}

pub type ThrottlingException {
  ThrottlingException(
    message: option.Option(String),
    throttling_reasons: option.Option(List(ThrottlingReason)),
  )
}

pub fn throttling_exception_default() -> ThrottlingException {
  ThrottlingException(message: option.None, throttling_reasons: option.None)
}

pub fn encode_throttling_exception_struct(
  input: ThrottlingException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.throttling_reasons {
    option.Some(v) -> [
      #(
        "throttlingReasons",
        fn(xs) { json.array(xs, encode_throttling_reason_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_throttling_exception_struct_top(
  input: ThrottlingException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.throttling_reasons {
    option.Some(v) -> [
      #(
        "throttlingReasons",
        fn(xs) { json.array(xs, encode_throttling_reason_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_throttling_exception_struct() -> decode.Decoder(
  ThrottlingException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  use throttling_reasons <- decode.optional_field(
    "throttlingReasons",
    option.None,
    decode.optional(decode.list(decode_throttling_reason_struct())),
  )
  decode.success(ThrottlingException(
    message: message,
    throttling_reasons: throttling_reasons,
  ))
}

pub type BatchGetItemInput {
  BatchGetItemInput(
    request_items: dict.Dict(String, KeysAndAttributes),
    return_consumed_capacity: option.Option(ReturnConsumedCapacity),
  )
}

pub fn batch_get_item_input_default(
  request_items request_items: dict.Dict(String, KeysAndAttributes),
) -> BatchGetItemInput {
  BatchGetItemInput(
    request_items: request_items,
    return_consumed_capacity: option.None,
  )
}

pub fn encode_batch_get_item_input_struct(
  input: BatchGetItemInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.request_items
    [
      #(
        "RequestItems",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_keys_and_attributes_struct(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_batch_get_item_input_struct_top(
  input: BatchGetItemInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.request_items
    [
      #(
        "RequestItems",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_keys_and_attributes_struct(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_batch_get_item_input_struct() -> decode.Decoder(BatchGetItemInput) {
  use <- decode.recursive
  use request_items <- decode.field(
    "RequestItems",
    decode.dict(decode.string, decode_keys_and_attributes_struct()),
  )
  use return_consumed_capacity <- decode.optional_field(
    "ReturnConsumedCapacity",
    option.None,
    decode.optional(decode_return_consumed_capacity_enum()),
  )
  decode.success(BatchGetItemInput(
    request_items: request_items,
    return_consumed_capacity: return_consumed_capacity,
  ))
}

pub type KeysAndAttributes {
  KeysAndAttributes(
    attributes_to_get: option.Option(List(String)),
    consistent_read: option.Option(Bool),
    expression_attribute_names: option.Option(dict.Dict(String, String)),
    keys: List(dict.Dict(String, AttributeValue)),
    projection_expression: option.Option(String),
  )
}

pub fn keys_and_attributes_default(
  keys keys: List(dict.Dict(String, AttributeValue)),
) -> KeysAndAttributes {
  KeysAndAttributes(
    attributes_to_get: option.None,
    consistent_read: option.None,
    expression_attribute_names: option.None,
    keys: keys,
    projection_expression: option.None,
  )
}

pub fn encode_keys_and_attributes_struct(
  input: KeysAndAttributes,
) -> json.Json {
  let pairs = []
  let pairs = case input.attributes_to_get {
    option.Some(v) -> [
      #("AttributesToGet", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consistent_read {
    option.Some(v) -> [#("ConsistentRead", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.keys
    [
      #(
        "Keys",
        fn(xs) {
          json.array(xs, fn(d) {
            json.object(
              dict.to_list(d)
              |> list.map(fn(pair) {
                #(pair.0, encode_attribute_value_union(pair.1))
              }),
            )
          })
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.projection_expression {
    option.Some(v) -> [#("ProjectionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_keys_and_attributes_struct_top(
  input: KeysAndAttributes,
) -> json.Json {
  let pairs = []
  let pairs = case input.attributes_to_get {
    option.Some(v) -> [
      #("AttributesToGet", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consistent_read {
    option.Some(v) -> [#("ConsistentRead", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.keys
    [
      #(
        "Keys",
        fn(xs) {
          json.array(xs, fn(d) {
            json.object(
              dict.to_list(d)
              |> list.map(fn(pair) {
                #(pair.0, encode_attribute_value_union(pair.1))
              }),
            )
          })
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.projection_expression {
    option.Some(v) -> [#("ProjectionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_keys_and_attributes_struct() -> decode.Decoder(KeysAndAttributes) {
  use <- decode.recursive
  use attributes_to_get <- decode.optional_field(
    "AttributesToGet",
    option.None,
    decode.optional(decode.list(decode.string)),
  )
  use consistent_read <- decode.optional_field(
    "ConsistentRead",
    option.None,
    decode.optional(decode.bool),
  )
  use expression_attribute_names <- decode.optional_field(
    "ExpressionAttributeNames",
    option.None,
    decode.optional(decode.dict(decode.string, decode.string)),
  )
  use keys <- decode.field(
    "Keys",
    decode.list(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use projection_expression <- decode.optional_field(
    "ProjectionExpression",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(KeysAndAttributes(
    attributes_to_get: attributes_to_get,
    consistent_read: consistent_read,
    expression_attribute_names: expression_attribute_names,
    keys: keys,
    projection_expression: projection_expression,
  ))
}

pub type BatchGetItemOutput {
  BatchGetItemOutput(
    consumed_capacity: option.Option(List(ConsumedCapacity)),
    responses: option.Option(
      dict.Dict(String, List(dict.Dict(String, AttributeValue))),
    ),
    unprocessed_keys: option.Option(dict.Dict(String, KeysAndAttributes)),
  )
}

pub fn batch_get_item_output_default() -> BatchGetItemOutput {
  BatchGetItemOutput(
    consumed_capacity: option.None,
    responses: option.None,
    unprocessed_keys: option.None,
  )
}

pub fn encode_batch_get_item_output_struct(
  input: BatchGetItemOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #(
        "ConsumedCapacity",
        fn(xs) { json.array(xs, encode_consumed_capacity_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.responses {
    option.Some(v) -> [
      #(
        "Responses",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(
                pair.0,
                fn(xs) {
                  json.array(xs, fn(d) {
                    json.object(
                      dict.to_list(d)
                      |> list.map(fn(pair) {
                        #(pair.0, encode_attribute_value_union(pair.1))
                      }),
                    )
                  })
                }(pair.1),
              )
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.unprocessed_keys {
    option.Some(v) -> [
      #(
        "UnprocessedKeys",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_keys_and_attributes_struct(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_batch_get_item_output_struct_top(
  input: BatchGetItemOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #(
        "ConsumedCapacity",
        fn(xs) { json.array(xs, encode_consumed_capacity_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.responses {
    option.Some(v) -> [
      #(
        "Responses",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(
                pair.0,
                fn(xs) {
                  json.array(xs, fn(d) {
                    json.object(
                      dict.to_list(d)
                      |> list.map(fn(pair) {
                        #(pair.0, encode_attribute_value_union(pair.1))
                      }),
                    )
                  })
                }(pair.1),
              )
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.unprocessed_keys {
    option.Some(v) -> [
      #(
        "UnprocessedKeys",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_keys_and_attributes_struct(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_batch_get_item_output_struct() -> decode.Decoder(
  BatchGetItemOutput,
) {
  use <- decode.recursive
  use consumed_capacity <- decode.optional_field(
    "ConsumedCapacity",
    option.None,
    decode.optional(decode.list(decode_consumed_capacity_struct())),
  )
  use responses <- decode.optional_field(
    "Responses",
    option.None,
    decode.optional(decode.dict(
      decode.string,
      decode.list(decode.dict(decode.string, decode_attribute_value_union())),
    )),
  )
  use unprocessed_keys <- decode.optional_field(
    "UnprocessedKeys",
    option.None,
    decode.optional(decode.dict(
      decode.string,
      decode_keys_and_attributes_struct(),
    )),
  )
  decode.success(BatchGetItemOutput(
    consumed_capacity: consumed_capacity,
    responses: responses,
    unprocessed_keys: unprocessed_keys,
  ))
}

pub type InvalidEndpointException {
  InvalidEndpointException(message: option.Option(String))
}

pub fn invalid_endpoint_exception_default() -> InvalidEndpointException {
  InvalidEndpointException(message: option.None)
}

pub fn encode_invalid_endpoint_exception_struct(
  input: InvalidEndpointException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("Message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_invalid_endpoint_exception_struct_top(
  input: InvalidEndpointException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("Message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_invalid_endpoint_exception_struct() -> decode.Decoder(
  InvalidEndpointException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "Message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(InvalidEndpointException(message: message))
}

pub type ProvisionedThroughputExceededException {
  ProvisionedThroughputExceededException(
    throttling_reasons: option.Option(List(ThrottlingReason)),
    message: option.Option(String),
  )
}

pub fn provisioned_throughput_exceeded_exception_default() -> ProvisionedThroughputExceededException {
  ProvisionedThroughputExceededException(
    throttling_reasons: option.None,
    message: option.None,
  )
}

pub fn encode_provisioned_throughput_exceeded_exception_struct(
  input: ProvisionedThroughputExceededException,
) -> json.Json {
  let pairs = []
  let pairs = case input.throttling_reasons {
    option.Some(v) -> [
      #(
        "ThrottlingReasons",
        fn(xs) { json.array(xs, encode_throttling_reason_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_provisioned_throughput_exceeded_exception_struct_top(
  input: ProvisionedThroughputExceededException,
) -> json.Json {
  let pairs = []
  let pairs = case input.throttling_reasons {
    option.Some(v) -> [
      #(
        "ThrottlingReasons",
        fn(xs) { json.array(xs, encode_throttling_reason_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_provisioned_throughput_exceeded_exception_struct() -> decode.Decoder(
  ProvisionedThroughputExceededException,
) {
  use <- decode.recursive
  use throttling_reasons <- decode.optional_field(
    "ThrottlingReasons",
    option.None,
    decode.optional(decode.list(decode_throttling_reason_struct())),
  )
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ProvisionedThroughputExceededException(
    throttling_reasons: throttling_reasons,
    message: message,
  ))
}

pub type ResourceNotFoundException {
  ResourceNotFoundException(message: option.Option(String))
}

pub fn resource_not_found_exception_default() -> ResourceNotFoundException {
  ResourceNotFoundException(message: option.None)
}

pub fn encode_resource_not_found_exception_struct(
  input: ResourceNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_resource_not_found_exception_struct_top(
  input: ResourceNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_resource_not_found_exception_struct() -> decode.Decoder(
  ResourceNotFoundException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ResourceNotFoundException(message: message))
}

pub type BatchWriteItemInput {
  BatchWriteItemInput(
    request_items: dict.Dict(String, List(WriteRequest)),
    return_consumed_capacity: option.Option(ReturnConsumedCapacity),
    return_item_collection_metrics: option.Option(ReturnItemCollectionMetrics),
  )
}

pub fn batch_write_item_input_default(
  request_items request_items: dict.Dict(String, List(WriteRequest)),
) -> BatchWriteItemInput {
  BatchWriteItemInput(
    request_items: request_items,
    return_consumed_capacity: option.None,
    return_item_collection_metrics: option.None,
  )
}

pub fn encode_batch_write_item_input_struct(
  input: BatchWriteItemInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.request_items
    [
      #(
        "RequestItems",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(
                pair.0,
                fn(xs) { json.array(xs, encode_write_request_struct) }(pair.1),
              )
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_item_collection_metrics {
    option.Some(v) -> [
      #(
        "ReturnItemCollectionMetrics",
        encode_return_item_collection_metrics_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_batch_write_item_input_struct_top(
  input: BatchWriteItemInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.request_items
    [
      #(
        "RequestItems",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(
                pair.0,
                fn(xs) { json.array(xs, encode_write_request_struct) }(pair.1),
              )
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_item_collection_metrics {
    option.Some(v) -> [
      #(
        "ReturnItemCollectionMetrics",
        encode_return_item_collection_metrics_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_batch_write_item_input_struct() -> decode.Decoder(
  BatchWriteItemInput,
) {
  use <- decode.recursive
  use request_items <- decode.field(
    "RequestItems",
    decode.dict(decode.string, decode.list(decode_write_request_struct())),
  )
  use return_consumed_capacity <- decode.optional_field(
    "ReturnConsumedCapacity",
    option.None,
    decode.optional(decode_return_consumed_capacity_enum()),
  )
  use return_item_collection_metrics <- decode.optional_field(
    "ReturnItemCollectionMetrics",
    option.None,
    decode.optional(decode_return_item_collection_metrics_enum()),
  )
  decode.success(BatchWriteItemInput(
    request_items: request_items,
    return_consumed_capacity: return_consumed_capacity,
    return_item_collection_metrics: return_item_collection_metrics,
  ))
}

pub type WriteRequest {
  WriteRequest(
    delete_request: option.Option(DeleteRequest),
    put_request: option.Option(PutRequest),
  )
}

pub fn write_request_default() -> WriteRequest {
  WriteRequest(delete_request: option.None, put_request: option.None)
}

pub fn encode_write_request_struct(input: WriteRequest) -> json.Json {
  let pairs = []
  let pairs = case input.delete_request {
    option.Some(v) -> [
      #("DeleteRequest", encode_delete_request_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.put_request {
    option.Some(v) -> [#("PutRequest", encode_put_request_struct(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_write_request_struct_top(input: WriteRequest) -> json.Json {
  let pairs = []
  let pairs = case input.delete_request {
    option.Some(v) -> [
      #("DeleteRequest", encode_delete_request_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.put_request {
    option.Some(v) -> [#("PutRequest", encode_put_request_struct(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_write_request_struct() -> decode.Decoder(WriteRequest) {
  use <- decode.recursive
  use delete_request <- decode.optional_field(
    "DeleteRequest",
    option.None,
    decode.optional(decode_delete_request_struct()),
  )
  use put_request <- decode.optional_field(
    "PutRequest",
    option.None,
    decode.optional(decode_put_request_struct()),
  )
  decode.success(WriteRequest(
    delete_request: delete_request,
    put_request: put_request,
  ))
}

pub type DeleteRequest {
  DeleteRequest(key: dict.Dict(String, AttributeValue))
}

pub fn delete_request_default(
  key key: dict.Dict(String, AttributeValue),
) -> DeleteRequest {
  DeleteRequest(key: key)
}

pub fn encode_delete_request_struct(input: DeleteRequest) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn encode_delete_request_struct_top(input: DeleteRequest) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn decode_delete_request_struct() -> decode.Decoder(DeleteRequest) {
  use <- decode.recursive
  use key <- decode.field(
    "Key",
    decode.dict(decode.string, decode_attribute_value_union()),
  )
  decode.success(DeleteRequest(key: key))
}

pub type PutRequest {
  PutRequest(item: dict.Dict(String, AttributeValue))
}

pub fn put_request_default(
  item item: dict.Dict(String, AttributeValue),
) -> PutRequest {
  PutRequest(item: item)
}

pub fn encode_put_request_struct(input: PutRequest) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.item
    [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn encode_put_request_struct_top(input: PutRequest) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.item
    [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn decode_put_request_struct() -> decode.Decoder(PutRequest) {
  use <- decode.recursive
  use item <- decode.field(
    "Item",
    decode.dict(decode.string, decode_attribute_value_union()),
  )
  decode.success(PutRequest(item: item))
}

pub type ReturnItemCollectionMetrics {
  ReturnItemCollectionMetricsNone
  ReturnItemCollectionMetricsSize
}

pub fn encode_return_item_collection_metrics_enum(
  v: ReturnItemCollectionMetrics,
) -> json.Json {
  case v {
    ReturnItemCollectionMetricsNone -> json.string("NONE")
    ReturnItemCollectionMetricsSize -> json.string("SIZE")
  }
}

pub fn decode_return_item_collection_metrics_enum() -> decode.Decoder(
  ReturnItemCollectionMetrics,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "NONE" -> decode.success(ReturnItemCollectionMetricsNone)
      "SIZE" -> decode.success(ReturnItemCollectionMetricsSize)
      _ -> decode.failure(ReturnItemCollectionMetricsNone, "unknown enum value")
    }
  })
}

pub type BatchWriteItemOutput {
  BatchWriteItemOutput(
    consumed_capacity: option.Option(List(ConsumedCapacity)),
    item_collection_metrics: option.Option(
      dict.Dict(String, List(ItemCollectionMetrics)),
    ),
    unprocessed_items: option.Option(dict.Dict(String, List(WriteRequest))),
  )
}

pub fn batch_write_item_output_default() -> BatchWriteItemOutput {
  BatchWriteItemOutput(
    consumed_capacity: option.None,
    item_collection_metrics: option.None,
    unprocessed_items: option.None,
  )
}

pub fn encode_batch_write_item_output_struct(
  input: BatchWriteItemOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #(
        "ConsumedCapacity",
        fn(xs) { json.array(xs, encode_consumed_capacity_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_collection_metrics {
    option.Some(v) -> [
      #(
        "ItemCollectionMetrics",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(
                pair.0,
                fn(xs) { json.array(xs, encode_item_collection_metrics_struct) }(
                  pair.1,
                ),
              )
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.unprocessed_items {
    option.Some(v) -> [
      #(
        "UnprocessedItems",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(
                pair.0,
                fn(xs) { json.array(xs, encode_write_request_struct) }(pair.1),
              )
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_batch_write_item_output_struct_top(
  input: BatchWriteItemOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #(
        "ConsumedCapacity",
        fn(xs) { json.array(xs, encode_consumed_capacity_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_collection_metrics {
    option.Some(v) -> [
      #(
        "ItemCollectionMetrics",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(
                pair.0,
                fn(xs) { json.array(xs, encode_item_collection_metrics_struct) }(
                  pair.1,
                ),
              )
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.unprocessed_items {
    option.Some(v) -> [
      #(
        "UnprocessedItems",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(
                pair.0,
                fn(xs) { json.array(xs, encode_write_request_struct) }(pair.1),
              )
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_batch_write_item_output_struct() -> decode.Decoder(
  BatchWriteItemOutput,
) {
  use <- decode.recursive
  use consumed_capacity <- decode.optional_field(
    "ConsumedCapacity",
    option.None,
    decode.optional(decode.list(decode_consumed_capacity_struct())),
  )
  use item_collection_metrics <- decode.optional_field(
    "ItemCollectionMetrics",
    option.None,
    decode.optional(decode.dict(
      decode.string,
      decode.list(decode_item_collection_metrics_struct()),
    )),
  )
  use unprocessed_items <- decode.optional_field(
    "UnprocessedItems",
    option.None,
    decode.optional(decode.dict(
      decode.string,
      decode.list(decode_write_request_struct()),
    )),
  )
  decode.success(BatchWriteItemOutput(
    consumed_capacity: consumed_capacity,
    item_collection_metrics: item_collection_metrics,
    unprocessed_items: unprocessed_items,
  ))
}

pub type ItemCollectionMetrics {
  ItemCollectionMetrics(
    item_collection_key: option.Option(dict.Dict(String, AttributeValue)),
    size_estimate_range_gb: option.Option(List(json_float.SmithyFloat)),
  )
}

pub fn item_collection_metrics_default() -> ItemCollectionMetrics {
  ItemCollectionMetrics(
    item_collection_key: option.None,
    size_estimate_range_gb: option.None,
  )
}

pub fn encode_item_collection_metrics_struct(
  input: ItemCollectionMetrics,
) -> json.Json {
  let pairs = []
  let pairs = case input.item_collection_key {
    option.Some(v) -> [
      #(
        "ItemCollectionKey",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.size_estimate_range_gb {
    option.Some(v) -> [
      #("SizeEstimateRangeGB", fn(xs) { json.array(xs, json_float.encode) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_item_collection_metrics_struct_top(
  input: ItemCollectionMetrics,
) -> json.Json {
  let pairs = []
  let pairs = case input.item_collection_key {
    option.Some(v) -> [
      #(
        "ItemCollectionKey",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.size_estimate_range_gb {
    option.Some(v) -> [
      #("SizeEstimateRangeGB", fn(xs) { json.array(xs, json_float.encode) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_item_collection_metrics_struct() -> decode.Decoder(
  ItemCollectionMetrics,
) {
  use <- decode.recursive
  use item_collection_key <- decode.optional_field(
    "ItemCollectionKey",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use size_estimate_range_gb <- decode.optional_field(
    "SizeEstimateRangeGB",
    option.None,
    decode.optional(decode.list(json_float.decoder())),
  )
  decode.success(ItemCollectionMetrics(
    item_collection_key: item_collection_key,
    size_estimate_range_gb: size_estimate_range_gb,
  ))
}

pub type ItemCollectionSizeLimitExceededException {
  ItemCollectionSizeLimitExceededException(message: option.Option(String))
}

pub fn item_collection_size_limit_exceeded_exception_default() -> ItemCollectionSizeLimitExceededException {
  ItemCollectionSizeLimitExceededException(message: option.None)
}

pub fn encode_item_collection_size_limit_exceeded_exception_struct(
  input: ItemCollectionSizeLimitExceededException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_item_collection_size_limit_exceeded_exception_struct_top(
  input: ItemCollectionSizeLimitExceededException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_item_collection_size_limit_exceeded_exception_struct() -> decode.Decoder(
  ItemCollectionSizeLimitExceededException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ItemCollectionSizeLimitExceededException(message: message))
}

pub type ReplicatedWriteConflictException {
  ReplicatedWriteConflictException(message: option.Option(String))
}

pub fn replicated_write_conflict_exception_default() -> ReplicatedWriteConflictException {
  ReplicatedWriteConflictException(message: option.None)
}

pub fn encode_replicated_write_conflict_exception_struct(
  input: ReplicatedWriteConflictException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replicated_write_conflict_exception_struct_top(
  input: ReplicatedWriteConflictException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replicated_write_conflict_exception_struct() -> decode.Decoder(
  ReplicatedWriteConflictException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ReplicatedWriteConflictException(message: message))
}

pub type CreateBackupInput {
  CreateBackupInput(backup_name: String, table_name: String)
}

pub fn create_backup_input_default(
  backup_name backup_name: String,
  table_name table_name: String,
) -> CreateBackupInput {
  CreateBackupInput(backup_name: backup_name, table_name: table_name)
}

pub fn encode_create_backup_input_struct(
  input: CreateBackupInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.backup_name
    [#("BackupName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_create_backup_input_struct_top(
  input: CreateBackupInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.backup_name
    [#("BackupName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_create_backup_input_struct() -> decode.Decoder(CreateBackupInput) {
  use <- decode.recursive
  use backup_name <- decode.field("BackupName", decode.string)
  use table_name <- decode.field("TableName", decode.string)
  decode.success(CreateBackupInput(
    backup_name: backup_name,
    table_name: table_name,
  ))
}

pub type CreateBackupOutput {
  CreateBackupOutput(backup_details: option.Option(BackupDetails))
}

pub fn create_backup_output_default() -> CreateBackupOutput {
  CreateBackupOutput(backup_details: option.None)
}

pub fn encode_create_backup_output_struct(
  input: CreateBackupOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.backup_details {
    option.Some(v) -> [
      #("BackupDetails", encode_backup_details_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_create_backup_output_struct_top(
  input: CreateBackupOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.backup_details {
    option.Some(v) -> [
      #("BackupDetails", encode_backup_details_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_create_backup_output_struct() -> decode.Decoder(
  CreateBackupOutput,
) {
  use <- decode.recursive
  use backup_details <- decode.optional_field(
    "BackupDetails",
    option.None,
    decode.optional(decode_backup_details_struct()),
  )
  decode.success(CreateBackupOutput(backup_details: backup_details))
}

pub type BackupDetails {
  BackupDetails(
    backup_arn: option.Option(String),
    backup_creation_date_time: option.Option(json_timestamp.Timestamp),
    backup_expiry_date_time: option.Option(json_timestamp.Timestamp),
    backup_name: option.Option(String),
    backup_size_bytes: option.Option(Int),
    backup_status: option.Option(BackupStatus),
    backup_type: option.Option(BackupType),
  )
}

pub fn backup_details_default() -> BackupDetails {
  BackupDetails(
    backup_arn: option.None,
    backup_creation_date_time: option.None,
    backup_expiry_date_time: option.None,
    backup_name: option.None,
    backup_size_bytes: option.None,
    backup_status: option.None,
    backup_type: option.None,
  )
}

pub fn encode_backup_details_struct(input: BackupDetails) -> json.Json {
  let pairs = []
  let pairs = case input.backup_arn {
    option.Some(v) -> [#("BackupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_creation_date_time {
    option.Some(v) -> [
      #("BackupCreationDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.backup_expiry_date_time {
    option.Some(v) -> [
      #("BackupExpiryDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.backup_name {
    option.Some(v) -> [#("BackupName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_size_bytes {
    option.Some(v) -> [#("BackupSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_status {
    option.Some(v) -> [#("BackupStatus", encode_backup_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_type {
    option.Some(v) -> [#("BackupType", encode_backup_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_backup_details_struct_top(input: BackupDetails) -> json.Json {
  let pairs = []
  let pairs = case input.backup_arn {
    option.Some(v) -> [#("BackupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_creation_date_time {
    option.Some(v) -> [
      #("BackupCreationDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.backup_expiry_date_time {
    option.Some(v) -> [
      #("BackupExpiryDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.backup_name {
    option.Some(v) -> [#("BackupName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_size_bytes {
    option.Some(v) -> [#("BackupSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_status {
    option.Some(v) -> [#("BackupStatus", encode_backup_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_type {
    option.Some(v) -> [#("BackupType", encode_backup_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_backup_details_struct() -> decode.Decoder(BackupDetails) {
  use <- decode.recursive
  use backup_arn <- decode.optional_field(
    "BackupArn",
    option.None,
    decode.optional(decode.string),
  )
  use backup_creation_date_time <- decode.optional_field(
    "BackupCreationDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use backup_expiry_date_time <- decode.optional_field(
    "BackupExpiryDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use backup_name <- decode.optional_field(
    "BackupName",
    option.None,
    decode.optional(decode.string),
  )
  use backup_size_bytes <- decode.optional_field(
    "BackupSizeBytes",
    option.None,
    decode.optional(decode.int),
  )
  use backup_status <- decode.optional_field(
    "BackupStatus",
    option.None,
    decode.optional(decode_backup_status_enum()),
  )
  use backup_type <- decode.optional_field(
    "BackupType",
    option.None,
    decode.optional(decode_backup_type_enum()),
  )
  decode.success(BackupDetails(
    backup_arn: backup_arn,
    backup_creation_date_time: backup_creation_date_time,
    backup_expiry_date_time: backup_expiry_date_time,
    backup_name: backup_name,
    backup_size_bytes: backup_size_bytes,
    backup_status: backup_status,
    backup_type: backup_type,
  ))
}

pub type BackupStatus {
  BackupStatusAvailable
  BackupStatusCreating
  BackupStatusDeleted
}

pub fn encode_backup_status_enum(v: BackupStatus) -> json.Json {
  case v {
    BackupStatusAvailable -> json.string("AVAILABLE")
    BackupStatusCreating -> json.string("CREATING")
    BackupStatusDeleted -> json.string("DELETED")
  }
}

pub fn decode_backup_status_enum() -> decode.Decoder(BackupStatus) {
  decode.then(decode.string, fn(s) {
    case s {
      "AVAILABLE" -> decode.success(BackupStatusAvailable)
      "CREATING" -> decode.success(BackupStatusCreating)
      "DELETED" -> decode.success(BackupStatusDeleted)
      _ -> decode.failure(BackupStatusAvailable, "unknown enum value")
    }
  })
}

pub type BackupType {
  BackupTypeAwsBackup
  BackupTypeSystem
  BackupTypeUser
}

pub fn encode_backup_type_enum(v: BackupType) -> json.Json {
  case v {
    BackupTypeAwsBackup -> json.string("AWS_BACKUP")
    BackupTypeSystem -> json.string("SYSTEM")
    BackupTypeUser -> json.string("USER")
  }
}

pub fn decode_backup_type_enum() -> decode.Decoder(BackupType) {
  decode.then(decode.string, fn(s) {
    case s {
      "AWS_BACKUP" -> decode.success(BackupTypeAwsBackup)
      "SYSTEM" -> decode.success(BackupTypeSystem)
      "USER" -> decode.success(BackupTypeUser)
      _ -> decode.failure(BackupTypeAwsBackup, "unknown enum value")
    }
  })
}

pub type BackupInUseException {
  BackupInUseException(message: option.Option(String))
}

pub fn backup_in_use_exception_default() -> BackupInUseException {
  BackupInUseException(message: option.None)
}

pub fn encode_backup_in_use_exception_struct(
  input: BackupInUseException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_backup_in_use_exception_struct_top(
  input: BackupInUseException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_backup_in_use_exception_struct() -> decode.Decoder(
  BackupInUseException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(BackupInUseException(message: message))
}

pub type ContinuousBackupsUnavailableException {
  ContinuousBackupsUnavailableException(message: option.Option(String))
}

pub fn continuous_backups_unavailable_exception_default() -> ContinuousBackupsUnavailableException {
  ContinuousBackupsUnavailableException(message: option.None)
}

pub fn encode_continuous_backups_unavailable_exception_struct(
  input: ContinuousBackupsUnavailableException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_continuous_backups_unavailable_exception_struct_top(
  input: ContinuousBackupsUnavailableException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_continuous_backups_unavailable_exception_struct() -> decode.Decoder(
  ContinuousBackupsUnavailableException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ContinuousBackupsUnavailableException(message: message))
}

pub type LimitExceededException {
  LimitExceededException(message: option.Option(String))
}

pub fn limit_exceeded_exception_default() -> LimitExceededException {
  LimitExceededException(message: option.None)
}

pub fn encode_limit_exceeded_exception_struct(
  input: LimitExceededException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_limit_exceeded_exception_struct_top(
  input: LimitExceededException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_limit_exceeded_exception_struct() -> decode.Decoder(
  LimitExceededException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(LimitExceededException(message: message))
}

pub type TableInUseException {
  TableInUseException(message: option.Option(String))
}

pub fn table_in_use_exception_default() -> TableInUseException {
  TableInUseException(message: option.None)
}

pub fn encode_table_in_use_exception_struct(
  input: TableInUseException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_table_in_use_exception_struct_top(
  input: TableInUseException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_table_in_use_exception_struct() -> decode.Decoder(
  TableInUseException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(TableInUseException(message: message))
}

pub type TableNotFoundException {
  TableNotFoundException(message: option.Option(String))
}

pub fn table_not_found_exception_default() -> TableNotFoundException {
  TableNotFoundException(message: option.None)
}

pub fn encode_table_not_found_exception_struct(
  input: TableNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_table_not_found_exception_struct_top(
  input: TableNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_table_not_found_exception_struct() -> decode.Decoder(
  TableNotFoundException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(TableNotFoundException(message: message))
}

pub type CreateGlobalTableInput {
  CreateGlobalTableInput(
    global_table_name: String,
    replication_group: List(Replica),
  )
}

pub fn create_global_table_input_default(
  global_table_name global_table_name: String,
  replication_group replication_group: List(Replica),
) -> CreateGlobalTableInput {
  CreateGlobalTableInput(
    global_table_name: global_table_name,
    replication_group: replication_group,
  )
}

pub fn encode_create_global_table_input_struct(
  input: CreateGlobalTableInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.global_table_name
    [#("GlobalTableName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.replication_group
    [
      #("ReplicationGroup", fn(xs) { json.array(xs, encode_replica_struct) }(v)),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn encode_create_global_table_input_struct_top(
  input: CreateGlobalTableInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.global_table_name
    [#("GlobalTableName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.replication_group
    [
      #("ReplicationGroup", fn(xs) { json.array(xs, encode_replica_struct) }(v)),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn decode_create_global_table_input_struct() -> decode.Decoder(
  CreateGlobalTableInput,
) {
  use <- decode.recursive
  use global_table_name <- decode.field("GlobalTableName", decode.string)
  use replication_group <- decode.field(
    "ReplicationGroup",
    decode.list(decode_replica_struct()),
  )
  decode.success(CreateGlobalTableInput(
    global_table_name: global_table_name,
    replication_group: replication_group,
  ))
}

pub type Replica {
  Replica(region_name: option.Option(String))
}

pub fn replica_default() -> Replica {
  Replica(region_name: option.None)
}

pub fn encode_replica_struct(input: Replica) -> json.Json {
  let pairs = []
  let pairs = case input.region_name {
    option.Some(v) -> [#("RegionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_struct_top(input: Replica) -> json.Json {
  let pairs = []
  let pairs = case input.region_name {
    option.Some(v) -> [#("RegionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_struct() -> decode.Decoder(Replica) {
  use <- decode.recursive
  use region_name <- decode.optional_field(
    "RegionName",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(Replica(region_name: region_name))
}

pub type CreateGlobalTableOutput {
  CreateGlobalTableOutput(
    global_table_description: option.Option(GlobalTableDescription),
  )
}

pub fn create_global_table_output_default() -> CreateGlobalTableOutput {
  CreateGlobalTableOutput(global_table_description: option.None)
}

pub fn encode_create_global_table_output_struct(
  input: CreateGlobalTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_description {
    option.Some(v) -> [
      #("GlobalTableDescription", encode_global_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_create_global_table_output_struct_top(
  input: CreateGlobalTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_description {
    option.Some(v) -> [
      #("GlobalTableDescription", encode_global_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_create_global_table_output_struct() -> decode.Decoder(
  CreateGlobalTableOutput,
) {
  use <- decode.recursive
  use global_table_description <- decode.optional_field(
    "GlobalTableDescription",
    option.None,
    decode.optional(decode_global_table_description_struct()),
  )
  decode.success(CreateGlobalTableOutput(
    global_table_description: global_table_description,
  ))
}

pub type GlobalTableDescription {
  GlobalTableDescription(
    creation_date_time: option.Option(json_timestamp.Timestamp),
    global_table_arn: option.Option(String),
    global_table_name: option.Option(String),
    global_table_status: option.Option(GlobalTableStatus),
    replication_group: option.Option(List(ReplicaDescription)),
  )
}

pub fn global_table_description_default() -> GlobalTableDescription {
  GlobalTableDescription(
    creation_date_time: option.None,
    global_table_arn: option.None,
    global_table_name: option.None,
    global_table_status: option.None,
    replication_group: option.None,
  )
}

pub fn encode_global_table_description_struct(
  input: GlobalTableDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.creation_date_time {
    option.Some(v) -> [
      #("CreationDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_arn {
    option.Some(v) -> [#("GlobalTableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_table_name {
    option.Some(v) -> [#("GlobalTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_table_status {
    option.Some(v) -> [
      #("GlobalTableStatus", encode_global_table_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replication_group {
    option.Some(v) -> [
      #(
        "ReplicationGroup",
        fn(xs) { json.array(xs, encode_replica_description_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_global_table_description_struct_top(
  input: GlobalTableDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.creation_date_time {
    option.Some(v) -> [
      #("CreationDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_arn {
    option.Some(v) -> [#("GlobalTableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_table_name {
    option.Some(v) -> [#("GlobalTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_table_status {
    option.Some(v) -> [
      #("GlobalTableStatus", encode_global_table_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replication_group {
    option.Some(v) -> [
      #(
        "ReplicationGroup",
        fn(xs) { json.array(xs, encode_replica_description_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_global_table_description_struct() -> decode.Decoder(
  GlobalTableDescription,
) {
  use <- decode.recursive
  use creation_date_time <- decode.optional_field(
    "CreationDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use global_table_arn <- decode.optional_field(
    "GlobalTableArn",
    option.None,
    decode.optional(decode.string),
  )
  use global_table_name <- decode.optional_field(
    "GlobalTableName",
    option.None,
    decode.optional(decode.string),
  )
  use global_table_status <- decode.optional_field(
    "GlobalTableStatus",
    option.None,
    decode.optional(decode_global_table_status_enum()),
  )
  use replication_group <- decode.optional_field(
    "ReplicationGroup",
    option.None,
    decode.optional(decode.list(decode_replica_description_struct())),
  )
  decode.success(GlobalTableDescription(
    creation_date_time: creation_date_time,
    global_table_arn: global_table_arn,
    global_table_name: global_table_name,
    global_table_status: global_table_status,
    replication_group: replication_group,
  ))
}

pub type GlobalTableStatus {
  GlobalTableStatusActive
  GlobalTableStatusCreating
  GlobalTableStatusDeleting
  GlobalTableStatusUpdating
}

pub fn encode_global_table_status_enum(v: GlobalTableStatus) -> json.Json {
  case v {
    GlobalTableStatusActive -> json.string("ACTIVE")
    GlobalTableStatusCreating -> json.string("CREATING")
    GlobalTableStatusDeleting -> json.string("DELETING")
    GlobalTableStatusUpdating -> json.string("UPDATING")
  }
}

pub fn decode_global_table_status_enum() -> decode.Decoder(GlobalTableStatus) {
  decode.then(decode.string, fn(s) {
    case s {
      "ACTIVE" -> decode.success(GlobalTableStatusActive)
      "CREATING" -> decode.success(GlobalTableStatusCreating)
      "DELETING" -> decode.success(GlobalTableStatusDeleting)
      "UPDATING" -> decode.success(GlobalTableStatusUpdating)
      _ -> decode.failure(GlobalTableStatusActive, "unknown enum value")
    }
  })
}

pub type ReplicaDescription {
  ReplicaDescription(
    global_secondary_indexes: option.Option(
      List(ReplicaGlobalSecondaryIndexDescription),
    ),
    global_table_settings_replication_mode: option.Option(
      GlobalTableSettingsReplicationMode,
    ),
    kms_master_key_id: option.Option(String),
    on_demand_throughput_override: option.Option(OnDemandThroughputOverride),
    provisioned_throughput_override: option.Option(
      ProvisionedThroughputOverride,
    ),
    region_name: option.Option(String),
    replica_arn: option.Option(String),
    replica_inaccessible_date_time: option.Option(json_timestamp.Timestamp),
    replica_status: option.Option(ReplicaStatus),
    replica_status_description: option.Option(String),
    replica_status_percent_progress: option.Option(String),
    replica_table_class_summary: option.Option(TableClassSummary),
    warm_throughput: option.Option(TableWarmThroughputDescription),
  )
}

pub fn replica_description_default() -> ReplicaDescription {
  ReplicaDescription(
    global_secondary_indexes: option.None,
    global_table_settings_replication_mode: option.None,
    kms_master_key_id: option.None,
    on_demand_throughput_override: option.None,
    provisioned_throughput_override: option.None,
    region_name: option.None,
    replica_arn: option.None,
    replica_inaccessible_date_time: option.None,
    replica_status: option.None,
    replica_status_description: option.None,
    replica_status_percent_progress: option.None,
    replica_table_class_summary: option.None,
    warm_throughput: option.None,
  )
}

pub fn encode_replica_description_struct(
  input: ReplicaDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) {
          json.array(
            xs,
            encode_replica_global_secondary_index_description_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_settings_replication_mode {
    option.Some(v) -> [
      #(
        "GlobalTableSettingsReplicationMode",
        encode_global_table_settings_replication_mode_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.kms_master_key_id {
    option.Some(v) -> [#("KMSMasterKeyId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #(
        "OnDemandThroughputOverride",
        encode_on_demand_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.region_name {
    option.Some(v) -> [#("RegionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replica_arn {
    option.Some(v) -> [#("ReplicaArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replica_inaccessible_date_time {
    option.Some(v) -> [
      #("ReplicaInaccessibleDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_status {
    option.Some(v) -> [
      #("ReplicaStatus", encode_replica_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_status_description {
    option.Some(v) -> [#("ReplicaStatusDescription", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replica_status_percent_progress {
    option.Some(v) -> [
      #("ReplicaStatusPercentProgress", json.string(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_table_class_summary {
    option.Some(v) -> [
      #("ReplicaTableClassSummary", encode_table_class_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_table_warm_throughput_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_description_struct_top(
  input: ReplicaDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) {
          json.array(
            xs,
            encode_replica_global_secondary_index_description_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_settings_replication_mode {
    option.Some(v) -> [
      #(
        "GlobalTableSettingsReplicationMode",
        encode_global_table_settings_replication_mode_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.kms_master_key_id {
    option.Some(v) -> [#("KMSMasterKeyId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #(
        "OnDemandThroughputOverride",
        encode_on_demand_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.region_name {
    option.Some(v) -> [#("RegionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replica_arn {
    option.Some(v) -> [#("ReplicaArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replica_inaccessible_date_time {
    option.Some(v) -> [
      #("ReplicaInaccessibleDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_status {
    option.Some(v) -> [
      #("ReplicaStatus", encode_replica_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_status_description {
    option.Some(v) -> [#("ReplicaStatusDescription", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replica_status_percent_progress {
    option.Some(v) -> [
      #("ReplicaStatusPercentProgress", json.string(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_table_class_summary {
    option.Some(v) -> [
      #("ReplicaTableClassSummary", encode_table_class_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_table_warm_throughput_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_description_struct() -> decode.Decoder(ReplicaDescription) {
  use <- decode.recursive
  use global_secondary_indexes <- decode.optional_field(
    "GlobalSecondaryIndexes",
    option.None,
    decode.optional(
      decode.list(decode_replica_global_secondary_index_description_struct()),
    ),
  )
  use global_table_settings_replication_mode <- decode.optional_field(
    "GlobalTableSettingsReplicationMode",
    option.None,
    decode.optional(decode_global_table_settings_replication_mode_enum()),
  )
  use kms_master_key_id <- decode.optional_field(
    "KMSMasterKeyId",
    option.None,
    decode.optional(decode.string),
  )
  use on_demand_throughput_override <- decode.optional_field(
    "OnDemandThroughputOverride",
    option.None,
    decode.optional(decode_on_demand_throughput_override_struct()),
  )
  use provisioned_throughput_override <- decode.optional_field(
    "ProvisionedThroughputOverride",
    option.None,
    decode.optional(decode_provisioned_throughput_override_struct()),
  )
  use region_name <- decode.optional_field(
    "RegionName",
    option.None,
    decode.optional(decode.string),
  )
  use replica_arn <- decode.optional_field(
    "ReplicaArn",
    option.None,
    decode.optional(decode.string),
  )
  use replica_inaccessible_date_time <- decode.optional_field(
    "ReplicaInaccessibleDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use replica_status <- decode.optional_field(
    "ReplicaStatus",
    option.None,
    decode.optional(decode_replica_status_enum()),
  )
  use replica_status_description <- decode.optional_field(
    "ReplicaStatusDescription",
    option.None,
    decode.optional(decode.string),
  )
  use replica_status_percent_progress <- decode.optional_field(
    "ReplicaStatusPercentProgress",
    option.None,
    decode.optional(decode.string),
  )
  use replica_table_class_summary <- decode.optional_field(
    "ReplicaTableClassSummary",
    option.None,
    decode.optional(decode_table_class_summary_struct()),
  )
  use warm_throughput <- decode.optional_field(
    "WarmThroughput",
    option.None,
    decode.optional(decode_table_warm_throughput_description_struct()),
  )
  decode.success(ReplicaDescription(
    global_secondary_indexes: global_secondary_indexes,
    global_table_settings_replication_mode: global_table_settings_replication_mode,
    kms_master_key_id: kms_master_key_id,
    on_demand_throughput_override: on_demand_throughput_override,
    provisioned_throughput_override: provisioned_throughput_override,
    region_name: region_name,
    replica_arn: replica_arn,
    replica_inaccessible_date_time: replica_inaccessible_date_time,
    replica_status: replica_status,
    replica_status_description: replica_status_description,
    replica_status_percent_progress: replica_status_percent_progress,
    replica_table_class_summary: replica_table_class_summary,
    warm_throughput: warm_throughput,
  ))
}

pub type ReplicaGlobalSecondaryIndexDescription {
  ReplicaGlobalSecondaryIndexDescription(
    index_name: option.Option(String),
    on_demand_throughput_override: option.Option(OnDemandThroughputOverride),
    provisioned_throughput_override: option.Option(
      ProvisionedThroughputOverride,
    ),
    warm_throughput: option.Option(
      GlobalSecondaryIndexWarmThroughputDescription,
    ),
  )
}

pub fn replica_global_secondary_index_description_default() -> ReplicaGlobalSecondaryIndexDescription {
  ReplicaGlobalSecondaryIndexDescription(
    index_name: option.None,
    on_demand_throughput_override: option.None,
    provisioned_throughput_override: option.None,
    warm_throughput: option.None,
  )
}

pub fn encode_replica_global_secondary_index_description_struct(
  input: ReplicaGlobalSecondaryIndexDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #(
        "OnDemandThroughputOverride",
        encode_on_demand_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #(
        "WarmThroughput",
        encode_global_secondary_index_warm_throughput_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_global_secondary_index_description_struct_top(
  input: ReplicaGlobalSecondaryIndexDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #(
        "OnDemandThroughputOverride",
        encode_on_demand_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #(
        "WarmThroughput",
        encode_global_secondary_index_warm_throughput_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_global_secondary_index_description_struct() -> decode.Decoder(
  ReplicaGlobalSecondaryIndexDescription,
) {
  use <- decode.recursive
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use on_demand_throughput_override <- decode.optional_field(
    "OnDemandThroughputOverride",
    option.None,
    decode.optional(decode_on_demand_throughput_override_struct()),
  )
  use provisioned_throughput_override <- decode.optional_field(
    "ProvisionedThroughputOverride",
    option.None,
    decode.optional(decode_provisioned_throughput_override_struct()),
  )
  use warm_throughput <- decode.optional_field(
    "WarmThroughput",
    option.None,
    decode.optional(
      decode_global_secondary_index_warm_throughput_description_struct(),
    ),
  )
  decode.success(ReplicaGlobalSecondaryIndexDescription(
    index_name: index_name,
    on_demand_throughput_override: on_demand_throughput_override,
    provisioned_throughput_override: provisioned_throughput_override,
    warm_throughput: warm_throughput,
  ))
}

pub type OnDemandThroughputOverride {
  OnDemandThroughputOverride(max_read_request_units: option.Option(Int))
}

pub fn on_demand_throughput_override_default() -> OnDemandThroughputOverride {
  OnDemandThroughputOverride(max_read_request_units: option.None)
}

pub fn encode_on_demand_throughput_override_struct(
  input: OnDemandThroughputOverride,
) -> json.Json {
  let pairs = []
  let pairs = case input.max_read_request_units {
    option.Some(v) -> [#("MaxReadRequestUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_on_demand_throughput_override_struct_top(
  input: OnDemandThroughputOverride,
) -> json.Json {
  let pairs = []
  let pairs = case input.max_read_request_units {
    option.Some(v) -> [#("MaxReadRequestUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_on_demand_throughput_override_struct() -> decode.Decoder(
  OnDemandThroughputOverride,
) {
  use <- decode.recursive
  use max_read_request_units <- decode.optional_field(
    "MaxReadRequestUnits",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(OnDemandThroughputOverride(
    max_read_request_units: max_read_request_units,
  ))
}

pub type ProvisionedThroughputOverride {
  ProvisionedThroughputOverride(read_capacity_units: option.Option(Int))
}

pub fn provisioned_throughput_override_default() -> ProvisionedThroughputOverride {
  ProvisionedThroughputOverride(read_capacity_units: option.None)
}

pub fn encode_provisioned_throughput_override_struct(
  input: ProvisionedThroughputOverride,
) -> json.Json {
  let pairs = []
  let pairs = case input.read_capacity_units {
    option.Some(v) -> [#("ReadCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_provisioned_throughput_override_struct_top(
  input: ProvisionedThroughputOverride,
) -> json.Json {
  let pairs = []
  let pairs = case input.read_capacity_units {
    option.Some(v) -> [#("ReadCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_provisioned_throughput_override_struct() -> decode.Decoder(
  ProvisionedThroughputOverride,
) {
  use <- decode.recursive
  use read_capacity_units <- decode.optional_field(
    "ReadCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(ProvisionedThroughputOverride(
    read_capacity_units: read_capacity_units,
  ))
}

pub type GlobalSecondaryIndexWarmThroughputDescription {
  GlobalSecondaryIndexWarmThroughputDescription(
    read_units_per_second: option.Option(Int),
    status: option.Option(IndexStatus),
    write_units_per_second: option.Option(Int),
  )
}

pub fn global_secondary_index_warm_throughput_description_default() -> GlobalSecondaryIndexWarmThroughputDescription {
  GlobalSecondaryIndexWarmThroughputDescription(
    read_units_per_second: option.None,
    status: option.None,
    write_units_per_second: option.None,
  )
}

pub fn encode_global_secondary_index_warm_throughput_description_struct(
  input: GlobalSecondaryIndexWarmThroughputDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.read_units_per_second {
    option.Some(v) -> [#("ReadUnitsPerSecond", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.status {
    option.Some(v) -> [#("Status", encode_index_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.write_units_per_second {
    option.Some(v) -> [#("WriteUnitsPerSecond", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_global_secondary_index_warm_throughput_description_struct_top(
  input: GlobalSecondaryIndexWarmThroughputDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.read_units_per_second {
    option.Some(v) -> [#("ReadUnitsPerSecond", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.status {
    option.Some(v) -> [#("Status", encode_index_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.write_units_per_second {
    option.Some(v) -> [#("WriteUnitsPerSecond", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_global_secondary_index_warm_throughput_description_struct() -> decode.Decoder(
  GlobalSecondaryIndexWarmThroughputDescription,
) {
  use <- decode.recursive
  use read_units_per_second <- decode.optional_field(
    "ReadUnitsPerSecond",
    option.None,
    decode.optional(decode.int),
  )
  use status <- decode.optional_field(
    "Status",
    option.None,
    decode.optional(decode_index_status_enum()),
  )
  use write_units_per_second <- decode.optional_field(
    "WriteUnitsPerSecond",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(GlobalSecondaryIndexWarmThroughputDescription(
    read_units_per_second: read_units_per_second,
    status: status,
    write_units_per_second: write_units_per_second,
  ))
}

pub type IndexStatus {
  IndexStatusActive
  IndexStatusCreating
  IndexStatusDeleting
  IndexStatusUpdating
}

pub fn encode_index_status_enum(v: IndexStatus) -> json.Json {
  case v {
    IndexStatusActive -> json.string("ACTIVE")
    IndexStatusCreating -> json.string("CREATING")
    IndexStatusDeleting -> json.string("DELETING")
    IndexStatusUpdating -> json.string("UPDATING")
  }
}

pub fn decode_index_status_enum() -> decode.Decoder(IndexStatus) {
  decode.then(decode.string, fn(s) {
    case s {
      "ACTIVE" -> decode.success(IndexStatusActive)
      "CREATING" -> decode.success(IndexStatusCreating)
      "DELETING" -> decode.success(IndexStatusDeleting)
      "UPDATING" -> decode.success(IndexStatusUpdating)
      _ -> decode.failure(IndexStatusActive, "unknown enum value")
    }
  })
}

pub type GlobalTableSettingsReplicationMode {
  GlobalTableSettingsReplicationModeDisabled
  GlobalTableSettingsReplicationModeEnabled
  GlobalTableSettingsReplicationModeEnabledWithOverrides
}

pub fn encode_global_table_settings_replication_mode_enum(
  v: GlobalTableSettingsReplicationMode,
) -> json.Json {
  case v {
    GlobalTableSettingsReplicationModeDisabled -> json.string("DISABLED")
    GlobalTableSettingsReplicationModeEnabled -> json.string("ENABLED")
    GlobalTableSettingsReplicationModeEnabledWithOverrides ->
      json.string("ENABLED_WITH_OVERRIDES")
  }
}

pub fn decode_global_table_settings_replication_mode_enum() -> decode.Decoder(
  GlobalTableSettingsReplicationMode,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "DISABLED" -> decode.success(GlobalTableSettingsReplicationModeDisabled)
      "ENABLED" -> decode.success(GlobalTableSettingsReplicationModeEnabled)
      "ENABLED_WITH_OVERRIDES" ->
        decode.success(GlobalTableSettingsReplicationModeEnabledWithOverrides)
      _ ->
        decode.failure(
          GlobalTableSettingsReplicationModeDisabled,
          "unknown enum value",
        )
    }
  })
}

pub type ReplicaStatus {
  ReplicaStatusActive
  ReplicaStatusArchived
  ReplicaStatusArchiving
  ReplicaStatusCreating
  ReplicaStatusCreationFailed
  ReplicaStatusDeleting
  ReplicaStatusInaccessibleEncryptionCredentials
  ReplicaStatusRegionDisabled
  ReplicaStatusReplicationNotAuthorized
  ReplicaStatusUpdating
}

pub fn encode_replica_status_enum(v: ReplicaStatus) -> json.Json {
  case v {
    ReplicaStatusActive -> json.string("ACTIVE")
    ReplicaStatusArchived -> json.string("ARCHIVED")
    ReplicaStatusArchiving -> json.string("ARCHIVING")
    ReplicaStatusCreating -> json.string("CREATING")
    ReplicaStatusCreationFailed -> json.string("CREATION_FAILED")
    ReplicaStatusDeleting -> json.string("DELETING")
    ReplicaStatusInaccessibleEncryptionCredentials ->
      json.string("INACCESSIBLE_ENCRYPTION_CREDENTIALS")
    ReplicaStatusRegionDisabled -> json.string("REGION_DISABLED")
    ReplicaStatusReplicationNotAuthorized ->
      json.string("REPLICATION_NOT_AUTHORIZED")
    ReplicaStatusUpdating -> json.string("UPDATING")
  }
}

pub fn decode_replica_status_enum() -> decode.Decoder(ReplicaStatus) {
  decode.then(decode.string, fn(s) {
    case s {
      "ACTIVE" -> decode.success(ReplicaStatusActive)
      "ARCHIVED" -> decode.success(ReplicaStatusArchived)
      "ARCHIVING" -> decode.success(ReplicaStatusArchiving)
      "CREATING" -> decode.success(ReplicaStatusCreating)
      "CREATION_FAILED" -> decode.success(ReplicaStatusCreationFailed)
      "DELETING" -> decode.success(ReplicaStatusDeleting)
      "INACCESSIBLE_ENCRYPTION_CREDENTIALS" ->
        decode.success(ReplicaStatusInaccessibleEncryptionCredentials)
      "REGION_DISABLED" -> decode.success(ReplicaStatusRegionDisabled)
      "REPLICATION_NOT_AUTHORIZED" ->
        decode.success(ReplicaStatusReplicationNotAuthorized)
      "UPDATING" -> decode.success(ReplicaStatusUpdating)
      _ -> decode.failure(ReplicaStatusActive, "unknown enum value")
    }
  })
}

pub type TableClassSummary {
  TableClassSummary(
    last_update_date_time: option.Option(json_timestamp.Timestamp),
    table_class: option.Option(TableClass),
  )
}

pub fn table_class_summary_default() -> TableClassSummary {
  TableClassSummary(
    last_update_date_time: option.None,
    table_class: option.None,
  )
}

pub fn encode_table_class_summary_struct(
  input: TableClassSummary,
) -> json.Json {
  let pairs = []
  let pairs = case input.last_update_date_time {
    option.Some(v) -> [
      #("LastUpdateDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_class {
    option.Some(v) -> [#("TableClass", encode_table_class_enum(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_table_class_summary_struct_top(
  input: TableClassSummary,
) -> json.Json {
  let pairs = []
  let pairs = case input.last_update_date_time {
    option.Some(v) -> [
      #("LastUpdateDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_class {
    option.Some(v) -> [#("TableClass", encode_table_class_enum(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_table_class_summary_struct() -> decode.Decoder(TableClassSummary) {
  use <- decode.recursive
  use last_update_date_time <- decode.optional_field(
    "LastUpdateDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use table_class <- decode.optional_field(
    "TableClass",
    option.None,
    decode.optional(decode_table_class_enum()),
  )
  decode.success(TableClassSummary(
    last_update_date_time: last_update_date_time,
    table_class: table_class,
  ))
}

pub type TableClass {
  TableClassStandard
  TableClassStandardInfrequentAccess
}

pub fn encode_table_class_enum(v: TableClass) -> json.Json {
  case v {
    TableClassStandard -> json.string("STANDARD")
    TableClassStandardInfrequentAccess ->
      json.string("STANDARD_INFREQUENT_ACCESS")
  }
}

pub fn decode_table_class_enum() -> decode.Decoder(TableClass) {
  decode.then(decode.string, fn(s) {
    case s {
      "STANDARD" -> decode.success(TableClassStandard)
      "STANDARD_INFREQUENT_ACCESS" ->
        decode.success(TableClassStandardInfrequentAccess)
      _ -> decode.failure(TableClassStandard, "unknown enum value")
    }
  })
}

pub type TableWarmThroughputDescription {
  TableWarmThroughputDescription(
    read_units_per_second: option.Option(Int),
    status: option.Option(TableStatus),
    write_units_per_second: option.Option(Int),
  )
}

pub fn table_warm_throughput_description_default() -> TableWarmThroughputDescription {
  TableWarmThroughputDescription(
    read_units_per_second: option.None,
    status: option.None,
    write_units_per_second: option.None,
  )
}

pub fn encode_table_warm_throughput_description_struct(
  input: TableWarmThroughputDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.read_units_per_second {
    option.Some(v) -> [#("ReadUnitsPerSecond", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.status {
    option.Some(v) -> [#("Status", encode_table_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.write_units_per_second {
    option.Some(v) -> [#("WriteUnitsPerSecond", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_table_warm_throughput_description_struct_top(
  input: TableWarmThroughputDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.read_units_per_second {
    option.Some(v) -> [#("ReadUnitsPerSecond", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.status {
    option.Some(v) -> [#("Status", encode_table_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.write_units_per_second {
    option.Some(v) -> [#("WriteUnitsPerSecond", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_table_warm_throughput_description_struct() -> decode.Decoder(
  TableWarmThroughputDescription,
) {
  use <- decode.recursive
  use read_units_per_second <- decode.optional_field(
    "ReadUnitsPerSecond",
    option.None,
    decode.optional(decode.int),
  )
  use status <- decode.optional_field(
    "Status",
    option.None,
    decode.optional(decode_table_status_enum()),
  )
  use write_units_per_second <- decode.optional_field(
    "WriteUnitsPerSecond",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(TableWarmThroughputDescription(
    read_units_per_second: read_units_per_second,
    status: status,
    write_units_per_second: write_units_per_second,
  ))
}

pub type TableStatus {
  TableStatusActive
  TableStatusArchived
  TableStatusArchiving
  TableStatusCreating
  TableStatusDeleting
  TableStatusInaccessibleEncryptionCredentials
  TableStatusReplicationNotAuthorized
  TableStatusUpdating
}

pub fn encode_table_status_enum(v: TableStatus) -> json.Json {
  case v {
    TableStatusActive -> json.string("ACTIVE")
    TableStatusArchived -> json.string("ARCHIVED")
    TableStatusArchiving -> json.string("ARCHIVING")
    TableStatusCreating -> json.string("CREATING")
    TableStatusDeleting -> json.string("DELETING")
    TableStatusInaccessibleEncryptionCredentials ->
      json.string("INACCESSIBLE_ENCRYPTION_CREDENTIALS")
    TableStatusReplicationNotAuthorized ->
      json.string("REPLICATION_NOT_AUTHORIZED")
    TableStatusUpdating -> json.string("UPDATING")
  }
}

pub fn decode_table_status_enum() -> decode.Decoder(TableStatus) {
  decode.then(decode.string, fn(s) {
    case s {
      "ACTIVE" -> decode.success(TableStatusActive)
      "ARCHIVED" -> decode.success(TableStatusArchived)
      "ARCHIVING" -> decode.success(TableStatusArchiving)
      "CREATING" -> decode.success(TableStatusCreating)
      "DELETING" -> decode.success(TableStatusDeleting)
      "INACCESSIBLE_ENCRYPTION_CREDENTIALS" ->
        decode.success(TableStatusInaccessibleEncryptionCredentials)
      "REPLICATION_NOT_AUTHORIZED" ->
        decode.success(TableStatusReplicationNotAuthorized)
      "UPDATING" -> decode.success(TableStatusUpdating)
      _ -> decode.failure(TableStatusActive, "unknown enum value")
    }
  })
}

pub type GlobalTableAlreadyExistsException {
  GlobalTableAlreadyExistsException(message: option.Option(String))
}

pub fn global_table_already_exists_exception_default() -> GlobalTableAlreadyExistsException {
  GlobalTableAlreadyExistsException(message: option.None)
}

pub fn encode_global_table_already_exists_exception_struct(
  input: GlobalTableAlreadyExistsException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_global_table_already_exists_exception_struct_top(
  input: GlobalTableAlreadyExistsException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_global_table_already_exists_exception_struct() -> decode.Decoder(
  GlobalTableAlreadyExistsException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(GlobalTableAlreadyExistsException(message: message))
}

pub type CreateTableInput {
  CreateTableInput(
    attribute_definitions: option.Option(List(AttributeDefinition)),
    billing_mode: option.Option(BillingMode),
    deletion_protection_enabled: option.Option(Bool),
    global_secondary_indexes: option.Option(List(GlobalSecondaryIndex)),
    global_table_settings_replication_mode: option.Option(
      GlobalTableSettingsReplicationMode,
    ),
    global_table_source_arn: option.Option(String),
    key_schema: option.Option(List(KeySchemaElement)),
    local_secondary_indexes: option.Option(List(LocalSecondaryIndex)),
    on_demand_throughput: option.Option(OnDemandThroughput),
    provisioned_throughput: option.Option(ProvisionedThroughput),
    resource_policy: option.Option(String),
    sse_specification: option.Option(SSESpecification),
    stream_specification: option.Option(StreamSpecification),
    table_class: option.Option(TableClass),
    table_name: String,
    tags: option.Option(List(Tag)),
    warm_throughput: option.Option(WarmThroughput),
  )
}

pub fn create_table_input_default(
  table_name table_name: String,
) -> CreateTableInput {
  CreateTableInput(
    attribute_definitions: option.None,
    billing_mode: option.None,
    deletion_protection_enabled: option.None,
    global_secondary_indexes: option.None,
    global_table_settings_replication_mode: option.None,
    global_table_source_arn: option.None,
    key_schema: option.None,
    local_secondary_indexes: option.None,
    on_demand_throughput: option.None,
    provisioned_throughput: option.None,
    resource_policy: option.None,
    sse_specification: option.None,
    stream_specification: option.None,
    table_class: option.None,
    table_name: table_name,
    tags: option.None,
    warm_throughput: option.None,
  )
}

pub fn encode_create_table_input_struct(input: CreateTableInput) -> json.Json {
  let pairs = []
  let pairs = case input.attribute_definitions {
    option.Some(v) -> [
      #(
        "AttributeDefinitions",
        fn(xs) { json.array(xs, encode_attribute_definition_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.billing_mode {
    option.Some(v) -> [#("BillingMode", encode_billing_mode_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.deletion_protection_enabled {
    option.Some(v) -> [#("DeletionProtectionEnabled", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_global_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_settings_replication_mode {
    option.Some(v) -> [
      #(
        "GlobalTableSettingsReplicationMode",
        encode_global_table_settings_replication_mode_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_source_arn {
    option.Some(v) -> [#("GlobalTableSourceArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.local_secondary_indexes {
    option.Some(v) -> [
      #(
        "LocalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_local_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.resource_policy {
    option.Some(v) -> [#("ResourcePolicy", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.sse_specification {
    option.Some(v) -> [
      #("SSESpecification", encode_sse_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_specification {
    option.Some(v) -> [
      #("StreamSpecification", encode_stream_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_class {
    option.Some(v) -> [#("TableClass", encode_table_class_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = case input.tags {
    option.Some(v) -> [
      #("Tags", fn(xs) { json.array(xs, encode_tag_struct) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_warm_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_create_table_input_struct_top(
  input: CreateTableInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.attribute_definitions {
    option.Some(v) -> [
      #(
        "AttributeDefinitions",
        fn(xs) { json.array(xs, encode_attribute_definition_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.billing_mode {
    option.Some(v) -> [#("BillingMode", encode_billing_mode_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.deletion_protection_enabled {
    option.Some(v) -> [#("DeletionProtectionEnabled", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_global_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_settings_replication_mode {
    option.Some(v) -> [
      #(
        "GlobalTableSettingsReplicationMode",
        encode_global_table_settings_replication_mode_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_source_arn {
    option.Some(v) -> [#("GlobalTableSourceArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.local_secondary_indexes {
    option.Some(v) -> [
      #(
        "LocalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_local_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.resource_policy {
    option.Some(v) -> [#("ResourcePolicy", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.sse_specification {
    option.Some(v) -> [
      #("SSESpecification", encode_sse_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_specification {
    option.Some(v) -> [
      #("StreamSpecification", encode_stream_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_class {
    option.Some(v) -> [#("TableClass", encode_table_class_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = case input.tags {
    option.Some(v) -> [
      #("Tags", fn(xs) { json.array(xs, encode_tag_struct) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_warm_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_create_table_input_struct() -> decode.Decoder(CreateTableInput) {
  use <- decode.recursive
  use attribute_definitions <- decode.optional_field(
    "AttributeDefinitions",
    option.None,
    decode.optional(decode.list(decode_attribute_definition_struct())),
  )
  use billing_mode <- decode.optional_field(
    "BillingMode",
    option.None,
    decode.optional(decode_billing_mode_enum()),
  )
  use deletion_protection_enabled <- decode.optional_field(
    "DeletionProtectionEnabled",
    option.None,
    decode.optional(decode.bool),
  )
  use global_secondary_indexes <- decode.optional_field(
    "GlobalSecondaryIndexes",
    option.None,
    decode.optional(decode.list(decode_global_secondary_index_struct())),
  )
  use global_table_settings_replication_mode <- decode.optional_field(
    "GlobalTableSettingsReplicationMode",
    option.None,
    decode.optional(decode_global_table_settings_replication_mode_enum()),
  )
  use global_table_source_arn <- decode.optional_field(
    "GlobalTableSourceArn",
    option.None,
    decode.optional(decode.string),
  )
  use key_schema <- decode.optional_field(
    "KeySchema",
    option.None,
    decode.optional(decode.list(decode_key_schema_element_struct())),
  )
  use local_secondary_indexes <- decode.optional_field(
    "LocalSecondaryIndexes",
    option.None,
    decode.optional(decode.list(decode_local_secondary_index_struct())),
  )
  use on_demand_throughput <- decode.optional_field(
    "OnDemandThroughput",
    option.None,
    decode.optional(decode_on_demand_throughput_struct()),
  )
  use provisioned_throughput <- decode.optional_field(
    "ProvisionedThroughput",
    option.None,
    decode.optional(decode_provisioned_throughput_struct()),
  )
  use resource_policy <- decode.optional_field(
    "ResourcePolicy",
    option.None,
    decode.optional(decode.string),
  )
  use sse_specification <- decode.optional_field(
    "SSESpecification",
    option.None,
    decode.optional(decode_sse_specification_struct()),
  )
  use stream_specification <- decode.optional_field(
    "StreamSpecification",
    option.None,
    decode.optional(decode_stream_specification_struct()),
  )
  use table_class <- decode.optional_field(
    "TableClass",
    option.None,
    decode.optional(decode_table_class_enum()),
  )
  use table_name <- decode.field("TableName", decode.string)
  use tags <- decode.optional_field(
    "Tags",
    option.None,
    decode.optional(decode.list(decode_tag_struct())),
  )
  use warm_throughput <- decode.optional_field(
    "WarmThroughput",
    option.None,
    decode.optional(decode_warm_throughput_struct()),
  )
  decode.success(CreateTableInput(
    attribute_definitions: attribute_definitions,
    billing_mode: billing_mode,
    deletion_protection_enabled: deletion_protection_enabled,
    global_secondary_indexes: global_secondary_indexes,
    global_table_settings_replication_mode: global_table_settings_replication_mode,
    global_table_source_arn: global_table_source_arn,
    key_schema: key_schema,
    local_secondary_indexes: local_secondary_indexes,
    on_demand_throughput: on_demand_throughput,
    provisioned_throughput: provisioned_throughput,
    resource_policy: resource_policy,
    sse_specification: sse_specification,
    stream_specification: stream_specification,
    table_class: table_class,
    table_name: table_name,
    tags: tags,
    warm_throughput: warm_throughput,
  ))
}

pub type AttributeDefinition {
  AttributeDefinition(
    attribute_name: String,
    attribute_type: ScalarAttributeType,
  )
}

pub fn attribute_definition_default(
  attribute_name attribute_name: String,
  attribute_type attribute_type: ScalarAttributeType,
) -> AttributeDefinition {
  AttributeDefinition(
    attribute_name: attribute_name,
    attribute_type: attribute_type,
  )
}

pub fn encode_attribute_definition_struct(
  input: AttributeDefinition,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.attribute_name
    [#("AttributeName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.attribute_type
    [#("AttributeType", encode_scalar_attribute_type_enum(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_attribute_definition_struct_top(
  input: AttributeDefinition,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.attribute_name
    [#("AttributeName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.attribute_type
    [#("AttributeType", encode_scalar_attribute_type_enum(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_attribute_definition_struct() -> decode.Decoder(
  AttributeDefinition,
) {
  use <- decode.recursive
  use attribute_name <- decode.field("AttributeName", decode.string)
  use attribute_type <- decode.field(
    "AttributeType",
    decode_scalar_attribute_type_enum(),
  )
  decode.success(AttributeDefinition(
    attribute_name: attribute_name,
    attribute_type: attribute_type,
  ))
}

pub type ScalarAttributeType {
  ScalarAttributeTypeB
  ScalarAttributeTypeN
  ScalarAttributeTypeS
}

pub fn encode_scalar_attribute_type_enum(v: ScalarAttributeType) -> json.Json {
  case v {
    ScalarAttributeTypeB -> json.string("B")
    ScalarAttributeTypeN -> json.string("N")
    ScalarAttributeTypeS -> json.string("S")
  }
}

pub fn decode_scalar_attribute_type_enum() -> decode.Decoder(
  ScalarAttributeType,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "B" -> decode.success(ScalarAttributeTypeB)
      "N" -> decode.success(ScalarAttributeTypeN)
      "S" -> decode.success(ScalarAttributeTypeS)
      _ -> decode.failure(ScalarAttributeTypeB, "unknown enum value")
    }
  })
}

pub type BillingMode {
  BillingModePayPerRequest
  BillingModeProvisioned
}

pub fn encode_billing_mode_enum(v: BillingMode) -> json.Json {
  case v {
    BillingModePayPerRequest -> json.string("PAY_PER_REQUEST")
    BillingModeProvisioned -> json.string("PROVISIONED")
  }
}

pub fn decode_billing_mode_enum() -> decode.Decoder(BillingMode) {
  decode.then(decode.string, fn(s) {
    case s {
      "PAY_PER_REQUEST" -> decode.success(BillingModePayPerRequest)
      "PROVISIONED" -> decode.success(BillingModeProvisioned)
      _ -> decode.failure(BillingModePayPerRequest, "unknown enum value")
    }
  })
}

pub type GlobalSecondaryIndex {
  GlobalSecondaryIndex(
    index_name: String,
    key_schema: List(KeySchemaElement),
    on_demand_throughput: option.Option(OnDemandThroughput),
    projection: Projection,
    provisioned_throughput: option.Option(ProvisionedThroughput),
    warm_throughput: option.Option(WarmThroughput),
  )
}

pub fn global_secondary_index_default(
  index_name index_name: String,
  key_schema key_schema: List(KeySchemaElement),
  projection projection: Projection,
) -> GlobalSecondaryIndex {
  GlobalSecondaryIndex(
    index_name: index_name,
    key_schema: key_schema,
    on_demand_throughput: option.None,
    projection: projection,
    provisioned_throughput: option.None,
    warm_throughput: option.None,
  )
}

pub fn encode_global_secondary_index_struct(
  input: GlobalSecondaryIndex,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.key_schema
    [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.projection
    [#("Projection", encode_projection_struct(v)), ..pairs]
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_warm_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_global_secondary_index_struct_top(
  input: GlobalSecondaryIndex,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.key_schema
    [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.projection
    [#("Projection", encode_projection_struct(v)), ..pairs]
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_warm_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_global_secondary_index_struct() -> decode.Decoder(
  GlobalSecondaryIndex,
) {
  use <- decode.recursive
  use index_name <- decode.field("IndexName", decode.string)
  use key_schema <- decode.field(
    "KeySchema",
    decode.list(decode_key_schema_element_struct()),
  )
  use on_demand_throughput <- decode.optional_field(
    "OnDemandThroughput",
    option.None,
    decode.optional(decode_on_demand_throughput_struct()),
  )
  use projection <- decode.field("Projection", decode_projection_struct())
  use provisioned_throughput <- decode.optional_field(
    "ProvisionedThroughput",
    option.None,
    decode.optional(decode_provisioned_throughput_struct()),
  )
  use warm_throughput <- decode.optional_field(
    "WarmThroughput",
    option.None,
    decode.optional(decode_warm_throughput_struct()),
  )
  decode.success(GlobalSecondaryIndex(
    index_name: index_name,
    key_schema: key_schema,
    on_demand_throughput: on_demand_throughput,
    projection: projection,
    provisioned_throughput: provisioned_throughput,
    warm_throughput: warm_throughput,
  ))
}

pub type KeySchemaElement {
  KeySchemaElement(attribute_name: String, key_type: KeyType)
}

pub fn key_schema_element_default(
  attribute_name attribute_name: String,
  key_type key_type: KeyType,
) -> KeySchemaElement {
  KeySchemaElement(attribute_name: attribute_name, key_type: key_type)
}

pub fn encode_key_schema_element_struct(input: KeySchemaElement) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.attribute_name
    [#("AttributeName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.key_type
    [#("KeyType", encode_key_type_enum(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_key_schema_element_struct_top(
  input: KeySchemaElement,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.attribute_name
    [#("AttributeName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.key_type
    [#("KeyType", encode_key_type_enum(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_key_schema_element_struct() -> decode.Decoder(KeySchemaElement) {
  use <- decode.recursive
  use attribute_name <- decode.field("AttributeName", decode.string)
  use key_type <- decode.field("KeyType", decode_key_type_enum())
  decode.success(KeySchemaElement(
    attribute_name: attribute_name,
    key_type: key_type,
  ))
}

pub type KeyType {
  KeyTypeHash
  KeyTypeRange
}

pub fn encode_key_type_enum(v: KeyType) -> json.Json {
  case v {
    KeyTypeHash -> json.string("HASH")
    KeyTypeRange -> json.string("RANGE")
  }
}

pub fn decode_key_type_enum() -> decode.Decoder(KeyType) {
  decode.then(decode.string, fn(s) {
    case s {
      "HASH" -> decode.success(KeyTypeHash)
      "RANGE" -> decode.success(KeyTypeRange)
      _ -> decode.failure(KeyTypeHash, "unknown enum value")
    }
  })
}

pub type OnDemandThroughput {
  OnDemandThroughput(
    max_read_request_units: option.Option(Int),
    max_write_request_units: option.Option(Int),
  )
}

pub fn on_demand_throughput_default() -> OnDemandThroughput {
  OnDemandThroughput(
    max_read_request_units: option.None,
    max_write_request_units: option.None,
  )
}

pub fn encode_on_demand_throughput_struct(
  input: OnDemandThroughput,
) -> json.Json {
  let pairs = []
  let pairs = case input.max_read_request_units {
    option.Some(v) -> [#("MaxReadRequestUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.max_write_request_units {
    option.Some(v) -> [#("MaxWriteRequestUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_on_demand_throughput_struct_top(
  input: OnDemandThroughput,
) -> json.Json {
  let pairs = []
  let pairs = case input.max_read_request_units {
    option.Some(v) -> [#("MaxReadRequestUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.max_write_request_units {
    option.Some(v) -> [#("MaxWriteRequestUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_on_demand_throughput_struct() -> decode.Decoder(
  OnDemandThroughput,
) {
  use <- decode.recursive
  use max_read_request_units <- decode.optional_field(
    "MaxReadRequestUnits",
    option.None,
    decode.optional(decode.int),
  )
  use max_write_request_units <- decode.optional_field(
    "MaxWriteRequestUnits",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(OnDemandThroughput(
    max_read_request_units: max_read_request_units,
    max_write_request_units: max_write_request_units,
  ))
}

pub type Projection {
  Projection(
    non_key_attributes: option.Option(List(String)),
    projection_type: option.Option(ProjectionType),
  )
}

pub fn projection_default() -> Projection {
  Projection(non_key_attributes: option.None, projection_type: option.None)
}

pub fn encode_projection_struct(input: Projection) -> json.Json {
  let pairs = []
  let pairs = case input.non_key_attributes {
    option.Some(v) -> [
      #("NonKeyAttributes", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.projection_type {
    option.Some(v) -> [
      #("ProjectionType", encode_projection_type_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_projection_struct_top(input: Projection) -> json.Json {
  let pairs = []
  let pairs = case input.non_key_attributes {
    option.Some(v) -> [
      #("NonKeyAttributes", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.projection_type {
    option.Some(v) -> [
      #("ProjectionType", encode_projection_type_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_projection_struct() -> decode.Decoder(Projection) {
  use <- decode.recursive
  use non_key_attributes <- decode.optional_field(
    "NonKeyAttributes",
    option.None,
    decode.optional(decode.list(decode.string)),
  )
  use projection_type <- decode.optional_field(
    "ProjectionType",
    option.None,
    decode.optional(decode_projection_type_enum()),
  )
  decode.success(Projection(
    non_key_attributes: non_key_attributes,
    projection_type: projection_type,
  ))
}

pub type ProjectionType {
  ProjectionTypeAll
  ProjectionTypeInclude
  ProjectionTypeKeysOnly
}

pub fn encode_projection_type_enum(v: ProjectionType) -> json.Json {
  case v {
    ProjectionTypeAll -> json.string("ALL")
    ProjectionTypeInclude -> json.string("INCLUDE")
    ProjectionTypeKeysOnly -> json.string("KEYS_ONLY")
  }
}

pub fn decode_projection_type_enum() -> decode.Decoder(ProjectionType) {
  decode.then(decode.string, fn(s) {
    case s {
      "ALL" -> decode.success(ProjectionTypeAll)
      "INCLUDE" -> decode.success(ProjectionTypeInclude)
      "KEYS_ONLY" -> decode.success(ProjectionTypeKeysOnly)
      _ -> decode.failure(ProjectionTypeAll, "unknown enum value")
    }
  })
}

pub type ProvisionedThroughput {
  ProvisionedThroughput(read_capacity_units: Int, write_capacity_units: Int)
}

pub fn provisioned_throughput_default(
  read_capacity_units read_capacity_units: Int,
  write_capacity_units write_capacity_units: Int,
) -> ProvisionedThroughput {
  ProvisionedThroughput(
    read_capacity_units: read_capacity_units,
    write_capacity_units: write_capacity_units,
  )
}

pub fn encode_provisioned_throughput_struct(
  input: ProvisionedThroughput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.read_capacity_units
    [#("ReadCapacityUnits", json.int(v)), ..pairs]
  }
  let pairs = {
    let v = input.write_capacity_units
    [#("WriteCapacityUnits", json.int(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_provisioned_throughput_struct_top(
  input: ProvisionedThroughput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.read_capacity_units
    [#("ReadCapacityUnits", json.int(v)), ..pairs]
  }
  let pairs = {
    let v = input.write_capacity_units
    [#("WriteCapacityUnits", json.int(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_provisioned_throughput_struct() -> decode.Decoder(
  ProvisionedThroughput,
) {
  use <- decode.recursive
  use read_capacity_units <- decode.field("ReadCapacityUnits", decode.int)
  use write_capacity_units <- decode.field("WriteCapacityUnits", decode.int)
  decode.success(ProvisionedThroughput(
    read_capacity_units: read_capacity_units,
    write_capacity_units: write_capacity_units,
  ))
}

pub type WarmThroughput {
  WarmThroughput(
    read_units_per_second: option.Option(Int),
    write_units_per_second: option.Option(Int),
  )
}

pub fn warm_throughput_default() -> WarmThroughput {
  WarmThroughput(
    read_units_per_second: option.None,
    write_units_per_second: option.None,
  )
}

pub fn encode_warm_throughput_struct(input: WarmThroughput) -> json.Json {
  let pairs = []
  let pairs = case input.read_units_per_second {
    option.Some(v) -> [#("ReadUnitsPerSecond", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.write_units_per_second {
    option.Some(v) -> [#("WriteUnitsPerSecond", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_warm_throughput_struct_top(input: WarmThroughput) -> json.Json {
  let pairs = []
  let pairs = case input.read_units_per_second {
    option.Some(v) -> [#("ReadUnitsPerSecond", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.write_units_per_second {
    option.Some(v) -> [#("WriteUnitsPerSecond", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_warm_throughput_struct() -> decode.Decoder(WarmThroughput) {
  use <- decode.recursive
  use read_units_per_second <- decode.optional_field(
    "ReadUnitsPerSecond",
    option.None,
    decode.optional(decode.int),
  )
  use write_units_per_second <- decode.optional_field(
    "WriteUnitsPerSecond",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(WarmThroughput(
    read_units_per_second: read_units_per_second,
    write_units_per_second: write_units_per_second,
  ))
}

pub type LocalSecondaryIndex {
  LocalSecondaryIndex(
    index_name: String,
    key_schema: List(KeySchemaElement),
    projection: Projection,
  )
}

pub fn local_secondary_index_default(
  index_name index_name: String,
  key_schema key_schema: List(KeySchemaElement),
  projection projection: Projection,
) -> LocalSecondaryIndex {
  LocalSecondaryIndex(
    index_name: index_name,
    key_schema: key_schema,
    projection: projection,
  )
}

pub fn encode_local_secondary_index_struct(
  input: LocalSecondaryIndex,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.key_schema
    [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
  }
  let pairs = {
    let v = input.projection
    [#("Projection", encode_projection_struct(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_local_secondary_index_struct_top(
  input: LocalSecondaryIndex,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.key_schema
    [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
  }
  let pairs = {
    let v = input.projection
    [#("Projection", encode_projection_struct(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_local_secondary_index_struct() -> decode.Decoder(
  LocalSecondaryIndex,
) {
  use <- decode.recursive
  use index_name <- decode.field("IndexName", decode.string)
  use key_schema <- decode.field(
    "KeySchema",
    decode.list(decode_key_schema_element_struct()),
  )
  use projection <- decode.field("Projection", decode_projection_struct())
  decode.success(LocalSecondaryIndex(
    index_name: index_name,
    key_schema: key_schema,
    projection: projection,
  ))
}

pub type SSESpecification {
  SSESpecification(
    enabled: option.Option(Bool),
    kms_master_key_id: option.Option(String),
    sse_type: option.Option(SSEType),
  )
}

pub fn sse_specification_default() -> SSESpecification {
  SSESpecification(
    enabled: option.None,
    kms_master_key_id: option.None,
    sse_type: option.None,
  )
}

pub fn encode_sse_specification_struct(input: SSESpecification) -> json.Json {
  let pairs = []
  let pairs = case input.enabled {
    option.Some(v) -> [#("Enabled", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.kms_master_key_id {
    option.Some(v) -> [#("KMSMasterKeyId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.sse_type {
    option.Some(v) -> [#("SSEType", encode_sse_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_sse_specification_struct_top(
  input: SSESpecification,
) -> json.Json {
  let pairs = []
  let pairs = case input.enabled {
    option.Some(v) -> [#("Enabled", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.kms_master_key_id {
    option.Some(v) -> [#("KMSMasterKeyId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.sse_type {
    option.Some(v) -> [#("SSEType", encode_sse_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_sse_specification_struct() -> decode.Decoder(SSESpecification) {
  use <- decode.recursive
  use enabled <- decode.optional_field(
    "Enabled",
    option.None,
    decode.optional(decode.bool),
  )
  use kms_master_key_id <- decode.optional_field(
    "KMSMasterKeyId",
    option.None,
    decode.optional(decode.string),
  )
  use sse_type <- decode.optional_field(
    "SSEType",
    option.None,
    decode.optional(decode_sse_type_enum()),
  )
  decode.success(SSESpecification(
    enabled: enabled,
    kms_master_key_id: kms_master_key_id,
    sse_type: sse_type,
  ))
}

pub type SSEType {
  SSETypeAes256
  SSETypeKms
}

pub fn encode_sse_type_enum(v: SSEType) -> json.Json {
  case v {
    SSETypeAes256 -> json.string("AES256")
    SSETypeKms -> json.string("KMS")
  }
}

pub fn decode_sse_type_enum() -> decode.Decoder(SSEType) {
  decode.then(decode.string, fn(s) {
    case s {
      "AES256" -> decode.success(SSETypeAes256)
      "KMS" -> decode.success(SSETypeKms)
      _ -> decode.failure(SSETypeAes256, "unknown enum value")
    }
  })
}

pub type StreamSpecification {
  StreamSpecification(
    stream_enabled: Bool,
    stream_view_type: option.Option(StreamViewType),
  )
}

pub fn stream_specification_default(
  stream_enabled stream_enabled: Bool,
) -> StreamSpecification {
  StreamSpecification(
    stream_enabled: stream_enabled,
    stream_view_type: option.None,
  )
}

pub fn encode_stream_specification_struct(
  input: StreamSpecification,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.stream_enabled
    [#("StreamEnabled", json.bool(v)), ..pairs]
  }
  let pairs = case input.stream_view_type {
    option.Some(v) -> [
      #("StreamViewType", encode_stream_view_type_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_stream_specification_struct_top(
  input: StreamSpecification,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.stream_enabled
    [#("StreamEnabled", json.bool(v)), ..pairs]
  }
  let pairs = case input.stream_view_type {
    option.Some(v) -> [
      #("StreamViewType", encode_stream_view_type_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_stream_specification_struct() -> decode.Decoder(
  StreamSpecification,
) {
  use <- decode.recursive
  use stream_enabled <- decode.field("StreamEnabled", decode.bool)
  use stream_view_type <- decode.optional_field(
    "StreamViewType",
    option.None,
    decode.optional(decode_stream_view_type_enum()),
  )
  decode.success(StreamSpecification(
    stream_enabled: stream_enabled,
    stream_view_type: stream_view_type,
  ))
}

pub type StreamViewType {
  StreamViewTypeKeysOnly
  StreamViewTypeNewAndOldImages
  StreamViewTypeNewImage
  StreamViewTypeOldImage
}

pub fn encode_stream_view_type_enum(v: StreamViewType) -> json.Json {
  case v {
    StreamViewTypeKeysOnly -> json.string("KEYS_ONLY")
    StreamViewTypeNewAndOldImages -> json.string("NEW_AND_OLD_IMAGES")
    StreamViewTypeNewImage -> json.string("NEW_IMAGE")
    StreamViewTypeOldImage -> json.string("OLD_IMAGE")
  }
}

pub fn decode_stream_view_type_enum() -> decode.Decoder(StreamViewType) {
  decode.then(decode.string, fn(s) {
    case s {
      "KEYS_ONLY" -> decode.success(StreamViewTypeKeysOnly)
      "NEW_AND_OLD_IMAGES" -> decode.success(StreamViewTypeNewAndOldImages)
      "NEW_IMAGE" -> decode.success(StreamViewTypeNewImage)
      "OLD_IMAGE" -> decode.success(StreamViewTypeOldImage)
      _ -> decode.failure(StreamViewTypeKeysOnly, "unknown enum value")
    }
  })
}

pub type Tag {
  Tag(key: String, value: String)
}

pub fn tag_default(key key: String, value value: String) -> Tag {
  Tag(key: key, value: value)
}

pub fn encode_tag_struct(input: Tag) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.key
    [#("Key", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.value
    [#("Value", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_tag_struct_top(input: Tag) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.key
    [#("Key", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.value
    [#("Value", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_tag_struct() -> decode.Decoder(Tag) {
  use <- decode.recursive
  use key <- decode.field("Key", decode.string)
  use value <- decode.field("Value", decode.string)
  decode.success(Tag(key: key, value: value))
}

pub type CreateTableOutput {
  CreateTableOutput(table_description: option.Option(TableDescription))
}

pub fn create_table_output_default() -> CreateTableOutput {
  CreateTableOutput(table_description: option.None)
}

pub fn encode_create_table_output_struct(
  input: CreateTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_description {
    option.Some(v) -> [
      #("TableDescription", encode_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_create_table_output_struct_top(
  input: CreateTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_description {
    option.Some(v) -> [
      #("TableDescription", encode_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_create_table_output_struct() -> decode.Decoder(CreateTableOutput) {
  use <- decode.recursive
  use table_description <- decode.optional_field(
    "TableDescription",
    option.None,
    decode.optional(decode_table_description_struct()),
  )
  decode.success(CreateTableOutput(table_description: table_description))
}

pub type TableDescription {
  TableDescription(
    archival_summary: option.Option(ArchivalSummary),
    attribute_definitions: option.Option(List(AttributeDefinition)),
    billing_mode_summary: option.Option(BillingModeSummary),
    creation_date_time: option.Option(json_timestamp.Timestamp),
    deletion_protection_enabled: option.Option(Bool),
    global_secondary_indexes: option.Option(
      List(GlobalSecondaryIndexDescription),
    ),
    global_table_settings_replication_mode: option.Option(
      GlobalTableSettingsReplicationMode,
    ),
    global_table_version: option.Option(String),
    global_table_witnesses: option.Option(List(GlobalTableWitnessDescription)),
    item_count: option.Option(Int),
    key_schema: option.Option(List(KeySchemaElement)),
    latest_stream_arn: option.Option(String),
    latest_stream_label: option.Option(String),
    local_secondary_indexes: option.Option(List(LocalSecondaryIndexDescription)),
    multi_region_consistency: option.Option(MultiRegionConsistency),
    on_demand_throughput: option.Option(OnDemandThroughput),
    provisioned_throughput: option.Option(ProvisionedThroughputDescription),
    replicas: option.Option(List(ReplicaDescription)),
    restore_summary: option.Option(RestoreSummary),
    sse_description: option.Option(SSEDescription),
    stream_specification: option.Option(StreamSpecification),
    table_arn: option.Option(String),
    table_class_summary: option.Option(TableClassSummary),
    table_id: option.Option(String),
    table_name: option.Option(String),
    table_size_bytes: option.Option(Int),
    table_status: option.Option(TableStatus),
    warm_throughput: option.Option(TableWarmThroughputDescription),
  )
}

pub fn table_description_default() -> TableDescription {
  TableDescription(
    archival_summary: option.None,
    attribute_definitions: option.None,
    billing_mode_summary: option.None,
    creation_date_time: option.None,
    deletion_protection_enabled: option.None,
    global_secondary_indexes: option.None,
    global_table_settings_replication_mode: option.None,
    global_table_version: option.None,
    global_table_witnesses: option.None,
    item_count: option.None,
    key_schema: option.None,
    latest_stream_arn: option.None,
    latest_stream_label: option.None,
    local_secondary_indexes: option.None,
    multi_region_consistency: option.None,
    on_demand_throughput: option.None,
    provisioned_throughput: option.None,
    replicas: option.None,
    restore_summary: option.None,
    sse_description: option.None,
    stream_specification: option.None,
    table_arn: option.None,
    table_class_summary: option.None,
    table_id: option.None,
    table_name: option.None,
    table_size_bytes: option.None,
    table_status: option.None,
    warm_throughput: option.None,
  )
}

pub fn encode_table_description_struct(input: TableDescription) -> json.Json {
  let pairs = []
  let pairs = case input.archival_summary {
    option.Some(v) -> [
      #("ArchivalSummary", encode_archival_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.attribute_definitions {
    option.Some(v) -> [
      #(
        "AttributeDefinitions",
        fn(xs) { json.array(xs, encode_attribute_definition_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.billing_mode_summary {
    option.Some(v) -> [
      #("BillingModeSummary", encode_billing_mode_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.creation_date_time {
    option.Some(v) -> [
      #("CreationDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.deletion_protection_enabled {
    option.Some(v) -> [#("DeletionProtectionEnabled", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) {
          json.array(xs, encode_global_secondary_index_description_struct)
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_settings_replication_mode {
    option.Some(v) -> [
      #(
        "GlobalTableSettingsReplicationMode",
        encode_global_table_settings_replication_mode_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_version {
    option.Some(v) -> [#("GlobalTableVersion", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_table_witnesses {
    option.Some(v) -> [
      #(
        "GlobalTableWitnesses",
        fn(xs) {
          json.array(xs, encode_global_table_witness_description_struct)
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_count {
    option.Some(v) -> [#("ItemCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.latest_stream_arn {
    option.Some(v) -> [#("LatestStreamArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.latest_stream_label {
    option.Some(v) -> [#("LatestStreamLabel", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.local_secondary_indexes {
    option.Some(v) -> [
      #(
        "LocalSecondaryIndexes",
        fn(xs) {
          json.array(xs, encode_local_secondary_index_description_struct)
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.multi_region_consistency {
    option.Some(v) -> [
      #("MultiRegionConsistency", encode_multi_region_consistency_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #(
        "ProvisionedThroughput",
        encode_provisioned_throughput_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replicas {
    option.Some(v) -> [
      #(
        "Replicas",
        fn(xs) { json.array(xs, encode_replica_description_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.restore_summary {
    option.Some(v) -> [
      #("RestoreSummary", encode_restore_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.sse_description {
    option.Some(v) -> [
      #("SSEDescription", encode_sse_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_specification {
    option.Some(v) -> [
      #("StreamSpecification", encode_stream_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_class_summary {
    option.Some(v) -> [
      #("TableClassSummary", encode_table_class_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_id {
    option.Some(v) -> [#("TableId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_size_bytes {
    option.Some(v) -> [#("TableSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_status {
    option.Some(v) -> [#("TableStatus", encode_table_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_table_warm_throughput_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_table_description_struct_top(
  input: TableDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.archival_summary {
    option.Some(v) -> [
      #("ArchivalSummary", encode_archival_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.attribute_definitions {
    option.Some(v) -> [
      #(
        "AttributeDefinitions",
        fn(xs) { json.array(xs, encode_attribute_definition_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.billing_mode_summary {
    option.Some(v) -> [
      #("BillingModeSummary", encode_billing_mode_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.creation_date_time {
    option.Some(v) -> [
      #("CreationDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.deletion_protection_enabled {
    option.Some(v) -> [#("DeletionProtectionEnabled", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) {
          json.array(xs, encode_global_secondary_index_description_struct)
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_settings_replication_mode {
    option.Some(v) -> [
      #(
        "GlobalTableSettingsReplicationMode",
        encode_global_table_settings_replication_mode_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_version {
    option.Some(v) -> [#("GlobalTableVersion", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_table_witnesses {
    option.Some(v) -> [
      #(
        "GlobalTableWitnesses",
        fn(xs) {
          json.array(xs, encode_global_table_witness_description_struct)
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_count {
    option.Some(v) -> [#("ItemCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.latest_stream_arn {
    option.Some(v) -> [#("LatestStreamArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.latest_stream_label {
    option.Some(v) -> [#("LatestStreamLabel", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.local_secondary_indexes {
    option.Some(v) -> [
      #(
        "LocalSecondaryIndexes",
        fn(xs) {
          json.array(xs, encode_local_secondary_index_description_struct)
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.multi_region_consistency {
    option.Some(v) -> [
      #("MultiRegionConsistency", encode_multi_region_consistency_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #(
        "ProvisionedThroughput",
        encode_provisioned_throughput_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replicas {
    option.Some(v) -> [
      #(
        "Replicas",
        fn(xs) { json.array(xs, encode_replica_description_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.restore_summary {
    option.Some(v) -> [
      #("RestoreSummary", encode_restore_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.sse_description {
    option.Some(v) -> [
      #("SSEDescription", encode_sse_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_specification {
    option.Some(v) -> [
      #("StreamSpecification", encode_stream_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_class_summary {
    option.Some(v) -> [
      #("TableClassSummary", encode_table_class_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_id {
    option.Some(v) -> [#("TableId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_size_bytes {
    option.Some(v) -> [#("TableSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_status {
    option.Some(v) -> [#("TableStatus", encode_table_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_table_warm_throughput_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_table_description_struct() -> decode.Decoder(TableDescription) {
  use <- decode.recursive
  use archival_summary <- decode.optional_field(
    "ArchivalSummary",
    option.None,
    decode.optional(decode_archival_summary_struct()),
  )
  use attribute_definitions <- decode.optional_field(
    "AttributeDefinitions",
    option.None,
    decode.optional(decode.list(decode_attribute_definition_struct())),
  )
  use billing_mode_summary <- decode.optional_field(
    "BillingModeSummary",
    option.None,
    decode.optional(decode_billing_mode_summary_struct()),
  )
  use creation_date_time <- decode.optional_field(
    "CreationDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use deletion_protection_enabled <- decode.optional_field(
    "DeletionProtectionEnabled",
    option.None,
    decode.optional(decode.bool),
  )
  use global_secondary_indexes <- decode.optional_field(
    "GlobalSecondaryIndexes",
    option.None,
    decode.optional(
      decode.list(decode_global_secondary_index_description_struct()),
    ),
  )
  use global_table_settings_replication_mode <- decode.optional_field(
    "GlobalTableSettingsReplicationMode",
    option.None,
    decode.optional(decode_global_table_settings_replication_mode_enum()),
  )
  use global_table_version <- decode.optional_field(
    "GlobalTableVersion",
    option.None,
    decode.optional(decode.string),
  )
  use global_table_witnesses <- decode.optional_field(
    "GlobalTableWitnesses",
    option.None,
    decode.optional(
      decode.list(decode_global_table_witness_description_struct()),
    ),
  )
  use item_count <- decode.optional_field(
    "ItemCount",
    option.None,
    decode.optional(decode.int),
  )
  use key_schema <- decode.optional_field(
    "KeySchema",
    option.None,
    decode.optional(decode.list(decode_key_schema_element_struct())),
  )
  use latest_stream_arn <- decode.optional_field(
    "LatestStreamArn",
    option.None,
    decode.optional(decode.string),
  )
  use latest_stream_label <- decode.optional_field(
    "LatestStreamLabel",
    option.None,
    decode.optional(decode.string),
  )
  use local_secondary_indexes <- decode.optional_field(
    "LocalSecondaryIndexes",
    option.None,
    decode.optional(
      decode.list(decode_local_secondary_index_description_struct()),
    ),
  )
  use multi_region_consistency <- decode.optional_field(
    "MultiRegionConsistency",
    option.None,
    decode.optional(decode_multi_region_consistency_enum()),
  )
  use on_demand_throughput <- decode.optional_field(
    "OnDemandThroughput",
    option.None,
    decode.optional(decode_on_demand_throughput_struct()),
  )
  use provisioned_throughput <- decode.optional_field(
    "ProvisionedThroughput",
    option.None,
    decode.optional(decode_provisioned_throughput_description_struct()),
  )
  use replicas <- decode.optional_field(
    "Replicas",
    option.None,
    decode.optional(decode.list(decode_replica_description_struct())),
  )
  use restore_summary <- decode.optional_field(
    "RestoreSummary",
    option.None,
    decode.optional(decode_restore_summary_struct()),
  )
  use sse_description <- decode.optional_field(
    "SSEDescription",
    option.None,
    decode.optional(decode_sse_description_struct()),
  )
  use stream_specification <- decode.optional_field(
    "StreamSpecification",
    option.None,
    decode.optional(decode_stream_specification_struct()),
  )
  use table_arn <- decode.optional_field(
    "TableArn",
    option.None,
    decode.optional(decode.string),
  )
  use table_class_summary <- decode.optional_field(
    "TableClassSummary",
    option.None,
    decode.optional(decode_table_class_summary_struct()),
  )
  use table_id <- decode.optional_field(
    "TableId",
    option.None,
    decode.optional(decode.string),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  use table_size_bytes <- decode.optional_field(
    "TableSizeBytes",
    option.None,
    decode.optional(decode.int),
  )
  use table_status <- decode.optional_field(
    "TableStatus",
    option.None,
    decode.optional(decode_table_status_enum()),
  )
  use warm_throughput <- decode.optional_field(
    "WarmThroughput",
    option.None,
    decode.optional(decode_table_warm_throughput_description_struct()),
  )
  decode.success(TableDescription(
    archival_summary: archival_summary,
    attribute_definitions: attribute_definitions,
    billing_mode_summary: billing_mode_summary,
    creation_date_time: creation_date_time,
    deletion_protection_enabled: deletion_protection_enabled,
    global_secondary_indexes: global_secondary_indexes,
    global_table_settings_replication_mode: global_table_settings_replication_mode,
    global_table_version: global_table_version,
    global_table_witnesses: global_table_witnesses,
    item_count: item_count,
    key_schema: key_schema,
    latest_stream_arn: latest_stream_arn,
    latest_stream_label: latest_stream_label,
    local_secondary_indexes: local_secondary_indexes,
    multi_region_consistency: multi_region_consistency,
    on_demand_throughput: on_demand_throughput,
    provisioned_throughput: provisioned_throughput,
    replicas: replicas,
    restore_summary: restore_summary,
    sse_description: sse_description,
    stream_specification: stream_specification,
    table_arn: table_arn,
    table_class_summary: table_class_summary,
    table_id: table_id,
    table_name: table_name,
    table_size_bytes: table_size_bytes,
    table_status: table_status,
    warm_throughput: warm_throughput,
  ))
}

pub type ArchivalSummary {
  ArchivalSummary(
    archival_backup_arn: option.Option(String),
    archival_date_time: option.Option(json_timestamp.Timestamp),
    archival_reason: option.Option(String),
  )
}

pub fn archival_summary_default() -> ArchivalSummary {
  ArchivalSummary(
    archival_backup_arn: option.None,
    archival_date_time: option.None,
    archival_reason: option.None,
  )
}

pub fn encode_archival_summary_struct(input: ArchivalSummary) -> json.Json {
  let pairs = []
  let pairs = case input.archival_backup_arn {
    option.Some(v) -> [#("ArchivalBackupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.archival_date_time {
    option.Some(v) -> [
      #("ArchivalDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.archival_reason {
    option.Some(v) -> [#("ArchivalReason", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_archival_summary_struct_top(input: ArchivalSummary) -> json.Json {
  let pairs = []
  let pairs = case input.archival_backup_arn {
    option.Some(v) -> [#("ArchivalBackupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.archival_date_time {
    option.Some(v) -> [
      #("ArchivalDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.archival_reason {
    option.Some(v) -> [#("ArchivalReason", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_archival_summary_struct() -> decode.Decoder(ArchivalSummary) {
  use <- decode.recursive
  use archival_backup_arn <- decode.optional_field(
    "ArchivalBackupArn",
    option.None,
    decode.optional(decode.string),
  )
  use archival_date_time <- decode.optional_field(
    "ArchivalDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use archival_reason <- decode.optional_field(
    "ArchivalReason",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ArchivalSummary(
    archival_backup_arn: archival_backup_arn,
    archival_date_time: archival_date_time,
    archival_reason: archival_reason,
  ))
}

pub type BillingModeSummary {
  BillingModeSummary(
    billing_mode: option.Option(BillingMode),
    last_update_to_pay_per_request_date_time: option.Option(
      json_timestamp.Timestamp,
    ),
  )
}

pub fn billing_mode_summary_default() -> BillingModeSummary {
  BillingModeSummary(
    billing_mode: option.None,
    last_update_to_pay_per_request_date_time: option.None,
  )
}

pub fn encode_billing_mode_summary_struct(
  input: BillingModeSummary,
) -> json.Json {
  let pairs = []
  let pairs = case input.billing_mode {
    option.Some(v) -> [#("BillingMode", encode_billing_mode_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.last_update_to_pay_per_request_date_time {
    option.Some(v) -> [
      #(
        "LastUpdateToPayPerRequestDateTime",
        json_timestamp.encode_epoch_seconds(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_billing_mode_summary_struct_top(
  input: BillingModeSummary,
) -> json.Json {
  let pairs = []
  let pairs = case input.billing_mode {
    option.Some(v) -> [#("BillingMode", encode_billing_mode_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.last_update_to_pay_per_request_date_time {
    option.Some(v) -> [
      #(
        "LastUpdateToPayPerRequestDateTime",
        json_timestamp.encode_epoch_seconds(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_billing_mode_summary_struct() -> decode.Decoder(
  BillingModeSummary,
) {
  use <- decode.recursive
  use billing_mode <- decode.optional_field(
    "BillingMode",
    option.None,
    decode.optional(decode_billing_mode_enum()),
  )
  use last_update_to_pay_per_request_date_time <- decode.optional_field(
    "LastUpdateToPayPerRequestDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  decode.success(BillingModeSummary(
    billing_mode: billing_mode,
    last_update_to_pay_per_request_date_time: last_update_to_pay_per_request_date_time,
  ))
}

pub type GlobalSecondaryIndexDescription {
  GlobalSecondaryIndexDescription(
    backfilling: option.Option(Bool),
    index_arn: option.Option(String),
    index_name: option.Option(String),
    index_size_bytes: option.Option(Int),
    index_status: option.Option(IndexStatus),
    item_count: option.Option(Int),
    key_schema: option.Option(List(KeySchemaElement)),
    on_demand_throughput: option.Option(OnDemandThroughput),
    projection: option.Option(Projection),
    provisioned_throughput: option.Option(ProvisionedThroughputDescription),
    warm_throughput: option.Option(
      GlobalSecondaryIndexWarmThroughputDescription,
    ),
  )
}

pub fn global_secondary_index_description_default() -> GlobalSecondaryIndexDescription {
  GlobalSecondaryIndexDescription(
    backfilling: option.None,
    index_arn: option.None,
    index_name: option.None,
    index_size_bytes: option.None,
    index_status: option.None,
    item_count: option.None,
    key_schema: option.None,
    on_demand_throughput: option.None,
    projection: option.None,
    provisioned_throughput: option.None,
    warm_throughput: option.None,
  )
}

pub fn encode_global_secondary_index_description_struct(
  input: GlobalSecondaryIndexDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.backfilling {
    option.Some(v) -> [#("Backfilling", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_arn {
    option.Some(v) -> [#("IndexArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_size_bytes {
    option.Some(v) -> [#("IndexSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_status {
    option.Some(v) -> [#("IndexStatus", encode_index_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.item_count {
    option.Some(v) -> [#("ItemCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.projection {
    option.Some(v) -> [#("Projection", encode_projection_struct(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #(
        "ProvisionedThroughput",
        encode_provisioned_throughput_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #(
        "WarmThroughput",
        encode_global_secondary_index_warm_throughput_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_global_secondary_index_description_struct_top(
  input: GlobalSecondaryIndexDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.backfilling {
    option.Some(v) -> [#("Backfilling", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_arn {
    option.Some(v) -> [#("IndexArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_size_bytes {
    option.Some(v) -> [#("IndexSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_status {
    option.Some(v) -> [#("IndexStatus", encode_index_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.item_count {
    option.Some(v) -> [#("ItemCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.projection {
    option.Some(v) -> [#("Projection", encode_projection_struct(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #(
        "ProvisionedThroughput",
        encode_provisioned_throughput_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #(
        "WarmThroughput",
        encode_global_secondary_index_warm_throughput_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_global_secondary_index_description_struct() -> decode.Decoder(
  GlobalSecondaryIndexDescription,
) {
  use <- decode.recursive
  use backfilling <- decode.optional_field(
    "Backfilling",
    option.None,
    decode.optional(decode.bool),
  )
  use index_arn <- decode.optional_field(
    "IndexArn",
    option.None,
    decode.optional(decode.string),
  )
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use index_size_bytes <- decode.optional_field(
    "IndexSizeBytes",
    option.None,
    decode.optional(decode.int),
  )
  use index_status <- decode.optional_field(
    "IndexStatus",
    option.None,
    decode.optional(decode_index_status_enum()),
  )
  use item_count <- decode.optional_field(
    "ItemCount",
    option.None,
    decode.optional(decode.int),
  )
  use key_schema <- decode.optional_field(
    "KeySchema",
    option.None,
    decode.optional(decode.list(decode_key_schema_element_struct())),
  )
  use on_demand_throughput <- decode.optional_field(
    "OnDemandThroughput",
    option.None,
    decode.optional(decode_on_demand_throughput_struct()),
  )
  use projection <- decode.optional_field(
    "Projection",
    option.None,
    decode.optional(decode_projection_struct()),
  )
  use provisioned_throughput <- decode.optional_field(
    "ProvisionedThroughput",
    option.None,
    decode.optional(decode_provisioned_throughput_description_struct()),
  )
  use warm_throughput <- decode.optional_field(
    "WarmThroughput",
    option.None,
    decode.optional(
      decode_global_secondary_index_warm_throughput_description_struct(),
    ),
  )
  decode.success(GlobalSecondaryIndexDescription(
    backfilling: backfilling,
    index_arn: index_arn,
    index_name: index_name,
    index_size_bytes: index_size_bytes,
    index_status: index_status,
    item_count: item_count,
    key_schema: key_schema,
    on_demand_throughput: on_demand_throughput,
    projection: projection,
    provisioned_throughput: provisioned_throughput,
    warm_throughput: warm_throughput,
  ))
}

pub type ProvisionedThroughputDescription {
  ProvisionedThroughputDescription(
    last_decrease_date_time: option.Option(json_timestamp.Timestamp),
    last_increase_date_time: option.Option(json_timestamp.Timestamp),
    number_of_decreases_today: option.Option(Int),
    read_capacity_units: option.Option(Int),
    write_capacity_units: option.Option(Int),
  )
}

pub fn provisioned_throughput_description_default() -> ProvisionedThroughputDescription {
  ProvisionedThroughputDescription(
    last_decrease_date_time: option.None,
    last_increase_date_time: option.None,
    number_of_decreases_today: option.None,
    read_capacity_units: option.None,
    write_capacity_units: option.None,
  )
}

pub fn encode_provisioned_throughput_description_struct(
  input: ProvisionedThroughputDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.last_decrease_date_time {
    option.Some(v) -> [
      #("LastDecreaseDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.last_increase_date_time {
    option.Some(v) -> [
      #("LastIncreaseDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.number_of_decreases_today {
    option.Some(v) -> [#("NumberOfDecreasesToday", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.read_capacity_units {
    option.Some(v) -> [#("ReadCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.write_capacity_units {
    option.Some(v) -> [#("WriteCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_provisioned_throughput_description_struct_top(
  input: ProvisionedThroughputDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.last_decrease_date_time {
    option.Some(v) -> [
      #("LastDecreaseDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.last_increase_date_time {
    option.Some(v) -> [
      #("LastIncreaseDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.number_of_decreases_today {
    option.Some(v) -> [#("NumberOfDecreasesToday", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.read_capacity_units {
    option.Some(v) -> [#("ReadCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.write_capacity_units {
    option.Some(v) -> [#("WriteCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_provisioned_throughput_description_struct() -> decode.Decoder(
  ProvisionedThroughputDescription,
) {
  use <- decode.recursive
  use last_decrease_date_time <- decode.optional_field(
    "LastDecreaseDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use last_increase_date_time <- decode.optional_field(
    "LastIncreaseDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use number_of_decreases_today <- decode.optional_field(
    "NumberOfDecreasesToday",
    option.None,
    decode.optional(decode.int),
  )
  use read_capacity_units <- decode.optional_field(
    "ReadCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  use write_capacity_units <- decode.optional_field(
    "WriteCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(ProvisionedThroughputDescription(
    last_decrease_date_time: last_decrease_date_time,
    last_increase_date_time: last_increase_date_time,
    number_of_decreases_today: number_of_decreases_today,
    read_capacity_units: read_capacity_units,
    write_capacity_units: write_capacity_units,
  ))
}

pub type GlobalTableWitnessDescription {
  GlobalTableWitnessDescription(
    region_name: option.Option(String),
    witness_status: option.Option(WitnessStatus),
  )
}

pub fn global_table_witness_description_default() -> GlobalTableWitnessDescription {
  GlobalTableWitnessDescription(
    region_name: option.None,
    witness_status: option.None,
  )
}

pub fn encode_global_table_witness_description_struct(
  input: GlobalTableWitnessDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.region_name {
    option.Some(v) -> [#("RegionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.witness_status {
    option.Some(v) -> [
      #("WitnessStatus", encode_witness_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_global_table_witness_description_struct_top(
  input: GlobalTableWitnessDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.region_name {
    option.Some(v) -> [#("RegionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.witness_status {
    option.Some(v) -> [
      #("WitnessStatus", encode_witness_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_global_table_witness_description_struct() -> decode.Decoder(
  GlobalTableWitnessDescription,
) {
  use <- decode.recursive
  use region_name <- decode.optional_field(
    "RegionName",
    option.None,
    decode.optional(decode.string),
  )
  use witness_status <- decode.optional_field(
    "WitnessStatus",
    option.None,
    decode.optional(decode_witness_status_enum()),
  )
  decode.success(GlobalTableWitnessDescription(
    region_name: region_name,
    witness_status: witness_status,
  ))
}

pub type WitnessStatus {
  WitnessStatusActive
  WitnessStatusCreating
  WitnessStatusDeleting
}

pub fn encode_witness_status_enum(v: WitnessStatus) -> json.Json {
  case v {
    WitnessStatusActive -> json.string("ACTIVE")
    WitnessStatusCreating -> json.string("CREATING")
    WitnessStatusDeleting -> json.string("DELETING")
  }
}

pub fn decode_witness_status_enum() -> decode.Decoder(WitnessStatus) {
  decode.then(decode.string, fn(s) {
    case s {
      "ACTIVE" -> decode.success(WitnessStatusActive)
      "CREATING" -> decode.success(WitnessStatusCreating)
      "DELETING" -> decode.success(WitnessStatusDeleting)
      _ -> decode.failure(WitnessStatusActive, "unknown enum value")
    }
  })
}

pub type LocalSecondaryIndexDescription {
  LocalSecondaryIndexDescription(
    index_arn: option.Option(String),
    index_name: option.Option(String),
    index_size_bytes: option.Option(Int),
    item_count: option.Option(Int),
    key_schema: option.Option(List(KeySchemaElement)),
    projection: option.Option(Projection),
  )
}

pub fn local_secondary_index_description_default() -> LocalSecondaryIndexDescription {
  LocalSecondaryIndexDescription(
    index_arn: option.None,
    index_name: option.None,
    index_size_bytes: option.None,
    item_count: option.None,
    key_schema: option.None,
    projection: option.None,
  )
}

pub fn encode_local_secondary_index_description_struct(
  input: LocalSecondaryIndexDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_arn {
    option.Some(v) -> [#("IndexArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_size_bytes {
    option.Some(v) -> [#("IndexSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.item_count {
    option.Some(v) -> [#("ItemCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.projection {
    option.Some(v) -> [#("Projection", encode_projection_struct(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_local_secondary_index_description_struct_top(
  input: LocalSecondaryIndexDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_arn {
    option.Some(v) -> [#("IndexArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_size_bytes {
    option.Some(v) -> [#("IndexSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.item_count {
    option.Some(v) -> [#("ItemCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.projection {
    option.Some(v) -> [#("Projection", encode_projection_struct(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_local_secondary_index_description_struct() -> decode.Decoder(
  LocalSecondaryIndexDescription,
) {
  use <- decode.recursive
  use index_arn <- decode.optional_field(
    "IndexArn",
    option.None,
    decode.optional(decode.string),
  )
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use index_size_bytes <- decode.optional_field(
    "IndexSizeBytes",
    option.None,
    decode.optional(decode.int),
  )
  use item_count <- decode.optional_field(
    "ItemCount",
    option.None,
    decode.optional(decode.int),
  )
  use key_schema <- decode.optional_field(
    "KeySchema",
    option.None,
    decode.optional(decode.list(decode_key_schema_element_struct())),
  )
  use projection <- decode.optional_field(
    "Projection",
    option.None,
    decode.optional(decode_projection_struct()),
  )
  decode.success(LocalSecondaryIndexDescription(
    index_arn: index_arn,
    index_name: index_name,
    index_size_bytes: index_size_bytes,
    item_count: item_count,
    key_schema: key_schema,
    projection: projection,
  ))
}

pub type MultiRegionConsistency {
  MultiRegionConsistencyEventual
  MultiRegionConsistencyStrong
}

pub fn encode_multi_region_consistency_enum(
  v: MultiRegionConsistency,
) -> json.Json {
  case v {
    MultiRegionConsistencyEventual -> json.string("EVENTUAL")
    MultiRegionConsistencyStrong -> json.string("STRONG")
  }
}

pub fn decode_multi_region_consistency_enum() -> decode.Decoder(
  MultiRegionConsistency,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "EVENTUAL" -> decode.success(MultiRegionConsistencyEventual)
      "STRONG" -> decode.success(MultiRegionConsistencyStrong)
      _ -> decode.failure(MultiRegionConsistencyEventual, "unknown enum value")
    }
  })
}

pub type RestoreSummary {
  RestoreSummary(
    restore_date_time: option.Option(json_timestamp.Timestamp),
    restore_in_progress: option.Option(Bool),
    source_backup_arn: option.Option(String),
    source_table_arn: option.Option(String),
  )
}

pub fn restore_summary_default() -> RestoreSummary {
  RestoreSummary(
    restore_date_time: option.None,
    restore_in_progress: option.None,
    source_backup_arn: option.None,
    source_table_arn: option.None,
  )
}

pub fn encode_restore_summary_struct(input: RestoreSummary) -> json.Json {
  let pairs = []
  let pairs = case input.restore_date_time {
    option.Some(v) -> [
      #("RestoreDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.restore_in_progress {
    option.Some(v) -> [#("RestoreInProgress", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.source_backup_arn {
    option.Some(v) -> [#("SourceBackupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.source_table_arn {
    option.Some(v) -> [#("SourceTableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_restore_summary_struct_top(input: RestoreSummary) -> json.Json {
  let pairs = []
  let pairs = case input.restore_date_time {
    option.Some(v) -> [
      #("RestoreDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.restore_in_progress {
    option.Some(v) -> [#("RestoreInProgress", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.source_backup_arn {
    option.Some(v) -> [#("SourceBackupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.source_table_arn {
    option.Some(v) -> [#("SourceTableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_restore_summary_struct() -> decode.Decoder(RestoreSummary) {
  use <- decode.recursive
  use restore_date_time <- decode.optional_field(
    "RestoreDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use restore_in_progress <- decode.optional_field(
    "RestoreInProgress",
    option.None,
    decode.optional(decode.bool),
  )
  use source_backup_arn <- decode.optional_field(
    "SourceBackupArn",
    option.None,
    decode.optional(decode.string),
  )
  use source_table_arn <- decode.optional_field(
    "SourceTableArn",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(RestoreSummary(
    restore_date_time: restore_date_time,
    restore_in_progress: restore_in_progress,
    source_backup_arn: source_backup_arn,
    source_table_arn: source_table_arn,
  ))
}

pub type SSEDescription {
  SSEDescription(
    inaccessible_encryption_date_time: option.Option(json_timestamp.Timestamp),
    kms_master_key_arn: option.Option(String),
    sse_type: option.Option(SSEType),
    status: option.Option(SSEStatus),
  )
}

pub fn sse_description_default() -> SSEDescription {
  SSEDescription(
    inaccessible_encryption_date_time: option.None,
    kms_master_key_arn: option.None,
    sse_type: option.None,
    status: option.None,
  )
}

pub fn encode_sse_description_struct(input: SSEDescription) -> json.Json {
  let pairs = []
  let pairs = case input.inaccessible_encryption_date_time {
    option.Some(v) -> [
      #(
        "InaccessibleEncryptionDateTime",
        json_timestamp.encode_epoch_seconds(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.kms_master_key_arn {
    option.Some(v) -> [#("KMSMasterKeyArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.sse_type {
    option.Some(v) -> [#("SSEType", encode_sse_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.status {
    option.Some(v) -> [#("Status", encode_sse_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_sse_description_struct_top(input: SSEDescription) -> json.Json {
  let pairs = []
  let pairs = case input.inaccessible_encryption_date_time {
    option.Some(v) -> [
      #(
        "InaccessibleEncryptionDateTime",
        json_timestamp.encode_epoch_seconds(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.kms_master_key_arn {
    option.Some(v) -> [#("KMSMasterKeyArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.sse_type {
    option.Some(v) -> [#("SSEType", encode_sse_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.status {
    option.Some(v) -> [#("Status", encode_sse_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_sse_description_struct() -> decode.Decoder(SSEDescription) {
  use <- decode.recursive
  use inaccessible_encryption_date_time <- decode.optional_field(
    "InaccessibleEncryptionDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use kms_master_key_arn <- decode.optional_field(
    "KMSMasterKeyArn",
    option.None,
    decode.optional(decode.string),
  )
  use sse_type <- decode.optional_field(
    "SSEType",
    option.None,
    decode.optional(decode_sse_type_enum()),
  )
  use status <- decode.optional_field(
    "Status",
    option.None,
    decode.optional(decode_sse_status_enum()),
  )
  decode.success(SSEDescription(
    inaccessible_encryption_date_time: inaccessible_encryption_date_time,
    kms_master_key_arn: kms_master_key_arn,
    sse_type: sse_type,
    status: status,
  ))
}

pub type SSEStatus {
  SSEStatusDisabled
  SSEStatusDisabling
  SSEStatusEnabled
  SSEStatusEnabling
  SSEStatusUpdating
}

pub fn encode_sse_status_enum(v: SSEStatus) -> json.Json {
  case v {
    SSEStatusDisabled -> json.string("DISABLED")
    SSEStatusDisabling -> json.string("DISABLING")
    SSEStatusEnabled -> json.string("ENABLED")
    SSEStatusEnabling -> json.string("ENABLING")
    SSEStatusUpdating -> json.string("UPDATING")
  }
}

pub fn decode_sse_status_enum() -> decode.Decoder(SSEStatus) {
  decode.then(decode.string, fn(s) {
    case s {
      "DISABLED" -> decode.success(SSEStatusDisabled)
      "DISABLING" -> decode.success(SSEStatusDisabling)
      "ENABLED" -> decode.success(SSEStatusEnabled)
      "ENABLING" -> decode.success(SSEStatusEnabling)
      "UPDATING" -> decode.success(SSEStatusUpdating)
      _ -> decode.failure(SSEStatusDisabled, "unknown enum value")
    }
  })
}

pub type ResourceInUseException {
  ResourceInUseException(message: option.Option(String))
}

pub fn resource_in_use_exception_default() -> ResourceInUseException {
  ResourceInUseException(message: option.None)
}

pub fn encode_resource_in_use_exception_struct(
  input: ResourceInUseException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_resource_in_use_exception_struct_top(
  input: ResourceInUseException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_resource_in_use_exception_struct() -> decode.Decoder(
  ResourceInUseException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ResourceInUseException(message: message))
}

pub type DeleteBackupInput {
  DeleteBackupInput(backup_arn: String)
}

pub fn delete_backup_input_default(
  backup_arn backup_arn: String,
) -> DeleteBackupInput {
  DeleteBackupInput(backup_arn: backup_arn)
}

pub fn encode_delete_backup_input_struct(
  input: DeleteBackupInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.backup_arn
    [#("BackupArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_delete_backup_input_struct_top(
  input: DeleteBackupInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.backup_arn
    [#("BackupArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_delete_backup_input_struct() -> decode.Decoder(DeleteBackupInput) {
  use <- decode.recursive
  use backup_arn <- decode.field("BackupArn", decode.string)
  decode.success(DeleteBackupInput(backup_arn: backup_arn))
}

pub type DeleteBackupOutput {
  DeleteBackupOutput(backup_description: option.Option(BackupDescription))
}

pub fn delete_backup_output_default() -> DeleteBackupOutput {
  DeleteBackupOutput(backup_description: option.None)
}

pub fn encode_delete_backup_output_struct(
  input: DeleteBackupOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.backup_description {
    option.Some(v) -> [
      #("BackupDescription", encode_backup_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_delete_backup_output_struct_top(
  input: DeleteBackupOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.backup_description {
    option.Some(v) -> [
      #("BackupDescription", encode_backup_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_delete_backup_output_struct() -> decode.Decoder(
  DeleteBackupOutput,
) {
  use <- decode.recursive
  use backup_description <- decode.optional_field(
    "BackupDescription",
    option.None,
    decode.optional(decode_backup_description_struct()),
  )
  decode.success(DeleteBackupOutput(backup_description: backup_description))
}

pub type BackupDescription {
  BackupDescription(
    backup_details: option.Option(BackupDetails),
    source_table_details: option.Option(SourceTableDetails),
    source_table_feature_details: option.Option(SourceTableFeatureDetails),
  )
}

pub fn backup_description_default() -> BackupDescription {
  BackupDescription(
    backup_details: option.None,
    source_table_details: option.None,
    source_table_feature_details: option.None,
  )
}

pub fn encode_backup_description_struct(input: BackupDescription) -> json.Json {
  let pairs = []
  let pairs = case input.backup_details {
    option.Some(v) -> [
      #("BackupDetails", encode_backup_details_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.source_table_details {
    option.Some(v) -> [
      #("SourceTableDetails", encode_source_table_details_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.source_table_feature_details {
    option.Some(v) -> [
      #(
        "SourceTableFeatureDetails",
        encode_source_table_feature_details_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_backup_description_struct_top(
  input: BackupDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.backup_details {
    option.Some(v) -> [
      #("BackupDetails", encode_backup_details_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.source_table_details {
    option.Some(v) -> [
      #("SourceTableDetails", encode_source_table_details_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.source_table_feature_details {
    option.Some(v) -> [
      #(
        "SourceTableFeatureDetails",
        encode_source_table_feature_details_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_backup_description_struct() -> decode.Decoder(BackupDescription) {
  use <- decode.recursive
  use backup_details <- decode.optional_field(
    "BackupDetails",
    option.None,
    decode.optional(decode_backup_details_struct()),
  )
  use source_table_details <- decode.optional_field(
    "SourceTableDetails",
    option.None,
    decode.optional(decode_source_table_details_struct()),
  )
  use source_table_feature_details <- decode.optional_field(
    "SourceTableFeatureDetails",
    option.None,
    decode.optional(decode_source_table_feature_details_struct()),
  )
  decode.success(BackupDescription(
    backup_details: backup_details,
    source_table_details: source_table_details,
    source_table_feature_details: source_table_feature_details,
  ))
}

pub type SourceTableDetails {
  SourceTableDetails(
    billing_mode: option.Option(BillingMode),
    item_count: option.Option(Int),
    key_schema: option.Option(List(KeySchemaElement)),
    on_demand_throughput: option.Option(OnDemandThroughput),
    provisioned_throughput: option.Option(ProvisionedThroughput),
    table_arn: option.Option(String),
    table_creation_date_time: option.Option(json_timestamp.Timestamp),
    table_id: option.Option(String),
    table_name: option.Option(String),
    table_size_bytes: option.Option(Int),
  )
}

pub fn source_table_details_default() -> SourceTableDetails {
  SourceTableDetails(
    billing_mode: option.None,
    item_count: option.None,
    key_schema: option.None,
    on_demand_throughput: option.None,
    provisioned_throughput: option.None,
    table_arn: option.None,
    table_creation_date_time: option.None,
    table_id: option.None,
    table_name: option.None,
    table_size_bytes: option.None,
  )
}

pub fn encode_source_table_details_struct(
  input: SourceTableDetails,
) -> json.Json {
  let pairs = []
  let pairs = case input.billing_mode {
    option.Some(v) -> [#("BillingMode", encode_billing_mode_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.item_count {
    option.Some(v) -> [#("ItemCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_creation_date_time {
    option.Some(v) -> [
      #("TableCreationDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_id {
    option.Some(v) -> [#("TableId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_size_bytes {
    option.Some(v) -> [#("TableSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_source_table_details_struct_top(
  input: SourceTableDetails,
) -> json.Json {
  let pairs = []
  let pairs = case input.billing_mode {
    option.Some(v) -> [#("BillingMode", encode_billing_mode_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.item_count {
    option.Some(v) -> [#("ItemCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_creation_date_time {
    option.Some(v) -> [
      #("TableCreationDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_id {
    option.Some(v) -> [#("TableId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_size_bytes {
    option.Some(v) -> [#("TableSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_source_table_details_struct() -> decode.Decoder(
  SourceTableDetails,
) {
  use <- decode.recursive
  use billing_mode <- decode.optional_field(
    "BillingMode",
    option.None,
    decode.optional(decode_billing_mode_enum()),
  )
  use item_count <- decode.optional_field(
    "ItemCount",
    option.None,
    decode.optional(decode.int),
  )
  use key_schema <- decode.optional_field(
    "KeySchema",
    option.None,
    decode.optional(decode.list(decode_key_schema_element_struct())),
  )
  use on_demand_throughput <- decode.optional_field(
    "OnDemandThroughput",
    option.None,
    decode.optional(decode_on_demand_throughput_struct()),
  )
  use provisioned_throughput <- decode.optional_field(
    "ProvisionedThroughput",
    option.None,
    decode.optional(decode_provisioned_throughput_struct()),
  )
  use table_arn <- decode.optional_field(
    "TableArn",
    option.None,
    decode.optional(decode.string),
  )
  use table_creation_date_time <- decode.optional_field(
    "TableCreationDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use table_id <- decode.optional_field(
    "TableId",
    option.None,
    decode.optional(decode.string),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  use table_size_bytes <- decode.optional_field(
    "TableSizeBytes",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(SourceTableDetails(
    billing_mode: billing_mode,
    item_count: item_count,
    key_schema: key_schema,
    on_demand_throughput: on_demand_throughput,
    provisioned_throughput: provisioned_throughput,
    table_arn: table_arn,
    table_creation_date_time: table_creation_date_time,
    table_id: table_id,
    table_name: table_name,
    table_size_bytes: table_size_bytes,
  ))
}

pub type SourceTableFeatureDetails {
  SourceTableFeatureDetails(
    global_secondary_indexes: option.Option(List(GlobalSecondaryIndexInfo)),
    local_secondary_indexes: option.Option(List(LocalSecondaryIndexInfo)),
    sse_description: option.Option(SSEDescription),
    stream_description: option.Option(StreamSpecification),
    time_to_live_description: option.Option(TimeToLiveDescription),
  )
}

pub fn source_table_feature_details_default() -> SourceTableFeatureDetails {
  SourceTableFeatureDetails(
    global_secondary_indexes: option.None,
    local_secondary_indexes: option.None,
    sse_description: option.None,
    stream_description: option.None,
    time_to_live_description: option.None,
  )
}

pub fn encode_source_table_feature_details_struct(
  input: SourceTableFeatureDetails,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_global_secondary_index_info_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.local_secondary_indexes {
    option.Some(v) -> [
      #(
        "LocalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_local_secondary_index_info_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.sse_description {
    option.Some(v) -> [
      #("SSEDescription", encode_sse_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_description {
    option.Some(v) -> [
      #("StreamDescription", encode_stream_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.time_to_live_description {
    option.Some(v) -> [
      #("TimeToLiveDescription", encode_time_to_live_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_source_table_feature_details_struct_top(
  input: SourceTableFeatureDetails,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_global_secondary_index_info_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.local_secondary_indexes {
    option.Some(v) -> [
      #(
        "LocalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_local_secondary_index_info_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.sse_description {
    option.Some(v) -> [
      #("SSEDescription", encode_sse_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_description {
    option.Some(v) -> [
      #("StreamDescription", encode_stream_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.time_to_live_description {
    option.Some(v) -> [
      #("TimeToLiveDescription", encode_time_to_live_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_source_table_feature_details_struct() -> decode.Decoder(
  SourceTableFeatureDetails,
) {
  use <- decode.recursive
  use global_secondary_indexes <- decode.optional_field(
    "GlobalSecondaryIndexes",
    option.None,
    decode.optional(decode.list(decode_global_secondary_index_info_struct())),
  )
  use local_secondary_indexes <- decode.optional_field(
    "LocalSecondaryIndexes",
    option.None,
    decode.optional(decode.list(decode_local_secondary_index_info_struct())),
  )
  use sse_description <- decode.optional_field(
    "SSEDescription",
    option.None,
    decode.optional(decode_sse_description_struct()),
  )
  use stream_description <- decode.optional_field(
    "StreamDescription",
    option.None,
    decode.optional(decode_stream_specification_struct()),
  )
  use time_to_live_description <- decode.optional_field(
    "TimeToLiveDescription",
    option.None,
    decode.optional(decode_time_to_live_description_struct()),
  )
  decode.success(SourceTableFeatureDetails(
    global_secondary_indexes: global_secondary_indexes,
    local_secondary_indexes: local_secondary_indexes,
    sse_description: sse_description,
    stream_description: stream_description,
    time_to_live_description: time_to_live_description,
  ))
}

pub type GlobalSecondaryIndexInfo {
  GlobalSecondaryIndexInfo(
    index_name: option.Option(String),
    key_schema: option.Option(List(KeySchemaElement)),
    on_demand_throughput: option.Option(OnDemandThroughput),
    projection: option.Option(Projection),
    provisioned_throughput: option.Option(ProvisionedThroughput),
  )
}

pub fn global_secondary_index_info_default() -> GlobalSecondaryIndexInfo {
  GlobalSecondaryIndexInfo(
    index_name: option.None,
    key_schema: option.None,
    on_demand_throughput: option.None,
    projection: option.None,
    provisioned_throughput: option.None,
  )
}

pub fn encode_global_secondary_index_info_struct(
  input: GlobalSecondaryIndexInfo,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.projection {
    option.Some(v) -> [#("Projection", encode_projection_struct(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_global_secondary_index_info_struct_top(
  input: GlobalSecondaryIndexInfo,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.projection {
    option.Some(v) -> [#("Projection", encode_projection_struct(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_global_secondary_index_info_struct() -> decode.Decoder(
  GlobalSecondaryIndexInfo,
) {
  use <- decode.recursive
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use key_schema <- decode.optional_field(
    "KeySchema",
    option.None,
    decode.optional(decode.list(decode_key_schema_element_struct())),
  )
  use on_demand_throughput <- decode.optional_field(
    "OnDemandThroughput",
    option.None,
    decode.optional(decode_on_demand_throughput_struct()),
  )
  use projection <- decode.optional_field(
    "Projection",
    option.None,
    decode.optional(decode_projection_struct()),
  )
  use provisioned_throughput <- decode.optional_field(
    "ProvisionedThroughput",
    option.None,
    decode.optional(decode_provisioned_throughput_struct()),
  )
  decode.success(GlobalSecondaryIndexInfo(
    index_name: index_name,
    key_schema: key_schema,
    on_demand_throughput: on_demand_throughput,
    projection: projection,
    provisioned_throughput: provisioned_throughput,
  ))
}

pub type LocalSecondaryIndexInfo {
  LocalSecondaryIndexInfo(
    index_name: option.Option(String),
    key_schema: option.Option(List(KeySchemaElement)),
    projection: option.Option(Projection),
  )
}

pub fn local_secondary_index_info_default() -> LocalSecondaryIndexInfo {
  LocalSecondaryIndexInfo(
    index_name: option.None,
    key_schema: option.None,
    projection: option.None,
  )
}

pub fn encode_local_secondary_index_info_struct(
  input: LocalSecondaryIndexInfo,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.projection {
    option.Some(v) -> [#("Projection", encode_projection_struct(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_local_secondary_index_info_struct_top(
  input: LocalSecondaryIndexInfo,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_schema {
    option.Some(v) -> [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.projection {
    option.Some(v) -> [#("Projection", encode_projection_struct(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_local_secondary_index_info_struct() -> decode.Decoder(
  LocalSecondaryIndexInfo,
) {
  use <- decode.recursive
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use key_schema <- decode.optional_field(
    "KeySchema",
    option.None,
    decode.optional(decode.list(decode_key_schema_element_struct())),
  )
  use projection <- decode.optional_field(
    "Projection",
    option.None,
    decode.optional(decode_projection_struct()),
  )
  decode.success(LocalSecondaryIndexInfo(
    index_name: index_name,
    key_schema: key_schema,
    projection: projection,
  ))
}

pub type TimeToLiveDescription {
  TimeToLiveDescription(
    attribute_name: option.Option(String),
    time_to_live_status: option.Option(TimeToLiveStatus),
  )
}

pub fn time_to_live_description_default() -> TimeToLiveDescription {
  TimeToLiveDescription(
    attribute_name: option.None,
    time_to_live_status: option.None,
  )
}

pub fn encode_time_to_live_description_struct(
  input: TimeToLiveDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.attribute_name {
    option.Some(v) -> [#("AttributeName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.time_to_live_status {
    option.Some(v) -> [
      #("TimeToLiveStatus", encode_time_to_live_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_time_to_live_description_struct_top(
  input: TimeToLiveDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.attribute_name {
    option.Some(v) -> [#("AttributeName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.time_to_live_status {
    option.Some(v) -> [
      #("TimeToLiveStatus", encode_time_to_live_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_time_to_live_description_struct() -> decode.Decoder(
  TimeToLiveDescription,
) {
  use <- decode.recursive
  use attribute_name <- decode.optional_field(
    "AttributeName",
    option.None,
    decode.optional(decode.string),
  )
  use time_to_live_status <- decode.optional_field(
    "TimeToLiveStatus",
    option.None,
    decode.optional(decode_time_to_live_status_enum()),
  )
  decode.success(TimeToLiveDescription(
    attribute_name: attribute_name,
    time_to_live_status: time_to_live_status,
  ))
}

pub type TimeToLiveStatus {
  TimeToLiveStatusDisabled
  TimeToLiveStatusDisabling
  TimeToLiveStatusEnabled
  TimeToLiveStatusEnabling
}

pub fn encode_time_to_live_status_enum(v: TimeToLiveStatus) -> json.Json {
  case v {
    TimeToLiveStatusDisabled -> json.string("DISABLED")
    TimeToLiveStatusDisabling -> json.string("DISABLING")
    TimeToLiveStatusEnabled -> json.string("ENABLED")
    TimeToLiveStatusEnabling -> json.string("ENABLING")
  }
}

pub fn decode_time_to_live_status_enum() -> decode.Decoder(TimeToLiveStatus) {
  decode.then(decode.string, fn(s) {
    case s {
      "DISABLED" -> decode.success(TimeToLiveStatusDisabled)
      "DISABLING" -> decode.success(TimeToLiveStatusDisabling)
      "ENABLED" -> decode.success(TimeToLiveStatusEnabled)
      "ENABLING" -> decode.success(TimeToLiveStatusEnabling)
      _ -> decode.failure(TimeToLiveStatusDisabled, "unknown enum value")
    }
  })
}

pub type BackupNotFoundException {
  BackupNotFoundException(message: option.Option(String))
}

pub fn backup_not_found_exception_default() -> BackupNotFoundException {
  BackupNotFoundException(message: option.None)
}

pub fn encode_backup_not_found_exception_struct(
  input: BackupNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_backup_not_found_exception_struct_top(
  input: BackupNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_backup_not_found_exception_struct() -> decode.Decoder(
  BackupNotFoundException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(BackupNotFoundException(message: message))
}

pub type DeleteItemInput {
  DeleteItemInput(
    condition_expression: option.Option(String),
    conditional_operator: option.Option(ConditionalOperator),
    expected: option.Option(dict.Dict(String, ExpectedAttributeValue)),
    expression_attribute_names: option.Option(dict.Dict(String, String)),
    expression_attribute_values: option.Option(
      dict.Dict(String, AttributeValue),
    ),
    key: dict.Dict(String, AttributeValue),
    return_consumed_capacity: option.Option(ReturnConsumedCapacity),
    return_item_collection_metrics: option.Option(ReturnItemCollectionMetrics),
    return_values: option.Option(ReturnValue),
    return_values_on_condition_check_failure: option.Option(
      ReturnValuesOnConditionCheckFailure,
    ),
    table_name: String,
  )
}

pub fn delete_item_input_default(
  key key: dict.Dict(String, AttributeValue),
  table_name table_name: String,
) -> DeleteItemInput {
  DeleteItemInput(
    condition_expression: option.None,
    conditional_operator: option.None,
    expected: option.None,
    expression_attribute_names: option.None,
    expression_attribute_values: option.None,
    key: key,
    return_consumed_capacity: option.None,
    return_item_collection_metrics: option.None,
    return_values: option.None,
    return_values_on_condition_check_failure: option.None,
    table_name: table_name,
  )
}

pub fn encode_delete_item_input_struct(input: DeleteItemInput) -> json.Json {
  let pairs = []
  let pairs = case input.condition_expression {
    option.Some(v) -> [#("ConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.conditional_operator {
    option.Some(v) -> [
      #("ConditionalOperator", encode_conditional_operator_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expected {
    option.Some(v) -> [
      #(
        "Expected",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_expected_attribute_value_struct(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_item_collection_metrics {
    option.Some(v) -> [
      #(
        "ReturnItemCollectionMetrics",
        encode_return_item_collection_metrics_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_values {
    option.Some(v) -> [#("ReturnValues", encode_return_value_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_delete_item_input_struct_top(
  input: DeleteItemInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.condition_expression {
    option.Some(v) -> [#("ConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.conditional_operator {
    option.Some(v) -> [
      #("ConditionalOperator", encode_conditional_operator_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expected {
    option.Some(v) -> [
      #(
        "Expected",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_expected_attribute_value_struct(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_item_collection_metrics {
    option.Some(v) -> [
      #(
        "ReturnItemCollectionMetrics",
        encode_return_item_collection_metrics_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_values {
    option.Some(v) -> [#("ReturnValues", encode_return_value_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_delete_item_input_struct() -> decode.Decoder(DeleteItemInput) {
  use <- decode.recursive
  use condition_expression <- decode.optional_field(
    "ConditionExpression",
    option.None,
    decode.optional(decode.string),
  )
  use conditional_operator <- decode.optional_field(
    "ConditionalOperator",
    option.None,
    decode.optional(decode_conditional_operator_enum()),
  )
  use expected <- decode.optional_field(
    "Expected",
    option.None,
    decode.optional(decode.dict(
      decode.string,
      decode_expected_attribute_value_struct(),
    )),
  )
  use expression_attribute_names <- decode.optional_field(
    "ExpressionAttributeNames",
    option.None,
    decode.optional(decode.dict(decode.string, decode.string)),
  )
  use expression_attribute_values <- decode.optional_field(
    "ExpressionAttributeValues",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use key <- decode.field(
    "Key",
    decode.dict(decode.string, decode_attribute_value_union()),
  )
  use return_consumed_capacity <- decode.optional_field(
    "ReturnConsumedCapacity",
    option.None,
    decode.optional(decode_return_consumed_capacity_enum()),
  )
  use return_item_collection_metrics <- decode.optional_field(
    "ReturnItemCollectionMetrics",
    option.None,
    decode.optional(decode_return_item_collection_metrics_enum()),
  )
  use return_values <- decode.optional_field(
    "ReturnValues",
    option.None,
    decode.optional(decode_return_value_enum()),
  )
  use return_values_on_condition_check_failure <- decode.optional_field(
    "ReturnValuesOnConditionCheckFailure",
    option.None,
    decode.optional(decode_return_values_on_condition_check_failure_enum()),
  )
  use table_name <- decode.field("TableName", decode.string)
  decode.success(DeleteItemInput(
    condition_expression: condition_expression,
    conditional_operator: conditional_operator,
    expected: expected,
    expression_attribute_names: expression_attribute_names,
    expression_attribute_values: expression_attribute_values,
    key: key,
    return_consumed_capacity: return_consumed_capacity,
    return_item_collection_metrics: return_item_collection_metrics,
    return_values: return_values,
    return_values_on_condition_check_failure: return_values_on_condition_check_failure,
    table_name: table_name,
  ))
}

pub type ConditionalOperator {
  ConditionalOperatorAnd
  ConditionalOperatorOr
}

pub fn encode_conditional_operator_enum(v: ConditionalOperator) -> json.Json {
  case v {
    ConditionalOperatorAnd -> json.string("AND")
    ConditionalOperatorOr -> json.string("OR")
  }
}

pub fn decode_conditional_operator_enum() -> decode.Decoder(ConditionalOperator) {
  decode.then(decode.string, fn(s) {
    case s {
      "AND" -> decode.success(ConditionalOperatorAnd)
      "OR" -> decode.success(ConditionalOperatorOr)
      _ -> decode.failure(ConditionalOperatorAnd, "unknown enum value")
    }
  })
}

pub type ExpectedAttributeValue {
  ExpectedAttributeValue(
    attribute_value_list: option.Option(List(AttributeValue)),
    comparison_operator: option.Option(ComparisonOperator),
    exists: option.Option(Bool),
    value: option.Option(AttributeValue),
  )
}

pub fn expected_attribute_value_default() -> ExpectedAttributeValue {
  ExpectedAttributeValue(
    attribute_value_list: option.None,
    comparison_operator: option.None,
    exists: option.None,
    value: option.None,
  )
}

pub fn encode_expected_attribute_value_struct(
  input: ExpectedAttributeValue,
) -> json.Json {
  let pairs = []
  let pairs = case input.attribute_value_list {
    option.Some(v) -> [
      #(
        "AttributeValueList",
        fn(xs) { json.array(xs, encode_attribute_value_union) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.comparison_operator {
    option.Some(v) -> [
      #("ComparisonOperator", encode_comparison_operator_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.exists {
    option.Some(v) -> [#("Exists", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.value {
    option.Some(v) -> [#("Value", encode_attribute_value_union(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_expected_attribute_value_struct_top(
  input: ExpectedAttributeValue,
) -> json.Json {
  let pairs = []
  let pairs = case input.attribute_value_list {
    option.Some(v) -> [
      #(
        "AttributeValueList",
        fn(xs) { json.array(xs, encode_attribute_value_union) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.comparison_operator {
    option.Some(v) -> [
      #("ComparisonOperator", encode_comparison_operator_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.exists {
    option.Some(v) -> [#("Exists", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.value {
    option.Some(v) -> [#("Value", encode_attribute_value_union(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_expected_attribute_value_struct() -> decode.Decoder(
  ExpectedAttributeValue,
) {
  use <- decode.recursive
  use attribute_value_list <- decode.optional_field(
    "AttributeValueList",
    option.None,
    decode.optional(decode.list(decode_attribute_value_union())),
  )
  use comparison_operator <- decode.optional_field(
    "ComparisonOperator",
    option.None,
    decode.optional(decode_comparison_operator_enum()),
  )
  use exists <- decode.optional_field(
    "Exists",
    option.None,
    decode.optional(decode.bool),
  )
  use value <- decode.optional_field(
    "Value",
    option.None,
    decode.optional(decode_attribute_value_union()),
  )
  decode.success(ExpectedAttributeValue(
    attribute_value_list: attribute_value_list,
    comparison_operator: comparison_operator,
    exists: exists,
    value: value,
  ))
}

pub type ComparisonOperator {
  ComparisonOperatorBeginsWith
  ComparisonOperatorBetween
  ComparisonOperatorContains
  ComparisonOperatorEq
  ComparisonOperatorGe
  ComparisonOperatorGt
  ComparisonOperatorIn
  ComparisonOperatorLe
  ComparisonOperatorLt
  ComparisonOperatorNe
  ComparisonOperatorNotContains
  ComparisonOperatorNotNull
  ComparisonOperatorNull
}

pub fn encode_comparison_operator_enum(v: ComparisonOperator) -> json.Json {
  case v {
    ComparisonOperatorBeginsWith -> json.string("BEGINS_WITH")
    ComparisonOperatorBetween -> json.string("BETWEEN")
    ComparisonOperatorContains -> json.string("CONTAINS")
    ComparisonOperatorEq -> json.string("EQ")
    ComparisonOperatorGe -> json.string("GE")
    ComparisonOperatorGt -> json.string("GT")
    ComparisonOperatorIn -> json.string("IN")
    ComparisonOperatorLe -> json.string("LE")
    ComparisonOperatorLt -> json.string("LT")
    ComparisonOperatorNe -> json.string("NE")
    ComparisonOperatorNotContains -> json.string("NOT_CONTAINS")
    ComparisonOperatorNotNull -> json.string("NOT_NULL")
    ComparisonOperatorNull -> json.string("NULL")
  }
}

pub fn decode_comparison_operator_enum() -> decode.Decoder(ComparisonOperator) {
  decode.then(decode.string, fn(s) {
    case s {
      "BEGINS_WITH" -> decode.success(ComparisonOperatorBeginsWith)
      "BETWEEN" -> decode.success(ComparisonOperatorBetween)
      "CONTAINS" -> decode.success(ComparisonOperatorContains)
      "EQ" -> decode.success(ComparisonOperatorEq)
      "GE" -> decode.success(ComparisonOperatorGe)
      "GT" -> decode.success(ComparisonOperatorGt)
      "IN" -> decode.success(ComparisonOperatorIn)
      "LE" -> decode.success(ComparisonOperatorLe)
      "LT" -> decode.success(ComparisonOperatorLt)
      "NE" -> decode.success(ComparisonOperatorNe)
      "NOT_CONTAINS" -> decode.success(ComparisonOperatorNotContains)
      "NOT_NULL" -> decode.success(ComparisonOperatorNotNull)
      "NULL" -> decode.success(ComparisonOperatorNull)
      _ -> decode.failure(ComparisonOperatorBeginsWith, "unknown enum value")
    }
  })
}

pub type ReturnValue {
  ReturnValueAllNew
  ReturnValueAllOld
  ReturnValueNone
  ReturnValueUpdatedNew
  ReturnValueUpdatedOld
}

pub fn encode_return_value_enum(v: ReturnValue) -> json.Json {
  case v {
    ReturnValueAllNew -> json.string("ALL_NEW")
    ReturnValueAllOld -> json.string("ALL_OLD")
    ReturnValueNone -> json.string("NONE")
    ReturnValueUpdatedNew -> json.string("UPDATED_NEW")
    ReturnValueUpdatedOld -> json.string("UPDATED_OLD")
  }
}

pub fn decode_return_value_enum() -> decode.Decoder(ReturnValue) {
  decode.then(decode.string, fn(s) {
    case s {
      "ALL_NEW" -> decode.success(ReturnValueAllNew)
      "ALL_OLD" -> decode.success(ReturnValueAllOld)
      "NONE" -> decode.success(ReturnValueNone)
      "UPDATED_NEW" -> decode.success(ReturnValueUpdatedNew)
      "UPDATED_OLD" -> decode.success(ReturnValueUpdatedOld)
      _ -> decode.failure(ReturnValueAllNew, "unknown enum value")
    }
  })
}

pub type DeleteItemOutput {
  DeleteItemOutput(
    attributes: option.Option(dict.Dict(String, AttributeValue)),
    consumed_capacity: option.Option(ConsumedCapacity),
    item_collection_metrics: option.Option(ItemCollectionMetrics),
  )
}

pub fn delete_item_output_default() -> DeleteItemOutput {
  DeleteItemOutput(
    attributes: option.None,
    consumed_capacity: option.None,
    item_collection_metrics: option.None,
  )
}

pub fn encode_delete_item_output_struct(input: DeleteItemOutput) -> json.Json {
  let pairs = []
  let pairs = case input.attributes {
    option.Some(v) -> [
      #(
        "Attributes",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_collection_metrics {
    option.Some(v) -> [
      #("ItemCollectionMetrics", encode_item_collection_metrics_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_delete_item_output_struct_top(
  input: DeleteItemOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.attributes {
    option.Some(v) -> [
      #(
        "Attributes",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_collection_metrics {
    option.Some(v) -> [
      #("ItemCollectionMetrics", encode_item_collection_metrics_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_delete_item_output_struct() -> decode.Decoder(DeleteItemOutput) {
  use <- decode.recursive
  use attributes <- decode.optional_field(
    "Attributes",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use consumed_capacity <- decode.optional_field(
    "ConsumedCapacity",
    option.None,
    decode.optional(decode_consumed_capacity_struct()),
  )
  use item_collection_metrics <- decode.optional_field(
    "ItemCollectionMetrics",
    option.None,
    decode.optional(decode_item_collection_metrics_struct()),
  )
  decode.success(DeleteItemOutput(
    attributes: attributes,
    consumed_capacity: consumed_capacity,
    item_collection_metrics: item_collection_metrics,
  ))
}

pub type ConditionalCheckFailedException {
  ConditionalCheckFailedException(
    item: option.Option(dict.Dict(String, AttributeValue)),
    message: option.Option(String),
  )
}

pub fn conditional_check_failed_exception_default() -> ConditionalCheckFailedException {
  ConditionalCheckFailedException(item: option.None, message: option.None)
}

pub fn encode_conditional_check_failed_exception_struct(
  input: ConditionalCheckFailedException,
) -> json.Json {
  let pairs = []
  let pairs = case input.item {
    option.Some(v) -> [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_conditional_check_failed_exception_struct_top(
  input: ConditionalCheckFailedException,
) -> json.Json {
  let pairs = []
  let pairs = case input.item {
    option.Some(v) -> [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_conditional_check_failed_exception_struct() -> decode.Decoder(
  ConditionalCheckFailedException,
) {
  use <- decode.recursive
  use item <- decode.optional_field(
    "Item",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ConditionalCheckFailedException(item: item, message: message))
}

pub type TransactionConflictException {
  TransactionConflictException(message: option.Option(String))
}

pub fn transaction_conflict_exception_default() -> TransactionConflictException {
  TransactionConflictException(message: option.None)
}

pub fn encode_transaction_conflict_exception_struct(
  input: TransactionConflictException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_transaction_conflict_exception_struct_top(
  input: TransactionConflictException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_transaction_conflict_exception_struct() -> decode.Decoder(
  TransactionConflictException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(TransactionConflictException(message: message))
}

pub type DeleteResourcePolicyInput {
  DeleteResourcePolicyInput(
    expected_revision_id: option.Option(String),
    resource_arn: String,
  )
}

pub fn delete_resource_policy_input_default(
  resource_arn resource_arn: String,
) -> DeleteResourcePolicyInput {
  DeleteResourcePolicyInput(
    expected_revision_id: option.None,
    resource_arn: resource_arn,
  )
}

pub fn encode_delete_resource_policy_input_struct(
  input: DeleteResourcePolicyInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.expected_revision_id {
    option.Some(v) -> [#("ExpectedRevisionId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.resource_arn
    [#("ResourceArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_delete_resource_policy_input_struct_top(
  input: DeleteResourcePolicyInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.expected_revision_id {
    option.Some(v) -> [#("ExpectedRevisionId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.resource_arn
    [#("ResourceArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_delete_resource_policy_input_struct() -> decode.Decoder(
  DeleteResourcePolicyInput,
) {
  use <- decode.recursive
  use expected_revision_id <- decode.optional_field(
    "ExpectedRevisionId",
    option.None,
    decode.optional(decode.string),
  )
  use resource_arn <- decode.field("ResourceArn", decode.string)
  decode.success(DeleteResourcePolicyInput(
    expected_revision_id: expected_revision_id,
    resource_arn: resource_arn,
  ))
}

pub type DeleteResourcePolicyOutput {
  DeleteResourcePolicyOutput(revision_id: option.Option(String))
}

pub fn delete_resource_policy_output_default() -> DeleteResourcePolicyOutput {
  DeleteResourcePolicyOutput(revision_id: option.None)
}

pub fn encode_delete_resource_policy_output_struct(
  input: DeleteResourcePolicyOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.revision_id {
    option.Some(v) -> [#("RevisionId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_delete_resource_policy_output_struct_top(
  input: DeleteResourcePolicyOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.revision_id {
    option.Some(v) -> [#("RevisionId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_delete_resource_policy_output_struct() -> decode.Decoder(
  DeleteResourcePolicyOutput,
) {
  use <- decode.recursive
  use revision_id <- decode.optional_field(
    "RevisionId",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(DeleteResourcePolicyOutput(revision_id: revision_id))
}

pub type PolicyNotFoundException {
  PolicyNotFoundException(message: option.Option(String))
}

pub fn policy_not_found_exception_default() -> PolicyNotFoundException {
  PolicyNotFoundException(message: option.None)
}

pub fn encode_policy_not_found_exception_struct(
  input: PolicyNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_policy_not_found_exception_struct_top(
  input: PolicyNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_policy_not_found_exception_struct() -> decode.Decoder(
  PolicyNotFoundException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(PolicyNotFoundException(message: message))
}

pub type DeleteTableInput {
  DeleteTableInput(table_name: String)
}

pub fn delete_table_input_default(
  table_name table_name: String,
) -> DeleteTableInput {
  DeleteTableInput(table_name: table_name)
}

pub fn encode_delete_table_input_struct(input: DeleteTableInput) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_delete_table_input_struct_top(
  input: DeleteTableInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_delete_table_input_struct() -> decode.Decoder(DeleteTableInput) {
  use <- decode.recursive
  use table_name <- decode.field("TableName", decode.string)
  decode.success(DeleteTableInput(table_name: table_name))
}

pub type DeleteTableOutput {
  DeleteTableOutput(table_description: option.Option(TableDescription))
}

pub fn delete_table_output_default() -> DeleteTableOutput {
  DeleteTableOutput(table_description: option.None)
}

pub fn encode_delete_table_output_struct(
  input: DeleteTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_description {
    option.Some(v) -> [
      #("TableDescription", encode_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_delete_table_output_struct_top(
  input: DeleteTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_description {
    option.Some(v) -> [
      #("TableDescription", encode_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_delete_table_output_struct() -> decode.Decoder(DeleteTableOutput) {
  use <- decode.recursive
  use table_description <- decode.optional_field(
    "TableDescription",
    option.None,
    decode.optional(decode_table_description_struct()),
  )
  decode.success(DeleteTableOutput(table_description: table_description))
}

pub type DescribeBackupInput {
  DescribeBackupInput(backup_arn: String)
}

pub fn describe_backup_input_default(
  backup_arn backup_arn: String,
) -> DescribeBackupInput {
  DescribeBackupInput(backup_arn: backup_arn)
}

pub fn encode_describe_backup_input_struct(
  input: DescribeBackupInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.backup_arn
    [#("BackupArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_describe_backup_input_struct_top(
  input: DescribeBackupInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.backup_arn
    [#("BackupArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_describe_backup_input_struct() -> decode.Decoder(
  DescribeBackupInput,
) {
  use <- decode.recursive
  use backup_arn <- decode.field("BackupArn", decode.string)
  decode.success(DescribeBackupInput(backup_arn: backup_arn))
}

pub type DescribeBackupOutput {
  DescribeBackupOutput(backup_description: option.Option(BackupDescription))
}

pub fn describe_backup_output_default() -> DescribeBackupOutput {
  DescribeBackupOutput(backup_description: option.None)
}

pub fn encode_describe_backup_output_struct(
  input: DescribeBackupOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.backup_description {
    option.Some(v) -> [
      #("BackupDescription", encode_backup_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_describe_backup_output_struct_top(
  input: DescribeBackupOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.backup_description {
    option.Some(v) -> [
      #("BackupDescription", encode_backup_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_describe_backup_output_struct() -> decode.Decoder(
  DescribeBackupOutput,
) {
  use <- decode.recursive
  use backup_description <- decode.optional_field(
    "BackupDescription",
    option.None,
    decode.optional(decode_backup_description_struct()),
  )
  decode.success(DescribeBackupOutput(backup_description: backup_description))
}

pub type DescribeContinuousBackupsInput {
  DescribeContinuousBackupsInput(table_name: String)
}

pub fn describe_continuous_backups_input_default(
  table_name table_name: String,
) -> DescribeContinuousBackupsInput {
  DescribeContinuousBackupsInput(table_name: table_name)
}

pub fn encode_describe_continuous_backups_input_struct(
  input: DescribeContinuousBackupsInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_describe_continuous_backups_input_struct_top(
  input: DescribeContinuousBackupsInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_describe_continuous_backups_input_struct() -> decode.Decoder(
  DescribeContinuousBackupsInput,
) {
  use <- decode.recursive
  use table_name <- decode.field("TableName", decode.string)
  decode.success(DescribeContinuousBackupsInput(table_name: table_name))
}

pub type DescribeContinuousBackupsOutput {
  DescribeContinuousBackupsOutput(
    continuous_backups_description: option.Option(ContinuousBackupsDescription),
  )
}

pub fn describe_continuous_backups_output_default() -> DescribeContinuousBackupsOutput {
  DescribeContinuousBackupsOutput(continuous_backups_description: option.None)
}

pub fn encode_describe_continuous_backups_output_struct(
  input: DescribeContinuousBackupsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.continuous_backups_description {
    option.Some(v) -> [
      #(
        "ContinuousBackupsDescription",
        encode_continuous_backups_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_describe_continuous_backups_output_struct_top(
  input: DescribeContinuousBackupsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.continuous_backups_description {
    option.Some(v) -> [
      #(
        "ContinuousBackupsDescription",
        encode_continuous_backups_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_describe_continuous_backups_output_struct() -> decode.Decoder(
  DescribeContinuousBackupsOutput,
) {
  use <- decode.recursive
  use continuous_backups_description <- decode.optional_field(
    "ContinuousBackupsDescription",
    option.None,
    decode.optional(decode_continuous_backups_description_struct()),
  )
  decode.success(DescribeContinuousBackupsOutput(
    continuous_backups_description: continuous_backups_description,
  ))
}

pub type ContinuousBackupsDescription {
  ContinuousBackupsDescription(
    continuous_backups_status: option.Option(ContinuousBackupsStatus),
    point_in_time_recovery_description: option.Option(
      PointInTimeRecoveryDescription,
    ),
  )
}

pub fn continuous_backups_description_default() -> ContinuousBackupsDescription {
  ContinuousBackupsDescription(
    continuous_backups_status: option.None,
    point_in_time_recovery_description: option.None,
  )
}

pub fn encode_continuous_backups_description_struct(
  input: ContinuousBackupsDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.continuous_backups_status {
    option.Some(v) -> [
      #("ContinuousBackupsStatus", encode_continuous_backups_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.point_in_time_recovery_description {
    option.Some(v) -> [
      #(
        "PointInTimeRecoveryDescription",
        encode_point_in_time_recovery_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_continuous_backups_description_struct_top(
  input: ContinuousBackupsDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.continuous_backups_status {
    option.Some(v) -> [
      #("ContinuousBackupsStatus", encode_continuous_backups_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.point_in_time_recovery_description {
    option.Some(v) -> [
      #(
        "PointInTimeRecoveryDescription",
        encode_point_in_time_recovery_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_continuous_backups_description_struct() -> decode.Decoder(
  ContinuousBackupsDescription,
) {
  use <- decode.recursive
  use continuous_backups_status <- decode.optional_field(
    "ContinuousBackupsStatus",
    option.None,
    decode.optional(decode_continuous_backups_status_enum()),
  )
  use point_in_time_recovery_description <- decode.optional_field(
    "PointInTimeRecoveryDescription",
    option.None,
    decode.optional(decode_point_in_time_recovery_description_struct()),
  )
  decode.success(ContinuousBackupsDescription(
    continuous_backups_status: continuous_backups_status,
    point_in_time_recovery_description: point_in_time_recovery_description,
  ))
}

pub type ContinuousBackupsStatus {
  ContinuousBackupsStatusDisabled
  ContinuousBackupsStatusEnabled
}

pub fn encode_continuous_backups_status_enum(
  v: ContinuousBackupsStatus,
) -> json.Json {
  case v {
    ContinuousBackupsStatusDisabled -> json.string("DISABLED")
    ContinuousBackupsStatusEnabled -> json.string("ENABLED")
  }
}

pub fn decode_continuous_backups_status_enum() -> decode.Decoder(
  ContinuousBackupsStatus,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "DISABLED" -> decode.success(ContinuousBackupsStatusDisabled)
      "ENABLED" -> decode.success(ContinuousBackupsStatusEnabled)
      _ -> decode.failure(ContinuousBackupsStatusDisabled, "unknown enum value")
    }
  })
}

pub type PointInTimeRecoveryDescription {
  PointInTimeRecoveryDescription(
    earliest_restorable_date_time: option.Option(json_timestamp.Timestamp),
    latest_restorable_date_time: option.Option(json_timestamp.Timestamp),
    point_in_time_recovery_status: option.Option(PointInTimeRecoveryStatus),
    recovery_period_in_days: option.Option(Int),
  )
}

pub fn point_in_time_recovery_description_default() -> PointInTimeRecoveryDescription {
  PointInTimeRecoveryDescription(
    earliest_restorable_date_time: option.None,
    latest_restorable_date_time: option.None,
    point_in_time_recovery_status: option.None,
    recovery_period_in_days: option.None,
  )
}

pub fn encode_point_in_time_recovery_description_struct(
  input: PointInTimeRecoveryDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.earliest_restorable_date_time {
    option.Some(v) -> [
      #("EarliestRestorableDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.latest_restorable_date_time {
    option.Some(v) -> [
      #("LatestRestorableDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.point_in_time_recovery_status {
    option.Some(v) -> [
      #(
        "PointInTimeRecoveryStatus",
        encode_point_in_time_recovery_status_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.recovery_period_in_days {
    option.Some(v) -> [#("RecoveryPeriodInDays", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_point_in_time_recovery_description_struct_top(
  input: PointInTimeRecoveryDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.earliest_restorable_date_time {
    option.Some(v) -> [
      #("EarliestRestorableDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.latest_restorable_date_time {
    option.Some(v) -> [
      #("LatestRestorableDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.point_in_time_recovery_status {
    option.Some(v) -> [
      #(
        "PointInTimeRecoveryStatus",
        encode_point_in_time_recovery_status_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.recovery_period_in_days {
    option.Some(v) -> [#("RecoveryPeriodInDays", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_point_in_time_recovery_description_struct() -> decode.Decoder(
  PointInTimeRecoveryDescription,
) {
  use <- decode.recursive
  use earliest_restorable_date_time <- decode.optional_field(
    "EarliestRestorableDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use latest_restorable_date_time <- decode.optional_field(
    "LatestRestorableDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use point_in_time_recovery_status <- decode.optional_field(
    "PointInTimeRecoveryStatus",
    option.None,
    decode.optional(decode_point_in_time_recovery_status_enum()),
  )
  use recovery_period_in_days <- decode.optional_field(
    "RecoveryPeriodInDays",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(PointInTimeRecoveryDescription(
    earliest_restorable_date_time: earliest_restorable_date_time,
    latest_restorable_date_time: latest_restorable_date_time,
    point_in_time_recovery_status: point_in_time_recovery_status,
    recovery_period_in_days: recovery_period_in_days,
  ))
}

pub type PointInTimeRecoveryStatus {
  PointInTimeRecoveryStatusDisabled
  PointInTimeRecoveryStatusEnabled
}

pub fn encode_point_in_time_recovery_status_enum(
  v: PointInTimeRecoveryStatus,
) -> json.Json {
  case v {
    PointInTimeRecoveryStatusDisabled -> json.string("DISABLED")
    PointInTimeRecoveryStatusEnabled -> json.string("ENABLED")
  }
}

pub fn decode_point_in_time_recovery_status_enum() -> decode.Decoder(
  PointInTimeRecoveryStatus,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "DISABLED" -> decode.success(PointInTimeRecoveryStatusDisabled)
      "ENABLED" -> decode.success(PointInTimeRecoveryStatusEnabled)
      _ ->
        decode.failure(PointInTimeRecoveryStatusDisabled, "unknown enum value")
    }
  })
}

pub type DescribeContributorInsightsInput {
  DescribeContributorInsightsInput(
    index_name: option.Option(String),
    table_name: String,
  )
}

pub fn describe_contributor_insights_input_default(
  table_name table_name: String,
) -> DescribeContributorInsightsInput {
  DescribeContributorInsightsInput(
    index_name: option.None,
    table_name: table_name,
  )
}

pub fn encode_describe_contributor_insights_input_struct(
  input: DescribeContributorInsightsInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_describe_contributor_insights_input_struct_top(
  input: DescribeContributorInsightsInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_describe_contributor_insights_input_struct() -> decode.Decoder(
  DescribeContributorInsightsInput,
) {
  use <- decode.recursive
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use table_name <- decode.field("TableName", decode.string)
  decode.success(DescribeContributorInsightsInput(
    index_name: index_name,
    table_name: table_name,
  ))
}

pub type DescribeContributorInsightsOutput {
  DescribeContributorInsightsOutput(
    contributor_insights_mode: option.Option(ContributorInsightsMode),
    contributor_insights_rule_list: option.Option(List(String)),
    contributor_insights_status: option.Option(ContributorInsightsStatus),
    failure_exception: option.Option(FailureException),
    index_name: option.Option(String),
    last_update_date_time: option.Option(json_timestamp.Timestamp),
    table_name: option.Option(String),
  )
}

pub fn describe_contributor_insights_output_default() -> DescribeContributorInsightsOutput {
  DescribeContributorInsightsOutput(
    contributor_insights_mode: option.None,
    contributor_insights_rule_list: option.None,
    contributor_insights_status: option.None,
    failure_exception: option.None,
    index_name: option.None,
    last_update_date_time: option.None,
    table_name: option.None,
  )
}

pub fn encode_describe_contributor_insights_output_struct(
  input: DescribeContributorInsightsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.contributor_insights_mode {
    option.Some(v) -> [
      #("ContributorInsightsMode", encode_contributor_insights_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.contributor_insights_rule_list {
    option.Some(v) -> [
      #(
        "ContributorInsightsRuleList",
        fn(xs) { json.array(xs, json.string) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.contributor_insights_status {
    option.Some(v) -> [
      #("ContributorInsightsStatus", encode_contributor_insights_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.failure_exception {
    option.Some(v) -> [
      #("FailureException", encode_failure_exception_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.last_update_date_time {
    option.Some(v) -> [
      #("LastUpdateDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_describe_contributor_insights_output_struct_top(
  input: DescribeContributorInsightsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.contributor_insights_mode {
    option.Some(v) -> [
      #("ContributorInsightsMode", encode_contributor_insights_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.contributor_insights_rule_list {
    option.Some(v) -> [
      #(
        "ContributorInsightsRuleList",
        fn(xs) { json.array(xs, json.string) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.contributor_insights_status {
    option.Some(v) -> [
      #("ContributorInsightsStatus", encode_contributor_insights_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.failure_exception {
    option.Some(v) -> [
      #("FailureException", encode_failure_exception_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.last_update_date_time {
    option.Some(v) -> [
      #("LastUpdateDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_describe_contributor_insights_output_struct() -> decode.Decoder(
  DescribeContributorInsightsOutput,
) {
  use <- decode.recursive
  use contributor_insights_mode <- decode.optional_field(
    "ContributorInsightsMode",
    option.None,
    decode.optional(decode_contributor_insights_mode_enum()),
  )
  use contributor_insights_rule_list <- decode.optional_field(
    "ContributorInsightsRuleList",
    option.None,
    decode.optional(decode.list(decode.string)),
  )
  use contributor_insights_status <- decode.optional_field(
    "ContributorInsightsStatus",
    option.None,
    decode.optional(decode_contributor_insights_status_enum()),
  )
  use failure_exception <- decode.optional_field(
    "FailureException",
    option.None,
    decode.optional(decode_failure_exception_struct()),
  )
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use last_update_date_time <- decode.optional_field(
    "LastUpdateDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(DescribeContributorInsightsOutput(
    contributor_insights_mode: contributor_insights_mode,
    contributor_insights_rule_list: contributor_insights_rule_list,
    contributor_insights_status: contributor_insights_status,
    failure_exception: failure_exception,
    index_name: index_name,
    last_update_date_time: last_update_date_time,
    table_name: table_name,
  ))
}

pub type ContributorInsightsMode {
  ContributorInsightsModeAccessedAndThrottledKeys
  ContributorInsightsModeThrottledKeys
}

pub fn encode_contributor_insights_mode_enum(
  v: ContributorInsightsMode,
) -> json.Json {
  case v {
    ContributorInsightsModeAccessedAndThrottledKeys ->
      json.string("ACCESSED_AND_THROTTLED_KEYS")
    ContributorInsightsModeThrottledKeys -> json.string("THROTTLED_KEYS")
  }
}

pub fn decode_contributor_insights_mode_enum() -> decode.Decoder(
  ContributorInsightsMode,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "ACCESSED_AND_THROTTLED_KEYS" ->
        decode.success(ContributorInsightsModeAccessedAndThrottledKeys)
      "THROTTLED_KEYS" -> decode.success(ContributorInsightsModeThrottledKeys)
      _ ->
        decode.failure(
          ContributorInsightsModeAccessedAndThrottledKeys,
          "unknown enum value",
        )
    }
  })
}

pub type ContributorInsightsStatus {
  ContributorInsightsStatusDisabled
  ContributorInsightsStatusDisabling
  ContributorInsightsStatusEnabled
  ContributorInsightsStatusEnabling
  ContributorInsightsStatusFailed
}

pub fn encode_contributor_insights_status_enum(
  v: ContributorInsightsStatus,
) -> json.Json {
  case v {
    ContributorInsightsStatusDisabled -> json.string("DISABLED")
    ContributorInsightsStatusDisabling -> json.string("DISABLING")
    ContributorInsightsStatusEnabled -> json.string("ENABLED")
    ContributorInsightsStatusEnabling -> json.string("ENABLING")
    ContributorInsightsStatusFailed -> json.string("FAILED")
  }
}

pub fn decode_contributor_insights_status_enum() -> decode.Decoder(
  ContributorInsightsStatus,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "DISABLED" -> decode.success(ContributorInsightsStatusDisabled)
      "DISABLING" -> decode.success(ContributorInsightsStatusDisabling)
      "ENABLED" -> decode.success(ContributorInsightsStatusEnabled)
      "ENABLING" -> decode.success(ContributorInsightsStatusEnabling)
      "FAILED" -> decode.success(ContributorInsightsStatusFailed)
      _ ->
        decode.failure(ContributorInsightsStatusDisabled, "unknown enum value")
    }
  })
}

pub type FailureException {
  FailureException(
    exception_description: option.Option(String),
    exception_name: option.Option(String),
  )
}

pub fn failure_exception_default() -> FailureException {
  FailureException(
    exception_description: option.None,
    exception_name: option.None,
  )
}

pub fn encode_failure_exception_struct(input: FailureException) -> json.Json {
  let pairs = []
  let pairs = case input.exception_description {
    option.Some(v) -> [#("ExceptionDescription", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.exception_name {
    option.Some(v) -> [#("ExceptionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_failure_exception_struct_top(
  input: FailureException,
) -> json.Json {
  let pairs = []
  let pairs = case input.exception_description {
    option.Some(v) -> [#("ExceptionDescription", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.exception_name {
    option.Some(v) -> [#("ExceptionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_failure_exception_struct() -> decode.Decoder(FailureException) {
  use <- decode.recursive
  use exception_description <- decode.optional_field(
    "ExceptionDescription",
    option.None,
    decode.optional(decode.string),
  )
  use exception_name <- decode.optional_field(
    "ExceptionName",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(FailureException(
    exception_description: exception_description,
    exception_name: exception_name,
  ))
}

pub type DescribeEndpointsRequest {
  DescribeEndpointsRequest
}

pub fn describe_endpoints_request_default() -> DescribeEndpointsRequest {
  DescribeEndpointsRequest
}

pub fn encode_describe_endpoints_request_struct(
  _v: DescribeEndpointsRequest,
) -> json.Json {
  json.object([])
}

pub fn encode_describe_endpoints_request_struct_top(
  _v: DescribeEndpointsRequest,
) -> json.Json {
  json.object([])
}

pub fn decode_describe_endpoints_request_struct() -> decode.Decoder(
  DescribeEndpointsRequest,
) {
  decode.success(DescribeEndpointsRequest)
}

pub type DescribeEndpointsResponse {
  DescribeEndpointsResponse(endpoints: option.Option(List(Endpoint)))
}

pub fn describe_endpoints_response_default() -> DescribeEndpointsResponse {
  DescribeEndpointsResponse(endpoints: option.None)
}

pub fn encode_describe_endpoints_response_struct(
  input: DescribeEndpointsResponse,
) -> json.Json {
  let pairs = []
  let pairs = case input.endpoints {
    option.Some(v) -> [
      #("Endpoints", fn(xs) { json.array(xs, encode_endpoint_struct) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_describe_endpoints_response_struct_top(
  input: DescribeEndpointsResponse,
) -> json.Json {
  let pairs = []
  let pairs = case input.endpoints {
    option.Some(v) -> [
      #("Endpoints", fn(xs) { json.array(xs, encode_endpoint_struct) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_describe_endpoints_response_struct() -> decode.Decoder(
  DescribeEndpointsResponse,
) {
  use <- decode.recursive
  use endpoints <- decode.optional_field(
    "Endpoints",
    option.None,
    decode.optional(decode.list(decode_endpoint_struct())),
  )
  decode.success(DescribeEndpointsResponse(endpoints: endpoints))
}

pub type Endpoint {
  Endpoint(
    address: option.Option(String),
    cache_period_in_minutes: option.Option(Int),
  )
}

pub fn endpoint_default() -> Endpoint {
  Endpoint(address: option.None, cache_period_in_minutes: option.None)
}

pub fn encode_endpoint_struct(input: Endpoint) -> json.Json {
  let pairs = []
  let pairs = case input.address {
    option.Some(v) -> [#("Address", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.cache_period_in_minutes {
    option.Some(v) -> [#("CachePeriodInMinutes", json.int(v)), ..pairs]
    option.None -> [#("CachePeriodInMinutes", json.int(0)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_endpoint_struct_top(input: Endpoint) -> json.Json {
  let pairs = []
  let pairs = case input.address {
    option.Some(v) -> [#("Address", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.cache_period_in_minutes {
    option.Some(v) -> [#("CachePeriodInMinutes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_endpoint_struct() -> decode.Decoder(Endpoint) {
  use <- decode.recursive
  use address <- decode.optional_field(
    "Address",
    option.None,
    decode.optional(decode.string),
  )
  use cache_period_in_minutes <- decode.optional_field(
    "CachePeriodInMinutes",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(Endpoint(
    address: address,
    cache_period_in_minutes: cache_period_in_minutes,
  ))
}

pub type DescribeExportInput {
  DescribeExportInput(export_arn: String)
}

pub fn describe_export_input_default(
  export_arn export_arn: String,
) -> DescribeExportInput {
  DescribeExportInput(export_arn: export_arn)
}

pub fn encode_describe_export_input_struct(
  input: DescribeExportInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.export_arn
    [#("ExportArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_describe_export_input_struct_top(
  input: DescribeExportInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.export_arn
    [#("ExportArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_describe_export_input_struct() -> decode.Decoder(
  DescribeExportInput,
) {
  use <- decode.recursive
  use export_arn <- decode.field("ExportArn", decode.string)
  decode.success(DescribeExportInput(export_arn: export_arn))
}

pub type DescribeExportOutput {
  DescribeExportOutput(export_description: option.Option(ExportDescription))
}

pub fn describe_export_output_default() -> DescribeExportOutput {
  DescribeExportOutput(export_description: option.None)
}

pub fn encode_describe_export_output_struct(
  input: DescribeExportOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.export_description {
    option.Some(v) -> [
      #("ExportDescription", encode_export_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_describe_export_output_struct_top(
  input: DescribeExportOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.export_description {
    option.Some(v) -> [
      #("ExportDescription", encode_export_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_describe_export_output_struct() -> decode.Decoder(
  DescribeExportOutput,
) {
  use <- decode.recursive
  use export_description <- decode.optional_field(
    "ExportDescription",
    option.None,
    decode.optional(decode_export_description_struct()),
  )
  decode.success(DescribeExportOutput(export_description: export_description))
}

pub type ExportDescription {
  ExportDescription(
    billed_size_bytes: option.Option(Int),
    client_token: option.Option(String),
    end_time: option.Option(json_timestamp.Timestamp),
    export_arn: option.Option(String),
    export_format: option.Option(ExportFormat),
    export_manifest: option.Option(String),
    export_status: option.Option(ExportStatus),
    export_time: option.Option(json_timestamp.Timestamp),
    export_type: option.Option(ExportType),
    failure_code: option.Option(String),
    failure_message: option.Option(String),
    incremental_export_specification: option.Option(
      IncrementalExportSpecification,
    ),
    item_count: option.Option(Int),
    s3_bucket: option.Option(String),
    s3_bucket_owner: option.Option(String),
    s3_prefix: option.Option(String),
    s3_sse_algorithm: option.Option(S3SseAlgorithm),
    s3_sse_kms_key_id: option.Option(String),
    start_time: option.Option(json_timestamp.Timestamp),
    table_arn: option.Option(String),
    table_id: option.Option(String),
  )
}

pub fn export_description_default() -> ExportDescription {
  ExportDescription(
    billed_size_bytes: option.None,
    client_token: option.None,
    end_time: option.None,
    export_arn: option.None,
    export_format: option.None,
    export_manifest: option.None,
    export_status: option.None,
    export_time: option.None,
    export_type: option.None,
    failure_code: option.None,
    failure_message: option.None,
    incremental_export_specification: option.None,
    item_count: option.None,
    s3_bucket: option.None,
    s3_bucket_owner: option.None,
    s3_prefix: option.None,
    s3_sse_algorithm: option.None,
    s3_sse_kms_key_id: option.None,
    start_time: option.None,
    table_arn: option.None,
    table_id: option.None,
  )
}

pub fn encode_export_description_struct(input: ExportDescription) -> json.Json {
  let pairs = []
  let pairs = case input.billed_size_bytes {
    option.Some(v) -> [#("BilledSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.client_token {
    option.Some(v) -> [#("ClientToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.end_time {
    option.Some(v) -> [
      #("EndTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.export_arn {
    option.Some(v) -> [#("ExportArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_format {
    option.Some(v) -> [#("ExportFormat", encode_export_format_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_manifest {
    option.Some(v) -> [#("ExportManifest", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_status {
    option.Some(v) -> [#("ExportStatus", encode_export_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_time {
    option.Some(v) -> [
      #("ExportTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.export_type {
    option.Some(v) -> [#("ExportType", encode_export_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.failure_code {
    option.Some(v) -> [#("FailureCode", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.failure_message {
    option.Some(v) -> [#("FailureMessage", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.incremental_export_specification {
    option.Some(v) -> [
      #(
        "IncrementalExportSpecification",
        encode_incremental_export_specification_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_count {
    option.Some(v) -> [#("ItemCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_bucket {
    option.Some(v) -> [#("S3Bucket", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_bucket_owner {
    option.Some(v) -> [#("S3BucketOwner", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_prefix {
    option.Some(v) -> [#("S3Prefix", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_sse_algorithm {
    option.Some(v) -> [
      #("S3SseAlgorithm", encode_s3_sse_algorithm_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.s3_sse_kms_key_id {
    option.Some(v) -> [#("S3SseKmsKeyId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.start_time {
    option.Some(v) -> [
      #("StartTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_id {
    option.Some(v) -> [#("TableId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_export_description_struct_top(
  input: ExportDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.billed_size_bytes {
    option.Some(v) -> [#("BilledSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.client_token {
    option.Some(v) -> [#("ClientToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.end_time {
    option.Some(v) -> [
      #("EndTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.export_arn {
    option.Some(v) -> [#("ExportArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_format {
    option.Some(v) -> [#("ExportFormat", encode_export_format_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_manifest {
    option.Some(v) -> [#("ExportManifest", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_status {
    option.Some(v) -> [#("ExportStatus", encode_export_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_time {
    option.Some(v) -> [
      #("ExportTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.export_type {
    option.Some(v) -> [#("ExportType", encode_export_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.failure_code {
    option.Some(v) -> [#("FailureCode", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.failure_message {
    option.Some(v) -> [#("FailureMessage", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.incremental_export_specification {
    option.Some(v) -> [
      #(
        "IncrementalExportSpecification",
        encode_incremental_export_specification_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_count {
    option.Some(v) -> [#("ItemCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_bucket {
    option.Some(v) -> [#("S3Bucket", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_bucket_owner {
    option.Some(v) -> [#("S3BucketOwner", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_prefix {
    option.Some(v) -> [#("S3Prefix", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_sse_algorithm {
    option.Some(v) -> [
      #("S3SseAlgorithm", encode_s3_sse_algorithm_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.s3_sse_kms_key_id {
    option.Some(v) -> [#("S3SseKmsKeyId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.start_time {
    option.Some(v) -> [
      #("StartTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_id {
    option.Some(v) -> [#("TableId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_export_description_struct() -> decode.Decoder(ExportDescription) {
  use <- decode.recursive
  use billed_size_bytes <- decode.optional_field(
    "BilledSizeBytes",
    option.None,
    decode.optional(decode.int),
  )
  use client_token <- decode.optional_field(
    "ClientToken",
    option.None,
    decode.optional(decode.string),
  )
  use end_time <- decode.optional_field(
    "EndTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use export_arn <- decode.optional_field(
    "ExportArn",
    option.None,
    decode.optional(decode.string),
  )
  use export_format <- decode.optional_field(
    "ExportFormat",
    option.None,
    decode.optional(decode_export_format_enum()),
  )
  use export_manifest <- decode.optional_field(
    "ExportManifest",
    option.None,
    decode.optional(decode.string),
  )
  use export_status <- decode.optional_field(
    "ExportStatus",
    option.None,
    decode.optional(decode_export_status_enum()),
  )
  use export_time <- decode.optional_field(
    "ExportTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use export_type <- decode.optional_field(
    "ExportType",
    option.None,
    decode.optional(decode_export_type_enum()),
  )
  use failure_code <- decode.optional_field(
    "FailureCode",
    option.None,
    decode.optional(decode.string),
  )
  use failure_message <- decode.optional_field(
    "FailureMessage",
    option.None,
    decode.optional(decode.string),
  )
  use incremental_export_specification <- decode.optional_field(
    "IncrementalExportSpecification",
    option.None,
    decode.optional(decode_incremental_export_specification_struct()),
  )
  use item_count <- decode.optional_field(
    "ItemCount",
    option.None,
    decode.optional(decode.int),
  )
  use s3_bucket <- decode.optional_field(
    "S3Bucket",
    option.None,
    decode.optional(decode.string),
  )
  use s3_bucket_owner <- decode.optional_field(
    "S3BucketOwner",
    option.None,
    decode.optional(decode.string),
  )
  use s3_prefix <- decode.optional_field(
    "S3Prefix",
    option.None,
    decode.optional(decode.string),
  )
  use s3_sse_algorithm <- decode.optional_field(
    "S3SseAlgorithm",
    option.None,
    decode.optional(decode_s3_sse_algorithm_enum()),
  )
  use s3_sse_kms_key_id <- decode.optional_field(
    "S3SseKmsKeyId",
    option.None,
    decode.optional(decode.string),
  )
  use start_time <- decode.optional_field(
    "StartTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use table_arn <- decode.optional_field(
    "TableArn",
    option.None,
    decode.optional(decode.string),
  )
  use table_id <- decode.optional_field(
    "TableId",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ExportDescription(
    billed_size_bytes: billed_size_bytes,
    client_token: client_token,
    end_time: end_time,
    export_arn: export_arn,
    export_format: export_format,
    export_manifest: export_manifest,
    export_status: export_status,
    export_time: export_time,
    export_type: export_type,
    failure_code: failure_code,
    failure_message: failure_message,
    incremental_export_specification: incremental_export_specification,
    item_count: item_count,
    s3_bucket: s3_bucket,
    s3_bucket_owner: s3_bucket_owner,
    s3_prefix: s3_prefix,
    s3_sse_algorithm: s3_sse_algorithm,
    s3_sse_kms_key_id: s3_sse_kms_key_id,
    start_time: start_time,
    table_arn: table_arn,
    table_id: table_id,
  ))
}

pub type ExportFormat {
  ExportFormatDynamodbJson
  ExportFormatIon
}

pub fn encode_export_format_enum(v: ExportFormat) -> json.Json {
  case v {
    ExportFormatDynamodbJson -> json.string("DYNAMODB_JSON")
    ExportFormatIon -> json.string("ION")
  }
}

pub fn decode_export_format_enum() -> decode.Decoder(ExportFormat) {
  decode.then(decode.string, fn(s) {
    case s {
      "DYNAMODB_JSON" -> decode.success(ExportFormatDynamodbJson)
      "ION" -> decode.success(ExportFormatIon)
      _ -> decode.failure(ExportFormatDynamodbJson, "unknown enum value")
    }
  })
}

pub type ExportStatus {
  ExportStatusCompleted
  ExportStatusFailed
  ExportStatusInProgress
}

pub fn encode_export_status_enum(v: ExportStatus) -> json.Json {
  case v {
    ExportStatusCompleted -> json.string("COMPLETED")
    ExportStatusFailed -> json.string("FAILED")
    ExportStatusInProgress -> json.string("IN_PROGRESS")
  }
}

pub fn decode_export_status_enum() -> decode.Decoder(ExportStatus) {
  decode.then(decode.string, fn(s) {
    case s {
      "COMPLETED" -> decode.success(ExportStatusCompleted)
      "FAILED" -> decode.success(ExportStatusFailed)
      "IN_PROGRESS" -> decode.success(ExportStatusInProgress)
      _ -> decode.failure(ExportStatusCompleted, "unknown enum value")
    }
  })
}

pub type ExportType {
  ExportTypeFullExport
  ExportTypeIncrementalExport
}

pub fn encode_export_type_enum(v: ExportType) -> json.Json {
  case v {
    ExportTypeFullExport -> json.string("FULL_EXPORT")
    ExportTypeIncrementalExport -> json.string("INCREMENTAL_EXPORT")
  }
}

pub fn decode_export_type_enum() -> decode.Decoder(ExportType) {
  decode.then(decode.string, fn(s) {
    case s {
      "FULL_EXPORT" -> decode.success(ExportTypeFullExport)
      "INCREMENTAL_EXPORT" -> decode.success(ExportTypeIncrementalExport)
      _ -> decode.failure(ExportTypeFullExport, "unknown enum value")
    }
  })
}

pub type IncrementalExportSpecification {
  IncrementalExportSpecification(
    export_from_time: option.Option(json_timestamp.Timestamp),
    export_to_time: option.Option(json_timestamp.Timestamp),
    export_view_type: option.Option(ExportViewType),
  )
}

pub fn incremental_export_specification_default() -> IncrementalExportSpecification {
  IncrementalExportSpecification(
    export_from_time: option.None,
    export_to_time: option.None,
    export_view_type: option.None,
  )
}

pub fn encode_incremental_export_specification_struct(
  input: IncrementalExportSpecification,
) -> json.Json {
  let pairs = []
  let pairs = case input.export_from_time {
    option.Some(v) -> [
      #("ExportFromTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.export_to_time {
    option.Some(v) -> [
      #("ExportToTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.export_view_type {
    option.Some(v) -> [
      #("ExportViewType", encode_export_view_type_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_incremental_export_specification_struct_top(
  input: IncrementalExportSpecification,
) -> json.Json {
  let pairs = []
  let pairs = case input.export_from_time {
    option.Some(v) -> [
      #("ExportFromTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.export_to_time {
    option.Some(v) -> [
      #("ExportToTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.export_view_type {
    option.Some(v) -> [
      #("ExportViewType", encode_export_view_type_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_incremental_export_specification_struct() -> decode.Decoder(
  IncrementalExportSpecification,
) {
  use <- decode.recursive
  use export_from_time <- decode.optional_field(
    "ExportFromTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use export_to_time <- decode.optional_field(
    "ExportToTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use export_view_type <- decode.optional_field(
    "ExportViewType",
    option.None,
    decode.optional(decode_export_view_type_enum()),
  )
  decode.success(IncrementalExportSpecification(
    export_from_time: export_from_time,
    export_to_time: export_to_time,
    export_view_type: export_view_type,
  ))
}

pub type ExportViewType {
  ExportViewTypeNewAndOldImages
  ExportViewTypeNewImage
}

pub fn encode_export_view_type_enum(v: ExportViewType) -> json.Json {
  case v {
    ExportViewTypeNewAndOldImages -> json.string("NEW_AND_OLD_IMAGES")
    ExportViewTypeNewImage -> json.string("NEW_IMAGE")
  }
}

pub fn decode_export_view_type_enum() -> decode.Decoder(ExportViewType) {
  decode.then(decode.string, fn(s) {
    case s {
      "NEW_AND_OLD_IMAGES" -> decode.success(ExportViewTypeNewAndOldImages)
      "NEW_IMAGE" -> decode.success(ExportViewTypeNewImage)
      _ -> decode.failure(ExportViewTypeNewAndOldImages, "unknown enum value")
    }
  })
}

pub type S3SseAlgorithm {
  S3SseAlgorithmAes256
  S3SseAlgorithmKms
}

pub fn encode_s3_sse_algorithm_enum(v: S3SseAlgorithm) -> json.Json {
  case v {
    S3SseAlgorithmAes256 -> json.string("AES256")
    S3SseAlgorithmKms -> json.string("KMS")
  }
}

pub fn decode_s3_sse_algorithm_enum() -> decode.Decoder(S3SseAlgorithm) {
  decode.then(decode.string, fn(s) {
    case s {
      "AES256" -> decode.success(S3SseAlgorithmAes256)
      "KMS" -> decode.success(S3SseAlgorithmKms)
      _ -> decode.failure(S3SseAlgorithmAes256, "unknown enum value")
    }
  })
}

pub type ExportNotFoundException {
  ExportNotFoundException(message: option.Option(String))
}

pub fn export_not_found_exception_default() -> ExportNotFoundException {
  ExportNotFoundException(message: option.None)
}

pub fn encode_export_not_found_exception_struct(
  input: ExportNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_export_not_found_exception_struct_top(
  input: ExportNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_export_not_found_exception_struct() -> decode.Decoder(
  ExportNotFoundException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ExportNotFoundException(message: message))
}

pub type DescribeGlobalTableInput {
  DescribeGlobalTableInput(global_table_name: String)
}

pub fn describe_global_table_input_default(
  global_table_name global_table_name: String,
) -> DescribeGlobalTableInput {
  DescribeGlobalTableInput(global_table_name: global_table_name)
}

pub fn encode_describe_global_table_input_struct(
  input: DescribeGlobalTableInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.global_table_name
    [#("GlobalTableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_describe_global_table_input_struct_top(
  input: DescribeGlobalTableInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.global_table_name
    [#("GlobalTableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_describe_global_table_input_struct() -> decode.Decoder(
  DescribeGlobalTableInput,
) {
  use <- decode.recursive
  use global_table_name <- decode.field("GlobalTableName", decode.string)
  decode.success(DescribeGlobalTableInput(global_table_name: global_table_name))
}

pub type DescribeGlobalTableOutput {
  DescribeGlobalTableOutput(
    global_table_description: option.Option(GlobalTableDescription),
  )
}

pub fn describe_global_table_output_default() -> DescribeGlobalTableOutput {
  DescribeGlobalTableOutput(global_table_description: option.None)
}

pub fn encode_describe_global_table_output_struct(
  input: DescribeGlobalTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_description {
    option.Some(v) -> [
      #("GlobalTableDescription", encode_global_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_describe_global_table_output_struct_top(
  input: DescribeGlobalTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_description {
    option.Some(v) -> [
      #("GlobalTableDescription", encode_global_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_describe_global_table_output_struct() -> decode.Decoder(
  DescribeGlobalTableOutput,
) {
  use <- decode.recursive
  use global_table_description <- decode.optional_field(
    "GlobalTableDescription",
    option.None,
    decode.optional(decode_global_table_description_struct()),
  )
  decode.success(DescribeGlobalTableOutput(
    global_table_description: global_table_description,
  ))
}

pub type GlobalTableNotFoundException {
  GlobalTableNotFoundException(message: option.Option(String))
}

pub fn global_table_not_found_exception_default() -> GlobalTableNotFoundException {
  GlobalTableNotFoundException(message: option.None)
}

pub fn encode_global_table_not_found_exception_struct(
  input: GlobalTableNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_global_table_not_found_exception_struct_top(
  input: GlobalTableNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_global_table_not_found_exception_struct() -> decode.Decoder(
  GlobalTableNotFoundException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(GlobalTableNotFoundException(message: message))
}

pub type DescribeGlobalTableSettingsInput {
  DescribeGlobalTableSettingsInput(global_table_name: String)
}

pub fn describe_global_table_settings_input_default(
  global_table_name global_table_name: String,
) -> DescribeGlobalTableSettingsInput {
  DescribeGlobalTableSettingsInput(global_table_name: global_table_name)
}

pub fn encode_describe_global_table_settings_input_struct(
  input: DescribeGlobalTableSettingsInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.global_table_name
    [#("GlobalTableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_describe_global_table_settings_input_struct_top(
  input: DescribeGlobalTableSettingsInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.global_table_name
    [#("GlobalTableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_describe_global_table_settings_input_struct() -> decode.Decoder(
  DescribeGlobalTableSettingsInput,
) {
  use <- decode.recursive
  use global_table_name <- decode.field("GlobalTableName", decode.string)
  decode.success(DescribeGlobalTableSettingsInput(
    global_table_name: global_table_name,
  ))
}

pub type DescribeGlobalTableSettingsOutput {
  DescribeGlobalTableSettingsOutput(
    global_table_name: option.Option(String),
    replica_settings: option.Option(List(ReplicaSettingsDescription)),
  )
}

pub fn describe_global_table_settings_output_default() -> DescribeGlobalTableSettingsOutput {
  DescribeGlobalTableSettingsOutput(
    global_table_name: option.None,
    replica_settings: option.None,
  )
}

pub fn encode_describe_global_table_settings_output_struct(
  input: DescribeGlobalTableSettingsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_name {
    option.Some(v) -> [#("GlobalTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replica_settings {
    option.Some(v) -> [
      #(
        "ReplicaSettings",
        fn(xs) { json.array(xs, encode_replica_settings_description_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_describe_global_table_settings_output_struct_top(
  input: DescribeGlobalTableSettingsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_name {
    option.Some(v) -> [#("GlobalTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replica_settings {
    option.Some(v) -> [
      #(
        "ReplicaSettings",
        fn(xs) { json.array(xs, encode_replica_settings_description_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_describe_global_table_settings_output_struct() -> decode.Decoder(
  DescribeGlobalTableSettingsOutput,
) {
  use <- decode.recursive
  use global_table_name <- decode.optional_field(
    "GlobalTableName",
    option.None,
    decode.optional(decode.string),
  )
  use replica_settings <- decode.optional_field(
    "ReplicaSettings",
    option.None,
    decode.optional(decode.list(decode_replica_settings_description_struct())),
  )
  decode.success(DescribeGlobalTableSettingsOutput(
    global_table_name: global_table_name,
    replica_settings: replica_settings,
  ))
}

pub type ReplicaSettingsDescription {
  ReplicaSettingsDescription(
    region_name: option.Option(String),
    replica_billing_mode_summary: option.Option(BillingModeSummary),
    replica_global_secondary_index_settings: option.Option(
      List(ReplicaGlobalSecondaryIndexSettingsDescription),
    ),
    replica_provisioned_read_capacity_auto_scaling_settings: option.Option(
      AutoScalingSettingsDescription,
    ),
    replica_provisioned_read_capacity_units: option.Option(Int),
    replica_provisioned_write_capacity_auto_scaling_settings: option.Option(
      AutoScalingSettingsDescription,
    ),
    replica_provisioned_write_capacity_units: option.Option(Int),
    replica_status: option.Option(ReplicaStatus),
    replica_table_class_summary: option.Option(TableClassSummary),
  )
}

pub fn replica_settings_description_default() -> ReplicaSettingsDescription {
  ReplicaSettingsDescription(
    region_name: option.None,
    replica_billing_mode_summary: option.None,
    replica_global_secondary_index_settings: option.None,
    replica_provisioned_read_capacity_auto_scaling_settings: option.None,
    replica_provisioned_read_capacity_units: option.None,
    replica_provisioned_write_capacity_auto_scaling_settings: option.None,
    replica_provisioned_write_capacity_units: option.None,
    replica_status: option.None,
    replica_table_class_summary: option.None,
  )
}

pub fn encode_replica_settings_description_struct(
  input: ReplicaSettingsDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.region_name {
    option.Some(v) -> [#("RegionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replica_billing_mode_summary {
    option.Some(v) -> [
      #("ReplicaBillingModeSummary", encode_billing_mode_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_global_secondary_index_settings {
    option.Some(v) -> [
      #(
        "ReplicaGlobalSecondaryIndexSettings",
        fn(xs) {
          json.array(
            xs,
            encode_replica_global_secondary_index_settings_description_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case
    input.replica_provisioned_read_capacity_auto_scaling_settings
  {
    option.Some(v) -> [
      #(
        "ReplicaProvisionedReadCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_provisioned_read_capacity_units {
    option.Some(v) -> [
      #("ReplicaProvisionedReadCapacityUnits", json.int(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case
    input.replica_provisioned_write_capacity_auto_scaling_settings
  {
    option.Some(v) -> [
      #(
        "ReplicaProvisionedWriteCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_provisioned_write_capacity_units {
    option.Some(v) -> [
      #("ReplicaProvisionedWriteCapacityUnits", json.int(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_status {
    option.Some(v) -> [
      #("ReplicaStatus", encode_replica_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_table_class_summary {
    option.Some(v) -> [
      #("ReplicaTableClassSummary", encode_table_class_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_settings_description_struct_top(
  input: ReplicaSettingsDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.region_name {
    option.Some(v) -> [#("RegionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replica_billing_mode_summary {
    option.Some(v) -> [
      #("ReplicaBillingModeSummary", encode_billing_mode_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_global_secondary_index_settings {
    option.Some(v) -> [
      #(
        "ReplicaGlobalSecondaryIndexSettings",
        fn(xs) {
          json.array(
            xs,
            encode_replica_global_secondary_index_settings_description_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case
    input.replica_provisioned_read_capacity_auto_scaling_settings
  {
    option.Some(v) -> [
      #(
        "ReplicaProvisionedReadCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_provisioned_read_capacity_units {
    option.Some(v) -> [
      #("ReplicaProvisionedReadCapacityUnits", json.int(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case
    input.replica_provisioned_write_capacity_auto_scaling_settings
  {
    option.Some(v) -> [
      #(
        "ReplicaProvisionedWriteCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_provisioned_write_capacity_units {
    option.Some(v) -> [
      #("ReplicaProvisionedWriteCapacityUnits", json.int(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_status {
    option.Some(v) -> [
      #("ReplicaStatus", encode_replica_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_table_class_summary {
    option.Some(v) -> [
      #("ReplicaTableClassSummary", encode_table_class_summary_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_settings_description_struct() -> decode.Decoder(
  ReplicaSettingsDescription,
) {
  use <- decode.recursive
  use region_name <- decode.optional_field(
    "RegionName",
    option.None,
    decode.optional(decode.string),
  )
  use replica_billing_mode_summary <- decode.optional_field(
    "ReplicaBillingModeSummary",
    option.None,
    decode.optional(decode_billing_mode_summary_struct()),
  )
  use replica_global_secondary_index_settings <- decode.optional_field(
    "ReplicaGlobalSecondaryIndexSettings",
    option.None,
    decode.optional(
      decode.list(
        decode_replica_global_secondary_index_settings_description_struct(),
      ),
    ),
  )
  use replica_provisioned_read_capacity_auto_scaling_settings <- decode.optional_field(
    "ReplicaProvisionedReadCapacityAutoScalingSettings",
    option.None,
    decode.optional(decode_auto_scaling_settings_description_struct()),
  )
  use replica_provisioned_read_capacity_units <- decode.optional_field(
    "ReplicaProvisionedReadCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  use replica_provisioned_write_capacity_auto_scaling_settings <- decode.optional_field(
    "ReplicaProvisionedWriteCapacityAutoScalingSettings",
    option.None,
    decode.optional(decode_auto_scaling_settings_description_struct()),
  )
  use replica_provisioned_write_capacity_units <- decode.optional_field(
    "ReplicaProvisionedWriteCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  use replica_status <- decode.optional_field(
    "ReplicaStatus",
    option.None,
    decode.optional(decode_replica_status_enum()),
  )
  use replica_table_class_summary <- decode.optional_field(
    "ReplicaTableClassSummary",
    option.None,
    decode.optional(decode_table_class_summary_struct()),
  )
  decode.success(ReplicaSettingsDescription(
    region_name: region_name,
    replica_billing_mode_summary: replica_billing_mode_summary,
    replica_global_secondary_index_settings: replica_global_secondary_index_settings,
    replica_provisioned_read_capacity_auto_scaling_settings: replica_provisioned_read_capacity_auto_scaling_settings,
    replica_provisioned_read_capacity_units: replica_provisioned_read_capacity_units,
    replica_provisioned_write_capacity_auto_scaling_settings: replica_provisioned_write_capacity_auto_scaling_settings,
    replica_provisioned_write_capacity_units: replica_provisioned_write_capacity_units,
    replica_status: replica_status,
    replica_table_class_summary: replica_table_class_summary,
  ))
}

pub type ReplicaGlobalSecondaryIndexSettingsDescription {
  ReplicaGlobalSecondaryIndexSettingsDescription(
    index_name: option.Option(String),
    index_status: option.Option(IndexStatus),
    provisioned_read_capacity_auto_scaling_settings: option.Option(
      AutoScalingSettingsDescription,
    ),
    provisioned_read_capacity_units: option.Option(Int),
    provisioned_write_capacity_auto_scaling_settings: option.Option(
      AutoScalingSettingsDescription,
    ),
    provisioned_write_capacity_units: option.Option(Int),
  )
}

pub fn replica_global_secondary_index_settings_description_default() -> ReplicaGlobalSecondaryIndexSettingsDescription {
  ReplicaGlobalSecondaryIndexSettingsDescription(
    index_name: option.None,
    index_status: option.None,
    provisioned_read_capacity_auto_scaling_settings: option.None,
    provisioned_read_capacity_units: option.None,
    provisioned_write_capacity_auto_scaling_settings: option.None,
    provisioned_write_capacity_units: option.None,
  )
}

pub fn encode_replica_global_secondary_index_settings_description_struct(
  input: ReplicaGlobalSecondaryIndexSettingsDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_status {
    option.Some(v) -> [#("IndexStatus", encode_index_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_read_capacity_auto_scaling_settings {
    option.Some(v) -> [
      #(
        "ProvisionedReadCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_read_capacity_units {
    option.Some(v) -> [#("ProvisionedReadCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_write_capacity_auto_scaling_settings {
    option.Some(v) -> [
      #(
        "ProvisionedWriteCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_write_capacity_units {
    option.Some(v) -> [#("ProvisionedWriteCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_global_secondary_index_settings_description_struct_top(
  input: ReplicaGlobalSecondaryIndexSettingsDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_status {
    option.Some(v) -> [#("IndexStatus", encode_index_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_read_capacity_auto_scaling_settings {
    option.Some(v) -> [
      #(
        "ProvisionedReadCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_read_capacity_units {
    option.Some(v) -> [#("ProvisionedReadCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_write_capacity_auto_scaling_settings {
    option.Some(v) -> [
      #(
        "ProvisionedWriteCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_write_capacity_units {
    option.Some(v) -> [#("ProvisionedWriteCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_global_secondary_index_settings_description_struct() -> decode.Decoder(
  ReplicaGlobalSecondaryIndexSettingsDescription,
) {
  use <- decode.recursive
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use index_status <- decode.optional_field(
    "IndexStatus",
    option.None,
    decode.optional(decode_index_status_enum()),
  )
  use provisioned_read_capacity_auto_scaling_settings <- decode.optional_field(
    "ProvisionedReadCapacityAutoScalingSettings",
    option.None,
    decode.optional(decode_auto_scaling_settings_description_struct()),
  )
  use provisioned_read_capacity_units <- decode.optional_field(
    "ProvisionedReadCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  use provisioned_write_capacity_auto_scaling_settings <- decode.optional_field(
    "ProvisionedWriteCapacityAutoScalingSettings",
    option.None,
    decode.optional(decode_auto_scaling_settings_description_struct()),
  )
  use provisioned_write_capacity_units <- decode.optional_field(
    "ProvisionedWriteCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(ReplicaGlobalSecondaryIndexSettingsDescription(
    index_name: index_name,
    index_status: index_status,
    provisioned_read_capacity_auto_scaling_settings: provisioned_read_capacity_auto_scaling_settings,
    provisioned_read_capacity_units: provisioned_read_capacity_units,
    provisioned_write_capacity_auto_scaling_settings: provisioned_write_capacity_auto_scaling_settings,
    provisioned_write_capacity_units: provisioned_write_capacity_units,
  ))
}

pub type AutoScalingSettingsDescription {
  AutoScalingSettingsDescription(
    auto_scaling_disabled: option.Option(Bool),
    auto_scaling_role_arn: option.Option(String),
    maximum_units: option.Option(Int),
    minimum_units: option.Option(Int),
    scaling_policies: option.Option(List(AutoScalingPolicyDescription)),
  )
}

pub fn auto_scaling_settings_description_default() -> AutoScalingSettingsDescription {
  AutoScalingSettingsDescription(
    auto_scaling_disabled: option.None,
    auto_scaling_role_arn: option.None,
    maximum_units: option.None,
    minimum_units: option.None,
    scaling_policies: option.None,
  )
}

pub fn encode_auto_scaling_settings_description_struct(
  input: AutoScalingSettingsDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.auto_scaling_disabled {
    option.Some(v) -> [#("AutoScalingDisabled", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.auto_scaling_role_arn {
    option.Some(v) -> [#("AutoScalingRoleArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.maximum_units {
    option.Some(v) -> [#("MaximumUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.minimum_units {
    option.Some(v) -> [#("MinimumUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.scaling_policies {
    option.Some(v) -> [
      #(
        "ScalingPolicies",
        fn(xs) { json.array(xs, encode_auto_scaling_policy_description_struct) }(
          v,
        ),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_auto_scaling_settings_description_struct_top(
  input: AutoScalingSettingsDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.auto_scaling_disabled {
    option.Some(v) -> [#("AutoScalingDisabled", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.auto_scaling_role_arn {
    option.Some(v) -> [#("AutoScalingRoleArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.maximum_units {
    option.Some(v) -> [#("MaximumUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.minimum_units {
    option.Some(v) -> [#("MinimumUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.scaling_policies {
    option.Some(v) -> [
      #(
        "ScalingPolicies",
        fn(xs) { json.array(xs, encode_auto_scaling_policy_description_struct) }(
          v,
        ),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_auto_scaling_settings_description_struct() -> decode.Decoder(
  AutoScalingSettingsDescription,
) {
  use <- decode.recursive
  use auto_scaling_disabled <- decode.optional_field(
    "AutoScalingDisabled",
    option.None,
    decode.optional(decode.bool),
  )
  use auto_scaling_role_arn <- decode.optional_field(
    "AutoScalingRoleArn",
    option.None,
    decode.optional(decode.string),
  )
  use maximum_units <- decode.optional_field(
    "MaximumUnits",
    option.None,
    decode.optional(decode.int),
  )
  use minimum_units <- decode.optional_field(
    "MinimumUnits",
    option.None,
    decode.optional(decode.int),
  )
  use scaling_policies <- decode.optional_field(
    "ScalingPolicies",
    option.None,
    decode.optional(
      decode.list(decode_auto_scaling_policy_description_struct()),
    ),
  )
  decode.success(AutoScalingSettingsDescription(
    auto_scaling_disabled: auto_scaling_disabled,
    auto_scaling_role_arn: auto_scaling_role_arn,
    maximum_units: maximum_units,
    minimum_units: minimum_units,
    scaling_policies: scaling_policies,
  ))
}

pub type AutoScalingPolicyDescription {
  AutoScalingPolicyDescription(
    policy_name: option.Option(String),
    target_tracking_scaling_policy_configuration: option.Option(
      AutoScalingTargetTrackingScalingPolicyConfigurationDescription,
    ),
  )
}

pub fn auto_scaling_policy_description_default() -> AutoScalingPolicyDescription {
  AutoScalingPolicyDescription(
    policy_name: option.None,
    target_tracking_scaling_policy_configuration: option.None,
  )
}

pub fn encode_auto_scaling_policy_description_struct(
  input: AutoScalingPolicyDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.policy_name {
    option.Some(v) -> [#("PolicyName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.target_tracking_scaling_policy_configuration {
    option.Some(v) -> [
      #(
        "TargetTrackingScalingPolicyConfiguration",
        encode_auto_scaling_target_tracking_scaling_policy_configuration_description_struct(
          v,
        ),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_auto_scaling_policy_description_struct_top(
  input: AutoScalingPolicyDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.policy_name {
    option.Some(v) -> [#("PolicyName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.target_tracking_scaling_policy_configuration {
    option.Some(v) -> [
      #(
        "TargetTrackingScalingPolicyConfiguration",
        encode_auto_scaling_target_tracking_scaling_policy_configuration_description_struct(
          v,
        ),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_auto_scaling_policy_description_struct() -> decode.Decoder(
  AutoScalingPolicyDescription,
) {
  use <- decode.recursive
  use policy_name <- decode.optional_field(
    "PolicyName",
    option.None,
    decode.optional(decode.string),
  )
  use target_tracking_scaling_policy_configuration <- decode.optional_field(
    "TargetTrackingScalingPolicyConfiguration",
    option.None,
    decode.optional(
      decode_auto_scaling_target_tracking_scaling_policy_configuration_description_struct(),
    ),
  )
  decode.success(AutoScalingPolicyDescription(
    policy_name: policy_name,
    target_tracking_scaling_policy_configuration: target_tracking_scaling_policy_configuration,
  ))
}

pub type AutoScalingTargetTrackingScalingPolicyConfigurationDescription {
  AutoScalingTargetTrackingScalingPolicyConfigurationDescription(
    disable_scale_in: option.Option(Bool),
    scale_in_cooldown: option.Option(Int),
    scale_out_cooldown: option.Option(Int),
    target_value: option.Option(json_float.SmithyFloat),
  )
}

pub fn auto_scaling_target_tracking_scaling_policy_configuration_description_default() -> AutoScalingTargetTrackingScalingPolicyConfigurationDescription {
  AutoScalingTargetTrackingScalingPolicyConfigurationDescription(
    disable_scale_in: option.None,
    scale_in_cooldown: option.None,
    scale_out_cooldown: option.None,
    target_value: option.None,
  )
}

pub fn encode_auto_scaling_target_tracking_scaling_policy_configuration_description_struct(
  input: AutoScalingTargetTrackingScalingPolicyConfigurationDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.disable_scale_in {
    option.Some(v) -> [#("DisableScaleIn", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.scale_in_cooldown {
    option.Some(v) -> [#("ScaleInCooldown", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.scale_out_cooldown {
    option.Some(v) -> [#("ScaleOutCooldown", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.target_value {
    option.Some(v) -> [#("TargetValue", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_auto_scaling_target_tracking_scaling_policy_configuration_description_struct_top(
  input: AutoScalingTargetTrackingScalingPolicyConfigurationDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.disable_scale_in {
    option.Some(v) -> [#("DisableScaleIn", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.scale_in_cooldown {
    option.Some(v) -> [#("ScaleInCooldown", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.scale_out_cooldown {
    option.Some(v) -> [#("ScaleOutCooldown", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.target_value {
    option.Some(v) -> [#("TargetValue", json_float.encode(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_auto_scaling_target_tracking_scaling_policy_configuration_description_struct() -> decode.Decoder(
  AutoScalingTargetTrackingScalingPolicyConfigurationDescription,
) {
  use <- decode.recursive
  use disable_scale_in <- decode.optional_field(
    "DisableScaleIn",
    option.None,
    decode.optional(decode.bool),
  )
  use scale_in_cooldown <- decode.optional_field(
    "ScaleInCooldown",
    option.None,
    decode.optional(decode.int),
  )
  use scale_out_cooldown <- decode.optional_field(
    "ScaleOutCooldown",
    option.None,
    decode.optional(decode.int),
  )
  use target_value <- decode.optional_field(
    "TargetValue",
    option.None,
    decode.optional(json_float.decoder()),
  )
  decode.success(AutoScalingTargetTrackingScalingPolicyConfigurationDescription(
    disable_scale_in: disable_scale_in,
    scale_in_cooldown: scale_in_cooldown,
    scale_out_cooldown: scale_out_cooldown,
    target_value: target_value,
  ))
}

pub type DescribeImportInput {
  DescribeImportInput(import_arn: String)
}

pub fn describe_import_input_default(
  import_arn import_arn: String,
) -> DescribeImportInput {
  DescribeImportInput(import_arn: import_arn)
}

pub fn encode_describe_import_input_struct(
  input: DescribeImportInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.import_arn
    [#("ImportArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_describe_import_input_struct_top(
  input: DescribeImportInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.import_arn
    [#("ImportArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_describe_import_input_struct() -> decode.Decoder(
  DescribeImportInput,
) {
  use <- decode.recursive
  use import_arn <- decode.field("ImportArn", decode.string)
  decode.success(DescribeImportInput(import_arn: import_arn))
}

pub type DescribeImportOutput {
  DescribeImportOutput(
    import_table_description: option.Option(ImportTableDescription),
  )
}

pub fn describe_import_output_default() -> DescribeImportOutput {
  DescribeImportOutput(import_table_description: option.None)
}

pub fn encode_describe_import_output_struct(
  input: DescribeImportOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.import_table_description {
    option.Some(v) -> [
      #("ImportTableDescription", encode_import_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_describe_import_output_struct_top(
  input: DescribeImportOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.import_table_description {
    option.Some(v) -> [
      #("ImportTableDescription", encode_import_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_describe_import_output_struct() -> decode.Decoder(
  DescribeImportOutput,
) {
  use <- decode.recursive
  use import_table_description <- decode.optional_field(
    "ImportTableDescription",
    option.None,
    decode.optional(decode_import_table_description_struct()),
  )
  decode.success(DescribeImportOutput(
    import_table_description: import_table_description,
  ))
}

pub type ImportTableDescription {
  ImportTableDescription(
    client_token: option.Option(String),
    cloud_watch_log_group_arn: option.Option(String),
    end_time: option.Option(json_timestamp.Timestamp),
    error_count: option.Option(Int),
    failure_code: option.Option(String),
    failure_message: option.Option(String),
    import_arn: option.Option(String),
    import_status: option.Option(ImportStatus),
    imported_item_count: option.Option(Int),
    input_compression_type: option.Option(InputCompressionType),
    input_format: option.Option(InputFormat),
    input_format_options: option.Option(InputFormatOptions),
    processed_item_count: option.Option(Int),
    processed_size_bytes: option.Option(Int),
    s3_bucket_source: option.Option(S3BucketSource),
    start_time: option.Option(json_timestamp.Timestamp),
    table_arn: option.Option(String),
    table_creation_parameters: option.Option(TableCreationParameters),
    table_id: option.Option(String),
  )
}

pub fn import_table_description_default() -> ImportTableDescription {
  ImportTableDescription(
    client_token: option.None,
    cloud_watch_log_group_arn: option.None,
    end_time: option.None,
    error_count: option.None,
    failure_code: option.None,
    failure_message: option.None,
    import_arn: option.None,
    import_status: option.None,
    imported_item_count: option.None,
    input_compression_type: option.None,
    input_format: option.None,
    input_format_options: option.None,
    processed_item_count: option.None,
    processed_size_bytes: option.None,
    s3_bucket_source: option.None,
    start_time: option.None,
    table_arn: option.None,
    table_creation_parameters: option.None,
    table_id: option.None,
  )
}

pub fn encode_import_table_description_struct(
  input: ImportTableDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.client_token {
    option.Some(v) -> [#("ClientToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.cloud_watch_log_group_arn {
    option.Some(v) -> [#("CloudWatchLogGroupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.end_time {
    option.Some(v) -> [
      #("EndTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.error_count {
    option.Some(v) -> [#("ErrorCount", json.int(v)), ..pairs]
    option.None -> [#("ErrorCount", json.int(0)), ..pairs]
  }
  let pairs = case input.failure_code {
    option.Some(v) -> [#("FailureCode", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.failure_message {
    option.Some(v) -> [#("FailureMessage", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.import_arn {
    option.Some(v) -> [#("ImportArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.import_status {
    option.Some(v) -> [#("ImportStatus", encode_import_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.imported_item_count {
    option.Some(v) -> [#("ImportedItemCount", json.int(v)), ..pairs]
    option.None -> [#("ImportedItemCount", json.int(0)), ..pairs]
  }
  let pairs = case input.input_compression_type {
    option.Some(v) -> [
      #("InputCompressionType", encode_input_compression_type_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.input_format {
    option.Some(v) -> [#("InputFormat", encode_input_format_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.input_format_options {
    option.Some(v) -> [
      #("InputFormatOptions", encode_input_format_options_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.processed_item_count {
    option.Some(v) -> [#("ProcessedItemCount", json.int(v)), ..pairs]
    option.None -> [#("ProcessedItemCount", json.int(0)), ..pairs]
  }
  let pairs = case input.processed_size_bytes {
    option.Some(v) -> [#("ProcessedSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_bucket_source {
    option.Some(v) -> [
      #("S3BucketSource", encode_s3_bucket_source_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.start_time {
    option.Some(v) -> [
      #("StartTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_creation_parameters {
    option.Some(v) -> [
      #("TableCreationParameters", encode_table_creation_parameters_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_id {
    option.Some(v) -> [#("TableId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_import_table_description_struct_top(
  input: ImportTableDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.client_token {
    option.Some(v) -> [#("ClientToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.cloud_watch_log_group_arn {
    option.Some(v) -> [#("CloudWatchLogGroupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.end_time {
    option.Some(v) -> [
      #("EndTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.error_count {
    option.Some(v) -> [#("ErrorCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.failure_code {
    option.Some(v) -> [#("FailureCode", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.failure_message {
    option.Some(v) -> [#("FailureMessage", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.import_arn {
    option.Some(v) -> [#("ImportArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.import_status {
    option.Some(v) -> [#("ImportStatus", encode_import_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.imported_item_count {
    option.Some(v) -> [#("ImportedItemCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.input_compression_type {
    option.Some(v) -> [
      #("InputCompressionType", encode_input_compression_type_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.input_format {
    option.Some(v) -> [#("InputFormat", encode_input_format_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.input_format_options {
    option.Some(v) -> [
      #("InputFormatOptions", encode_input_format_options_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.processed_item_count {
    option.Some(v) -> [#("ProcessedItemCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.processed_size_bytes {
    option.Some(v) -> [#("ProcessedSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_bucket_source {
    option.Some(v) -> [
      #("S3BucketSource", encode_s3_bucket_source_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.start_time {
    option.Some(v) -> [
      #("StartTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_creation_parameters {
    option.Some(v) -> [
      #("TableCreationParameters", encode_table_creation_parameters_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_id {
    option.Some(v) -> [#("TableId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_import_table_description_struct() -> decode.Decoder(
  ImportTableDescription,
) {
  use <- decode.recursive
  use client_token <- decode.optional_field(
    "ClientToken",
    option.None,
    decode.optional(decode.string),
  )
  use cloud_watch_log_group_arn <- decode.optional_field(
    "CloudWatchLogGroupArn",
    option.None,
    decode.optional(decode.string),
  )
  use end_time <- decode.optional_field(
    "EndTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use error_count <- decode.optional_field(
    "ErrorCount",
    option.None,
    decode.optional(decode.int),
  )
  use failure_code <- decode.optional_field(
    "FailureCode",
    option.None,
    decode.optional(decode.string),
  )
  use failure_message <- decode.optional_field(
    "FailureMessage",
    option.None,
    decode.optional(decode.string),
  )
  use import_arn <- decode.optional_field(
    "ImportArn",
    option.None,
    decode.optional(decode.string),
  )
  use import_status <- decode.optional_field(
    "ImportStatus",
    option.None,
    decode.optional(decode_import_status_enum()),
  )
  use imported_item_count <- decode.optional_field(
    "ImportedItemCount",
    option.None,
    decode.optional(decode.int),
  )
  use input_compression_type <- decode.optional_field(
    "InputCompressionType",
    option.None,
    decode.optional(decode_input_compression_type_enum()),
  )
  use input_format <- decode.optional_field(
    "InputFormat",
    option.None,
    decode.optional(decode_input_format_enum()),
  )
  use input_format_options <- decode.optional_field(
    "InputFormatOptions",
    option.None,
    decode.optional(decode_input_format_options_struct()),
  )
  use processed_item_count <- decode.optional_field(
    "ProcessedItemCount",
    option.None,
    decode.optional(decode.int),
  )
  use processed_size_bytes <- decode.optional_field(
    "ProcessedSizeBytes",
    option.None,
    decode.optional(decode.int),
  )
  use s3_bucket_source <- decode.optional_field(
    "S3BucketSource",
    option.None,
    decode.optional(decode_s3_bucket_source_struct()),
  )
  use start_time <- decode.optional_field(
    "StartTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use table_arn <- decode.optional_field(
    "TableArn",
    option.None,
    decode.optional(decode.string),
  )
  use table_creation_parameters <- decode.optional_field(
    "TableCreationParameters",
    option.None,
    decode.optional(decode_table_creation_parameters_struct()),
  )
  use table_id <- decode.optional_field(
    "TableId",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ImportTableDescription(
    client_token: client_token,
    cloud_watch_log_group_arn: cloud_watch_log_group_arn,
    end_time: end_time,
    error_count: error_count,
    failure_code: failure_code,
    failure_message: failure_message,
    import_arn: import_arn,
    import_status: import_status,
    imported_item_count: imported_item_count,
    input_compression_type: input_compression_type,
    input_format: input_format,
    input_format_options: input_format_options,
    processed_item_count: processed_item_count,
    processed_size_bytes: processed_size_bytes,
    s3_bucket_source: s3_bucket_source,
    start_time: start_time,
    table_arn: table_arn,
    table_creation_parameters: table_creation_parameters,
    table_id: table_id,
  ))
}

pub type ImportStatus {
  ImportStatusCancelled
  ImportStatusCancelling
  ImportStatusCompleted
  ImportStatusFailed
  ImportStatusInProgress
}

pub fn encode_import_status_enum(v: ImportStatus) -> json.Json {
  case v {
    ImportStatusCancelled -> json.string("CANCELLED")
    ImportStatusCancelling -> json.string("CANCELLING")
    ImportStatusCompleted -> json.string("COMPLETED")
    ImportStatusFailed -> json.string("FAILED")
    ImportStatusInProgress -> json.string("IN_PROGRESS")
  }
}

pub fn decode_import_status_enum() -> decode.Decoder(ImportStatus) {
  decode.then(decode.string, fn(s) {
    case s {
      "CANCELLED" -> decode.success(ImportStatusCancelled)
      "CANCELLING" -> decode.success(ImportStatusCancelling)
      "COMPLETED" -> decode.success(ImportStatusCompleted)
      "FAILED" -> decode.success(ImportStatusFailed)
      "IN_PROGRESS" -> decode.success(ImportStatusInProgress)
      _ -> decode.failure(ImportStatusCancelled, "unknown enum value")
    }
  })
}

pub type InputCompressionType {
  InputCompressionTypeGzip
  InputCompressionTypeNone
  InputCompressionTypeZstd
}

pub fn encode_input_compression_type_enum(
  v: InputCompressionType,
) -> json.Json {
  case v {
    InputCompressionTypeGzip -> json.string("GZIP")
    InputCompressionTypeNone -> json.string("NONE")
    InputCompressionTypeZstd -> json.string("ZSTD")
  }
}

pub fn decode_input_compression_type_enum() -> decode.Decoder(
  InputCompressionType,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "GZIP" -> decode.success(InputCompressionTypeGzip)
      "NONE" -> decode.success(InputCompressionTypeNone)
      "ZSTD" -> decode.success(InputCompressionTypeZstd)
      _ -> decode.failure(InputCompressionTypeGzip, "unknown enum value")
    }
  })
}

pub type InputFormat {
  InputFormatCsv
  InputFormatDynamodbJson
  InputFormatIon
}

pub fn encode_input_format_enum(v: InputFormat) -> json.Json {
  case v {
    InputFormatCsv -> json.string("CSV")
    InputFormatDynamodbJson -> json.string("DYNAMODB_JSON")
    InputFormatIon -> json.string("ION")
  }
}

pub fn decode_input_format_enum() -> decode.Decoder(InputFormat) {
  decode.then(decode.string, fn(s) {
    case s {
      "CSV" -> decode.success(InputFormatCsv)
      "DYNAMODB_JSON" -> decode.success(InputFormatDynamodbJson)
      "ION" -> decode.success(InputFormatIon)
      _ -> decode.failure(InputFormatCsv, "unknown enum value")
    }
  })
}

pub type InputFormatOptions {
  InputFormatOptions(csv: option.Option(CsvOptions))
}

pub fn input_format_options_default() -> InputFormatOptions {
  InputFormatOptions(csv: option.None)
}

pub fn encode_input_format_options_struct(
  input: InputFormatOptions,
) -> json.Json {
  let pairs = []
  let pairs = case input.csv {
    option.Some(v) -> [#("Csv", encode_csv_options_struct(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_input_format_options_struct_top(
  input: InputFormatOptions,
) -> json.Json {
  let pairs = []
  let pairs = case input.csv {
    option.Some(v) -> [#("Csv", encode_csv_options_struct(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_input_format_options_struct() -> decode.Decoder(
  InputFormatOptions,
) {
  use <- decode.recursive
  use csv <- decode.optional_field(
    "Csv",
    option.None,
    decode.optional(decode_csv_options_struct()),
  )
  decode.success(InputFormatOptions(csv: csv))
}

pub type CsvOptions {
  CsvOptions(
    delimiter: option.Option(String),
    header_list: option.Option(List(String)),
  )
}

pub fn csv_options_default() -> CsvOptions {
  CsvOptions(delimiter: option.None, header_list: option.None)
}

pub fn encode_csv_options_struct(input: CsvOptions) -> json.Json {
  let pairs = []
  let pairs = case input.delimiter {
    option.Some(v) -> [#("Delimiter", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.header_list {
    option.Some(v) -> [
      #("HeaderList", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_csv_options_struct_top(input: CsvOptions) -> json.Json {
  let pairs = []
  let pairs = case input.delimiter {
    option.Some(v) -> [#("Delimiter", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.header_list {
    option.Some(v) -> [
      #("HeaderList", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_csv_options_struct() -> decode.Decoder(CsvOptions) {
  use <- decode.recursive
  use delimiter <- decode.optional_field(
    "Delimiter",
    option.None,
    decode.optional(decode.string),
  )
  use header_list <- decode.optional_field(
    "HeaderList",
    option.None,
    decode.optional(decode.list(decode.string)),
  )
  decode.success(CsvOptions(delimiter: delimiter, header_list: header_list))
}

pub type S3BucketSource {
  S3BucketSource(
    s3_bucket: String,
    s3_bucket_owner: option.Option(String),
    s3_key_prefix: option.Option(String),
  )
}

pub fn s3_bucket_source_default(s3_bucket s3_bucket: String) -> S3BucketSource {
  S3BucketSource(
    s3_bucket: s3_bucket,
    s3_bucket_owner: option.None,
    s3_key_prefix: option.None,
  )
}

pub fn encode_s3_bucket_source_struct(input: S3BucketSource) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.s3_bucket
    [#("S3Bucket", json.string(v)), ..pairs]
  }
  let pairs = case input.s3_bucket_owner {
    option.Some(v) -> [#("S3BucketOwner", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_key_prefix {
    option.Some(v) -> [#("S3KeyPrefix", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_s3_bucket_source_struct_top(input: S3BucketSource) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.s3_bucket
    [#("S3Bucket", json.string(v)), ..pairs]
  }
  let pairs = case input.s3_bucket_owner {
    option.Some(v) -> [#("S3BucketOwner", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_key_prefix {
    option.Some(v) -> [#("S3KeyPrefix", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_s3_bucket_source_struct() -> decode.Decoder(S3BucketSource) {
  use <- decode.recursive
  use s3_bucket <- decode.field("S3Bucket", decode.string)
  use s3_bucket_owner <- decode.optional_field(
    "S3BucketOwner",
    option.None,
    decode.optional(decode.string),
  )
  use s3_key_prefix <- decode.optional_field(
    "S3KeyPrefix",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(S3BucketSource(
    s3_bucket: s3_bucket,
    s3_bucket_owner: s3_bucket_owner,
    s3_key_prefix: s3_key_prefix,
  ))
}

pub type TableCreationParameters {
  TableCreationParameters(
    attribute_definitions: List(AttributeDefinition),
    billing_mode: option.Option(BillingMode),
    global_secondary_indexes: option.Option(List(GlobalSecondaryIndex)),
    key_schema: List(KeySchemaElement),
    on_demand_throughput: option.Option(OnDemandThroughput),
    provisioned_throughput: option.Option(ProvisionedThroughput),
    sse_specification: option.Option(SSESpecification),
    table_name: String,
  )
}

pub fn table_creation_parameters_default(
  attribute_definitions attribute_definitions: List(AttributeDefinition),
  key_schema key_schema: List(KeySchemaElement),
  table_name table_name: String,
) -> TableCreationParameters {
  TableCreationParameters(
    attribute_definitions: attribute_definitions,
    billing_mode: option.None,
    global_secondary_indexes: option.None,
    key_schema: key_schema,
    on_demand_throughput: option.None,
    provisioned_throughput: option.None,
    sse_specification: option.None,
    table_name: table_name,
  )
}

pub fn encode_table_creation_parameters_struct(
  input: TableCreationParameters,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.attribute_definitions
    [
      #(
        "AttributeDefinitions",
        fn(xs) { json.array(xs, encode_attribute_definition_struct) }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.billing_mode {
    option.Some(v) -> [#("BillingMode", encode_billing_mode_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_global_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key_schema
    [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.sse_specification {
    option.Some(v) -> [
      #("SSESpecification", encode_sse_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_table_creation_parameters_struct_top(
  input: TableCreationParameters,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.attribute_definitions
    [
      #(
        "AttributeDefinitions",
        fn(xs) { json.array(xs, encode_attribute_definition_struct) }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.billing_mode {
    option.Some(v) -> [#("BillingMode", encode_billing_mode_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_global_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key_schema
    [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.sse_specification {
    option.Some(v) -> [
      #("SSESpecification", encode_sse_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_table_creation_parameters_struct() -> decode.Decoder(
  TableCreationParameters,
) {
  use <- decode.recursive
  use attribute_definitions <- decode.field(
    "AttributeDefinitions",
    decode.list(decode_attribute_definition_struct()),
  )
  use billing_mode <- decode.optional_field(
    "BillingMode",
    option.None,
    decode.optional(decode_billing_mode_enum()),
  )
  use global_secondary_indexes <- decode.optional_field(
    "GlobalSecondaryIndexes",
    option.None,
    decode.optional(decode.list(decode_global_secondary_index_struct())),
  )
  use key_schema <- decode.field(
    "KeySchema",
    decode.list(decode_key_schema_element_struct()),
  )
  use on_demand_throughput <- decode.optional_field(
    "OnDemandThroughput",
    option.None,
    decode.optional(decode_on_demand_throughput_struct()),
  )
  use provisioned_throughput <- decode.optional_field(
    "ProvisionedThroughput",
    option.None,
    decode.optional(decode_provisioned_throughput_struct()),
  )
  use sse_specification <- decode.optional_field(
    "SSESpecification",
    option.None,
    decode.optional(decode_sse_specification_struct()),
  )
  use table_name <- decode.field("TableName", decode.string)
  decode.success(TableCreationParameters(
    attribute_definitions: attribute_definitions,
    billing_mode: billing_mode,
    global_secondary_indexes: global_secondary_indexes,
    key_schema: key_schema,
    on_demand_throughput: on_demand_throughput,
    provisioned_throughput: provisioned_throughput,
    sse_specification: sse_specification,
    table_name: table_name,
  ))
}

pub type ImportNotFoundException {
  ImportNotFoundException(message: option.Option(String))
}

pub fn import_not_found_exception_default() -> ImportNotFoundException {
  ImportNotFoundException(message: option.None)
}

pub fn encode_import_not_found_exception_struct(
  input: ImportNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_import_not_found_exception_struct_top(
  input: ImportNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_import_not_found_exception_struct() -> decode.Decoder(
  ImportNotFoundException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ImportNotFoundException(message: message))
}

pub type DescribeKinesisStreamingDestinationInput {
  DescribeKinesisStreamingDestinationInput(table_name: String)
}

pub fn describe_kinesis_streaming_destination_input_default(
  table_name table_name: String,
) -> DescribeKinesisStreamingDestinationInput {
  DescribeKinesisStreamingDestinationInput(table_name: table_name)
}

pub fn encode_describe_kinesis_streaming_destination_input_struct(
  input: DescribeKinesisStreamingDestinationInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_describe_kinesis_streaming_destination_input_struct_top(
  input: DescribeKinesisStreamingDestinationInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_describe_kinesis_streaming_destination_input_struct() -> decode.Decoder(
  DescribeKinesisStreamingDestinationInput,
) {
  use <- decode.recursive
  use table_name <- decode.field("TableName", decode.string)
  decode.success(DescribeKinesisStreamingDestinationInput(
    table_name: table_name,
  ))
}

pub type DescribeKinesisStreamingDestinationOutput {
  DescribeKinesisStreamingDestinationOutput(
    kinesis_data_stream_destinations: option.Option(
      List(KinesisDataStreamDestination),
    ),
    table_name: option.Option(String),
  )
}

pub fn describe_kinesis_streaming_destination_output_default() -> DescribeKinesisStreamingDestinationOutput {
  DescribeKinesisStreamingDestinationOutput(
    kinesis_data_stream_destinations: option.None,
    table_name: option.None,
  )
}

pub fn encode_describe_kinesis_streaming_destination_output_struct(
  input: DescribeKinesisStreamingDestinationOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.kinesis_data_stream_destinations {
    option.Some(v) -> [
      #(
        "KinesisDataStreamDestinations",
        fn(xs) { json.array(xs, encode_kinesis_data_stream_destination_struct) }(
          v,
        ),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_describe_kinesis_streaming_destination_output_struct_top(
  input: DescribeKinesisStreamingDestinationOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.kinesis_data_stream_destinations {
    option.Some(v) -> [
      #(
        "KinesisDataStreamDestinations",
        fn(xs) { json.array(xs, encode_kinesis_data_stream_destination_struct) }(
          v,
        ),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_describe_kinesis_streaming_destination_output_struct() -> decode.Decoder(
  DescribeKinesisStreamingDestinationOutput,
) {
  use <- decode.recursive
  use kinesis_data_stream_destinations <- decode.optional_field(
    "KinesisDataStreamDestinations",
    option.None,
    decode.optional(
      decode.list(decode_kinesis_data_stream_destination_struct()),
    ),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(DescribeKinesisStreamingDestinationOutput(
    kinesis_data_stream_destinations: kinesis_data_stream_destinations,
    table_name: table_name,
  ))
}

pub type KinesisDataStreamDestination {
  KinesisDataStreamDestination(
    approximate_creation_date_time_precision: option.Option(
      ApproximateCreationDateTimePrecision,
    ),
    destination_status: option.Option(DestinationStatus),
    destination_status_description: option.Option(String),
    stream_arn: option.Option(String),
  )
}

pub fn kinesis_data_stream_destination_default() -> KinesisDataStreamDestination {
  KinesisDataStreamDestination(
    approximate_creation_date_time_precision: option.None,
    destination_status: option.None,
    destination_status_description: option.None,
    stream_arn: option.None,
  )
}

pub fn encode_kinesis_data_stream_destination_struct(
  input: KinesisDataStreamDestination,
) -> json.Json {
  let pairs = []
  let pairs = case input.approximate_creation_date_time_precision {
    option.Some(v) -> [
      #(
        "ApproximateCreationDateTimePrecision",
        encode_approximate_creation_date_time_precision_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.destination_status {
    option.Some(v) -> [
      #("DestinationStatus", encode_destination_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.destination_status_description {
    option.Some(v) -> [
      #("DestinationStatusDescription", json.string(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_arn {
    option.Some(v) -> [#("StreamArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_kinesis_data_stream_destination_struct_top(
  input: KinesisDataStreamDestination,
) -> json.Json {
  let pairs = []
  let pairs = case input.approximate_creation_date_time_precision {
    option.Some(v) -> [
      #(
        "ApproximateCreationDateTimePrecision",
        encode_approximate_creation_date_time_precision_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.destination_status {
    option.Some(v) -> [
      #("DestinationStatus", encode_destination_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.destination_status_description {
    option.Some(v) -> [
      #("DestinationStatusDescription", json.string(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_arn {
    option.Some(v) -> [#("StreamArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_kinesis_data_stream_destination_struct() -> decode.Decoder(
  KinesisDataStreamDestination,
) {
  use <- decode.recursive
  use approximate_creation_date_time_precision <- decode.optional_field(
    "ApproximateCreationDateTimePrecision",
    option.None,
    decode.optional(decode_approximate_creation_date_time_precision_enum()),
  )
  use destination_status <- decode.optional_field(
    "DestinationStatus",
    option.None,
    decode.optional(decode_destination_status_enum()),
  )
  use destination_status_description <- decode.optional_field(
    "DestinationStatusDescription",
    option.None,
    decode.optional(decode.string),
  )
  use stream_arn <- decode.optional_field(
    "StreamArn",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(KinesisDataStreamDestination(
    approximate_creation_date_time_precision: approximate_creation_date_time_precision,
    destination_status: destination_status,
    destination_status_description: destination_status_description,
    stream_arn: stream_arn,
  ))
}

pub type ApproximateCreationDateTimePrecision {
  ApproximateCreationDateTimePrecisionMicrosecond
  ApproximateCreationDateTimePrecisionMillisecond
}

pub fn encode_approximate_creation_date_time_precision_enum(
  v: ApproximateCreationDateTimePrecision,
) -> json.Json {
  case v {
    ApproximateCreationDateTimePrecisionMicrosecond ->
      json.string("MICROSECOND")
    ApproximateCreationDateTimePrecisionMillisecond ->
      json.string("MILLISECOND")
  }
}

pub fn decode_approximate_creation_date_time_precision_enum() -> decode.Decoder(
  ApproximateCreationDateTimePrecision,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "MICROSECOND" ->
        decode.success(ApproximateCreationDateTimePrecisionMicrosecond)
      "MILLISECOND" ->
        decode.success(ApproximateCreationDateTimePrecisionMillisecond)
      _ ->
        decode.failure(
          ApproximateCreationDateTimePrecisionMicrosecond,
          "unknown enum value",
        )
    }
  })
}

pub type DestinationStatus {
  DestinationStatusActive
  DestinationStatusDisabled
  DestinationStatusDisabling
  DestinationStatusEnableFailed
  DestinationStatusEnabling
  DestinationStatusUpdating
}

pub fn encode_destination_status_enum(v: DestinationStatus) -> json.Json {
  case v {
    DestinationStatusActive -> json.string("ACTIVE")
    DestinationStatusDisabled -> json.string("DISABLED")
    DestinationStatusDisabling -> json.string("DISABLING")
    DestinationStatusEnableFailed -> json.string("ENABLE_FAILED")
    DestinationStatusEnabling -> json.string("ENABLING")
    DestinationStatusUpdating -> json.string("UPDATING")
  }
}

pub fn decode_destination_status_enum() -> decode.Decoder(DestinationStatus) {
  decode.then(decode.string, fn(s) {
    case s {
      "ACTIVE" -> decode.success(DestinationStatusActive)
      "DISABLED" -> decode.success(DestinationStatusDisabled)
      "DISABLING" -> decode.success(DestinationStatusDisabling)
      "ENABLE_FAILED" -> decode.success(DestinationStatusEnableFailed)
      "ENABLING" -> decode.success(DestinationStatusEnabling)
      "UPDATING" -> decode.success(DestinationStatusUpdating)
      _ -> decode.failure(DestinationStatusActive, "unknown enum value")
    }
  })
}

pub type DescribeLimitsInput {
  DescribeLimitsInput
}

pub fn describe_limits_input_default() -> DescribeLimitsInput {
  DescribeLimitsInput
}

pub fn encode_describe_limits_input_struct(
  _v: DescribeLimitsInput,
) -> json.Json {
  json.object([])
}

pub fn encode_describe_limits_input_struct_top(
  _v: DescribeLimitsInput,
) -> json.Json {
  json.object([])
}

pub fn decode_describe_limits_input_struct() -> decode.Decoder(
  DescribeLimitsInput,
) {
  decode.success(DescribeLimitsInput)
}

pub type DescribeLimitsOutput {
  DescribeLimitsOutput(
    account_max_read_capacity_units: option.Option(Int),
    account_max_write_capacity_units: option.Option(Int),
    table_max_read_capacity_units: option.Option(Int),
    table_max_write_capacity_units: option.Option(Int),
  )
}

pub fn describe_limits_output_default() -> DescribeLimitsOutput {
  DescribeLimitsOutput(
    account_max_read_capacity_units: option.None,
    account_max_write_capacity_units: option.None,
    table_max_read_capacity_units: option.None,
    table_max_write_capacity_units: option.None,
  )
}

pub fn encode_describe_limits_output_struct(
  input: DescribeLimitsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.account_max_read_capacity_units {
    option.Some(v) -> [#("AccountMaxReadCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.account_max_write_capacity_units {
    option.Some(v) -> [#("AccountMaxWriteCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_max_read_capacity_units {
    option.Some(v) -> [#("TableMaxReadCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_max_write_capacity_units {
    option.Some(v) -> [#("TableMaxWriteCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_describe_limits_output_struct_top(
  input: DescribeLimitsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.account_max_read_capacity_units {
    option.Some(v) -> [#("AccountMaxReadCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.account_max_write_capacity_units {
    option.Some(v) -> [#("AccountMaxWriteCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_max_read_capacity_units {
    option.Some(v) -> [#("TableMaxReadCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_max_write_capacity_units {
    option.Some(v) -> [#("TableMaxWriteCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_describe_limits_output_struct() -> decode.Decoder(
  DescribeLimitsOutput,
) {
  use <- decode.recursive
  use account_max_read_capacity_units <- decode.optional_field(
    "AccountMaxReadCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  use account_max_write_capacity_units <- decode.optional_field(
    "AccountMaxWriteCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  use table_max_read_capacity_units <- decode.optional_field(
    "TableMaxReadCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  use table_max_write_capacity_units <- decode.optional_field(
    "TableMaxWriteCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(DescribeLimitsOutput(
    account_max_read_capacity_units: account_max_read_capacity_units,
    account_max_write_capacity_units: account_max_write_capacity_units,
    table_max_read_capacity_units: table_max_read_capacity_units,
    table_max_write_capacity_units: table_max_write_capacity_units,
  ))
}

pub type DescribeTableInput {
  DescribeTableInput(table_name: String)
}

pub fn describe_table_input_default(
  table_name table_name: String,
) -> DescribeTableInput {
  DescribeTableInput(table_name: table_name)
}

pub fn encode_describe_table_input_struct(
  input: DescribeTableInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_describe_table_input_struct_top(
  input: DescribeTableInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_describe_table_input_struct() -> decode.Decoder(
  DescribeTableInput,
) {
  use <- decode.recursive
  use table_name <- decode.field("TableName", decode.string)
  decode.success(DescribeTableInput(table_name: table_name))
}

pub type DescribeTableOutput {
  DescribeTableOutput(table: option.Option(TableDescription))
}

pub fn describe_table_output_default() -> DescribeTableOutput {
  DescribeTableOutput(table: option.None)
}

pub fn encode_describe_table_output_struct(
  input: DescribeTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table {
    option.Some(v) -> [#("Table", encode_table_description_struct(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_describe_table_output_struct_top(
  input: DescribeTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table {
    option.Some(v) -> [#("Table", encode_table_description_struct(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_describe_table_output_struct() -> decode.Decoder(
  DescribeTableOutput,
) {
  use <- decode.recursive
  use table <- decode.optional_field(
    "Table",
    option.None,
    decode.optional(decode_table_description_struct()),
  )
  decode.success(DescribeTableOutput(table: table))
}

pub type DescribeTableReplicaAutoScalingInput {
  DescribeTableReplicaAutoScalingInput(table_name: String)
}

pub fn describe_table_replica_auto_scaling_input_default(
  table_name table_name: String,
) -> DescribeTableReplicaAutoScalingInput {
  DescribeTableReplicaAutoScalingInput(table_name: table_name)
}

pub fn encode_describe_table_replica_auto_scaling_input_struct(
  input: DescribeTableReplicaAutoScalingInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_describe_table_replica_auto_scaling_input_struct_top(
  input: DescribeTableReplicaAutoScalingInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_describe_table_replica_auto_scaling_input_struct() -> decode.Decoder(
  DescribeTableReplicaAutoScalingInput,
) {
  use <- decode.recursive
  use table_name <- decode.field("TableName", decode.string)
  decode.success(DescribeTableReplicaAutoScalingInput(table_name: table_name))
}

pub type DescribeTableReplicaAutoScalingOutput {
  DescribeTableReplicaAutoScalingOutput(
    table_auto_scaling_description: option.Option(TableAutoScalingDescription),
  )
}

pub fn describe_table_replica_auto_scaling_output_default() -> DescribeTableReplicaAutoScalingOutput {
  DescribeTableReplicaAutoScalingOutput(
    table_auto_scaling_description: option.None,
  )
}

pub fn encode_describe_table_replica_auto_scaling_output_struct(
  input: DescribeTableReplicaAutoScalingOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_auto_scaling_description {
    option.Some(v) -> [
      #(
        "TableAutoScalingDescription",
        encode_table_auto_scaling_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_describe_table_replica_auto_scaling_output_struct_top(
  input: DescribeTableReplicaAutoScalingOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_auto_scaling_description {
    option.Some(v) -> [
      #(
        "TableAutoScalingDescription",
        encode_table_auto_scaling_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_describe_table_replica_auto_scaling_output_struct() -> decode.Decoder(
  DescribeTableReplicaAutoScalingOutput,
) {
  use <- decode.recursive
  use table_auto_scaling_description <- decode.optional_field(
    "TableAutoScalingDescription",
    option.None,
    decode.optional(decode_table_auto_scaling_description_struct()),
  )
  decode.success(DescribeTableReplicaAutoScalingOutput(
    table_auto_scaling_description: table_auto_scaling_description,
  ))
}

pub type TableAutoScalingDescription {
  TableAutoScalingDescription(
    replicas: option.Option(List(ReplicaAutoScalingDescription)),
    table_name: option.Option(String),
    table_status: option.Option(TableStatus),
  )
}

pub fn table_auto_scaling_description_default() -> TableAutoScalingDescription {
  TableAutoScalingDescription(
    replicas: option.None,
    table_name: option.None,
    table_status: option.None,
  )
}

pub fn encode_table_auto_scaling_description_struct(
  input: TableAutoScalingDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.replicas {
    option.Some(v) -> [
      #(
        "Replicas",
        fn(xs) {
          json.array(xs, encode_replica_auto_scaling_description_struct)
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_status {
    option.Some(v) -> [#("TableStatus", encode_table_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_table_auto_scaling_description_struct_top(
  input: TableAutoScalingDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.replicas {
    option.Some(v) -> [
      #(
        "Replicas",
        fn(xs) {
          json.array(xs, encode_replica_auto_scaling_description_struct)
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_status {
    option.Some(v) -> [#("TableStatus", encode_table_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_table_auto_scaling_description_struct() -> decode.Decoder(
  TableAutoScalingDescription,
) {
  use <- decode.recursive
  use replicas <- decode.optional_field(
    "Replicas",
    option.None,
    decode.optional(
      decode.list(decode_replica_auto_scaling_description_struct()),
    ),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  use table_status <- decode.optional_field(
    "TableStatus",
    option.None,
    decode.optional(decode_table_status_enum()),
  )
  decode.success(TableAutoScalingDescription(
    replicas: replicas,
    table_name: table_name,
    table_status: table_status,
  ))
}

pub type ReplicaAutoScalingDescription {
  ReplicaAutoScalingDescription(
    global_secondary_indexes: option.Option(
      List(ReplicaGlobalSecondaryIndexAutoScalingDescription),
    ),
    region_name: option.Option(String),
    replica_provisioned_read_capacity_auto_scaling_settings: option.Option(
      AutoScalingSettingsDescription,
    ),
    replica_provisioned_write_capacity_auto_scaling_settings: option.Option(
      AutoScalingSettingsDescription,
    ),
    replica_status: option.Option(ReplicaStatus),
  )
}

pub fn replica_auto_scaling_description_default() -> ReplicaAutoScalingDescription {
  ReplicaAutoScalingDescription(
    global_secondary_indexes: option.None,
    region_name: option.None,
    replica_provisioned_read_capacity_auto_scaling_settings: option.None,
    replica_provisioned_write_capacity_auto_scaling_settings: option.None,
    replica_status: option.None,
  )
}

pub fn encode_replica_auto_scaling_description_struct(
  input: ReplicaAutoScalingDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) {
          json.array(
            xs,
            encode_replica_global_secondary_index_auto_scaling_description_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.region_name {
    option.Some(v) -> [#("RegionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case
    input.replica_provisioned_read_capacity_auto_scaling_settings
  {
    option.Some(v) -> [
      #(
        "ReplicaProvisionedReadCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case
    input.replica_provisioned_write_capacity_auto_scaling_settings
  {
    option.Some(v) -> [
      #(
        "ReplicaProvisionedWriteCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_status {
    option.Some(v) -> [
      #("ReplicaStatus", encode_replica_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_auto_scaling_description_struct_top(
  input: ReplicaAutoScalingDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) {
          json.array(
            xs,
            encode_replica_global_secondary_index_auto_scaling_description_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.region_name {
    option.Some(v) -> [#("RegionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case
    input.replica_provisioned_read_capacity_auto_scaling_settings
  {
    option.Some(v) -> [
      #(
        "ReplicaProvisionedReadCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case
    input.replica_provisioned_write_capacity_auto_scaling_settings
  {
    option.Some(v) -> [
      #(
        "ReplicaProvisionedWriteCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_status {
    option.Some(v) -> [
      #("ReplicaStatus", encode_replica_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_auto_scaling_description_struct() -> decode.Decoder(
  ReplicaAutoScalingDescription,
) {
  use <- decode.recursive
  use global_secondary_indexes <- decode.optional_field(
    "GlobalSecondaryIndexes",
    option.None,
    decode.optional(
      decode.list(
        decode_replica_global_secondary_index_auto_scaling_description_struct(),
      ),
    ),
  )
  use region_name <- decode.optional_field(
    "RegionName",
    option.None,
    decode.optional(decode.string),
  )
  use replica_provisioned_read_capacity_auto_scaling_settings <- decode.optional_field(
    "ReplicaProvisionedReadCapacityAutoScalingSettings",
    option.None,
    decode.optional(decode_auto_scaling_settings_description_struct()),
  )
  use replica_provisioned_write_capacity_auto_scaling_settings <- decode.optional_field(
    "ReplicaProvisionedWriteCapacityAutoScalingSettings",
    option.None,
    decode.optional(decode_auto_scaling_settings_description_struct()),
  )
  use replica_status <- decode.optional_field(
    "ReplicaStatus",
    option.None,
    decode.optional(decode_replica_status_enum()),
  )
  decode.success(ReplicaAutoScalingDescription(
    global_secondary_indexes: global_secondary_indexes,
    region_name: region_name,
    replica_provisioned_read_capacity_auto_scaling_settings: replica_provisioned_read_capacity_auto_scaling_settings,
    replica_provisioned_write_capacity_auto_scaling_settings: replica_provisioned_write_capacity_auto_scaling_settings,
    replica_status: replica_status,
  ))
}

pub type ReplicaGlobalSecondaryIndexAutoScalingDescription {
  ReplicaGlobalSecondaryIndexAutoScalingDescription(
    index_name: option.Option(String),
    index_status: option.Option(IndexStatus),
    provisioned_read_capacity_auto_scaling_settings: option.Option(
      AutoScalingSettingsDescription,
    ),
    provisioned_write_capacity_auto_scaling_settings: option.Option(
      AutoScalingSettingsDescription,
    ),
  )
}

pub fn replica_global_secondary_index_auto_scaling_description_default() -> ReplicaGlobalSecondaryIndexAutoScalingDescription {
  ReplicaGlobalSecondaryIndexAutoScalingDescription(
    index_name: option.None,
    index_status: option.None,
    provisioned_read_capacity_auto_scaling_settings: option.None,
    provisioned_write_capacity_auto_scaling_settings: option.None,
  )
}

pub fn encode_replica_global_secondary_index_auto_scaling_description_struct(
  input: ReplicaGlobalSecondaryIndexAutoScalingDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_status {
    option.Some(v) -> [#("IndexStatus", encode_index_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_read_capacity_auto_scaling_settings {
    option.Some(v) -> [
      #(
        "ProvisionedReadCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_write_capacity_auto_scaling_settings {
    option.Some(v) -> [
      #(
        "ProvisionedWriteCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_global_secondary_index_auto_scaling_description_struct_top(
  input: ReplicaGlobalSecondaryIndexAutoScalingDescription,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_status {
    option.Some(v) -> [#("IndexStatus", encode_index_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_read_capacity_auto_scaling_settings {
    option.Some(v) -> [
      #(
        "ProvisionedReadCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_write_capacity_auto_scaling_settings {
    option.Some(v) -> [
      #(
        "ProvisionedWriteCapacityAutoScalingSettings",
        encode_auto_scaling_settings_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_global_secondary_index_auto_scaling_description_struct() -> decode.Decoder(
  ReplicaGlobalSecondaryIndexAutoScalingDescription,
) {
  use <- decode.recursive
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use index_status <- decode.optional_field(
    "IndexStatus",
    option.None,
    decode.optional(decode_index_status_enum()),
  )
  use provisioned_read_capacity_auto_scaling_settings <- decode.optional_field(
    "ProvisionedReadCapacityAutoScalingSettings",
    option.None,
    decode.optional(decode_auto_scaling_settings_description_struct()),
  )
  use provisioned_write_capacity_auto_scaling_settings <- decode.optional_field(
    "ProvisionedWriteCapacityAutoScalingSettings",
    option.None,
    decode.optional(decode_auto_scaling_settings_description_struct()),
  )
  decode.success(ReplicaGlobalSecondaryIndexAutoScalingDescription(
    index_name: index_name,
    index_status: index_status,
    provisioned_read_capacity_auto_scaling_settings: provisioned_read_capacity_auto_scaling_settings,
    provisioned_write_capacity_auto_scaling_settings: provisioned_write_capacity_auto_scaling_settings,
  ))
}

pub type DescribeTimeToLiveInput {
  DescribeTimeToLiveInput(table_name: String)
}

pub fn describe_time_to_live_input_default(
  table_name table_name: String,
) -> DescribeTimeToLiveInput {
  DescribeTimeToLiveInput(table_name: table_name)
}

pub fn encode_describe_time_to_live_input_struct(
  input: DescribeTimeToLiveInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_describe_time_to_live_input_struct_top(
  input: DescribeTimeToLiveInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_describe_time_to_live_input_struct() -> decode.Decoder(
  DescribeTimeToLiveInput,
) {
  use <- decode.recursive
  use table_name <- decode.field("TableName", decode.string)
  decode.success(DescribeTimeToLiveInput(table_name: table_name))
}

pub type DescribeTimeToLiveOutput {
  DescribeTimeToLiveOutput(
    time_to_live_description: option.Option(TimeToLiveDescription),
  )
}

pub fn describe_time_to_live_output_default() -> DescribeTimeToLiveOutput {
  DescribeTimeToLiveOutput(time_to_live_description: option.None)
}

pub fn encode_describe_time_to_live_output_struct(
  input: DescribeTimeToLiveOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.time_to_live_description {
    option.Some(v) -> [
      #("TimeToLiveDescription", encode_time_to_live_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_describe_time_to_live_output_struct_top(
  input: DescribeTimeToLiveOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.time_to_live_description {
    option.Some(v) -> [
      #("TimeToLiveDescription", encode_time_to_live_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_describe_time_to_live_output_struct() -> decode.Decoder(
  DescribeTimeToLiveOutput,
) {
  use <- decode.recursive
  use time_to_live_description <- decode.optional_field(
    "TimeToLiveDescription",
    option.None,
    decode.optional(decode_time_to_live_description_struct()),
  )
  decode.success(DescribeTimeToLiveOutput(
    time_to_live_description: time_to_live_description,
  ))
}

pub type KinesisStreamingDestinationInput {
  KinesisStreamingDestinationInput(
    enable_kinesis_streaming_configuration: option.Option(
      EnableKinesisStreamingConfiguration,
    ),
    stream_arn: String,
    table_name: String,
  )
}

pub fn kinesis_streaming_destination_input_default(
  stream_arn stream_arn: String,
  table_name table_name: String,
) -> KinesisStreamingDestinationInput {
  KinesisStreamingDestinationInput(
    enable_kinesis_streaming_configuration: option.None,
    stream_arn: stream_arn,
    table_name: table_name,
  )
}

pub fn encode_kinesis_streaming_destination_input_struct(
  input: KinesisStreamingDestinationInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.enable_kinesis_streaming_configuration {
    option.Some(v) -> [
      #(
        "EnableKinesisStreamingConfiguration",
        encode_enable_kinesis_streaming_configuration_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.stream_arn
    [#("StreamArn", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_kinesis_streaming_destination_input_struct_top(
  input: KinesisStreamingDestinationInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.enable_kinesis_streaming_configuration {
    option.Some(v) -> [
      #(
        "EnableKinesisStreamingConfiguration",
        encode_enable_kinesis_streaming_configuration_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.stream_arn
    [#("StreamArn", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_kinesis_streaming_destination_input_struct() -> decode.Decoder(
  KinesisStreamingDestinationInput,
) {
  use <- decode.recursive
  use enable_kinesis_streaming_configuration <- decode.optional_field(
    "EnableKinesisStreamingConfiguration",
    option.None,
    decode.optional(decode_enable_kinesis_streaming_configuration_struct()),
  )
  use stream_arn <- decode.field("StreamArn", decode.string)
  use table_name <- decode.field("TableName", decode.string)
  decode.success(KinesisStreamingDestinationInput(
    enable_kinesis_streaming_configuration: enable_kinesis_streaming_configuration,
    stream_arn: stream_arn,
    table_name: table_name,
  ))
}

pub type EnableKinesisStreamingConfiguration {
  EnableKinesisStreamingConfiguration(
    approximate_creation_date_time_precision: option.Option(
      ApproximateCreationDateTimePrecision,
    ),
  )
}

pub fn enable_kinesis_streaming_configuration_default() -> EnableKinesisStreamingConfiguration {
  EnableKinesisStreamingConfiguration(
    approximate_creation_date_time_precision: option.None,
  )
}

pub fn encode_enable_kinesis_streaming_configuration_struct(
  input: EnableKinesisStreamingConfiguration,
) -> json.Json {
  let pairs = []
  let pairs = case input.approximate_creation_date_time_precision {
    option.Some(v) -> [
      #(
        "ApproximateCreationDateTimePrecision",
        encode_approximate_creation_date_time_precision_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_enable_kinesis_streaming_configuration_struct_top(
  input: EnableKinesisStreamingConfiguration,
) -> json.Json {
  let pairs = []
  let pairs = case input.approximate_creation_date_time_precision {
    option.Some(v) -> [
      #(
        "ApproximateCreationDateTimePrecision",
        encode_approximate_creation_date_time_precision_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_enable_kinesis_streaming_configuration_struct() -> decode.Decoder(
  EnableKinesisStreamingConfiguration,
) {
  use <- decode.recursive
  use approximate_creation_date_time_precision <- decode.optional_field(
    "ApproximateCreationDateTimePrecision",
    option.None,
    decode.optional(decode_approximate_creation_date_time_precision_enum()),
  )
  decode.success(EnableKinesisStreamingConfiguration(
    approximate_creation_date_time_precision: approximate_creation_date_time_precision,
  ))
}

pub type KinesisStreamingDestinationOutput {
  KinesisStreamingDestinationOutput(
    destination_status: option.Option(DestinationStatus),
    enable_kinesis_streaming_configuration: option.Option(
      EnableKinesisStreamingConfiguration,
    ),
    stream_arn: option.Option(String),
    table_name: option.Option(String),
  )
}

pub fn kinesis_streaming_destination_output_default() -> KinesisStreamingDestinationOutput {
  KinesisStreamingDestinationOutput(
    destination_status: option.None,
    enable_kinesis_streaming_configuration: option.None,
    stream_arn: option.None,
    table_name: option.None,
  )
}

pub fn encode_kinesis_streaming_destination_output_struct(
  input: KinesisStreamingDestinationOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.destination_status {
    option.Some(v) -> [
      #("DestinationStatus", encode_destination_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.enable_kinesis_streaming_configuration {
    option.Some(v) -> [
      #(
        "EnableKinesisStreamingConfiguration",
        encode_enable_kinesis_streaming_configuration_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_arn {
    option.Some(v) -> [#("StreamArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_kinesis_streaming_destination_output_struct_top(
  input: KinesisStreamingDestinationOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.destination_status {
    option.Some(v) -> [
      #("DestinationStatus", encode_destination_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.enable_kinesis_streaming_configuration {
    option.Some(v) -> [
      #(
        "EnableKinesisStreamingConfiguration",
        encode_enable_kinesis_streaming_configuration_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_arn {
    option.Some(v) -> [#("StreamArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_kinesis_streaming_destination_output_struct() -> decode.Decoder(
  KinesisStreamingDestinationOutput,
) {
  use <- decode.recursive
  use destination_status <- decode.optional_field(
    "DestinationStatus",
    option.None,
    decode.optional(decode_destination_status_enum()),
  )
  use enable_kinesis_streaming_configuration <- decode.optional_field(
    "EnableKinesisStreamingConfiguration",
    option.None,
    decode.optional(decode_enable_kinesis_streaming_configuration_struct()),
  )
  use stream_arn <- decode.optional_field(
    "StreamArn",
    option.None,
    decode.optional(decode.string),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(KinesisStreamingDestinationOutput(
    destination_status: destination_status,
    enable_kinesis_streaming_configuration: enable_kinesis_streaming_configuration,
    stream_arn: stream_arn,
    table_name: table_name,
  ))
}

pub type ExecuteStatementInput {
  ExecuteStatementInput(
    consistent_read: option.Option(Bool),
    limit: option.Option(Int),
    next_token: option.Option(String),
    parameters: option.Option(List(AttributeValue)),
    return_consumed_capacity: option.Option(ReturnConsumedCapacity),
    return_values_on_condition_check_failure: option.Option(
      ReturnValuesOnConditionCheckFailure,
    ),
    statement: String,
  )
}

pub fn execute_statement_input_default(
  statement statement: String,
) -> ExecuteStatementInput {
  ExecuteStatementInput(
    consistent_read: option.None,
    limit: option.None,
    next_token: option.None,
    parameters: option.None,
    return_consumed_capacity: option.None,
    return_values_on_condition_check_failure: option.None,
    statement: statement,
  )
}

pub fn encode_execute_statement_input_struct(
  input: ExecuteStatementInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consistent_read {
    option.Some(v) -> [#("ConsistentRead", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.limit {
    option.Some(v) -> [#("Limit", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.parameters {
    option.Some(v) -> [
      #(
        "Parameters",
        fn(xs) { json.array(xs, encode_attribute_value_union) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.statement
    [#("Statement", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_execute_statement_input_struct_top(
  input: ExecuteStatementInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consistent_read {
    option.Some(v) -> [#("ConsistentRead", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.limit {
    option.Some(v) -> [#("Limit", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.parameters {
    option.Some(v) -> [
      #(
        "Parameters",
        fn(xs) { json.array(xs, encode_attribute_value_union) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.statement
    [#("Statement", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_execute_statement_input_struct() -> decode.Decoder(
  ExecuteStatementInput,
) {
  use <- decode.recursive
  use consistent_read <- decode.optional_field(
    "ConsistentRead",
    option.None,
    decode.optional(decode.bool),
  )
  use limit <- decode.optional_field(
    "Limit",
    option.None,
    decode.optional(decode.int),
  )
  use next_token <- decode.optional_field(
    "NextToken",
    option.None,
    decode.optional(decode.string),
  )
  use parameters <- decode.optional_field(
    "Parameters",
    option.None,
    decode.optional(decode.list(decode_attribute_value_union())),
  )
  use return_consumed_capacity <- decode.optional_field(
    "ReturnConsumedCapacity",
    option.None,
    decode.optional(decode_return_consumed_capacity_enum()),
  )
  use return_values_on_condition_check_failure <- decode.optional_field(
    "ReturnValuesOnConditionCheckFailure",
    option.None,
    decode.optional(decode_return_values_on_condition_check_failure_enum()),
  )
  use statement <- decode.field("Statement", decode.string)
  decode.success(ExecuteStatementInput(
    consistent_read: consistent_read,
    limit: limit,
    next_token: next_token,
    parameters: parameters,
    return_consumed_capacity: return_consumed_capacity,
    return_values_on_condition_check_failure: return_values_on_condition_check_failure,
    statement: statement,
  ))
}

pub type ExecuteStatementOutput {
  ExecuteStatementOutput(
    consumed_capacity: option.Option(ConsumedCapacity),
    items: option.Option(List(dict.Dict(String, AttributeValue))),
    last_evaluated_key: option.Option(dict.Dict(String, AttributeValue)),
    next_token: option.Option(String),
  )
}

pub fn execute_statement_output_default() -> ExecuteStatementOutput {
  ExecuteStatementOutput(
    consumed_capacity: option.None,
    items: option.None,
    last_evaluated_key: option.None,
    next_token: option.None,
  )
}

pub fn encode_execute_statement_output_struct(
  input: ExecuteStatementOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.items {
    option.Some(v) -> [
      #(
        "Items",
        fn(xs) {
          json.array(xs, fn(d) {
            json.object(
              dict.to_list(d)
              |> list.map(fn(pair) {
                #(pair.0, encode_attribute_value_union(pair.1))
              }),
            )
          })
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.last_evaluated_key {
    option.Some(v) -> [
      #(
        "LastEvaluatedKey",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_execute_statement_output_struct_top(
  input: ExecuteStatementOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.items {
    option.Some(v) -> [
      #(
        "Items",
        fn(xs) {
          json.array(xs, fn(d) {
            json.object(
              dict.to_list(d)
              |> list.map(fn(pair) {
                #(pair.0, encode_attribute_value_union(pair.1))
              }),
            )
          })
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.last_evaluated_key {
    option.Some(v) -> [
      #(
        "LastEvaluatedKey",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_execute_statement_output_struct() -> decode.Decoder(
  ExecuteStatementOutput,
) {
  use <- decode.recursive
  use consumed_capacity <- decode.optional_field(
    "ConsumedCapacity",
    option.None,
    decode.optional(decode_consumed_capacity_struct()),
  )
  use items <- decode.optional_field(
    "Items",
    option.None,
    decode.optional(
      decode.list(decode.dict(decode.string, decode_attribute_value_union())),
    ),
  )
  use last_evaluated_key <- decode.optional_field(
    "LastEvaluatedKey",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use next_token <- decode.optional_field(
    "NextToken",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ExecuteStatementOutput(
    consumed_capacity: consumed_capacity,
    items: items,
    last_evaluated_key: last_evaluated_key,
    next_token: next_token,
  ))
}

pub type DuplicateItemException {
  DuplicateItemException(message: option.Option(String))
}

pub fn duplicate_item_exception_default() -> DuplicateItemException {
  DuplicateItemException(message: option.None)
}

pub fn encode_duplicate_item_exception_struct(
  input: DuplicateItemException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_duplicate_item_exception_struct_top(
  input: DuplicateItemException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_duplicate_item_exception_struct() -> decode.Decoder(
  DuplicateItemException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(DuplicateItemException(message: message))
}

pub type ExecuteTransactionInput {
  ExecuteTransactionInput(
    client_request_token: option.Option(String),
    return_consumed_capacity: option.Option(ReturnConsumedCapacity),
    transact_statements: List(ParameterizedStatement),
  )
}

pub fn execute_transaction_input_default(
  transact_statements transact_statements: List(ParameterizedStatement),
) -> ExecuteTransactionInput {
  ExecuteTransactionInput(
    client_request_token: option.None,
    return_consumed_capacity: option.None,
    transact_statements: transact_statements,
  )
}

pub fn encode_execute_transaction_input_struct(
  input: ExecuteTransactionInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.client_request_token {
    option.Some(v) -> [#("ClientRequestToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.transact_statements
    [
      #(
        "TransactStatements",
        fn(xs) { json.array(xs, encode_parameterized_statement_struct) }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn encode_execute_transaction_input_struct_top(
  input: ExecuteTransactionInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.client_request_token {
    option.Some(v) -> [#("ClientRequestToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.transact_statements
    [
      #(
        "TransactStatements",
        fn(xs) { json.array(xs, encode_parameterized_statement_struct) }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn decode_execute_transaction_input_struct() -> decode.Decoder(
  ExecuteTransactionInput,
) {
  use <- decode.recursive
  use client_request_token <- decode.optional_field(
    "ClientRequestToken",
    option.None,
    decode.optional(decode.string),
  )
  use return_consumed_capacity <- decode.optional_field(
    "ReturnConsumedCapacity",
    option.None,
    decode.optional(decode_return_consumed_capacity_enum()),
  )
  use transact_statements <- decode.field(
    "TransactStatements",
    decode.list(decode_parameterized_statement_struct()),
  )
  decode.success(ExecuteTransactionInput(
    client_request_token: client_request_token,
    return_consumed_capacity: return_consumed_capacity,
    transact_statements: transact_statements,
  ))
}

pub type ParameterizedStatement {
  ParameterizedStatement(
    parameters: option.Option(List(AttributeValue)),
    return_values_on_condition_check_failure: option.Option(
      ReturnValuesOnConditionCheckFailure,
    ),
    statement: String,
  )
}

pub fn parameterized_statement_default(
  statement statement: String,
) -> ParameterizedStatement {
  ParameterizedStatement(
    parameters: option.None,
    return_values_on_condition_check_failure: option.None,
    statement: statement,
  )
}

pub fn encode_parameterized_statement_struct(
  input: ParameterizedStatement,
) -> json.Json {
  let pairs = []
  let pairs = case input.parameters {
    option.Some(v) -> [
      #(
        "Parameters",
        fn(xs) { json.array(xs, encode_attribute_value_union) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.statement
    [#("Statement", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_parameterized_statement_struct_top(
  input: ParameterizedStatement,
) -> json.Json {
  let pairs = []
  let pairs = case input.parameters {
    option.Some(v) -> [
      #(
        "Parameters",
        fn(xs) { json.array(xs, encode_attribute_value_union) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.statement
    [#("Statement", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_parameterized_statement_struct() -> decode.Decoder(
  ParameterizedStatement,
) {
  use <- decode.recursive
  use parameters <- decode.optional_field(
    "Parameters",
    option.None,
    decode.optional(decode.list(decode_attribute_value_union())),
  )
  use return_values_on_condition_check_failure <- decode.optional_field(
    "ReturnValuesOnConditionCheckFailure",
    option.None,
    decode.optional(decode_return_values_on_condition_check_failure_enum()),
  )
  use statement <- decode.field("Statement", decode.string)
  decode.success(ParameterizedStatement(
    parameters: parameters,
    return_values_on_condition_check_failure: return_values_on_condition_check_failure,
    statement: statement,
  ))
}

pub type ExecuteTransactionOutput {
  ExecuteTransactionOutput(
    consumed_capacity: option.Option(List(ConsumedCapacity)),
    responses: option.Option(List(ItemResponse)),
  )
}

pub fn execute_transaction_output_default() -> ExecuteTransactionOutput {
  ExecuteTransactionOutput(
    consumed_capacity: option.None,
    responses: option.None,
  )
}

pub fn encode_execute_transaction_output_struct(
  input: ExecuteTransactionOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #(
        "ConsumedCapacity",
        fn(xs) { json.array(xs, encode_consumed_capacity_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.responses {
    option.Some(v) -> [
      #("Responses", fn(xs) { json.array(xs, encode_item_response_struct) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_execute_transaction_output_struct_top(
  input: ExecuteTransactionOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #(
        "ConsumedCapacity",
        fn(xs) { json.array(xs, encode_consumed_capacity_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.responses {
    option.Some(v) -> [
      #("Responses", fn(xs) { json.array(xs, encode_item_response_struct) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_execute_transaction_output_struct() -> decode.Decoder(
  ExecuteTransactionOutput,
) {
  use <- decode.recursive
  use consumed_capacity <- decode.optional_field(
    "ConsumedCapacity",
    option.None,
    decode.optional(decode.list(decode_consumed_capacity_struct())),
  )
  use responses <- decode.optional_field(
    "Responses",
    option.None,
    decode.optional(decode.list(decode_item_response_struct())),
  )
  decode.success(ExecuteTransactionOutput(
    consumed_capacity: consumed_capacity,
    responses: responses,
  ))
}

pub type ItemResponse {
  ItemResponse(item: option.Option(dict.Dict(String, AttributeValue)))
}

pub fn item_response_default() -> ItemResponse {
  ItemResponse(item: option.None)
}

pub fn encode_item_response_struct(input: ItemResponse) -> json.Json {
  let pairs = []
  let pairs = case input.item {
    option.Some(v) -> [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_item_response_struct_top(input: ItemResponse) -> json.Json {
  let pairs = []
  let pairs = case input.item {
    option.Some(v) -> [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_item_response_struct() -> decode.Decoder(ItemResponse) {
  use <- decode.recursive
  use item <- decode.optional_field(
    "Item",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  decode.success(ItemResponse(item: item))
}

pub type IdempotentParameterMismatchException {
  IdempotentParameterMismatchException(message: option.Option(String))
}

pub fn idempotent_parameter_mismatch_exception_default() -> IdempotentParameterMismatchException {
  IdempotentParameterMismatchException(message: option.None)
}

pub fn encode_idempotent_parameter_mismatch_exception_struct(
  input: IdempotentParameterMismatchException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("Message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_idempotent_parameter_mismatch_exception_struct_top(
  input: IdempotentParameterMismatchException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("Message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_idempotent_parameter_mismatch_exception_struct() -> decode.Decoder(
  IdempotentParameterMismatchException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "Message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(IdempotentParameterMismatchException(message: message))
}

pub type TransactionCanceledException {
  TransactionCanceledException(
    cancellation_reasons: option.Option(List(CancellationReason)),
    message: option.Option(String),
  )
}

pub fn transaction_canceled_exception_default() -> TransactionCanceledException {
  TransactionCanceledException(
    cancellation_reasons: option.None,
    message: option.None,
  )
}

pub fn encode_transaction_canceled_exception_struct(
  input: TransactionCanceledException,
) -> json.Json {
  let pairs = []
  let pairs = case input.cancellation_reasons {
    option.Some(v) -> [
      #(
        "CancellationReasons",
        fn(xs) { json.array(xs, encode_cancellation_reason_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.message {
    option.Some(v) -> [#("Message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_transaction_canceled_exception_struct_top(
  input: TransactionCanceledException,
) -> json.Json {
  let pairs = []
  let pairs = case input.cancellation_reasons {
    option.Some(v) -> [
      #(
        "CancellationReasons",
        fn(xs) { json.array(xs, encode_cancellation_reason_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.message {
    option.Some(v) -> [#("Message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_transaction_canceled_exception_struct() -> decode.Decoder(
  TransactionCanceledException,
) {
  use <- decode.recursive
  use cancellation_reasons <- decode.optional_field(
    "CancellationReasons",
    option.None,
    decode.optional(decode.list(decode_cancellation_reason_struct())),
  )
  use message <- decode.optional_field(
    "Message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(TransactionCanceledException(
    cancellation_reasons: cancellation_reasons,
    message: message,
  ))
}

pub type CancellationReason {
  CancellationReason(
    code: option.Option(String),
    item: option.Option(dict.Dict(String, AttributeValue)),
    message: option.Option(String),
  )
}

pub fn cancellation_reason_default() -> CancellationReason {
  CancellationReason(code: option.None, item: option.None, message: option.None)
}

pub fn encode_cancellation_reason_struct(
  input: CancellationReason,
) -> json.Json {
  let pairs = []
  let pairs = case input.code {
    option.Some(v) -> [#("Code", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.item {
    option.Some(v) -> [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.message {
    option.Some(v) -> [#("Message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_cancellation_reason_struct_top(
  input: CancellationReason,
) -> json.Json {
  let pairs = []
  let pairs = case input.code {
    option.Some(v) -> [#("Code", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.item {
    option.Some(v) -> [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.message {
    option.Some(v) -> [#("Message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_cancellation_reason_struct() -> decode.Decoder(CancellationReason) {
  use <- decode.recursive
  use code <- decode.optional_field(
    "Code",
    option.None,
    decode.optional(decode.string),
  )
  use item <- decode.optional_field(
    "Item",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use message <- decode.optional_field(
    "Message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(CancellationReason(code: code, item: item, message: message))
}

pub type TransactionInProgressException {
  TransactionInProgressException(message: option.Option(String))
}

pub fn transaction_in_progress_exception_default() -> TransactionInProgressException {
  TransactionInProgressException(message: option.None)
}

pub fn encode_transaction_in_progress_exception_struct(
  input: TransactionInProgressException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("Message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_transaction_in_progress_exception_struct_top(
  input: TransactionInProgressException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("Message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_transaction_in_progress_exception_struct() -> decode.Decoder(
  TransactionInProgressException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "Message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(TransactionInProgressException(message: message))
}

pub type ExportTableToPointInTimeInput {
  ExportTableToPointInTimeInput(
    client_token: option.Option(String),
    export_format: option.Option(ExportFormat),
    export_time: option.Option(json_timestamp.Timestamp),
    export_type: option.Option(ExportType),
    incremental_export_specification: option.Option(
      IncrementalExportSpecification,
    ),
    s3_bucket: String,
    s3_bucket_owner: option.Option(String),
    s3_prefix: option.Option(String),
    s3_sse_algorithm: option.Option(S3SseAlgorithm),
    s3_sse_kms_key_id: option.Option(String),
    table_arn: String,
  )
}

pub fn export_table_to_point_in_time_input_default(
  s3_bucket s3_bucket: String,
  table_arn table_arn: String,
) -> ExportTableToPointInTimeInput {
  ExportTableToPointInTimeInput(
    client_token: option.None,
    export_format: option.None,
    export_time: option.None,
    export_type: option.None,
    incremental_export_specification: option.None,
    s3_bucket: s3_bucket,
    s3_bucket_owner: option.None,
    s3_prefix: option.None,
    s3_sse_algorithm: option.None,
    s3_sse_kms_key_id: option.None,
    table_arn: table_arn,
  )
}

pub fn encode_export_table_to_point_in_time_input_struct(
  input: ExportTableToPointInTimeInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.client_token {
    option.Some(v) -> [#("ClientToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_format {
    option.Some(v) -> [#("ExportFormat", encode_export_format_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_time {
    option.Some(v) -> [
      #("ExportTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.export_type {
    option.Some(v) -> [#("ExportType", encode_export_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.incremental_export_specification {
    option.Some(v) -> [
      #(
        "IncrementalExportSpecification",
        encode_incremental_export_specification_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.s3_bucket
    [#("S3Bucket", json.string(v)), ..pairs]
  }
  let pairs = case input.s3_bucket_owner {
    option.Some(v) -> [#("S3BucketOwner", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_prefix {
    option.Some(v) -> [#("S3Prefix", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_sse_algorithm {
    option.Some(v) -> [
      #("S3SseAlgorithm", encode_s3_sse_algorithm_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.s3_sse_kms_key_id {
    option.Some(v) -> [#("S3SseKmsKeyId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_arn
    [#("TableArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_export_table_to_point_in_time_input_struct_top(
  input: ExportTableToPointInTimeInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.client_token {
    option.Some(v) -> [#("ClientToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_format {
    option.Some(v) -> [#("ExportFormat", encode_export_format_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_time {
    option.Some(v) -> [
      #("ExportTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.export_type {
    option.Some(v) -> [#("ExportType", encode_export_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.incremental_export_specification {
    option.Some(v) -> [
      #(
        "IncrementalExportSpecification",
        encode_incremental_export_specification_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.s3_bucket
    [#("S3Bucket", json.string(v)), ..pairs]
  }
  let pairs = case input.s3_bucket_owner {
    option.Some(v) -> [#("S3BucketOwner", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_prefix {
    option.Some(v) -> [#("S3Prefix", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_sse_algorithm {
    option.Some(v) -> [
      #("S3SseAlgorithm", encode_s3_sse_algorithm_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.s3_sse_kms_key_id {
    option.Some(v) -> [#("S3SseKmsKeyId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_arn
    [#("TableArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_export_table_to_point_in_time_input_struct() -> decode.Decoder(
  ExportTableToPointInTimeInput,
) {
  use <- decode.recursive
  use client_token <- decode.optional_field(
    "ClientToken",
    option.None,
    decode.optional(decode.string),
  )
  use export_format <- decode.optional_field(
    "ExportFormat",
    option.None,
    decode.optional(decode_export_format_enum()),
  )
  use export_time <- decode.optional_field(
    "ExportTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use export_type <- decode.optional_field(
    "ExportType",
    option.None,
    decode.optional(decode_export_type_enum()),
  )
  use incremental_export_specification <- decode.optional_field(
    "IncrementalExportSpecification",
    option.None,
    decode.optional(decode_incremental_export_specification_struct()),
  )
  use s3_bucket <- decode.field("S3Bucket", decode.string)
  use s3_bucket_owner <- decode.optional_field(
    "S3BucketOwner",
    option.None,
    decode.optional(decode.string),
  )
  use s3_prefix <- decode.optional_field(
    "S3Prefix",
    option.None,
    decode.optional(decode.string),
  )
  use s3_sse_algorithm <- decode.optional_field(
    "S3SseAlgorithm",
    option.None,
    decode.optional(decode_s3_sse_algorithm_enum()),
  )
  use s3_sse_kms_key_id <- decode.optional_field(
    "S3SseKmsKeyId",
    option.None,
    decode.optional(decode.string),
  )
  use table_arn <- decode.field("TableArn", decode.string)
  decode.success(ExportTableToPointInTimeInput(
    client_token: client_token,
    export_format: export_format,
    export_time: export_time,
    export_type: export_type,
    incremental_export_specification: incremental_export_specification,
    s3_bucket: s3_bucket,
    s3_bucket_owner: s3_bucket_owner,
    s3_prefix: s3_prefix,
    s3_sse_algorithm: s3_sse_algorithm,
    s3_sse_kms_key_id: s3_sse_kms_key_id,
    table_arn: table_arn,
  ))
}

pub type ExportTableToPointInTimeOutput {
  ExportTableToPointInTimeOutput(
    export_description: option.Option(ExportDescription),
  )
}

pub fn export_table_to_point_in_time_output_default() -> ExportTableToPointInTimeOutput {
  ExportTableToPointInTimeOutput(export_description: option.None)
}

pub fn encode_export_table_to_point_in_time_output_struct(
  input: ExportTableToPointInTimeOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.export_description {
    option.Some(v) -> [
      #("ExportDescription", encode_export_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_export_table_to_point_in_time_output_struct_top(
  input: ExportTableToPointInTimeOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.export_description {
    option.Some(v) -> [
      #("ExportDescription", encode_export_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_export_table_to_point_in_time_output_struct() -> decode.Decoder(
  ExportTableToPointInTimeOutput,
) {
  use <- decode.recursive
  use export_description <- decode.optional_field(
    "ExportDescription",
    option.None,
    decode.optional(decode_export_description_struct()),
  )
  decode.success(ExportTableToPointInTimeOutput(
    export_description: export_description,
  ))
}

pub type ExportConflictException {
  ExportConflictException(message: option.Option(String))
}

pub fn export_conflict_exception_default() -> ExportConflictException {
  ExportConflictException(message: option.None)
}

pub fn encode_export_conflict_exception_struct(
  input: ExportConflictException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_export_conflict_exception_struct_top(
  input: ExportConflictException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_export_conflict_exception_struct() -> decode.Decoder(
  ExportConflictException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ExportConflictException(message: message))
}

pub type InvalidExportTimeException {
  InvalidExportTimeException(message: option.Option(String))
}

pub fn invalid_export_time_exception_default() -> InvalidExportTimeException {
  InvalidExportTimeException(message: option.None)
}

pub fn encode_invalid_export_time_exception_struct(
  input: InvalidExportTimeException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_invalid_export_time_exception_struct_top(
  input: InvalidExportTimeException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_invalid_export_time_exception_struct() -> decode.Decoder(
  InvalidExportTimeException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(InvalidExportTimeException(message: message))
}

pub type PointInTimeRecoveryUnavailableException {
  PointInTimeRecoveryUnavailableException(message: option.Option(String))
}

pub fn point_in_time_recovery_unavailable_exception_default() -> PointInTimeRecoveryUnavailableException {
  PointInTimeRecoveryUnavailableException(message: option.None)
}

pub fn encode_point_in_time_recovery_unavailable_exception_struct(
  input: PointInTimeRecoveryUnavailableException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_point_in_time_recovery_unavailable_exception_struct_top(
  input: PointInTimeRecoveryUnavailableException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_point_in_time_recovery_unavailable_exception_struct() -> decode.Decoder(
  PointInTimeRecoveryUnavailableException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(PointInTimeRecoveryUnavailableException(message: message))
}

pub type GetItemInput {
  GetItemInput(
    attributes_to_get: option.Option(List(String)),
    consistent_read: option.Option(Bool),
    expression_attribute_names: option.Option(dict.Dict(String, String)),
    key: dict.Dict(String, AttributeValue),
    projection_expression: option.Option(String),
    return_consumed_capacity: option.Option(ReturnConsumedCapacity),
    table_name: String,
  )
}

pub fn get_item_input_default(
  key key: dict.Dict(String, AttributeValue),
  table_name table_name: String,
) -> GetItemInput {
  GetItemInput(
    attributes_to_get: option.None,
    consistent_read: option.None,
    expression_attribute_names: option.None,
    key: key,
    projection_expression: option.None,
    return_consumed_capacity: option.None,
    table_name: table_name,
  )
}

pub fn encode_get_item_input_struct(input: GetItemInput) -> json.Json {
  let pairs = []
  let pairs = case input.attributes_to_get {
    option.Some(v) -> [
      #("AttributesToGet", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consistent_read {
    option.Some(v) -> [#("ConsistentRead", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.projection_expression {
    option.Some(v) -> [#("ProjectionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_get_item_input_struct_top(input: GetItemInput) -> json.Json {
  let pairs = []
  let pairs = case input.attributes_to_get {
    option.Some(v) -> [
      #("AttributesToGet", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consistent_read {
    option.Some(v) -> [#("ConsistentRead", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.projection_expression {
    option.Some(v) -> [#("ProjectionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_get_item_input_struct() -> decode.Decoder(GetItemInput) {
  use <- decode.recursive
  use attributes_to_get <- decode.optional_field(
    "AttributesToGet",
    option.None,
    decode.optional(decode.list(decode.string)),
  )
  use consistent_read <- decode.optional_field(
    "ConsistentRead",
    option.None,
    decode.optional(decode.bool),
  )
  use expression_attribute_names <- decode.optional_field(
    "ExpressionAttributeNames",
    option.None,
    decode.optional(decode.dict(decode.string, decode.string)),
  )
  use key <- decode.field(
    "Key",
    decode.dict(decode.string, decode_attribute_value_union()),
  )
  use projection_expression <- decode.optional_field(
    "ProjectionExpression",
    option.None,
    decode.optional(decode.string),
  )
  use return_consumed_capacity <- decode.optional_field(
    "ReturnConsumedCapacity",
    option.None,
    decode.optional(decode_return_consumed_capacity_enum()),
  )
  use table_name <- decode.field("TableName", decode.string)
  decode.success(GetItemInput(
    attributes_to_get: attributes_to_get,
    consistent_read: consistent_read,
    expression_attribute_names: expression_attribute_names,
    key: key,
    projection_expression: projection_expression,
    return_consumed_capacity: return_consumed_capacity,
    table_name: table_name,
  ))
}

pub type GetItemOutput {
  GetItemOutput(
    consumed_capacity: option.Option(ConsumedCapacity),
    item: option.Option(dict.Dict(String, AttributeValue)),
  )
}

pub fn get_item_output_default() -> GetItemOutput {
  GetItemOutput(consumed_capacity: option.None, item: option.None)
}

pub fn encode_get_item_output_struct(input: GetItemOutput) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item {
    option.Some(v) -> [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_get_item_output_struct_top(input: GetItemOutput) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item {
    option.Some(v) -> [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_get_item_output_struct() -> decode.Decoder(GetItemOutput) {
  use <- decode.recursive
  use consumed_capacity <- decode.optional_field(
    "ConsumedCapacity",
    option.None,
    decode.optional(decode_consumed_capacity_struct()),
  )
  use item <- decode.optional_field(
    "Item",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  decode.success(GetItemOutput(consumed_capacity: consumed_capacity, item: item))
}

pub type GetResourcePolicyInput {
  GetResourcePolicyInput(resource_arn: String)
}

pub fn get_resource_policy_input_default(
  resource_arn resource_arn: String,
) -> GetResourcePolicyInput {
  GetResourcePolicyInput(resource_arn: resource_arn)
}

pub fn encode_get_resource_policy_input_struct(
  input: GetResourcePolicyInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.resource_arn
    [#("ResourceArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_get_resource_policy_input_struct_top(
  input: GetResourcePolicyInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.resource_arn
    [#("ResourceArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_get_resource_policy_input_struct() -> decode.Decoder(
  GetResourcePolicyInput,
) {
  use <- decode.recursive
  use resource_arn <- decode.field("ResourceArn", decode.string)
  decode.success(GetResourcePolicyInput(resource_arn: resource_arn))
}

pub type GetResourcePolicyOutput {
  GetResourcePolicyOutput(
    policy: option.Option(String),
    revision_id: option.Option(String),
  )
}

pub fn get_resource_policy_output_default() -> GetResourcePolicyOutput {
  GetResourcePolicyOutput(policy: option.None, revision_id: option.None)
}

pub fn encode_get_resource_policy_output_struct(
  input: GetResourcePolicyOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.policy {
    option.Some(v) -> [#("Policy", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.revision_id {
    option.Some(v) -> [#("RevisionId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_get_resource_policy_output_struct_top(
  input: GetResourcePolicyOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.policy {
    option.Some(v) -> [#("Policy", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.revision_id {
    option.Some(v) -> [#("RevisionId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_get_resource_policy_output_struct() -> decode.Decoder(
  GetResourcePolicyOutput,
) {
  use <- decode.recursive
  use policy <- decode.optional_field(
    "Policy",
    option.None,
    decode.optional(decode.string),
  )
  use revision_id <- decode.optional_field(
    "RevisionId",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(GetResourcePolicyOutput(
    policy: policy,
    revision_id: revision_id,
  ))
}

pub type ImportTableInput {
  ImportTableInput(
    client_token: option.Option(String),
    input_compression_type: option.Option(InputCompressionType),
    input_format: InputFormat,
    input_format_options: option.Option(InputFormatOptions),
    s3_bucket_source: S3BucketSource,
    table_creation_parameters: TableCreationParameters,
  )
}

pub fn import_table_input_default(
  input_format input_format: InputFormat,
  s3_bucket_source s3_bucket_source: S3BucketSource,
  table_creation_parameters table_creation_parameters: TableCreationParameters,
) -> ImportTableInput {
  ImportTableInput(
    client_token: option.None,
    input_compression_type: option.None,
    input_format: input_format,
    input_format_options: option.None,
    s3_bucket_source: s3_bucket_source,
    table_creation_parameters: table_creation_parameters,
  )
}

pub fn encode_import_table_input_struct(input: ImportTableInput) -> json.Json {
  let pairs = []
  let pairs = case input.client_token {
    option.Some(v) -> [#("ClientToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.input_compression_type {
    option.Some(v) -> [
      #("InputCompressionType", encode_input_compression_type_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.input_format
    [#("InputFormat", encode_input_format_enum(v)), ..pairs]
  }
  let pairs = case input.input_format_options {
    option.Some(v) -> [
      #("InputFormatOptions", encode_input_format_options_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.s3_bucket_source
    [#("S3BucketSource", encode_s3_bucket_source_struct(v)), ..pairs]
  }
  let pairs = {
    let v = input.table_creation_parameters
    [
      #("TableCreationParameters", encode_table_creation_parameters_struct(v)),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn encode_import_table_input_struct_top(
  input: ImportTableInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.client_token {
    option.Some(v) -> [#("ClientToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.input_compression_type {
    option.Some(v) -> [
      #("InputCompressionType", encode_input_compression_type_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.input_format
    [#("InputFormat", encode_input_format_enum(v)), ..pairs]
  }
  let pairs = case input.input_format_options {
    option.Some(v) -> [
      #("InputFormatOptions", encode_input_format_options_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.s3_bucket_source
    [#("S3BucketSource", encode_s3_bucket_source_struct(v)), ..pairs]
  }
  let pairs = {
    let v = input.table_creation_parameters
    [
      #("TableCreationParameters", encode_table_creation_parameters_struct(v)),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn decode_import_table_input_struct() -> decode.Decoder(ImportTableInput) {
  use <- decode.recursive
  use client_token <- decode.optional_field(
    "ClientToken",
    option.None,
    decode.optional(decode.string),
  )
  use input_compression_type <- decode.optional_field(
    "InputCompressionType",
    option.None,
    decode.optional(decode_input_compression_type_enum()),
  )
  use input_format <- decode.field("InputFormat", decode_input_format_enum())
  use input_format_options <- decode.optional_field(
    "InputFormatOptions",
    option.None,
    decode.optional(decode_input_format_options_struct()),
  )
  use s3_bucket_source <- decode.field(
    "S3BucketSource",
    decode_s3_bucket_source_struct(),
  )
  use table_creation_parameters <- decode.field(
    "TableCreationParameters",
    decode_table_creation_parameters_struct(),
  )
  decode.success(ImportTableInput(
    client_token: client_token,
    input_compression_type: input_compression_type,
    input_format: input_format,
    input_format_options: input_format_options,
    s3_bucket_source: s3_bucket_source,
    table_creation_parameters: table_creation_parameters,
  ))
}

pub type ImportTableOutput {
  ImportTableOutput(
    import_table_description: option.Option(ImportTableDescription),
  )
}

pub fn import_table_output_default() -> ImportTableOutput {
  ImportTableOutput(import_table_description: option.None)
}

pub fn encode_import_table_output_struct(
  input: ImportTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.import_table_description {
    option.Some(v) -> [
      #("ImportTableDescription", encode_import_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_import_table_output_struct_top(
  input: ImportTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.import_table_description {
    option.Some(v) -> [
      #("ImportTableDescription", encode_import_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_import_table_output_struct() -> decode.Decoder(ImportTableOutput) {
  use <- decode.recursive
  use import_table_description <- decode.optional_field(
    "ImportTableDescription",
    option.None,
    decode.optional(decode_import_table_description_struct()),
  )
  decode.success(ImportTableOutput(
    import_table_description: import_table_description,
  ))
}

pub type ImportConflictException {
  ImportConflictException(message: option.Option(String))
}

pub fn import_conflict_exception_default() -> ImportConflictException {
  ImportConflictException(message: option.None)
}

pub fn encode_import_conflict_exception_struct(
  input: ImportConflictException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_import_conflict_exception_struct_top(
  input: ImportConflictException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_import_conflict_exception_struct() -> decode.Decoder(
  ImportConflictException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ImportConflictException(message: message))
}

pub type ListBackupsInput {
  ListBackupsInput(
    backup_type: option.Option(BackupTypeFilter),
    exclusive_start_backup_arn: option.Option(String),
    limit: option.Option(Int),
    table_name: option.Option(String),
    time_range_lower_bound: option.Option(json_timestamp.Timestamp),
    time_range_upper_bound: option.Option(json_timestamp.Timestamp),
  )
}

pub fn list_backups_input_default() -> ListBackupsInput {
  ListBackupsInput(
    backup_type: option.None,
    exclusive_start_backup_arn: option.None,
    limit: option.None,
    table_name: option.None,
    time_range_lower_bound: option.None,
    time_range_upper_bound: option.None,
  )
}

pub fn encode_list_backups_input_struct(input: ListBackupsInput) -> json.Json {
  let pairs = []
  let pairs = case input.backup_type {
    option.Some(v) -> [
      #("BackupType", encode_backup_type_filter_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.exclusive_start_backup_arn {
    option.Some(v) -> [#("ExclusiveStartBackupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.limit {
    option.Some(v) -> [#("Limit", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.time_range_lower_bound {
    option.Some(v) -> [
      #("TimeRangeLowerBound", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.time_range_upper_bound {
    option.Some(v) -> [
      #("TimeRangeUpperBound", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_list_backups_input_struct_top(
  input: ListBackupsInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.backup_type {
    option.Some(v) -> [
      #("BackupType", encode_backup_type_filter_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.exclusive_start_backup_arn {
    option.Some(v) -> [#("ExclusiveStartBackupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.limit {
    option.Some(v) -> [#("Limit", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.time_range_lower_bound {
    option.Some(v) -> [
      #("TimeRangeLowerBound", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.time_range_upper_bound {
    option.Some(v) -> [
      #("TimeRangeUpperBound", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_list_backups_input_struct() -> decode.Decoder(ListBackupsInput) {
  use <- decode.recursive
  use backup_type <- decode.optional_field(
    "BackupType",
    option.None,
    decode.optional(decode_backup_type_filter_enum()),
  )
  use exclusive_start_backup_arn <- decode.optional_field(
    "ExclusiveStartBackupArn",
    option.None,
    decode.optional(decode.string),
  )
  use limit <- decode.optional_field(
    "Limit",
    option.None,
    decode.optional(decode.int),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  use time_range_lower_bound <- decode.optional_field(
    "TimeRangeLowerBound",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use time_range_upper_bound <- decode.optional_field(
    "TimeRangeUpperBound",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  decode.success(ListBackupsInput(
    backup_type: backup_type,
    exclusive_start_backup_arn: exclusive_start_backup_arn,
    limit: limit,
    table_name: table_name,
    time_range_lower_bound: time_range_lower_bound,
    time_range_upper_bound: time_range_upper_bound,
  ))
}

pub type BackupTypeFilter {
  BackupTypeFilterAll
  BackupTypeFilterAwsBackup
  BackupTypeFilterSystem
  BackupTypeFilterUser
}

pub fn encode_backup_type_filter_enum(v: BackupTypeFilter) -> json.Json {
  case v {
    BackupTypeFilterAll -> json.string("ALL")
    BackupTypeFilterAwsBackup -> json.string("AWS_BACKUP")
    BackupTypeFilterSystem -> json.string("SYSTEM")
    BackupTypeFilterUser -> json.string("USER")
  }
}

pub fn decode_backup_type_filter_enum() -> decode.Decoder(BackupTypeFilter) {
  decode.then(decode.string, fn(s) {
    case s {
      "ALL" -> decode.success(BackupTypeFilterAll)
      "AWS_BACKUP" -> decode.success(BackupTypeFilterAwsBackup)
      "SYSTEM" -> decode.success(BackupTypeFilterSystem)
      "USER" -> decode.success(BackupTypeFilterUser)
      _ -> decode.failure(BackupTypeFilterAll, "unknown enum value")
    }
  })
}

pub type ListBackupsOutput {
  ListBackupsOutput(
    backup_summaries: option.Option(List(BackupSummary)),
    last_evaluated_backup_arn: option.Option(String),
  )
}

pub fn list_backups_output_default() -> ListBackupsOutput {
  ListBackupsOutput(
    backup_summaries: option.None,
    last_evaluated_backup_arn: option.None,
  )
}

pub fn encode_list_backups_output_struct(
  input: ListBackupsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.backup_summaries {
    option.Some(v) -> [
      #(
        "BackupSummaries",
        fn(xs) { json.array(xs, encode_backup_summary_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.last_evaluated_backup_arn {
    option.Some(v) -> [#("LastEvaluatedBackupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_list_backups_output_struct_top(
  input: ListBackupsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.backup_summaries {
    option.Some(v) -> [
      #(
        "BackupSummaries",
        fn(xs) { json.array(xs, encode_backup_summary_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.last_evaluated_backup_arn {
    option.Some(v) -> [#("LastEvaluatedBackupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_list_backups_output_struct() -> decode.Decoder(ListBackupsOutput) {
  use <- decode.recursive
  use backup_summaries <- decode.optional_field(
    "BackupSummaries",
    option.None,
    decode.optional(decode.list(decode_backup_summary_struct())),
  )
  use last_evaluated_backup_arn <- decode.optional_field(
    "LastEvaluatedBackupArn",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ListBackupsOutput(
    backup_summaries: backup_summaries,
    last_evaluated_backup_arn: last_evaluated_backup_arn,
  ))
}

pub type BackupSummary {
  BackupSummary(
    backup_arn: option.Option(String),
    backup_creation_date_time: option.Option(json_timestamp.Timestamp),
    backup_expiry_date_time: option.Option(json_timestamp.Timestamp),
    backup_name: option.Option(String),
    backup_size_bytes: option.Option(Int),
    backup_status: option.Option(BackupStatus),
    backup_type: option.Option(BackupType),
    table_arn: option.Option(String),
    table_id: option.Option(String),
    table_name: option.Option(String),
  )
}

pub fn backup_summary_default() -> BackupSummary {
  BackupSummary(
    backup_arn: option.None,
    backup_creation_date_time: option.None,
    backup_expiry_date_time: option.None,
    backup_name: option.None,
    backup_size_bytes: option.None,
    backup_status: option.None,
    backup_type: option.None,
    table_arn: option.None,
    table_id: option.None,
    table_name: option.None,
  )
}

pub fn encode_backup_summary_struct(input: BackupSummary) -> json.Json {
  let pairs = []
  let pairs = case input.backup_arn {
    option.Some(v) -> [#("BackupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_creation_date_time {
    option.Some(v) -> [
      #("BackupCreationDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.backup_expiry_date_time {
    option.Some(v) -> [
      #("BackupExpiryDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.backup_name {
    option.Some(v) -> [#("BackupName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_size_bytes {
    option.Some(v) -> [#("BackupSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_status {
    option.Some(v) -> [#("BackupStatus", encode_backup_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_type {
    option.Some(v) -> [#("BackupType", encode_backup_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_id {
    option.Some(v) -> [#("TableId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_backup_summary_struct_top(input: BackupSummary) -> json.Json {
  let pairs = []
  let pairs = case input.backup_arn {
    option.Some(v) -> [#("BackupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_creation_date_time {
    option.Some(v) -> [
      #("BackupCreationDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.backup_expiry_date_time {
    option.Some(v) -> [
      #("BackupExpiryDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.backup_name {
    option.Some(v) -> [#("BackupName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_size_bytes {
    option.Some(v) -> [#("BackupSizeBytes", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_status {
    option.Some(v) -> [#("BackupStatus", encode_backup_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.backup_type {
    option.Some(v) -> [#("BackupType", encode_backup_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_id {
    option.Some(v) -> [#("TableId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_backup_summary_struct() -> decode.Decoder(BackupSummary) {
  use <- decode.recursive
  use backup_arn <- decode.optional_field(
    "BackupArn",
    option.None,
    decode.optional(decode.string),
  )
  use backup_creation_date_time <- decode.optional_field(
    "BackupCreationDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use backup_expiry_date_time <- decode.optional_field(
    "BackupExpiryDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use backup_name <- decode.optional_field(
    "BackupName",
    option.None,
    decode.optional(decode.string),
  )
  use backup_size_bytes <- decode.optional_field(
    "BackupSizeBytes",
    option.None,
    decode.optional(decode.int),
  )
  use backup_status <- decode.optional_field(
    "BackupStatus",
    option.None,
    decode.optional(decode_backup_status_enum()),
  )
  use backup_type <- decode.optional_field(
    "BackupType",
    option.None,
    decode.optional(decode_backup_type_enum()),
  )
  use table_arn <- decode.optional_field(
    "TableArn",
    option.None,
    decode.optional(decode.string),
  )
  use table_id <- decode.optional_field(
    "TableId",
    option.None,
    decode.optional(decode.string),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(BackupSummary(
    backup_arn: backup_arn,
    backup_creation_date_time: backup_creation_date_time,
    backup_expiry_date_time: backup_expiry_date_time,
    backup_name: backup_name,
    backup_size_bytes: backup_size_bytes,
    backup_status: backup_status,
    backup_type: backup_type,
    table_arn: table_arn,
    table_id: table_id,
    table_name: table_name,
  ))
}

pub type ListContributorInsightsInput {
  ListContributorInsightsInput(
    max_results: option.Option(Int),
    next_token: option.Option(String),
    table_name: option.Option(String),
  )
}

pub fn list_contributor_insights_input_default() -> ListContributorInsightsInput {
  ListContributorInsightsInput(
    max_results: option.None,
    next_token: option.None,
    table_name: option.None,
  )
}

pub fn encode_list_contributor_insights_input_struct(
  input: ListContributorInsightsInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.max_results {
    option.Some(v) -> [#("MaxResults", json.int(v)), ..pairs]
    option.None -> [#("MaxResults", json.int(0)), ..pairs]
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_list_contributor_insights_input_struct_top(
  input: ListContributorInsightsInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.max_results {
    option.Some(v) -> [#("MaxResults", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_list_contributor_insights_input_struct() -> decode.Decoder(
  ListContributorInsightsInput,
) {
  use <- decode.recursive
  use max_results <- decode.optional_field(
    "MaxResults",
    option.None,
    decode.optional(decode.int),
  )
  use next_token <- decode.optional_field(
    "NextToken",
    option.None,
    decode.optional(decode.string),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ListContributorInsightsInput(
    max_results: max_results,
    next_token: next_token,
    table_name: table_name,
  ))
}

pub type ListContributorInsightsOutput {
  ListContributorInsightsOutput(
    contributor_insights_summaries: option.Option(
      List(ContributorInsightsSummary),
    ),
    next_token: option.Option(String),
  )
}

pub fn list_contributor_insights_output_default() -> ListContributorInsightsOutput {
  ListContributorInsightsOutput(
    contributor_insights_summaries: option.None,
    next_token: option.None,
  )
}

pub fn encode_list_contributor_insights_output_struct(
  input: ListContributorInsightsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.contributor_insights_summaries {
    option.Some(v) -> [
      #(
        "ContributorInsightsSummaries",
        fn(xs) { json.array(xs, encode_contributor_insights_summary_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_list_contributor_insights_output_struct_top(
  input: ListContributorInsightsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.contributor_insights_summaries {
    option.Some(v) -> [
      #(
        "ContributorInsightsSummaries",
        fn(xs) { json.array(xs, encode_contributor_insights_summary_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_list_contributor_insights_output_struct() -> decode.Decoder(
  ListContributorInsightsOutput,
) {
  use <- decode.recursive
  use contributor_insights_summaries <- decode.optional_field(
    "ContributorInsightsSummaries",
    option.None,
    decode.optional(decode.list(decode_contributor_insights_summary_struct())),
  )
  use next_token <- decode.optional_field(
    "NextToken",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ListContributorInsightsOutput(
    contributor_insights_summaries: contributor_insights_summaries,
    next_token: next_token,
  ))
}

pub type ContributorInsightsSummary {
  ContributorInsightsSummary(
    contributor_insights_mode: option.Option(ContributorInsightsMode),
    contributor_insights_status: option.Option(ContributorInsightsStatus),
    index_name: option.Option(String),
    table_name: option.Option(String),
  )
}

pub fn contributor_insights_summary_default() -> ContributorInsightsSummary {
  ContributorInsightsSummary(
    contributor_insights_mode: option.None,
    contributor_insights_status: option.None,
    index_name: option.None,
    table_name: option.None,
  )
}

pub fn encode_contributor_insights_summary_struct(
  input: ContributorInsightsSummary,
) -> json.Json {
  let pairs = []
  let pairs = case input.contributor_insights_mode {
    option.Some(v) -> [
      #("ContributorInsightsMode", encode_contributor_insights_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.contributor_insights_status {
    option.Some(v) -> [
      #("ContributorInsightsStatus", encode_contributor_insights_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_contributor_insights_summary_struct_top(
  input: ContributorInsightsSummary,
) -> json.Json {
  let pairs = []
  let pairs = case input.contributor_insights_mode {
    option.Some(v) -> [
      #("ContributorInsightsMode", encode_contributor_insights_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.contributor_insights_status {
    option.Some(v) -> [
      #("ContributorInsightsStatus", encode_contributor_insights_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_contributor_insights_summary_struct() -> decode.Decoder(
  ContributorInsightsSummary,
) {
  use <- decode.recursive
  use contributor_insights_mode <- decode.optional_field(
    "ContributorInsightsMode",
    option.None,
    decode.optional(decode_contributor_insights_mode_enum()),
  )
  use contributor_insights_status <- decode.optional_field(
    "ContributorInsightsStatus",
    option.None,
    decode.optional(decode_contributor_insights_status_enum()),
  )
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ContributorInsightsSummary(
    contributor_insights_mode: contributor_insights_mode,
    contributor_insights_status: contributor_insights_status,
    index_name: index_name,
    table_name: table_name,
  ))
}

pub type ListExportsInput {
  ListExportsInput(
    max_results: option.Option(Int),
    next_token: option.Option(String),
    table_arn: option.Option(String),
  )
}

pub fn list_exports_input_default() -> ListExportsInput {
  ListExportsInput(
    max_results: option.None,
    next_token: option.None,
    table_arn: option.None,
  )
}

pub fn encode_list_exports_input_struct(input: ListExportsInput) -> json.Json {
  let pairs = []
  let pairs = case input.max_results {
    option.Some(v) -> [#("MaxResults", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_list_exports_input_struct_top(
  input: ListExportsInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.max_results {
    option.Some(v) -> [#("MaxResults", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_list_exports_input_struct() -> decode.Decoder(ListExportsInput) {
  use <- decode.recursive
  use max_results <- decode.optional_field(
    "MaxResults",
    option.None,
    decode.optional(decode.int),
  )
  use next_token <- decode.optional_field(
    "NextToken",
    option.None,
    decode.optional(decode.string),
  )
  use table_arn <- decode.optional_field(
    "TableArn",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ListExportsInput(
    max_results: max_results,
    next_token: next_token,
    table_arn: table_arn,
  ))
}

pub type ListExportsOutput {
  ListExportsOutput(
    export_summaries: option.Option(List(ExportSummary)),
    next_token: option.Option(String),
  )
}

pub fn list_exports_output_default() -> ListExportsOutput {
  ListExportsOutput(export_summaries: option.None, next_token: option.None)
}

pub fn encode_list_exports_output_struct(
  input: ListExportsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.export_summaries {
    option.Some(v) -> [
      #(
        "ExportSummaries",
        fn(xs) { json.array(xs, encode_export_summary_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_list_exports_output_struct_top(
  input: ListExportsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.export_summaries {
    option.Some(v) -> [
      #(
        "ExportSummaries",
        fn(xs) { json.array(xs, encode_export_summary_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_list_exports_output_struct() -> decode.Decoder(ListExportsOutput) {
  use <- decode.recursive
  use export_summaries <- decode.optional_field(
    "ExportSummaries",
    option.None,
    decode.optional(decode.list(decode_export_summary_struct())),
  )
  use next_token <- decode.optional_field(
    "NextToken",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ListExportsOutput(
    export_summaries: export_summaries,
    next_token: next_token,
  ))
}

pub type ExportSummary {
  ExportSummary(
    export_arn: option.Option(String),
    export_status: option.Option(ExportStatus),
    export_type: option.Option(ExportType),
  )
}

pub fn export_summary_default() -> ExportSummary {
  ExportSummary(
    export_arn: option.None,
    export_status: option.None,
    export_type: option.None,
  )
}

pub fn encode_export_summary_struct(input: ExportSummary) -> json.Json {
  let pairs = []
  let pairs = case input.export_arn {
    option.Some(v) -> [#("ExportArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_status {
    option.Some(v) -> [#("ExportStatus", encode_export_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_type {
    option.Some(v) -> [#("ExportType", encode_export_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_export_summary_struct_top(input: ExportSummary) -> json.Json {
  let pairs = []
  let pairs = case input.export_arn {
    option.Some(v) -> [#("ExportArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_status {
    option.Some(v) -> [#("ExportStatus", encode_export_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.export_type {
    option.Some(v) -> [#("ExportType", encode_export_type_enum(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_export_summary_struct() -> decode.Decoder(ExportSummary) {
  use <- decode.recursive
  use export_arn <- decode.optional_field(
    "ExportArn",
    option.None,
    decode.optional(decode.string),
  )
  use export_status <- decode.optional_field(
    "ExportStatus",
    option.None,
    decode.optional(decode_export_status_enum()),
  )
  use export_type <- decode.optional_field(
    "ExportType",
    option.None,
    decode.optional(decode_export_type_enum()),
  )
  decode.success(ExportSummary(
    export_arn: export_arn,
    export_status: export_status,
    export_type: export_type,
  ))
}

pub type ListGlobalTablesInput {
  ListGlobalTablesInput(
    exclusive_start_global_table_name: option.Option(String),
    limit: option.Option(Int),
    region_name: option.Option(String),
  )
}

pub fn list_global_tables_input_default() -> ListGlobalTablesInput {
  ListGlobalTablesInput(
    exclusive_start_global_table_name: option.None,
    limit: option.None,
    region_name: option.None,
  )
}

pub fn encode_list_global_tables_input_struct(
  input: ListGlobalTablesInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.exclusive_start_global_table_name {
    option.Some(v) -> [
      #("ExclusiveStartGlobalTableName", json.string(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.limit {
    option.Some(v) -> [#("Limit", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.region_name {
    option.Some(v) -> [#("RegionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_list_global_tables_input_struct_top(
  input: ListGlobalTablesInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.exclusive_start_global_table_name {
    option.Some(v) -> [
      #("ExclusiveStartGlobalTableName", json.string(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.limit {
    option.Some(v) -> [#("Limit", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.region_name {
    option.Some(v) -> [#("RegionName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_list_global_tables_input_struct() -> decode.Decoder(
  ListGlobalTablesInput,
) {
  use <- decode.recursive
  use exclusive_start_global_table_name <- decode.optional_field(
    "ExclusiveStartGlobalTableName",
    option.None,
    decode.optional(decode.string),
  )
  use limit <- decode.optional_field(
    "Limit",
    option.None,
    decode.optional(decode.int),
  )
  use region_name <- decode.optional_field(
    "RegionName",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ListGlobalTablesInput(
    exclusive_start_global_table_name: exclusive_start_global_table_name,
    limit: limit,
    region_name: region_name,
  ))
}

pub type ListGlobalTablesOutput {
  ListGlobalTablesOutput(
    global_tables: option.Option(List(GlobalTable)),
    last_evaluated_global_table_name: option.Option(String),
  )
}

pub fn list_global_tables_output_default() -> ListGlobalTablesOutput {
  ListGlobalTablesOutput(
    global_tables: option.None,
    last_evaluated_global_table_name: option.None,
  )
}

pub fn encode_list_global_tables_output_struct(
  input: ListGlobalTablesOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_tables {
    option.Some(v) -> [
      #(
        "GlobalTables",
        fn(xs) { json.array(xs, encode_global_table_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.last_evaluated_global_table_name {
    option.Some(v) -> [
      #("LastEvaluatedGlobalTableName", json.string(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_list_global_tables_output_struct_top(
  input: ListGlobalTablesOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_tables {
    option.Some(v) -> [
      #(
        "GlobalTables",
        fn(xs) { json.array(xs, encode_global_table_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.last_evaluated_global_table_name {
    option.Some(v) -> [
      #("LastEvaluatedGlobalTableName", json.string(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_list_global_tables_output_struct() -> decode.Decoder(
  ListGlobalTablesOutput,
) {
  use <- decode.recursive
  use global_tables <- decode.optional_field(
    "GlobalTables",
    option.None,
    decode.optional(decode.list(decode_global_table_struct())),
  )
  use last_evaluated_global_table_name <- decode.optional_field(
    "LastEvaluatedGlobalTableName",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ListGlobalTablesOutput(
    global_tables: global_tables,
    last_evaluated_global_table_name: last_evaluated_global_table_name,
  ))
}

pub type GlobalTable {
  GlobalTable(
    global_table_name: option.Option(String),
    replication_group: option.Option(List(Replica)),
  )
}

pub fn global_table_default() -> GlobalTable {
  GlobalTable(global_table_name: option.None, replication_group: option.None)
}

pub fn encode_global_table_struct(input: GlobalTable) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_name {
    option.Some(v) -> [#("GlobalTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replication_group {
    option.Some(v) -> [
      #("ReplicationGroup", fn(xs) { json.array(xs, encode_replica_struct) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_global_table_struct_top(input: GlobalTable) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_name {
    option.Some(v) -> [#("GlobalTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replication_group {
    option.Some(v) -> [
      #("ReplicationGroup", fn(xs) { json.array(xs, encode_replica_struct) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_global_table_struct() -> decode.Decoder(GlobalTable) {
  use <- decode.recursive
  use global_table_name <- decode.optional_field(
    "GlobalTableName",
    option.None,
    decode.optional(decode.string),
  )
  use replication_group <- decode.optional_field(
    "ReplicationGroup",
    option.None,
    decode.optional(decode.list(decode_replica_struct())),
  )
  decode.success(GlobalTable(
    global_table_name: global_table_name,
    replication_group: replication_group,
  ))
}

pub type ListImportsInput {
  ListImportsInput(
    next_token: option.Option(String),
    page_size: option.Option(Int),
    table_arn: option.Option(String),
  )
}

pub fn list_imports_input_default() -> ListImportsInput {
  ListImportsInput(
    next_token: option.None,
    page_size: option.None,
    table_arn: option.None,
  )
}

pub fn encode_list_imports_input_struct(input: ListImportsInput) -> json.Json {
  let pairs = []
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.page_size {
    option.Some(v) -> [#("PageSize", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_list_imports_input_struct_top(
  input: ListImportsInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.page_size {
    option.Some(v) -> [#("PageSize", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_list_imports_input_struct() -> decode.Decoder(ListImportsInput) {
  use <- decode.recursive
  use next_token <- decode.optional_field(
    "NextToken",
    option.None,
    decode.optional(decode.string),
  )
  use page_size <- decode.optional_field(
    "PageSize",
    option.None,
    decode.optional(decode.int),
  )
  use table_arn <- decode.optional_field(
    "TableArn",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ListImportsInput(
    next_token: next_token,
    page_size: page_size,
    table_arn: table_arn,
  ))
}

pub type ListImportsOutput {
  ListImportsOutput(
    import_summary_list: option.Option(List(ImportSummary)),
    next_token: option.Option(String),
  )
}

pub fn list_imports_output_default() -> ListImportsOutput {
  ListImportsOutput(import_summary_list: option.None, next_token: option.None)
}

pub fn encode_list_imports_output_struct(
  input: ListImportsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.import_summary_list {
    option.Some(v) -> [
      #(
        "ImportSummaryList",
        fn(xs) { json.array(xs, encode_import_summary_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_list_imports_output_struct_top(
  input: ListImportsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.import_summary_list {
    option.Some(v) -> [
      #(
        "ImportSummaryList",
        fn(xs) { json.array(xs, encode_import_summary_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_list_imports_output_struct() -> decode.Decoder(ListImportsOutput) {
  use <- decode.recursive
  use import_summary_list <- decode.optional_field(
    "ImportSummaryList",
    option.None,
    decode.optional(decode.list(decode_import_summary_struct())),
  )
  use next_token <- decode.optional_field(
    "NextToken",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ListImportsOutput(
    import_summary_list: import_summary_list,
    next_token: next_token,
  ))
}

pub type ImportSummary {
  ImportSummary(
    cloud_watch_log_group_arn: option.Option(String),
    end_time: option.Option(json_timestamp.Timestamp),
    import_arn: option.Option(String),
    import_status: option.Option(ImportStatus),
    input_format: option.Option(InputFormat),
    s3_bucket_source: option.Option(S3BucketSource),
    start_time: option.Option(json_timestamp.Timestamp),
    table_arn: option.Option(String),
  )
}

pub fn import_summary_default() -> ImportSummary {
  ImportSummary(
    cloud_watch_log_group_arn: option.None,
    end_time: option.None,
    import_arn: option.None,
    import_status: option.None,
    input_format: option.None,
    s3_bucket_source: option.None,
    start_time: option.None,
    table_arn: option.None,
  )
}

pub fn encode_import_summary_struct(input: ImportSummary) -> json.Json {
  let pairs = []
  let pairs = case input.cloud_watch_log_group_arn {
    option.Some(v) -> [#("CloudWatchLogGroupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.end_time {
    option.Some(v) -> [
      #("EndTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.import_arn {
    option.Some(v) -> [#("ImportArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.import_status {
    option.Some(v) -> [#("ImportStatus", encode_import_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.input_format {
    option.Some(v) -> [#("InputFormat", encode_input_format_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_bucket_source {
    option.Some(v) -> [
      #("S3BucketSource", encode_s3_bucket_source_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.start_time {
    option.Some(v) -> [
      #("StartTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_import_summary_struct_top(input: ImportSummary) -> json.Json {
  let pairs = []
  let pairs = case input.cloud_watch_log_group_arn {
    option.Some(v) -> [#("CloudWatchLogGroupArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.end_time {
    option.Some(v) -> [
      #("EndTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.import_arn {
    option.Some(v) -> [#("ImportArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.import_status {
    option.Some(v) -> [#("ImportStatus", encode_import_status_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.input_format {
    option.Some(v) -> [#("InputFormat", encode_input_format_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.s3_bucket_source {
    option.Some(v) -> [
      #("S3BucketSource", encode_s3_bucket_source_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.start_time {
    option.Some(v) -> [
      #("StartTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_arn {
    option.Some(v) -> [#("TableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_import_summary_struct() -> decode.Decoder(ImportSummary) {
  use <- decode.recursive
  use cloud_watch_log_group_arn <- decode.optional_field(
    "CloudWatchLogGroupArn",
    option.None,
    decode.optional(decode.string),
  )
  use end_time <- decode.optional_field(
    "EndTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use import_arn <- decode.optional_field(
    "ImportArn",
    option.None,
    decode.optional(decode.string),
  )
  use import_status <- decode.optional_field(
    "ImportStatus",
    option.None,
    decode.optional(decode_import_status_enum()),
  )
  use input_format <- decode.optional_field(
    "InputFormat",
    option.None,
    decode.optional(decode_input_format_enum()),
  )
  use s3_bucket_source <- decode.optional_field(
    "S3BucketSource",
    option.None,
    decode.optional(decode_s3_bucket_source_struct()),
  )
  use start_time <- decode.optional_field(
    "StartTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use table_arn <- decode.optional_field(
    "TableArn",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ImportSummary(
    cloud_watch_log_group_arn: cloud_watch_log_group_arn,
    end_time: end_time,
    import_arn: import_arn,
    import_status: import_status,
    input_format: input_format,
    s3_bucket_source: s3_bucket_source,
    start_time: start_time,
    table_arn: table_arn,
  ))
}

pub type ListTablesInput {
  ListTablesInput(
    exclusive_start_table_name: option.Option(String),
    limit: option.Option(Int),
  )
}

pub fn list_tables_input_default() -> ListTablesInput {
  ListTablesInput(exclusive_start_table_name: option.None, limit: option.None)
}

pub fn encode_list_tables_input_struct(input: ListTablesInput) -> json.Json {
  let pairs = []
  let pairs = case input.exclusive_start_table_name {
    option.Some(v) -> [#("ExclusiveStartTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.limit {
    option.Some(v) -> [#("Limit", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_list_tables_input_struct_top(
  input: ListTablesInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.exclusive_start_table_name {
    option.Some(v) -> [#("ExclusiveStartTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.limit {
    option.Some(v) -> [#("Limit", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_list_tables_input_struct() -> decode.Decoder(ListTablesInput) {
  use <- decode.recursive
  use exclusive_start_table_name <- decode.optional_field(
    "ExclusiveStartTableName",
    option.None,
    decode.optional(decode.string),
  )
  use limit <- decode.optional_field(
    "Limit",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(ListTablesInput(
    exclusive_start_table_name: exclusive_start_table_name,
    limit: limit,
  ))
}

pub type ListTablesOutput {
  ListTablesOutput(
    last_evaluated_table_name: option.Option(String),
    table_names: option.Option(List(String)),
  )
}

pub fn list_tables_output_default() -> ListTablesOutput {
  ListTablesOutput(
    last_evaluated_table_name: option.None,
    table_names: option.None,
  )
}

pub fn encode_list_tables_output_struct(input: ListTablesOutput) -> json.Json {
  let pairs = []
  let pairs = case input.last_evaluated_table_name {
    option.Some(v) -> [#("LastEvaluatedTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_names {
    option.Some(v) -> [
      #("TableNames", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_list_tables_output_struct_top(
  input: ListTablesOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.last_evaluated_table_name {
    option.Some(v) -> [#("LastEvaluatedTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_names {
    option.Some(v) -> [
      #("TableNames", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_list_tables_output_struct() -> decode.Decoder(ListTablesOutput) {
  use <- decode.recursive
  use last_evaluated_table_name <- decode.optional_field(
    "LastEvaluatedTableName",
    option.None,
    decode.optional(decode.string),
  )
  use table_names <- decode.optional_field(
    "TableNames",
    option.None,
    decode.optional(decode.list(decode.string)),
  )
  decode.success(ListTablesOutput(
    last_evaluated_table_name: last_evaluated_table_name,
    table_names: table_names,
  ))
}

pub type ListTagsOfResourceInput {
  ListTagsOfResourceInput(
    next_token: option.Option(String),
    resource_arn: String,
  )
}

pub fn list_tags_of_resource_input_default(
  resource_arn resource_arn: String,
) -> ListTagsOfResourceInput {
  ListTagsOfResourceInput(next_token: option.None, resource_arn: resource_arn)
}

pub fn encode_list_tags_of_resource_input_struct(
  input: ListTagsOfResourceInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.resource_arn
    [#("ResourceArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_list_tags_of_resource_input_struct_top(
  input: ListTagsOfResourceInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.resource_arn
    [#("ResourceArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_list_tags_of_resource_input_struct() -> decode.Decoder(
  ListTagsOfResourceInput,
) {
  use <- decode.recursive
  use next_token <- decode.optional_field(
    "NextToken",
    option.None,
    decode.optional(decode.string),
  )
  use resource_arn <- decode.field("ResourceArn", decode.string)
  decode.success(ListTagsOfResourceInput(
    next_token: next_token,
    resource_arn: resource_arn,
  ))
}

pub type ListTagsOfResourceOutput {
  ListTagsOfResourceOutput(
    next_token: option.Option(String),
    tags: option.Option(List(Tag)),
  )
}

pub fn list_tags_of_resource_output_default() -> ListTagsOfResourceOutput {
  ListTagsOfResourceOutput(next_token: option.None, tags: option.None)
}

pub fn encode_list_tags_of_resource_output_struct(
  input: ListTagsOfResourceOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.tags {
    option.Some(v) -> [
      #("Tags", fn(xs) { json.array(xs, encode_tag_struct) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_list_tags_of_resource_output_struct_top(
  input: ListTagsOfResourceOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.next_token {
    option.Some(v) -> [#("NextToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.tags {
    option.Some(v) -> [
      #("Tags", fn(xs) { json.array(xs, encode_tag_struct) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_list_tags_of_resource_output_struct() -> decode.Decoder(
  ListTagsOfResourceOutput,
) {
  use <- decode.recursive
  use next_token <- decode.optional_field(
    "NextToken",
    option.None,
    decode.optional(decode.string),
  )
  use tags <- decode.optional_field(
    "Tags",
    option.None,
    decode.optional(decode.list(decode_tag_struct())),
  )
  decode.success(ListTagsOfResourceOutput(next_token: next_token, tags: tags))
}

pub type PutItemInput {
  PutItemInput(
    condition_expression: option.Option(String),
    conditional_operator: option.Option(ConditionalOperator),
    expected: option.Option(dict.Dict(String, ExpectedAttributeValue)),
    expression_attribute_names: option.Option(dict.Dict(String, String)),
    expression_attribute_values: option.Option(
      dict.Dict(String, AttributeValue),
    ),
    item: dict.Dict(String, AttributeValue),
    return_consumed_capacity: option.Option(ReturnConsumedCapacity),
    return_item_collection_metrics: option.Option(ReturnItemCollectionMetrics),
    return_values: option.Option(ReturnValue),
    return_values_on_condition_check_failure: option.Option(
      ReturnValuesOnConditionCheckFailure,
    ),
    table_name: String,
  )
}

pub fn put_item_input_default(
  item item: dict.Dict(String, AttributeValue),
  table_name table_name: String,
) -> PutItemInput {
  PutItemInput(
    condition_expression: option.None,
    conditional_operator: option.None,
    expected: option.None,
    expression_attribute_names: option.None,
    expression_attribute_values: option.None,
    item: item,
    return_consumed_capacity: option.None,
    return_item_collection_metrics: option.None,
    return_values: option.None,
    return_values_on_condition_check_failure: option.None,
    table_name: table_name,
  )
}

pub fn encode_put_item_input_struct(input: PutItemInput) -> json.Json {
  let pairs = []
  let pairs = case input.condition_expression {
    option.Some(v) -> [#("ConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.conditional_operator {
    option.Some(v) -> [
      #("ConditionalOperator", encode_conditional_operator_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expected {
    option.Some(v) -> [
      #(
        "Expected",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_expected_attribute_value_struct(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.item
    [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_item_collection_metrics {
    option.Some(v) -> [
      #(
        "ReturnItemCollectionMetrics",
        encode_return_item_collection_metrics_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_values {
    option.Some(v) -> [#("ReturnValues", encode_return_value_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_put_item_input_struct_top(input: PutItemInput) -> json.Json {
  let pairs = []
  let pairs = case input.condition_expression {
    option.Some(v) -> [#("ConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.conditional_operator {
    option.Some(v) -> [
      #("ConditionalOperator", encode_conditional_operator_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expected {
    option.Some(v) -> [
      #(
        "Expected",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_expected_attribute_value_struct(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.item
    [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_item_collection_metrics {
    option.Some(v) -> [
      #(
        "ReturnItemCollectionMetrics",
        encode_return_item_collection_metrics_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_values {
    option.Some(v) -> [#("ReturnValues", encode_return_value_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_put_item_input_struct() -> decode.Decoder(PutItemInput) {
  use <- decode.recursive
  use condition_expression <- decode.optional_field(
    "ConditionExpression",
    option.None,
    decode.optional(decode.string),
  )
  use conditional_operator <- decode.optional_field(
    "ConditionalOperator",
    option.None,
    decode.optional(decode_conditional_operator_enum()),
  )
  use expected <- decode.optional_field(
    "Expected",
    option.None,
    decode.optional(decode.dict(
      decode.string,
      decode_expected_attribute_value_struct(),
    )),
  )
  use expression_attribute_names <- decode.optional_field(
    "ExpressionAttributeNames",
    option.None,
    decode.optional(decode.dict(decode.string, decode.string)),
  )
  use expression_attribute_values <- decode.optional_field(
    "ExpressionAttributeValues",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use item <- decode.field(
    "Item",
    decode.dict(decode.string, decode_attribute_value_union()),
  )
  use return_consumed_capacity <- decode.optional_field(
    "ReturnConsumedCapacity",
    option.None,
    decode.optional(decode_return_consumed_capacity_enum()),
  )
  use return_item_collection_metrics <- decode.optional_field(
    "ReturnItemCollectionMetrics",
    option.None,
    decode.optional(decode_return_item_collection_metrics_enum()),
  )
  use return_values <- decode.optional_field(
    "ReturnValues",
    option.None,
    decode.optional(decode_return_value_enum()),
  )
  use return_values_on_condition_check_failure <- decode.optional_field(
    "ReturnValuesOnConditionCheckFailure",
    option.None,
    decode.optional(decode_return_values_on_condition_check_failure_enum()),
  )
  use table_name <- decode.field("TableName", decode.string)
  decode.success(PutItemInput(
    condition_expression: condition_expression,
    conditional_operator: conditional_operator,
    expected: expected,
    expression_attribute_names: expression_attribute_names,
    expression_attribute_values: expression_attribute_values,
    item: item,
    return_consumed_capacity: return_consumed_capacity,
    return_item_collection_metrics: return_item_collection_metrics,
    return_values: return_values,
    return_values_on_condition_check_failure: return_values_on_condition_check_failure,
    table_name: table_name,
  ))
}

pub type PutItemOutput {
  PutItemOutput(
    attributes: option.Option(dict.Dict(String, AttributeValue)),
    consumed_capacity: option.Option(ConsumedCapacity),
    item_collection_metrics: option.Option(ItemCollectionMetrics),
  )
}

pub fn put_item_output_default() -> PutItemOutput {
  PutItemOutput(
    attributes: option.None,
    consumed_capacity: option.None,
    item_collection_metrics: option.None,
  )
}

pub fn encode_put_item_output_struct(input: PutItemOutput) -> json.Json {
  let pairs = []
  let pairs = case input.attributes {
    option.Some(v) -> [
      #(
        "Attributes",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_collection_metrics {
    option.Some(v) -> [
      #("ItemCollectionMetrics", encode_item_collection_metrics_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_put_item_output_struct_top(input: PutItemOutput) -> json.Json {
  let pairs = []
  let pairs = case input.attributes {
    option.Some(v) -> [
      #(
        "Attributes",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_collection_metrics {
    option.Some(v) -> [
      #("ItemCollectionMetrics", encode_item_collection_metrics_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_put_item_output_struct() -> decode.Decoder(PutItemOutput) {
  use <- decode.recursive
  use attributes <- decode.optional_field(
    "Attributes",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use consumed_capacity <- decode.optional_field(
    "ConsumedCapacity",
    option.None,
    decode.optional(decode_consumed_capacity_struct()),
  )
  use item_collection_metrics <- decode.optional_field(
    "ItemCollectionMetrics",
    option.None,
    decode.optional(decode_item_collection_metrics_struct()),
  )
  decode.success(PutItemOutput(
    attributes: attributes,
    consumed_capacity: consumed_capacity,
    item_collection_metrics: item_collection_metrics,
  ))
}

pub type PutResourcePolicyInput {
  PutResourcePolicyInput(
    confirm_remove_self_resource_access: option.Option(Bool),
    expected_revision_id: option.Option(String),
    policy: String,
    resource_arn: String,
  )
}

pub fn put_resource_policy_input_default(
  policy policy: String,
  resource_arn resource_arn: String,
) -> PutResourcePolicyInput {
  PutResourcePolicyInput(
    confirm_remove_self_resource_access: option.None,
    expected_revision_id: option.None,
    policy: policy,
    resource_arn: resource_arn,
  )
}

pub fn encode_put_resource_policy_input_struct(
  input: PutResourcePolicyInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.confirm_remove_self_resource_access {
    option.Some(v) -> [
      #("ConfirmRemoveSelfResourceAccess", json.bool(v)),
      ..pairs
    ]
    option.None -> [
      #("ConfirmRemoveSelfResourceAccess", json.bool(False)),
      ..pairs
    ]
  }
  let pairs = case input.expected_revision_id {
    option.Some(v) -> [#("ExpectedRevisionId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.policy
    [#("Policy", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.resource_arn
    [#("ResourceArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_put_resource_policy_input_struct_top(
  input: PutResourcePolicyInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.confirm_remove_self_resource_access {
    option.Some(v) -> [
      #("ConfirmRemoveSelfResourceAccess", json.bool(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expected_revision_id {
    option.Some(v) -> [#("ExpectedRevisionId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.policy
    [#("Policy", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.resource_arn
    [#("ResourceArn", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_put_resource_policy_input_struct() -> decode.Decoder(
  PutResourcePolicyInput,
) {
  use <- decode.recursive
  use confirm_remove_self_resource_access <- decode.optional_field(
    "ConfirmRemoveSelfResourceAccess",
    option.None,
    decode.optional(decode.bool),
  )
  use expected_revision_id <- decode.optional_field(
    "ExpectedRevisionId",
    option.None,
    decode.optional(decode.string),
  )
  use policy <- decode.field("Policy", decode.string)
  use resource_arn <- decode.field("ResourceArn", decode.string)
  decode.success(PutResourcePolicyInput(
    confirm_remove_self_resource_access: confirm_remove_self_resource_access,
    expected_revision_id: expected_revision_id,
    policy: policy,
    resource_arn: resource_arn,
  ))
}

pub type PutResourcePolicyOutput {
  PutResourcePolicyOutput(revision_id: option.Option(String))
}

pub fn put_resource_policy_output_default() -> PutResourcePolicyOutput {
  PutResourcePolicyOutput(revision_id: option.None)
}

pub fn encode_put_resource_policy_output_struct(
  input: PutResourcePolicyOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.revision_id {
    option.Some(v) -> [#("RevisionId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_put_resource_policy_output_struct_top(
  input: PutResourcePolicyOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.revision_id {
    option.Some(v) -> [#("RevisionId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_put_resource_policy_output_struct() -> decode.Decoder(
  PutResourcePolicyOutput,
) {
  use <- decode.recursive
  use revision_id <- decode.optional_field(
    "RevisionId",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(PutResourcePolicyOutput(revision_id: revision_id))
}

pub type QueryInput {
  QueryInput(
    attributes_to_get: option.Option(List(String)),
    conditional_operator: option.Option(ConditionalOperator),
    consistent_read: option.Option(Bool),
    exclusive_start_key: option.Option(dict.Dict(String, AttributeValue)),
    expression_attribute_names: option.Option(dict.Dict(String, String)),
    expression_attribute_values: option.Option(
      dict.Dict(String, AttributeValue),
    ),
    filter_expression: option.Option(String),
    index_name: option.Option(String),
    key_condition_expression: option.Option(String),
    key_conditions: option.Option(dict.Dict(String, Condition)),
    limit: option.Option(Int),
    projection_expression: option.Option(String),
    query_filter: option.Option(dict.Dict(String, Condition)),
    return_consumed_capacity: option.Option(ReturnConsumedCapacity),
    scan_index_forward: option.Option(Bool),
    select: option.Option(Select),
    table_name: String,
  )
}

pub fn query_input_default(table_name table_name: String) -> QueryInput {
  QueryInput(
    attributes_to_get: option.None,
    conditional_operator: option.None,
    consistent_read: option.None,
    exclusive_start_key: option.None,
    expression_attribute_names: option.None,
    expression_attribute_values: option.None,
    filter_expression: option.None,
    index_name: option.None,
    key_condition_expression: option.None,
    key_conditions: option.None,
    limit: option.None,
    projection_expression: option.None,
    query_filter: option.None,
    return_consumed_capacity: option.None,
    scan_index_forward: option.None,
    select: option.None,
    table_name: table_name,
  )
}

pub fn encode_query_input_struct(input: QueryInput) -> json.Json {
  let pairs = []
  let pairs = case input.attributes_to_get {
    option.Some(v) -> [
      #("AttributesToGet", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.conditional_operator {
    option.Some(v) -> [
      #("ConditionalOperator", encode_conditional_operator_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consistent_read {
    option.Some(v) -> [#("ConsistentRead", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.exclusive_start_key {
    option.Some(v) -> [
      #(
        "ExclusiveStartKey",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.filter_expression {
    option.Some(v) -> [#("FilterExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_condition_expression {
    option.Some(v) -> [#("KeyConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_conditions {
    option.Some(v) -> [
      #(
        "KeyConditions",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, encode_condition_struct(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.limit {
    option.Some(v) -> [#("Limit", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.projection_expression {
    option.Some(v) -> [#("ProjectionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.query_filter {
    option.Some(v) -> [
      #(
        "QueryFilter",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, encode_condition_struct(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.scan_index_forward {
    option.Some(v) -> [#("ScanIndexForward", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.select {
    option.Some(v) -> [#("Select", encode_select_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_query_input_struct_top(input: QueryInput) -> json.Json {
  let pairs = []
  let pairs = case input.attributes_to_get {
    option.Some(v) -> [
      #("AttributesToGet", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.conditional_operator {
    option.Some(v) -> [
      #("ConditionalOperator", encode_conditional_operator_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consistent_read {
    option.Some(v) -> [#("ConsistentRead", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.exclusive_start_key {
    option.Some(v) -> [
      #(
        "ExclusiveStartKey",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.filter_expression {
    option.Some(v) -> [#("FilterExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_condition_expression {
    option.Some(v) -> [#("KeyConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.key_conditions {
    option.Some(v) -> [
      #(
        "KeyConditions",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, encode_condition_struct(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.limit {
    option.Some(v) -> [#("Limit", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.projection_expression {
    option.Some(v) -> [#("ProjectionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.query_filter {
    option.Some(v) -> [
      #(
        "QueryFilter",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, encode_condition_struct(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.scan_index_forward {
    option.Some(v) -> [#("ScanIndexForward", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.select {
    option.Some(v) -> [#("Select", encode_select_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_query_input_struct() -> decode.Decoder(QueryInput) {
  use <- decode.recursive
  use attributes_to_get <- decode.optional_field(
    "AttributesToGet",
    option.None,
    decode.optional(decode.list(decode.string)),
  )
  use conditional_operator <- decode.optional_field(
    "ConditionalOperator",
    option.None,
    decode.optional(decode_conditional_operator_enum()),
  )
  use consistent_read <- decode.optional_field(
    "ConsistentRead",
    option.None,
    decode.optional(decode.bool),
  )
  use exclusive_start_key <- decode.optional_field(
    "ExclusiveStartKey",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use expression_attribute_names <- decode.optional_field(
    "ExpressionAttributeNames",
    option.None,
    decode.optional(decode.dict(decode.string, decode.string)),
  )
  use expression_attribute_values <- decode.optional_field(
    "ExpressionAttributeValues",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use filter_expression <- decode.optional_field(
    "FilterExpression",
    option.None,
    decode.optional(decode.string),
  )
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use key_condition_expression <- decode.optional_field(
    "KeyConditionExpression",
    option.None,
    decode.optional(decode.string),
  )
  use key_conditions <- decode.optional_field(
    "KeyConditions",
    option.None,
    decode.optional(decode.dict(decode.string, decode_condition_struct())),
  )
  use limit <- decode.optional_field(
    "Limit",
    option.None,
    decode.optional(decode.int),
  )
  use projection_expression <- decode.optional_field(
    "ProjectionExpression",
    option.None,
    decode.optional(decode.string),
  )
  use query_filter <- decode.optional_field(
    "QueryFilter",
    option.None,
    decode.optional(decode.dict(decode.string, decode_condition_struct())),
  )
  use return_consumed_capacity <- decode.optional_field(
    "ReturnConsumedCapacity",
    option.None,
    decode.optional(decode_return_consumed_capacity_enum()),
  )
  use scan_index_forward <- decode.optional_field(
    "ScanIndexForward",
    option.None,
    decode.optional(decode.bool),
  )
  use select <- decode.optional_field(
    "Select",
    option.None,
    decode.optional(decode_select_enum()),
  )
  use table_name <- decode.field("TableName", decode.string)
  decode.success(QueryInput(
    attributes_to_get: attributes_to_get,
    conditional_operator: conditional_operator,
    consistent_read: consistent_read,
    exclusive_start_key: exclusive_start_key,
    expression_attribute_names: expression_attribute_names,
    expression_attribute_values: expression_attribute_values,
    filter_expression: filter_expression,
    index_name: index_name,
    key_condition_expression: key_condition_expression,
    key_conditions: key_conditions,
    limit: limit,
    projection_expression: projection_expression,
    query_filter: query_filter,
    return_consumed_capacity: return_consumed_capacity,
    scan_index_forward: scan_index_forward,
    select: select,
    table_name: table_name,
  ))
}

pub type Condition {
  Condition(
    attribute_value_list: option.Option(List(AttributeValue)),
    comparison_operator: ComparisonOperator,
  )
}

pub fn condition_default(
  comparison_operator comparison_operator: ComparisonOperator,
) -> Condition {
  Condition(
    attribute_value_list: option.None,
    comparison_operator: comparison_operator,
  )
}

pub fn encode_condition_struct(input: Condition) -> json.Json {
  let pairs = []
  let pairs = case input.attribute_value_list {
    option.Some(v) -> [
      #(
        "AttributeValueList",
        fn(xs) { json.array(xs, encode_attribute_value_union) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.comparison_operator
    [#("ComparisonOperator", encode_comparison_operator_enum(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_condition_struct_top(input: Condition) -> json.Json {
  let pairs = []
  let pairs = case input.attribute_value_list {
    option.Some(v) -> [
      #(
        "AttributeValueList",
        fn(xs) { json.array(xs, encode_attribute_value_union) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.comparison_operator
    [#("ComparisonOperator", encode_comparison_operator_enum(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_condition_struct() -> decode.Decoder(Condition) {
  use <- decode.recursive
  use attribute_value_list <- decode.optional_field(
    "AttributeValueList",
    option.None,
    decode.optional(decode.list(decode_attribute_value_union())),
  )
  use comparison_operator <- decode.field(
    "ComparisonOperator",
    decode_comparison_operator_enum(),
  )
  decode.success(Condition(
    attribute_value_list: attribute_value_list,
    comparison_operator: comparison_operator,
  ))
}

pub type Select {
  SelectAllAttributes
  SelectAllProjectedAttributes
  SelectCount
  SelectSpecificAttributes
}

pub fn encode_select_enum(v: Select) -> json.Json {
  case v {
    SelectAllAttributes -> json.string("ALL_ATTRIBUTES")
    SelectAllProjectedAttributes -> json.string("ALL_PROJECTED_ATTRIBUTES")
    SelectCount -> json.string("COUNT")
    SelectSpecificAttributes -> json.string("SPECIFIC_ATTRIBUTES")
  }
}

pub fn decode_select_enum() -> decode.Decoder(Select) {
  decode.then(decode.string, fn(s) {
    case s {
      "ALL_ATTRIBUTES" -> decode.success(SelectAllAttributes)
      "ALL_PROJECTED_ATTRIBUTES" -> decode.success(SelectAllProjectedAttributes)
      "COUNT" -> decode.success(SelectCount)
      "SPECIFIC_ATTRIBUTES" -> decode.success(SelectSpecificAttributes)
      _ -> decode.failure(SelectAllAttributes, "unknown enum value")
    }
  })
}

pub type QueryOutput {
  QueryOutput(
    consumed_capacity: option.Option(ConsumedCapacity),
    count: option.Option(Int),
    items: option.Option(List(dict.Dict(String, AttributeValue))),
    last_evaluated_key: option.Option(dict.Dict(String, AttributeValue)),
    scanned_count: option.Option(Int),
  )
}

pub fn query_output_default() -> QueryOutput {
  QueryOutput(
    consumed_capacity: option.None,
    count: option.None,
    items: option.None,
    last_evaluated_key: option.None,
    scanned_count: option.None,
  )
}

pub fn encode_query_output_struct(input: QueryOutput) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.count {
    option.Some(v) -> [#("Count", json.int(v)), ..pairs]
    option.None -> [#("Count", json.int(0)), ..pairs]
  }
  let pairs = case input.items {
    option.Some(v) -> [
      #(
        "Items",
        fn(xs) {
          json.array(xs, fn(d) {
            json.object(
              dict.to_list(d)
              |> list.map(fn(pair) {
                #(pair.0, encode_attribute_value_union(pair.1))
              }),
            )
          })
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.last_evaluated_key {
    option.Some(v) -> [
      #(
        "LastEvaluatedKey",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.scanned_count {
    option.Some(v) -> [#("ScannedCount", json.int(v)), ..pairs]
    option.None -> [#("ScannedCount", json.int(0)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_query_output_struct_top(input: QueryOutput) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.count {
    option.Some(v) -> [#("Count", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.items {
    option.Some(v) -> [
      #(
        "Items",
        fn(xs) {
          json.array(xs, fn(d) {
            json.object(
              dict.to_list(d)
              |> list.map(fn(pair) {
                #(pair.0, encode_attribute_value_union(pair.1))
              }),
            )
          })
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.last_evaluated_key {
    option.Some(v) -> [
      #(
        "LastEvaluatedKey",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.scanned_count {
    option.Some(v) -> [#("ScannedCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_query_output_struct() -> decode.Decoder(QueryOutput) {
  use <- decode.recursive
  use consumed_capacity <- decode.optional_field(
    "ConsumedCapacity",
    option.None,
    decode.optional(decode_consumed_capacity_struct()),
  )
  use count <- decode.optional_field(
    "Count",
    option.None,
    decode.optional(decode.int),
  )
  use items <- decode.optional_field(
    "Items",
    option.None,
    decode.optional(
      decode.list(decode.dict(decode.string, decode_attribute_value_union())),
    ),
  )
  use last_evaluated_key <- decode.optional_field(
    "LastEvaluatedKey",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use scanned_count <- decode.optional_field(
    "ScannedCount",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(QueryOutput(
    consumed_capacity: consumed_capacity,
    count: count,
    items: items,
    last_evaluated_key: last_evaluated_key,
    scanned_count: scanned_count,
  ))
}

pub type RestoreTableFromBackupInput {
  RestoreTableFromBackupInput(
    backup_arn: String,
    billing_mode_override: option.Option(BillingMode),
    global_secondary_index_override: option.Option(List(GlobalSecondaryIndex)),
    local_secondary_index_override: option.Option(List(LocalSecondaryIndex)),
    on_demand_throughput_override: option.Option(OnDemandThroughput),
    provisioned_throughput_override: option.Option(ProvisionedThroughput),
    sse_specification_override: option.Option(SSESpecification),
    target_table_name: String,
  )
}

pub fn restore_table_from_backup_input_default(
  backup_arn backup_arn: String,
  target_table_name target_table_name: String,
) -> RestoreTableFromBackupInput {
  RestoreTableFromBackupInput(
    backup_arn: backup_arn,
    billing_mode_override: option.None,
    global_secondary_index_override: option.None,
    local_secondary_index_override: option.None,
    on_demand_throughput_override: option.None,
    provisioned_throughput_override: option.None,
    sse_specification_override: option.None,
    target_table_name: target_table_name,
  )
}

pub fn encode_restore_table_from_backup_input_struct(
  input: RestoreTableFromBackupInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.backup_arn
    [#("BackupArn", json.string(v)), ..pairs]
  }
  let pairs = case input.billing_mode_override {
    option.Some(v) -> [
      #("BillingModeOverride", encode_billing_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_index_override {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexOverride",
        fn(xs) { json.array(xs, encode_global_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.local_secondary_index_override {
    option.Some(v) -> [
      #(
        "LocalSecondaryIndexOverride",
        fn(xs) { json.array(xs, encode_local_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #("OnDemandThroughputOverride", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.sse_specification_override {
    option.Some(v) -> [
      #("SSESpecificationOverride", encode_sse_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.target_table_name
    [#("TargetTableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_restore_table_from_backup_input_struct_top(
  input: RestoreTableFromBackupInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.backup_arn
    [#("BackupArn", json.string(v)), ..pairs]
  }
  let pairs = case input.billing_mode_override {
    option.Some(v) -> [
      #("BillingModeOverride", encode_billing_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_index_override {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexOverride",
        fn(xs) { json.array(xs, encode_global_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.local_secondary_index_override {
    option.Some(v) -> [
      #(
        "LocalSecondaryIndexOverride",
        fn(xs) { json.array(xs, encode_local_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #("OnDemandThroughputOverride", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.sse_specification_override {
    option.Some(v) -> [
      #("SSESpecificationOverride", encode_sse_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.target_table_name
    [#("TargetTableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_restore_table_from_backup_input_struct() -> decode.Decoder(
  RestoreTableFromBackupInput,
) {
  use <- decode.recursive
  use backup_arn <- decode.field("BackupArn", decode.string)
  use billing_mode_override <- decode.optional_field(
    "BillingModeOverride",
    option.None,
    decode.optional(decode_billing_mode_enum()),
  )
  use global_secondary_index_override <- decode.optional_field(
    "GlobalSecondaryIndexOverride",
    option.None,
    decode.optional(decode.list(decode_global_secondary_index_struct())),
  )
  use local_secondary_index_override <- decode.optional_field(
    "LocalSecondaryIndexOverride",
    option.None,
    decode.optional(decode.list(decode_local_secondary_index_struct())),
  )
  use on_demand_throughput_override <- decode.optional_field(
    "OnDemandThroughputOverride",
    option.None,
    decode.optional(decode_on_demand_throughput_struct()),
  )
  use provisioned_throughput_override <- decode.optional_field(
    "ProvisionedThroughputOverride",
    option.None,
    decode.optional(decode_provisioned_throughput_struct()),
  )
  use sse_specification_override <- decode.optional_field(
    "SSESpecificationOverride",
    option.None,
    decode.optional(decode_sse_specification_struct()),
  )
  use target_table_name <- decode.field("TargetTableName", decode.string)
  decode.success(RestoreTableFromBackupInput(
    backup_arn: backup_arn,
    billing_mode_override: billing_mode_override,
    global_secondary_index_override: global_secondary_index_override,
    local_secondary_index_override: local_secondary_index_override,
    on_demand_throughput_override: on_demand_throughput_override,
    provisioned_throughput_override: provisioned_throughput_override,
    sse_specification_override: sse_specification_override,
    target_table_name: target_table_name,
  ))
}

pub type RestoreTableFromBackupOutput {
  RestoreTableFromBackupOutput(
    table_description: option.Option(TableDescription),
  )
}

pub fn restore_table_from_backup_output_default() -> RestoreTableFromBackupOutput {
  RestoreTableFromBackupOutput(table_description: option.None)
}

pub fn encode_restore_table_from_backup_output_struct(
  input: RestoreTableFromBackupOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_description {
    option.Some(v) -> [
      #("TableDescription", encode_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_restore_table_from_backup_output_struct_top(
  input: RestoreTableFromBackupOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_description {
    option.Some(v) -> [
      #("TableDescription", encode_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_restore_table_from_backup_output_struct() -> decode.Decoder(
  RestoreTableFromBackupOutput,
) {
  use <- decode.recursive
  use table_description <- decode.optional_field(
    "TableDescription",
    option.None,
    decode.optional(decode_table_description_struct()),
  )
  decode.success(RestoreTableFromBackupOutput(
    table_description: table_description,
  ))
}

pub type TableAlreadyExistsException {
  TableAlreadyExistsException(message: option.Option(String))
}

pub fn table_already_exists_exception_default() -> TableAlreadyExistsException {
  TableAlreadyExistsException(message: option.None)
}

pub fn encode_table_already_exists_exception_struct(
  input: TableAlreadyExistsException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_table_already_exists_exception_struct_top(
  input: TableAlreadyExistsException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_table_already_exists_exception_struct() -> decode.Decoder(
  TableAlreadyExistsException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(TableAlreadyExistsException(message: message))
}

pub type RestoreTableToPointInTimeInput {
  RestoreTableToPointInTimeInput(
    billing_mode_override: option.Option(BillingMode),
    global_secondary_index_override: option.Option(List(GlobalSecondaryIndex)),
    local_secondary_index_override: option.Option(List(LocalSecondaryIndex)),
    on_demand_throughput_override: option.Option(OnDemandThroughput),
    provisioned_throughput_override: option.Option(ProvisionedThroughput),
    restore_date_time: option.Option(json_timestamp.Timestamp),
    sse_specification_override: option.Option(SSESpecification),
    source_table_arn: option.Option(String),
    source_table_name: option.Option(String),
    target_table_name: String,
    use_latest_restorable_time: option.Option(Bool),
  )
}

pub fn restore_table_to_point_in_time_input_default(
  target_table_name target_table_name: String,
) -> RestoreTableToPointInTimeInput {
  RestoreTableToPointInTimeInput(
    billing_mode_override: option.None,
    global_secondary_index_override: option.None,
    local_secondary_index_override: option.None,
    on_demand_throughput_override: option.None,
    provisioned_throughput_override: option.None,
    restore_date_time: option.None,
    sse_specification_override: option.None,
    source_table_arn: option.None,
    source_table_name: option.None,
    target_table_name: target_table_name,
    use_latest_restorable_time: option.None,
  )
}

pub fn encode_restore_table_to_point_in_time_input_struct(
  input: RestoreTableToPointInTimeInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.billing_mode_override {
    option.Some(v) -> [
      #("BillingModeOverride", encode_billing_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_index_override {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexOverride",
        fn(xs) { json.array(xs, encode_global_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.local_secondary_index_override {
    option.Some(v) -> [
      #(
        "LocalSecondaryIndexOverride",
        fn(xs) { json.array(xs, encode_local_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #("OnDemandThroughputOverride", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.restore_date_time {
    option.Some(v) -> [
      #("RestoreDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.sse_specification_override {
    option.Some(v) -> [
      #("SSESpecificationOverride", encode_sse_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.source_table_arn {
    option.Some(v) -> [#("SourceTableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.source_table_name {
    option.Some(v) -> [#("SourceTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.target_table_name
    [#("TargetTableName", json.string(v)), ..pairs]
  }
  let pairs = case input.use_latest_restorable_time {
    option.Some(v) -> [#("UseLatestRestorableTime", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_restore_table_to_point_in_time_input_struct_top(
  input: RestoreTableToPointInTimeInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.billing_mode_override {
    option.Some(v) -> [
      #("BillingModeOverride", encode_billing_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_index_override {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexOverride",
        fn(xs) { json.array(xs, encode_global_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.local_secondary_index_override {
    option.Some(v) -> [
      #(
        "LocalSecondaryIndexOverride",
        fn(xs) { json.array(xs, encode_local_secondary_index_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #("OnDemandThroughputOverride", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.restore_date_time {
    option.Some(v) -> [
      #("RestoreDateTime", json_timestamp.encode_epoch_seconds(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.sse_specification_override {
    option.Some(v) -> [
      #("SSESpecificationOverride", encode_sse_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.source_table_arn {
    option.Some(v) -> [#("SourceTableArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.source_table_name {
    option.Some(v) -> [#("SourceTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.target_table_name
    [#("TargetTableName", json.string(v)), ..pairs]
  }
  let pairs = case input.use_latest_restorable_time {
    option.Some(v) -> [#("UseLatestRestorableTime", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_restore_table_to_point_in_time_input_struct() -> decode.Decoder(
  RestoreTableToPointInTimeInput,
) {
  use <- decode.recursive
  use billing_mode_override <- decode.optional_field(
    "BillingModeOverride",
    option.None,
    decode.optional(decode_billing_mode_enum()),
  )
  use global_secondary_index_override <- decode.optional_field(
    "GlobalSecondaryIndexOverride",
    option.None,
    decode.optional(decode.list(decode_global_secondary_index_struct())),
  )
  use local_secondary_index_override <- decode.optional_field(
    "LocalSecondaryIndexOverride",
    option.None,
    decode.optional(decode.list(decode_local_secondary_index_struct())),
  )
  use on_demand_throughput_override <- decode.optional_field(
    "OnDemandThroughputOverride",
    option.None,
    decode.optional(decode_on_demand_throughput_struct()),
  )
  use provisioned_throughput_override <- decode.optional_field(
    "ProvisionedThroughputOverride",
    option.None,
    decode.optional(decode_provisioned_throughput_struct()),
  )
  use restore_date_time <- decode.optional_field(
    "RestoreDateTime",
    option.None,
    decode.optional(json_timestamp.decoder_precise()),
  )
  use sse_specification_override <- decode.optional_field(
    "SSESpecificationOverride",
    option.None,
    decode.optional(decode_sse_specification_struct()),
  )
  use source_table_arn <- decode.optional_field(
    "SourceTableArn",
    option.None,
    decode.optional(decode.string),
  )
  use source_table_name <- decode.optional_field(
    "SourceTableName",
    option.None,
    decode.optional(decode.string),
  )
  use target_table_name <- decode.field("TargetTableName", decode.string)
  use use_latest_restorable_time <- decode.optional_field(
    "UseLatestRestorableTime",
    option.None,
    decode.optional(decode.bool),
  )
  decode.success(RestoreTableToPointInTimeInput(
    billing_mode_override: billing_mode_override,
    global_secondary_index_override: global_secondary_index_override,
    local_secondary_index_override: local_secondary_index_override,
    on_demand_throughput_override: on_demand_throughput_override,
    provisioned_throughput_override: provisioned_throughput_override,
    restore_date_time: restore_date_time,
    sse_specification_override: sse_specification_override,
    source_table_arn: source_table_arn,
    source_table_name: source_table_name,
    target_table_name: target_table_name,
    use_latest_restorable_time: use_latest_restorable_time,
  ))
}

pub type RestoreTableToPointInTimeOutput {
  RestoreTableToPointInTimeOutput(
    table_description: option.Option(TableDescription),
  )
}

pub fn restore_table_to_point_in_time_output_default() -> RestoreTableToPointInTimeOutput {
  RestoreTableToPointInTimeOutput(table_description: option.None)
}

pub fn encode_restore_table_to_point_in_time_output_struct(
  input: RestoreTableToPointInTimeOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_description {
    option.Some(v) -> [
      #("TableDescription", encode_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_restore_table_to_point_in_time_output_struct_top(
  input: RestoreTableToPointInTimeOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_description {
    option.Some(v) -> [
      #("TableDescription", encode_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_restore_table_to_point_in_time_output_struct() -> decode.Decoder(
  RestoreTableToPointInTimeOutput,
) {
  use <- decode.recursive
  use table_description <- decode.optional_field(
    "TableDescription",
    option.None,
    decode.optional(decode_table_description_struct()),
  )
  decode.success(RestoreTableToPointInTimeOutput(
    table_description: table_description,
  ))
}

pub type InvalidRestoreTimeException {
  InvalidRestoreTimeException(message: option.Option(String))
}

pub fn invalid_restore_time_exception_default() -> InvalidRestoreTimeException {
  InvalidRestoreTimeException(message: option.None)
}

pub fn encode_invalid_restore_time_exception_struct(
  input: InvalidRestoreTimeException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_invalid_restore_time_exception_struct_top(
  input: InvalidRestoreTimeException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_invalid_restore_time_exception_struct() -> decode.Decoder(
  InvalidRestoreTimeException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(InvalidRestoreTimeException(message: message))
}

pub type ScanInput {
  ScanInput(
    attributes_to_get: option.Option(List(String)),
    conditional_operator: option.Option(ConditionalOperator),
    consistent_read: option.Option(Bool),
    exclusive_start_key: option.Option(dict.Dict(String, AttributeValue)),
    expression_attribute_names: option.Option(dict.Dict(String, String)),
    expression_attribute_values: option.Option(
      dict.Dict(String, AttributeValue),
    ),
    filter_expression: option.Option(String),
    index_name: option.Option(String),
    limit: option.Option(Int),
    projection_expression: option.Option(String),
    return_consumed_capacity: option.Option(ReturnConsumedCapacity),
    scan_filter: option.Option(dict.Dict(String, Condition)),
    segment: option.Option(Int),
    select: option.Option(Select),
    table_name: String,
    total_segments: option.Option(Int),
  )
}

pub fn scan_input_default(table_name table_name: String) -> ScanInput {
  ScanInput(
    attributes_to_get: option.None,
    conditional_operator: option.None,
    consistent_read: option.None,
    exclusive_start_key: option.None,
    expression_attribute_names: option.None,
    expression_attribute_values: option.None,
    filter_expression: option.None,
    index_name: option.None,
    limit: option.None,
    projection_expression: option.None,
    return_consumed_capacity: option.None,
    scan_filter: option.None,
    segment: option.None,
    select: option.None,
    table_name: table_name,
    total_segments: option.None,
  )
}

pub fn encode_scan_input_struct(input: ScanInput) -> json.Json {
  let pairs = []
  let pairs = case input.attributes_to_get {
    option.Some(v) -> [
      #("AttributesToGet", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.conditional_operator {
    option.Some(v) -> [
      #("ConditionalOperator", encode_conditional_operator_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consistent_read {
    option.Some(v) -> [#("ConsistentRead", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.exclusive_start_key {
    option.Some(v) -> [
      #(
        "ExclusiveStartKey",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.filter_expression {
    option.Some(v) -> [#("FilterExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.limit {
    option.Some(v) -> [#("Limit", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.projection_expression {
    option.Some(v) -> [#("ProjectionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.scan_filter {
    option.Some(v) -> [
      #(
        "ScanFilter",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, encode_condition_struct(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.segment {
    option.Some(v) -> [#("Segment", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.select {
    option.Some(v) -> [#("Select", encode_select_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = case input.total_segments {
    option.Some(v) -> [#("TotalSegments", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_scan_input_struct_top(input: ScanInput) -> json.Json {
  let pairs = []
  let pairs = case input.attributes_to_get {
    option.Some(v) -> [
      #("AttributesToGet", fn(xs) { json.array(xs, json.string) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.conditional_operator {
    option.Some(v) -> [
      #("ConditionalOperator", encode_conditional_operator_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consistent_read {
    option.Some(v) -> [#("ConsistentRead", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.exclusive_start_key {
    option.Some(v) -> [
      #(
        "ExclusiveStartKey",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.filter_expression {
    option.Some(v) -> [#("FilterExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.limit {
    option.Some(v) -> [#("Limit", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.projection_expression {
    option.Some(v) -> [#("ProjectionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.scan_filter {
    option.Some(v) -> [
      #(
        "ScanFilter",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, encode_condition_struct(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.segment {
    option.Some(v) -> [#("Segment", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.select {
    option.Some(v) -> [#("Select", encode_select_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = case input.total_segments {
    option.Some(v) -> [#("TotalSegments", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_scan_input_struct() -> decode.Decoder(ScanInput) {
  use <- decode.recursive
  use attributes_to_get <- decode.optional_field(
    "AttributesToGet",
    option.None,
    decode.optional(decode.list(decode.string)),
  )
  use conditional_operator <- decode.optional_field(
    "ConditionalOperator",
    option.None,
    decode.optional(decode_conditional_operator_enum()),
  )
  use consistent_read <- decode.optional_field(
    "ConsistentRead",
    option.None,
    decode.optional(decode.bool),
  )
  use exclusive_start_key <- decode.optional_field(
    "ExclusiveStartKey",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use expression_attribute_names <- decode.optional_field(
    "ExpressionAttributeNames",
    option.None,
    decode.optional(decode.dict(decode.string, decode.string)),
  )
  use expression_attribute_values <- decode.optional_field(
    "ExpressionAttributeValues",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use filter_expression <- decode.optional_field(
    "FilterExpression",
    option.None,
    decode.optional(decode.string),
  )
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use limit <- decode.optional_field(
    "Limit",
    option.None,
    decode.optional(decode.int),
  )
  use projection_expression <- decode.optional_field(
    "ProjectionExpression",
    option.None,
    decode.optional(decode.string),
  )
  use return_consumed_capacity <- decode.optional_field(
    "ReturnConsumedCapacity",
    option.None,
    decode.optional(decode_return_consumed_capacity_enum()),
  )
  use scan_filter <- decode.optional_field(
    "ScanFilter",
    option.None,
    decode.optional(decode.dict(decode.string, decode_condition_struct())),
  )
  use segment <- decode.optional_field(
    "Segment",
    option.None,
    decode.optional(decode.int),
  )
  use select <- decode.optional_field(
    "Select",
    option.None,
    decode.optional(decode_select_enum()),
  )
  use table_name <- decode.field("TableName", decode.string)
  use total_segments <- decode.optional_field(
    "TotalSegments",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(ScanInput(
    attributes_to_get: attributes_to_get,
    conditional_operator: conditional_operator,
    consistent_read: consistent_read,
    exclusive_start_key: exclusive_start_key,
    expression_attribute_names: expression_attribute_names,
    expression_attribute_values: expression_attribute_values,
    filter_expression: filter_expression,
    index_name: index_name,
    limit: limit,
    projection_expression: projection_expression,
    return_consumed_capacity: return_consumed_capacity,
    scan_filter: scan_filter,
    segment: segment,
    select: select,
    table_name: table_name,
    total_segments: total_segments,
  ))
}

pub type ScanOutput {
  ScanOutput(
    consumed_capacity: option.Option(ConsumedCapacity),
    count: option.Option(Int),
    items: option.Option(List(dict.Dict(String, AttributeValue))),
    last_evaluated_key: option.Option(dict.Dict(String, AttributeValue)),
    scanned_count: option.Option(Int),
  )
}

pub fn scan_output_default() -> ScanOutput {
  ScanOutput(
    consumed_capacity: option.None,
    count: option.None,
    items: option.None,
    last_evaluated_key: option.None,
    scanned_count: option.None,
  )
}

pub fn encode_scan_output_struct(input: ScanOutput) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.count {
    option.Some(v) -> [#("Count", json.int(v)), ..pairs]
    option.None -> [#("Count", json.int(0)), ..pairs]
  }
  let pairs = case input.items {
    option.Some(v) -> [
      #(
        "Items",
        fn(xs) {
          json.array(xs, fn(d) {
            json.object(
              dict.to_list(d)
              |> list.map(fn(pair) {
                #(pair.0, encode_attribute_value_union(pair.1))
              }),
            )
          })
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.last_evaluated_key {
    option.Some(v) -> [
      #(
        "LastEvaluatedKey",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.scanned_count {
    option.Some(v) -> [#("ScannedCount", json.int(v)), ..pairs]
    option.None -> [#("ScannedCount", json.int(0)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_scan_output_struct_top(input: ScanOutput) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.count {
    option.Some(v) -> [#("Count", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.items {
    option.Some(v) -> [
      #(
        "Items",
        fn(xs) {
          json.array(xs, fn(d) {
            json.object(
              dict.to_list(d)
              |> list.map(fn(pair) {
                #(pair.0, encode_attribute_value_union(pair.1))
              }),
            )
          })
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.last_evaluated_key {
    option.Some(v) -> [
      #(
        "LastEvaluatedKey",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.scanned_count {
    option.Some(v) -> [#("ScannedCount", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_scan_output_struct() -> decode.Decoder(ScanOutput) {
  use <- decode.recursive
  use consumed_capacity <- decode.optional_field(
    "ConsumedCapacity",
    option.None,
    decode.optional(decode_consumed_capacity_struct()),
  )
  use count <- decode.optional_field(
    "Count",
    option.None,
    decode.optional(decode.int),
  )
  use items <- decode.optional_field(
    "Items",
    option.None,
    decode.optional(
      decode.list(decode.dict(decode.string, decode_attribute_value_union())),
    ),
  )
  use last_evaluated_key <- decode.optional_field(
    "LastEvaluatedKey",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use scanned_count <- decode.optional_field(
    "ScannedCount",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(ScanOutput(
    consumed_capacity: consumed_capacity,
    count: count,
    items: items,
    last_evaluated_key: last_evaluated_key,
    scanned_count: scanned_count,
  ))
}

pub type TagResourceInput {
  TagResourceInput(resource_arn: String, tags: List(Tag))
}

pub fn tag_resource_input_default(
  resource_arn resource_arn: String,
  tags tags: List(Tag),
) -> TagResourceInput {
  TagResourceInput(resource_arn: resource_arn, tags: tags)
}

pub fn encode_tag_resource_input_struct(input: TagResourceInput) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.resource_arn
    [#("ResourceArn", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.tags
    [#("Tags", fn(xs) { json.array(xs, encode_tag_struct) }(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_tag_resource_input_struct_top(
  input: TagResourceInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.resource_arn
    [#("ResourceArn", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.tags
    [#("Tags", fn(xs) { json.array(xs, encode_tag_struct) }(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_tag_resource_input_struct() -> decode.Decoder(TagResourceInput) {
  use <- decode.recursive
  use resource_arn <- decode.field("ResourceArn", decode.string)
  use tags <- decode.field("Tags", decode.list(decode_tag_struct()))
  decode.success(TagResourceInput(resource_arn: resource_arn, tags: tags))
}

pub type TransactGetItemsInput {
  TransactGetItemsInput(
    return_consumed_capacity: option.Option(ReturnConsumedCapacity),
    transact_items: List(TransactGetItem),
  )
}

pub fn transact_get_items_input_default(
  transact_items transact_items: List(TransactGetItem),
) -> TransactGetItemsInput {
  TransactGetItemsInput(
    return_consumed_capacity: option.None,
    transact_items: transact_items,
  )
}

pub fn encode_transact_get_items_input_struct(
  input: TransactGetItemsInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.transact_items
    [
      #(
        "TransactItems",
        fn(xs) { json.array(xs, encode_transact_get_item_struct) }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn encode_transact_get_items_input_struct_top(
  input: TransactGetItemsInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.transact_items
    [
      #(
        "TransactItems",
        fn(xs) { json.array(xs, encode_transact_get_item_struct) }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn decode_transact_get_items_input_struct() -> decode.Decoder(
  TransactGetItemsInput,
) {
  use <- decode.recursive
  use return_consumed_capacity <- decode.optional_field(
    "ReturnConsumedCapacity",
    option.None,
    decode.optional(decode_return_consumed_capacity_enum()),
  )
  use transact_items <- decode.field(
    "TransactItems",
    decode.list(decode_transact_get_item_struct()),
  )
  decode.success(TransactGetItemsInput(
    return_consumed_capacity: return_consumed_capacity,
    transact_items: transact_items,
  ))
}

pub type TransactGetItem {
  TransactGetItem(get: Get)
}

pub fn transact_get_item_default(get get: Get) -> TransactGetItem {
  TransactGetItem(get: get)
}

pub fn encode_transact_get_item_struct(input: TransactGetItem) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.get
    [#("Get", encode_get_struct(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_transact_get_item_struct_top(
  input: TransactGetItem,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.get
    [#("Get", encode_get_struct(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_transact_get_item_struct() -> decode.Decoder(TransactGetItem) {
  use <- decode.recursive
  use get <- decode.field("Get", decode_get_struct())
  decode.success(TransactGetItem(get: get))
}

pub type Get {
  Get(
    expression_attribute_names: option.Option(dict.Dict(String, String)),
    key: dict.Dict(String, AttributeValue),
    projection_expression: option.Option(String),
    table_name: String,
  )
}

pub fn get_default(
  key key: dict.Dict(String, AttributeValue),
  table_name table_name: String,
) -> Get {
  Get(
    expression_attribute_names: option.None,
    key: key,
    projection_expression: option.None,
    table_name: table_name,
  )
}

pub fn encode_get_struct(input: Get) -> json.Json {
  let pairs = []
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.projection_expression {
    option.Some(v) -> [#("ProjectionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_get_struct_top(input: Get) -> json.Json {
  let pairs = []
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.projection_expression {
    option.Some(v) -> [#("ProjectionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_get_struct() -> decode.Decoder(Get) {
  use <- decode.recursive
  use expression_attribute_names <- decode.optional_field(
    "ExpressionAttributeNames",
    option.None,
    decode.optional(decode.dict(decode.string, decode.string)),
  )
  use key <- decode.field(
    "Key",
    decode.dict(decode.string, decode_attribute_value_union()),
  )
  use projection_expression <- decode.optional_field(
    "ProjectionExpression",
    option.None,
    decode.optional(decode.string),
  )
  use table_name <- decode.field("TableName", decode.string)
  decode.success(Get(
    expression_attribute_names: expression_attribute_names,
    key: key,
    projection_expression: projection_expression,
    table_name: table_name,
  ))
}

pub type TransactGetItemsOutput {
  TransactGetItemsOutput(
    consumed_capacity: option.Option(List(ConsumedCapacity)),
    responses: option.Option(List(ItemResponse)),
  )
}

pub fn transact_get_items_output_default() -> TransactGetItemsOutput {
  TransactGetItemsOutput(consumed_capacity: option.None, responses: option.None)
}

pub fn encode_transact_get_items_output_struct(
  input: TransactGetItemsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #(
        "ConsumedCapacity",
        fn(xs) { json.array(xs, encode_consumed_capacity_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.responses {
    option.Some(v) -> [
      #("Responses", fn(xs) { json.array(xs, encode_item_response_struct) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_transact_get_items_output_struct_top(
  input: TransactGetItemsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #(
        "ConsumedCapacity",
        fn(xs) { json.array(xs, encode_consumed_capacity_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.responses {
    option.Some(v) -> [
      #("Responses", fn(xs) { json.array(xs, encode_item_response_struct) }(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_transact_get_items_output_struct() -> decode.Decoder(
  TransactGetItemsOutput,
) {
  use <- decode.recursive
  use consumed_capacity <- decode.optional_field(
    "ConsumedCapacity",
    option.None,
    decode.optional(decode.list(decode_consumed_capacity_struct())),
  )
  use responses <- decode.optional_field(
    "Responses",
    option.None,
    decode.optional(decode.list(decode_item_response_struct())),
  )
  decode.success(TransactGetItemsOutput(
    consumed_capacity: consumed_capacity,
    responses: responses,
  ))
}

pub type TransactWriteItemsInput {
  TransactWriteItemsInput(
    client_request_token: option.Option(String),
    return_consumed_capacity: option.Option(ReturnConsumedCapacity),
    return_item_collection_metrics: option.Option(ReturnItemCollectionMetrics),
    transact_items: List(TransactWriteItem),
  )
}

pub fn transact_write_items_input_default(
  transact_items transact_items: List(TransactWriteItem),
) -> TransactWriteItemsInput {
  TransactWriteItemsInput(
    client_request_token: option.None,
    return_consumed_capacity: option.None,
    return_item_collection_metrics: option.None,
    transact_items: transact_items,
  )
}

pub fn encode_transact_write_items_input_struct(
  input: TransactWriteItemsInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.client_request_token {
    option.Some(v) -> [#("ClientRequestToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_item_collection_metrics {
    option.Some(v) -> [
      #(
        "ReturnItemCollectionMetrics",
        encode_return_item_collection_metrics_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.transact_items
    [
      #(
        "TransactItems",
        fn(xs) { json.array(xs, encode_transact_write_item_struct) }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn encode_transact_write_items_input_struct_top(
  input: TransactWriteItemsInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.client_request_token {
    option.Some(v) -> [#("ClientRequestToken", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_item_collection_metrics {
    option.Some(v) -> [
      #(
        "ReturnItemCollectionMetrics",
        encode_return_item_collection_metrics_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.transact_items
    [
      #(
        "TransactItems",
        fn(xs) { json.array(xs, encode_transact_write_item_struct) }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn decode_transact_write_items_input_struct() -> decode.Decoder(
  TransactWriteItemsInput,
) {
  use <- decode.recursive
  use client_request_token <- decode.optional_field(
    "ClientRequestToken",
    option.None,
    decode.optional(decode.string),
  )
  use return_consumed_capacity <- decode.optional_field(
    "ReturnConsumedCapacity",
    option.None,
    decode.optional(decode_return_consumed_capacity_enum()),
  )
  use return_item_collection_metrics <- decode.optional_field(
    "ReturnItemCollectionMetrics",
    option.None,
    decode.optional(decode_return_item_collection_metrics_enum()),
  )
  use transact_items <- decode.field(
    "TransactItems",
    decode.list(decode_transact_write_item_struct()),
  )
  decode.success(TransactWriteItemsInput(
    client_request_token: client_request_token,
    return_consumed_capacity: return_consumed_capacity,
    return_item_collection_metrics: return_item_collection_metrics,
    transact_items: transact_items,
  ))
}

pub type TransactWriteItem {
  TransactWriteItem(
    condition_check: option.Option(ConditionCheck),
    delete: option.Option(Delete),
    put: option.Option(Put),
    update: option.Option(Update),
  )
}

pub fn transact_write_item_default() -> TransactWriteItem {
  TransactWriteItem(
    condition_check: option.None,
    delete: option.None,
    put: option.None,
    update: option.None,
  )
}

pub fn encode_transact_write_item_struct(
  input: TransactWriteItem,
) -> json.Json {
  let pairs = []
  let pairs = case input.condition_check {
    option.Some(v) -> [
      #("ConditionCheck", encode_condition_check_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.delete {
    option.Some(v) -> [#("Delete", encode_delete_struct(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.put {
    option.Some(v) -> [#("Put", encode_put_struct(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.update {
    option.Some(v) -> [#("Update", encode_update_struct(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_transact_write_item_struct_top(
  input: TransactWriteItem,
) -> json.Json {
  let pairs = []
  let pairs = case input.condition_check {
    option.Some(v) -> [
      #("ConditionCheck", encode_condition_check_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.delete {
    option.Some(v) -> [#("Delete", encode_delete_struct(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.put {
    option.Some(v) -> [#("Put", encode_put_struct(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.update {
    option.Some(v) -> [#("Update", encode_update_struct(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_transact_write_item_struct() -> decode.Decoder(TransactWriteItem) {
  use <- decode.recursive
  use condition_check <- decode.optional_field(
    "ConditionCheck",
    option.None,
    decode.optional(decode_condition_check_struct()),
  )
  use delete <- decode.optional_field(
    "Delete",
    option.None,
    decode.optional(decode_delete_struct()),
  )
  use put <- decode.optional_field(
    "Put",
    option.None,
    decode.optional(decode_put_struct()),
  )
  use update <- decode.optional_field(
    "Update",
    option.None,
    decode.optional(decode_update_struct()),
  )
  decode.success(TransactWriteItem(
    condition_check: condition_check,
    delete: delete,
    put: put,
    update: update,
  ))
}

pub type ConditionCheck {
  ConditionCheck(
    condition_expression: String,
    expression_attribute_names: option.Option(dict.Dict(String, String)),
    expression_attribute_values: option.Option(
      dict.Dict(String, AttributeValue),
    ),
    key: dict.Dict(String, AttributeValue),
    return_values_on_condition_check_failure: option.Option(
      ReturnValuesOnConditionCheckFailure,
    ),
    table_name: String,
  )
}

pub fn condition_check_default(
  condition_expression condition_expression: String,
  key key: dict.Dict(String, AttributeValue),
  table_name table_name: String,
) -> ConditionCheck {
  ConditionCheck(
    condition_expression: condition_expression,
    expression_attribute_names: option.None,
    expression_attribute_values: option.None,
    key: key,
    return_values_on_condition_check_failure: option.None,
    table_name: table_name,
  )
}

pub fn encode_condition_check_struct(input: ConditionCheck) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.condition_expression
    [#("ConditionExpression", json.string(v)), ..pairs]
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_condition_check_struct_top(input: ConditionCheck) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.condition_expression
    [#("ConditionExpression", json.string(v)), ..pairs]
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_condition_check_struct() -> decode.Decoder(ConditionCheck) {
  use <- decode.recursive
  use condition_expression <- decode.field("ConditionExpression", decode.string)
  use expression_attribute_names <- decode.optional_field(
    "ExpressionAttributeNames",
    option.None,
    decode.optional(decode.dict(decode.string, decode.string)),
  )
  use expression_attribute_values <- decode.optional_field(
    "ExpressionAttributeValues",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use key <- decode.field(
    "Key",
    decode.dict(decode.string, decode_attribute_value_union()),
  )
  use return_values_on_condition_check_failure <- decode.optional_field(
    "ReturnValuesOnConditionCheckFailure",
    option.None,
    decode.optional(decode_return_values_on_condition_check_failure_enum()),
  )
  use table_name <- decode.field("TableName", decode.string)
  decode.success(ConditionCheck(
    condition_expression: condition_expression,
    expression_attribute_names: expression_attribute_names,
    expression_attribute_values: expression_attribute_values,
    key: key,
    return_values_on_condition_check_failure: return_values_on_condition_check_failure,
    table_name: table_name,
  ))
}

pub type Delete {
  Delete(
    condition_expression: option.Option(String),
    expression_attribute_names: option.Option(dict.Dict(String, String)),
    expression_attribute_values: option.Option(
      dict.Dict(String, AttributeValue),
    ),
    key: dict.Dict(String, AttributeValue),
    return_values_on_condition_check_failure: option.Option(
      ReturnValuesOnConditionCheckFailure,
    ),
    table_name: String,
  )
}

pub fn delete_default(
  key key: dict.Dict(String, AttributeValue),
  table_name table_name: String,
) -> Delete {
  Delete(
    condition_expression: option.None,
    expression_attribute_names: option.None,
    expression_attribute_values: option.None,
    key: key,
    return_values_on_condition_check_failure: option.None,
    table_name: table_name,
  )
}

pub fn encode_delete_struct(input: Delete) -> json.Json {
  let pairs = []
  let pairs = case input.condition_expression {
    option.Some(v) -> [#("ConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_delete_struct_top(input: Delete) -> json.Json {
  let pairs = []
  let pairs = case input.condition_expression {
    option.Some(v) -> [#("ConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_delete_struct() -> decode.Decoder(Delete) {
  use <- decode.recursive
  use condition_expression <- decode.optional_field(
    "ConditionExpression",
    option.None,
    decode.optional(decode.string),
  )
  use expression_attribute_names <- decode.optional_field(
    "ExpressionAttributeNames",
    option.None,
    decode.optional(decode.dict(decode.string, decode.string)),
  )
  use expression_attribute_values <- decode.optional_field(
    "ExpressionAttributeValues",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use key <- decode.field(
    "Key",
    decode.dict(decode.string, decode_attribute_value_union()),
  )
  use return_values_on_condition_check_failure <- decode.optional_field(
    "ReturnValuesOnConditionCheckFailure",
    option.None,
    decode.optional(decode_return_values_on_condition_check_failure_enum()),
  )
  use table_name <- decode.field("TableName", decode.string)
  decode.success(Delete(
    condition_expression: condition_expression,
    expression_attribute_names: expression_attribute_names,
    expression_attribute_values: expression_attribute_values,
    key: key,
    return_values_on_condition_check_failure: return_values_on_condition_check_failure,
    table_name: table_name,
  ))
}

pub type Put {
  Put(
    condition_expression: option.Option(String),
    expression_attribute_names: option.Option(dict.Dict(String, String)),
    expression_attribute_values: option.Option(
      dict.Dict(String, AttributeValue),
    ),
    item: dict.Dict(String, AttributeValue),
    return_values_on_condition_check_failure: option.Option(
      ReturnValuesOnConditionCheckFailure,
    ),
    table_name: String,
  )
}

pub fn put_default(
  item item: dict.Dict(String, AttributeValue),
  table_name table_name: String,
) -> Put {
  Put(
    condition_expression: option.None,
    expression_attribute_names: option.None,
    expression_attribute_values: option.None,
    item: item,
    return_values_on_condition_check_failure: option.None,
    table_name: table_name,
  )
}

pub fn encode_put_struct(input: Put) -> json.Json {
  let pairs = []
  let pairs = case input.condition_expression {
    option.Some(v) -> [#("ConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.item
    [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_put_struct_top(input: Put) -> json.Json {
  let pairs = []
  let pairs = case input.condition_expression {
    option.Some(v) -> [#("ConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.item
    [
      #(
        "Item",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_put_struct() -> decode.Decoder(Put) {
  use <- decode.recursive
  use condition_expression <- decode.optional_field(
    "ConditionExpression",
    option.None,
    decode.optional(decode.string),
  )
  use expression_attribute_names <- decode.optional_field(
    "ExpressionAttributeNames",
    option.None,
    decode.optional(decode.dict(decode.string, decode.string)),
  )
  use expression_attribute_values <- decode.optional_field(
    "ExpressionAttributeValues",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use item <- decode.field(
    "Item",
    decode.dict(decode.string, decode_attribute_value_union()),
  )
  use return_values_on_condition_check_failure <- decode.optional_field(
    "ReturnValuesOnConditionCheckFailure",
    option.None,
    decode.optional(decode_return_values_on_condition_check_failure_enum()),
  )
  use table_name <- decode.field("TableName", decode.string)
  decode.success(Put(
    condition_expression: condition_expression,
    expression_attribute_names: expression_attribute_names,
    expression_attribute_values: expression_attribute_values,
    item: item,
    return_values_on_condition_check_failure: return_values_on_condition_check_failure,
    table_name: table_name,
  ))
}

pub type Update {
  Update(
    condition_expression: option.Option(String),
    expression_attribute_names: option.Option(dict.Dict(String, String)),
    expression_attribute_values: option.Option(
      dict.Dict(String, AttributeValue),
    ),
    key: dict.Dict(String, AttributeValue),
    return_values_on_condition_check_failure: option.Option(
      ReturnValuesOnConditionCheckFailure,
    ),
    table_name: String,
    update_expression: String,
  )
}

pub fn update_default(
  key key: dict.Dict(String, AttributeValue),
  table_name table_name: String,
  update_expression update_expression: String,
) -> Update {
  Update(
    condition_expression: option.None,
    expression_attribute_names: option.None,
    expression_attribute_values: option.None,
    key: key,
    return_values_on_condition_check_failure: option.None,
    table_name: table_name,
    update_expression: update_expression,
  )
}

pub fn encode_update_struct(input: Update) -> json.Json {
  let pairs = []
  let pairs = case input.condition_expression {
    option.Some(v) -> [#("ConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.update_expression
    [#("UpdateExpression", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_update_struct_top(input: Update) -> json.Json {
  let pairs = []
  let pairs = case input.condition_expression {
    option.Some(v) -> [#("ConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.update_expression
    [#("UpdateExpression", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_update_struct() -> decode.Decoder(Update) {
  use <- decode.recursive
  use condition_expression <- decode.optional_field(
    "ConditionExpression",
    option.None,
    decode.optional(decode.string),
  )
  use expression_attribute_names <- decode.optional_field(
    "ExpressionAttributeNames",
    option.None,
    decode.optional(decode.dict(decode.string, decode.string)),
  )
  use expression_attribute_values <- decode.optional_field(
    "ExpressionAttributeValues",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use key <- decode.field(
    "Key",
    decode.dict(decode.string, decode_attribute_value_union()),
  )
  use return_values_on_condition_check_failure <- decode.optional_field(
    "ReturnValuesOnConditionCheckFailure",
    option.None,
    decode.optional(decode_return_values_on_condition_check_failure_enum()),
  )
  use table_name <- decode.field("TableName", decode.string)
  use update_expression <- decode.field("UpdateExpression", decode.string)
  decode.success(Update(
    condition_expression: condition_expression,
    expression_attribute_names: expression_attribute_names,
    expression_attribute_values: expression_attribute_values,
    key: key,
    return_values_on_condition_check_failure: return_values_on_condition_check_failure,
    table_name: table_name,
    update_expression: update_expression,
  ))
}

pub type TransactWriteItemsOutput {
  TransactWriteItemsOutput(
    consumed_capacity: option.Option(List(ConsumedCapacity)),
    item_collection_metrics: option.Option(
      dict.Dict(String, List(ItemCollectionMetrics)),
    ),
  )
}

pub fn transact_write_items_output_default() -> TransactWriteItemsOutput {
  TransactWriteItemsOutput(
    consumed_capacity: option.None,
    item_collection_metrics: option.None,
  )
}

pub fn encode_transact_write_items_output_struct(
  input: TransactWriteItemsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #(
        "ConsumedCapacity",
        fn(xs) { json.array(xs, encode_consumed_capacity_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_collection_metrics {
    option.Some(v) -> [
      #(
        "ItemCollectionMetrics",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(
                pair.0,
                fn(xs) { json.array(xs, encode_item_collection_metrics_struct) }(
                  pair.1,
                ),
              )
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_transact_write_items_output_struct_top(
  input: TransactWriteItemsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #(
        "ConsumedCapacity",
        fn(xs) { json.array(xs, encode_consumed_capacity_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_collection_metrics {
    option.Some(v) -> [
      #(
        "ItemCollectionMetrics",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(
                pair.0,
                fn(xs) { json.array(xs, encode_item_collection_metrics_struct) }(
                  pair.1,
                ),
              )
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_transact_write_items_output_struct() -> decode.Decoder(
  TransactWriteItemsOutput,
) {
  use <- decode.recursive
  use consumed_capacity <- decode.optional_field(
    "ConsumedCapacity",
    option.None,
    decode.optional(decode.list(decode_consumed_capacity_struct())),
  )
  use item_collection_metrics <- decode.optional_field(
    "ItemCollectionMetrics",
    option.None,
    decode.optional(decode.dict(
      decode.string,
      decode.list(decode_item_collection_metrics_struct()),
    )),
  )
  decode.success(TransactWriteItemsOutput(
    consumed_capacity: consumed_capacity,
    item_collection_metrics: item_collection_metrics,
  ))
}

pub type UntagResourceInput {
  UntagResourceInput(resource_arn: String, tag_keys: List(String))
}

pub fn untag_resource_input_default(
  resource_arn resource_arn: String,
  tag_keys tag_keys: List(String),
) -> UntagResourceInput {
  UntagResourceInput(resource_arn: resource_arn, tag_keys: tag_keys)
}

pub fn encode_untag_resource_input_struct(
  input: UntagResourceInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.resource_arn
    [#("ResourceArn", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.tag_keys
    [#("TagKeys", fn(xs) { json.array(xs, json.string) }(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_untag_resource_input_struct_top(
  input: UntagResourceInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.resource_arn
    [#("ResourceArn", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.tag_keys
    [#("TagKeys", fn(xs) { json.array(xs, json.string) }(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_untag_resource_input_struct() -> decode.Decoder(
  UntagResourceInput,
) {
  use <- decode.recursive
  use resource_arn <- decode.field("ResourceArn", decode.string)
  use tag_keys <- decode.field("TagKeys", decode.list(decode.string))
  decode.success(UntagResourceInput(
    resource_arn: resource_arn,
    tag_keys: tag_keys,
  ))
}

pub type UpdateContinuousBackupsInput {
  UpdateContinuousBackupsInput(
    point_in_time_recovery_specification: PointInTimeRecoverySpecification,
    table_name: String,
  )
}

pub fn update_continuous_backups_input_default(
  point_in_time_recovery_specification point_in_time_recovery_specification: PointInTimeRecoverySpecification,
  table_name table_name: String,
) -> UpdateContinuousBackupsInput {
  UpdateContinuousBackupsInput(
    point_in_time_recovery_specification: point_in_time_recovery_specification,
    table_name: table_name,
  )
}

pub fn encode_update_continuous_backups_input_struct(
  input: UpdateContinuousBackupsInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.point_in_time_recovery_specification
    [
      #(
        "PointInTimeRecoverySpecification",
        encode_point_in_time_recovery_specification_struct(v),
      ),
      ..pairs
    ]
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_update_continuous_backups_input_struct_top(
  input: UpdateContinuousBackupsInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.point_in_time_recovery_specification
    [
      #(
        "PointInTimeRecoverySpecification",
        encode_point_in_time_recovery_specification_struct(v),
      ),
      ..pairs
    ]
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_update_continuous_backups_input_struct() -> decode.Decoder(
  UpdateContinuousBackupsInput,
) {
  use <- decode.recursive
  use point_in_time_recovery_specification <- decode.field(
    "PointInTimeRecoverySpecification",
    decode_point_in_time_recovery_specification_struct(),
  )
  use table_name <- decode.field("TableName", decode.string)
  decode.success(UpdateContinuousBackupsInput(
    point_in_time_recovery_specification: point_in_time_recovery_specification,
    table_name: table_name,
  ))
}

pub type PointInTimeRecoverySpecification {
  PointInTimeRecoverySpecification(
    point_in_time_recovery_enabled: Bool,
    recovery_period_in_days: option.Option(Int),
  )
}

pub fn point_in_time_recovery_specification_default(
  point_in_time_recovery_enabled point_in_time_recovery_enabled: Bool,
) -> PointInTimeRecoverySpecification {
  PointInTimeRecoverySpecification(
    point_in_time_recovery_enabled: point_in_time_recovery_enabled,
    recovery_period_in_days: option.None,
  )
}

pub fn encode_point_in_time_recovery_specification_struct(
  input: PointInTimeRecoverySpecification,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.point_in_time_recovery_enabled
    [#("PointInTimeRecoveryEnabled", json.bool(v)), ..pairs]
  }
  let pairs = case input.recovery_period_in_days {
    option.Some(v) -> [#("RecoveryPeriodInDays", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_point_in_time_recovery_specification_struct_top(
  input: PointInTimeRecoverySpecification,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.point_in_time_recovery_enabled
    [#("PointInTimeRecoveryEnabled", json.bool(v)), ..pairs]
  }
  let pairs = case input.recovery_period_in_days {
    option.Some(v) -> [#("RecoveryPeriodInDays", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_point_in_time_recovery_specification_struct() -> decode.Decoder(
  PointInTimeRecoverySpecification,
) {
  use <- decode.recursive
  use point_in_time_recovery_enabled <- decode.field(
    "PointInTimeRecoveryEnabled",
    decode.bool,
  )
  use recovery_period_in_days <- decode.optional_field(
    "RecoveryPeriodInDays",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(PointInTimeRecoverySpecification(
    point_in_time_recovery_enabled: point_in_time_recovery_enabled,
    recovery_period_in_days: recovery_period_in_days,
  ))
}

pub type UpdateContinuousBackupsOutput {
  UpdateContinuousBackupsOutput(
    continuous_backups_description: option.Option(ContinuousBackupsDescription),
  )
}

pub fn update_continuous_backups_output_default() -> UpdateContinuousBackupsOutput {
  UpdateContinuousBackupsOutput(continuous_backups_description: option.None)
}

pub fn encode_update_continuous_backups_output_struct(
  input: UpdateContinuousBackupsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.continuous_backups_description {
    option.Some(v) -> [
      #(
        "ContinuousBackupsDescription",
        encode_continuous_backups_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_continuous_backups_output_struct_top(
  input: UpdateContinuousBackupsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.continuous_backups_description {
    option.Some(v) -> [
      #(
        "ContinuousBackupsDescription",
        encode_continuous_backups_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_continuous_backups_output_struct() -> decode.Decoder(
  UpdateContinuousBackupsOutput,
) {
  use <- decode.recursive
  use continuous_backups_description <- decode.optional_field(
    "ContinuousBackupsDescription",
    option.None,
    decode.optional(decode_continuous_backups_description_struct()),
  )
  decode.success(UpdateContinuousBackupsOutput(
    continuous_backups_description: continuous_backups_description,
  ))
}

pub type UpdateContributorInsightsInput {
  UpdateContributorInsightsInput(
    contributor_insights_action: ContributorInsightsAction,
    contributor_insights_mode: option.Option(ContributorInsightsMode),
    index_name: option.Option(String),
    table_name: String,
  )
}

pub fn update_contributor_insights_input_default(
  contributor_insights_action contributor_insights_action: ContributorInsightsAction,
  table_name table_name: String,
) -> UpdateContributorInsightsInput {
  UpdateContributorInsightsInput(
    contributor_insights_action: contributor_insights_action,
    contributor_insights_mode: option.None,
    index_name: option.None,
    table_name: table_name,
  )
}

pub fn encode_update_contributor_insights_input_struct(
  input: UpdateContributorInsightsInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.contributor_insights_action
    [
      #("ContributorInsightsAction", encode_contributor_insights_action_enum(v)),
      ..pairs
    ]
  }
  let pairs = case input.contributor_insights_mode {
    option.Some(v) -> [
      #("ContributorInsightsMode", encode_contributor_insights_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_update_contributor_insights_input_struct_top(
  input: UpdateContributorInsightsInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.contributor_insights_action
    [
      #("ContributorInsightsAction", encode_contributor_insights_action_enum(v)),
      ..pairs
    ]
  }
  let pairs = case input.contributor_insights_mode {
    option.Some(v) -> [
      #("ContributorInsightsMode", encode_contributor_insights_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_update_contributor_insights_input_struct() -> decode.Decoder(
  UpdateContributorInsightsInput,
) {
  use <- decode.recursive
  use contributor_insights_action <- decode.field(
    "ContributorInsightsAction",
    decode_contributor_insights_action_enum(),
  )
  use contributor_insights_mode <- decode.optional_field(
    "ContributorInsightsMode",
    option.None,
    decode.optional(decode_contributor_insights_mode_enum()),
  )
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use table_name <- decode.field("TableName", decode.string)
  decode.success(UpdateContributorInsightsInput(
    contributor_insights_action: contributor_insights_action,
    contributor_insights_mode: contributor_insights_mode,
    index_name: index_name,
    table_name: table_name,
  ))
}

pub type ContributorInsightsAction {
  ContributorInsightsActionDisable
  ContributorInsightsActionEnable
}

pub fn encode_contributor_insights_action_enum(
  v: ContributorInsightsAction,
) -> json.Json {
  case v {
    ContributorInsightsActionDisable -> json.string("DISABLE")
    ContributorInsightsActionEnable -> json.string("ENABLE")
  }
}

pub fn decode_contributor_insights_action_enum() -> decode.Decoder(
  ContributorInsightsAction,
) {
  decode.then(decode.string, fn(s) {
    case s {
      "DISABLE" -> decode.success(ContributorInsightsActionDisable)
      "ENABLE" -> decode.success(ContributorInsightsActionEnable)
      _ ->
        decode.failure(ContributorInsightsActionDisable, "unknown enum value")
    }
  })
}

pub type UpdateContributorInsightsOutput {
  UpdateContributorInsightsOutput(
    contributor_insights_mode: option.Option(ContributorInsightsMode),
    contributor_insights_status: option.Option(ContributorInsightsStatus),
    index_name: option.Option(String),
    table_name: option.Option(String),
  )
}

pub fn update_contributor_insights_output_default() -> UpdateContributorInsightsOutput {
  UpdateContributorInsightsOutput(
    contributor_insights_mode: option.None,
    contributor_insights_status: option.None,
    index_name: option.None,
    table_name: option.None,
  )
}

pub fn encode_update_contributor_insights_output_struct(
  input: UpdateContributorInsightsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.contributor_insights_mode {
    option.Some(v) -> [
      #("ContributorInsightsMode", encode_contributor_insights_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.contributor_insights_status {
    option.Some(v) -> [
      #("ContributorInsightsStatus", encode_contributor_insights_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_contributor_insights_output_struct_top(
  input: UpdateContributorInsightsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.contributor_insights_mode {
    option.Some(v) -> [
      #("ContributorInsightsMode", encode_contributor_insights_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.contributor_insights_status {
    option.Some(v) -> [
      #("ContributorInsightsStatus", encode_contributor_insights_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_contributor_insights_output_struct() -> decode.Decoder(
  UpdateContributorInsightsOutput,
) {
  use <- decode.recursive
  use contributor_insights_mode <- decode.optional_field(
    "ContributorInsightsMode",
    option.None,
    decode.optional(decode_contributor_insights_mode_enum()),
  )
  use contributor_insights_status <- decode.optional_field(
    "ContributorInsightsStatus",
    option.None,
    decode.optional(decode_contributor_insights_status_enum()),
  )
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(UpdateContributorInsightsOutput(
    contributor_insights_mode: contributor_insights_mode,
    contributor_insights_status: contributor_insights_status,
    index_name: index_name,
    table_name: table_name,
  ))
}

pub type UpdateGlobalTableInput {
  UpdateGlobalTableInput(
    global_table_name: String,
    replica_updates: List(ReplicaUpdate),
  )
}

pub fn update_global_table_input_default(
  global_table_name global_table_name: String,
  replica_updates replica_updates: List(ReplicaUpdate),
) -> UpdateGlobalTableInput {
  UpdateGlobalTableInput(
    global_table_name: global_table_name,
    replica_updates: replica_updates,
  )
}

pub fn encode_update_global_table_input_struct(
  input: UpdateGlobalTableInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.global_table_name
    [#("GlobalTableName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.replica_updates
    [
      #(
        "ReplicaUpdates",
        fn(xs) { json.array(xs, encode_replica_update_struct) }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn encode_update_global_table_input_struct_top(
  input: UpdateGlobalTableInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.global_table_name
    [#("GlobalTableName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.replica_updates
    [
      #(
        "ReplicaUpdates",
        fn(xs) { json.array(xs, encode_replica_update_struct) }(v),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn decode_update_global_table_input_struct() -> decode.Decoder(
  UpdateGlobalTableInput,
) {
  use <- decode.recursive
  use global_table_name <- decode.field("GlobalTableName", decode.string)
  use replica_updates <- decode.field(
    "ReplicaUpdates",
    decode.list(decode_replica_update_struct()),
  )
  decode.success(UpdateGlobalTableInput(
    global_table_name: global_table_name,
    replica_updates: replica_updates,
  ))
}

pub type ReplicaUpdate {
  ReplicaUpdate(
    create: option.Option(CreateReplicaAction),
    delete: option.Option(DeleteReplicaAction),
  )
}

pub fn replica_update_default() -> ReplicaUpdate {
  ReplicaUpdate(create: option.None, delete: option.None)
}

pub fn encode_replica_update_struct(input: ReplicaUpdate) -> json.Json {
  let pairs = []
  let pairs = case input.create {
    option.Some(v) -> [
      #("Create", encode_create_replica_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.delete {
    option.Some(v) -> [
      #("Delete", encode_delete_replica_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_update_struct_top(input: ReplicaUpdate) -> json.Json {
  let pairs = []
  let pairs = case input.create {
    option.Some(v) -> [
      #("Create", encode_create_replica_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.delete {
    option.Some(v) -> [
      #("Delete", encode_delete_replica_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_update_struct() -> decode.Decoder(ReplicaUpdate) {
  use <- decode.recursive
  use create <- decode.optional_field(
    "Create",
    option.None,
    decode.optional(decode_create_replica_action_struct()),
  )
  use delete <- decode.optional_field(
    "Delete",
    option.None,
    decode.optional(decode_delete_replica_action_struct()),
  )
  decode.success(ReplicaUpdate(create: create, delete: delete))
}

pub type CreateReplicaAction {
  CreateReplicaAction(region_name: String)
}

pub fn create_replica_action_default(
  region_name region_name: String,
) -> CreateReplicaAction {
  CreateReplicaAction(region_name: region_name)
}

pub fn encode_create_replica_action_struct(
  input: CreateReplicaAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_create_replica_action_struct_top(
  input: CreateReplicaAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_create_replica_action_struct() -> decode.Decoder(
  CreateReplicaAction,
) {
  use <- decode.recursive
  use region_name <- decode.field("RegionName", decode.string)
  decode.success(CreateReplicaAction(region_name: region_name))
}

pub type DeleteReplicaAction {
  DeleteReplicaAction(region_name: String)
}

pub fn delete_replica_action_default(
  region_name region_name: String,
) -> DeleteReplicaAction {
  DeleteReplicaAction(region_name: region_name)
}

pub fn encode_delete_replica_action_struct(
  input: DeleteReplicaAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_delete_replica_action_struct_top(
  input: DeleteReplicaAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_delete_replica_action_struct() -> decode.Decoder(
  DeleteReplicaAction,
) {
  use <- decode.recursive
  use region_name <- decode.field("RegionName", decode.string)
  decode.success(DeleteReplicaAction(region_name: region_name))
}

pub type UpdateGlobalTableOutput {
  UpdateGlobalTableOutput(
    global_table_description: option.Option(GlobalTableDescription),
  )
}

pub fn update_global_table_output_default() -> UpdateGlobalTableOutput {
  UpdateGlobalTableOutput(global_table_description: option.None)
}

pub fn encode_update_global_table_output_struct(
  input: UpdateGlobalTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_description {
    option.Some(v) -> [
      #("GlobalTableDescription", encode_global_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_global_table_output_struct_top(
  input: UpdateGlobalTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_description {
    option.Some(v) -> [
      #("GlobalTableDescription", encode_global_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_global_table_output_struct() -> decode.Decoder(
  UpdateGlobalTableOutput,
) {
  use <- decode.recursive
  use global_table_description <- decode.optional_field(
    "GlobalTableDescription",
    option.None,
    decode.optional(decode_global_table_description_struct()),
  )
  decode.success(UpdateGlobalTableOutput(
    global_table_description: global_table_description,
  ))
}

pub type ReplicaAlreadyExistsException {
  ReplicaAlreadyExistsException(message: option.Option(String))
}

pub fn replica_already_exists_exception_default() -> ReplicaAlreadyExistsException {
  ReplicaAlreadyExistsException(message: option.None)
}

pub fn encode_replica_already_exists_exception_struct(
  input: ReplicaAlreadyExistsException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_already_exists_exception_struct_top(
  input: ReplicaAlreadyExistsException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_already_exists_exception_struct() -> decode.Decoder(
  ReplicaAlreadyExistsException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ReplicaAlreadyExistsException(message: message))
}

pub type ReplicaNotFoundException {
  ReplicaNotFoundException(message: option.Option(String))
}

pub fn replica_not_found_exception_default() -> ReplicaNotFoundException {
  ReplicaNotFoundException(message: option.None)
}

pub fn encode_replica_not_found_exception_struct(
  input: ReplicaNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_not_found_exception_struct_top(
  input: ReplicaNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_not_found_exception_struct() -> decode.Decoder(
  ReplicaNotFoundException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(ReplicaNotFoundException(message: message))
}

pub type UpdateGlobalTableSettingsInput {
  UpdateGlobalTableSettingsInput(
    global_table_billing_mode: option.Option(BillingMode),
    global_table_global_secondary_index_settings_update: option.Option(
      List(GlobalTableGlobalSecondaryIndexSettingsUpdate),
    ),
    global_table_name: String,
    global_table_provisioned_write_capacity_auto_scaling_settings_update: option.Option(
      AutoScalingSettingsUpdate,
    ),
    global_table_provisioned_write_capacity_units: option.Option(Int),
    replica_settings_update: option.Option(List(ReplicaSettingsUpdate)),
  )
}

pub fn update_global_table_settings_input_default(
  global_table_name global_table_name: String,
) -> UpdateGlobalTableSettingsInput {
  UpdateGlobalTableSettingsInput(
    global_table_billing_mode: option.None,
    global_table_global_secondary_index_settings_update: option.None,
    global_table_name: global_table_name,
    global_table_provisioned_write_capacity_auto_scaling_settings_update: option.None,
    global_table_provisioned_write_capacity_units: option.None,
    replica_settings_update: option.None,
  )
}

pub fn encode_update_global_table_settings_input_struct(
  input: UpdateGlobalTableSettingsInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_billing_mode {
    option.Some(v) -> [
      #("GlobalTableBillingMode", encode_billing_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_global_secondary_index_settings_update {
    option.Some(v) -> [
      #(
        "GlobalTableGlobalSecondaryIndexSettingsUpdate",
        fn(xs) {
          json.array(
            xs,
            encode_global_table_global_secondary_index_settings_update_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.global_table_name
    [#("GlobalTableName", json.string(v)), ..pairs]
  }
  let pairs = case
    input.global_table_provisioned_write_capacity_auto_scaling_settings_update
  {
    option.Some(v) -> [
      #(
        "GlobalTableProvisionedWriteCapacityAutoScalingSettingsUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_provisioned_write_capacity_units {
    option.Some(v) -> [
      #("GlobalTableProvisionedWriteCapacityUnits", json.int(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_settings_update {
    option.Some(v) -> [
      #(
        "ReplicaSettingsUpdate",
        fn(xs) { json.array(xs, encode_replica_settings_update_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_global_table_settings_input_struct_top(
  input: UpdateGlobalTableSettingsInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_billing_mode {
    option.Some(v) -> [
      #("GlobalTableBillingMode", encode_billing_mode_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_global_secondary_index_settings_update {
    option.Some(v) -> [
      #(
        "GlobalTableGlobalSecondaryIndexSettingsUpdate",
        fn(xs) {
          json.array(
            xs,
            encode_global_table_global_secondary_index_settings_update_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.global_table_name
    [#("GlobalTableName", json.string(v)), ..pairs]
  }
  let pairs = case
    input.global_table_provisioned_write_capacity_auto_scaling_settings_update
  {
    option.Some(v) -> [
      #(
        "GlobalTableProvisionedWriteCapacityAutoScalingSettingsUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_provisioned_write_capacity_units {
    option.Some(v) -> [
      #("GlobalTableProvisionedWriteCapacityUnits", json.int(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_settings_update {
    option.Some(v) -> [
      #(
        "ReplicaSettingsUpdate",
        fn(xs) { json.array(xs, encode_replica_settings_update_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_global_table_settings_input_struct() -> decode.Decoder(
  UpdateGlobalTableSettingsInput,
) {
  use <- decode.recursive
  use global_table_billing_mode <- decode.optional_field(
    "GlobalTableBillingMode",
    option.None,
    decode.optional(decode_billing_mode_enum()),
  )
  use global_table_global_secondary_index_settings_update <- decode.optional_field(
    "GlobalTableGlobalSecondaryIndexSettingsUpdate",
    option.None,
    decode.optional(
      decode.list(
        decode_global_table_global_secondary_index_settings_update_struct(),
      ),
    ),
  )
  use global_table_name <- decode.field("GlobalTableName", decode.string)
  use global_table_provisioned_write_capacity_auto_scaling_settings_update <- decode.optional_field(
    "GlobalTableProvisionedWriteCapacityAutoScalingSettingsUpdate",
    option.None,
    decode.optional(decode_auto_scaling_settings_update_struct()),
  )
  use global_table_provisioned_write_capacity_units <- decode.optional_field(
    "GlobalTableProvisionedWriteCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  use replica_settings_update <- decode.optional_field(
    "ReplicaSettingsUpdate",
    option.None,
    decode.optional(decode.list(decode_replica_settings_update_struct())),
  )
  decode.success(UpdateGlobalTableSettingsInput(
    global_table_billing_mode: global_table_billing_mode,
    global_table_global_secondary_index_settings_update: global_table_global_secondary_index_settings_update,
    global_table_name: global_table_name,
    global_table_provisioned_write_capacity_auto_scaling_settings_update: global_table_provisioned_write_capacity_auto_scaling_settings_update,
    global_table_provisioned_write_capacity_units: global_table_provisioned_write_capacity_units,
    replica_settings_update: replica_settings_update,
  ))
}

pub type GlobalTableGlobalSecondaryIndexSettingsUpdate {
  GlobalTableGlobalSecondaryIndexSettingsUpdate(
    index_name: String,
    provisioned_write_capacity_auto_scaling_settings_update: option.Option(
      AutoScalingSettingsUpdate,
    ),
    provisioned_write_capacity_units: option.Option(Int),
  )
}

pub fn global_table_global_secondary_index_settings_update_default(
  index_name index_name: String,
) -> GlobalTableGlobalSecondaryIndexSettingsUpdate {
  GlobalTableGlobalSecondaryIndexSettingsUpdate(
    index_name: index_name,
    provisioned_write_capacity_auto_scaling_settings_update: option.None,
    provisioned_write_capacity_units: option.None,
  )
}

pub fn encode_global_table_global_secondary_index_settings_update_struct(
  input: GlobalTableGlobalSecondaryIndexSettingsUpdate,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = case
    input.provisioned_write_capacity_auto_scaling_settings_update
  {
    option.Some(v) -> [
      #(
        "ProvisionedWriteCapacityAutoScalingSettingsUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_write_capacity_units {
    option.Some(v) -> [#("ProvisionedWriteCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_global_table_global_secondary_index_settings_update_struct_top(
  input: GlobalTableGlobalSecondaryIndexSettingsUpdate,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = case
    input.provisioned_write_capacity_auto_scaling_settings_update
  {
    option.Some(v) -> [
      #(
        "ProvisionedWriteCapacityAutoScalingSettingsUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_write_capacity_units {
    option.Some(v) -> [#("ProvisionedWriteCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_global_table_global_secondary_index_settings_update_struct() -> decode.Decoder(
  GlobalTableGlobalSecondaryIndexSettingsUpdate,
) {
  use <- decode.recursive
  use index_name <- decode.field("IndexName", decode.string)
  use provisioned_write_capacity_auto_scaling_settings_update <- decode.optional_field(
    "ProvisionedWriteCapacityAutoScalingSettingsUpdate",
    option.None,
    decode.optional(decode_auto_scaling_settings_update_struct()),
  )
  use provisioned_write_capacity_units <- decode.optional_field(
    "ProvisionedWriteCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(GlobalTableGlobalSecondaryIndexSettingsUpdate(
    index_name: index_name,
    provisioned_write_capacity_auto_scaling_settings_update: provisioned_write_capacity_auto_scaling_settings_update,
    provisioned_write_capacity_units: provisioned_write_capacity_units,
  ))
}

pub type AutoScalingSettingsUpdate {
  AutoScalingSettingsUpdate(
    auto_scaling_disabled: option.Option(Bool),
    auto_scaling_role_arn: option.Option(String),
    maximum_units: option.Option(Int),
    minimum_units: option.Option(Int),
    scaling_policy_update: option.Option(AutoScalingPolicyUpdate),
  )
}

pub fn auto_scaling_settings_update_default() -> AutoScalingSettingsUpdate {
  AutoScalingSettingsUpdate(
    auto_scaling_disabled: option.None,
    auto_scaling_role_arn: option.None,
    maximum_units: option.None,
    minimum_units: option.None,
    scaling_policy_update: option.None,
  )
}

pub fn encode_auto_scaling_settings_update_struct(
  input: AutoScalingSettingsUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.auto_scaling_disabled {
    option.Some(v) -> [#("AutoScalingDisabled", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.auto_scaling_role_arn {
    option.Some(v) -> [#("AutoScalingRoleArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.maximum_units {
    option.Some(v) -> [#("MaximumUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.minimum_units {
    option.Some(v) -> [#("MinimumUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.scaling_policy_update {
    option.Some(v) -> [
      #("ScalingPolicyUpdate", encode_auto_scaling_policy_update_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_auto_scaling_settings_update_struct_top(
  input: AutoScalingSettingsUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.auto_scaling_disabled {
    option.Some(v) -> [#("AutoScalingDisabled", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.auto_scaling_role_arn {
    option.Some(v) -> [#("AutoScalingRoleArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.maximum_units {
    option.Some(v) -> [#("MaximumUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.minimum_units {
    option.Some(v) -> [#("MinimumUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.scaling_policy_update {
    option.Some(v) -> [
      #("ScalingPolicyUpdate", encode_auto_scaling_policy_update_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_auto_scaling_settings_update_struct() -> decode.Decoder(
  AutoScalingSettingsUpdate,
) {
  use <- decode.recursive
  use auto_scaling_disabled <- decode.optional_field(
    "AutoScalingDisabled",
    option.None,
    decode.optional(decode.bool),
  )
  use auto_scaling_role_arn <- decode.optional_field(
    "AutoScalingRoleArn",
    option.None,
    decode.optional(decode.string),
  )
  use maximum_units <- decode.optional_field(
    "MaximumUnits",
    option.None,
    decode.optional(decode.int),
  )
  use minimum_units <- decode.optional_field(
    "MinimumUnits",
    option.None,
    decode.optional(decode.int),
  )
  use scaling_policy_update <- decode.optional_field(
    "ScalingPolicyUpdate",
    option.None,
    decode.optional(decode_auto_scaling_policy_update_struct()),
  )
  decode.success(AutoScalingSettingsUpdate(
    auto_scaling_disabled: auto_scaling_disabled,
    auto_scaling_role_arn: auto_scaling_role_arn,
    maximum_units: maximum_units,
    minimum_units: minimum_units,
    scaling_policy_update: scaling_policy_update,
  ))
}

pub type AutoScalingPolicyUpdate {
  AutoScalingPolicyUpdate(
    policy_name: option.Option(String),
    target_tracking_scaling_policy_configuration: AutoScalingTargetTrackingScalingPolicyConfigurationUpdate,
  )
}

pub fn auto_scaling_policy_update_default(
  target_tracking_scaling_policy_configuration target_tracking_scaling_policy_configuration: AutoScalingTargetTrackingScalingPolicyConfigurationUpdate,
) -> AutoScalingPolicyUpdate {
  AutoScalingPolicyUpdate(
    policy_name: option.None,
    target_tracking_scaling_policy_configuration: target_tracking_scaling_policy_configuration,
  )
}

pub fn encode_auto_scaling_policy_update_struct(
  input: AutoScalingPolicyUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.policy_name {
    option.Some(v) -> [#("PolicyName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.target_tracking_scaling_policy_configuration
    [
      #(
        "TargetTrackingScalingPolicyConfiguration",
        encode_auto_scaling_target_tracking_scaling_policy_configuration_update_struct(
          v,
        ),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn encode_auto_scaling_policy_update_struct_top(
  input: AutoScalingPolicyUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.policy_name {
    option.Some(v) -> [#("PolicyName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.target_tracking_scaling_policy_configuration
    [
      #(
        "TargetTrackingScalingPolicyConfiguration",
        encode_auto_scaling_target_tracking_scaling_policy_configuration_update_struct(
          v,
        ),
      ),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn decode_auto_scaling_policy_update_struct() -> decode.Decoder(
  AutoScalingPolicyUpdate,
) {
  use <- decode.recursive
  use policy_name <- decode.optional_field(
    "PolicyName",
    option.None,
    decode.optional(decode.string),
  )
  use target_tracking_scaling_policy_configuration <- decode.field(
    "TargetTrackingScalingPolicyConfiguration",
    decode_auto_scaling_target_tracking_scaling_policy_configuration_update_struct(),
  )
  decode.success(AutoScalingPolicyUpdate(
    policy_name: policy_name,
    target_tracking_scaling_policy_configuration: target_tracking_scaling_policy_configuration,
  ))
}

pub type AutoScalingTargetTrackingScalingPolicyConfigurationUpdate {
  AutoScalingTargetTrackingScalingPolicyConfigurationUpdate(
    disable_scale_in: option.Option(Bool),
    scale_in_cooldown: option.Option(Int),
    scale_out_cooldown: option.Option(Int),
    target_value: json_float.SmithyFloat,
  )
}

pub fn auto_scaling_target_tracking_scaling_policy_configuration_update_default(
  target_value target_value: json_float.SmithyFloat,
) -> AutoScalingTargetTrackingScalingPolicyConfigurationUpdate {
  AutoScalingTargetTrackingScalingPolicyConfigurationUpdate(
    disable_scale_in: option.None,
    scale_in_cooldown: option.None,
    scale_out_cooldown: option.None,
    target_value: target_value,
  )
}

pub fn encode_auto_scaling_target_tracking_scaling_policy_configuration_update_struct(
  input: AutoScalingTargetTrackingScalingPolicyConfigurationUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.disable_scale_in {
    option.Some(v) -> [#("DisableScaleIn", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.scale_in_cooldown {
    option.Some(v) -> [#("ScaleInCooldown", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.scale_out_cooldown {
    option.Some(v) -> [#("ScaleOutCooldown", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.target_value
    [#("TargetValue", json_float.encode(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_auto_scaling_target_tracking_scaling_policy_configuration_update_struct_top(
  input: AutoScalingTargetTrackingScalingPolicyConfigurationUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.disable_scale_in {
    option.Some(v) -> [#("DisableScaleIn", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.scale_in_cooldown {
    option.Some(v) -> [#("ScaleInCooldown", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.scale_out_cooldown {
    option.Some(v) -> [#("ScaleOutCooldown", json.int(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.target_value
    [#("TargetValue", json_float.encode(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_auto_scaling_target_tracking_scaling_policy_configuration_update_struct() -> decode.Decoder(
  AutoScalingTargetTrackingScalingPolicyConfigurationUpdate,
) {
  use <- decode.recursive
  use disable_scale_in <- decode.optional_field(
    "DisableScaleIn",
    option.None,
    decode.optional(decode.bool),
  )
  use scale_in_cooldown <- decode.optional_field(
    "ScaleInCooldown",
    option.None,
    decode.optional(decode.int),
  )
  use scale_out_cooldown <- decode.optional_field(
    "ScaleOutCooldown",
    option.None,
    decode.optional(decode.int),
  )
  use target_value <- decode.field("TargetValue", json_float.decoder())
  decode.success(AutoScalingTargetTrackingScalingPolicyConfigurationUpdate(
    disable_scale_in: disable_scale_in,
    scale_in_cooldown: scale_in_cooldown,
    scale_out_cooldown: scale_out_cooldown,
    target_value: target_value,
  ))
}

pub type ReplicaSettingsUpdate {
  ReplicaSettingsUpdate(
    region_name: String,
    replica_global_secondary_index_settings_update: option.Option(
      List(ReplicaGlobalSecondaryIndexSettingsUpdate),
    ),
    replica_provisioned_read_capacity_auto_scaling_settings_update: option.Option(
      AutoScalingSettingsUpdate,
    ),
    replica_provisioned_read_capacity_units: option.Option(Int),
    replica_table_class: option.Option(TableClass),
  )
}

pub fn replica_settings_update_default(
  region_name region_name: String,
) -> ReplicaSettingsUpdate {
  ReplicaSettingsUpdate(
    region_name: region_name,
    replica_global_secondary_index_settings_update: option.None,
    replica_provisioned_read_capacity_auto_scaling_settings_update: option.None,
    replica_provisioned_read_capacity_units: option.None,
    replica_table_class: option.None,
  )
}

pub fn encode_replica_settings_update_struct(
  input: ReplicaSettingsUpdate,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  let pairs = case input.replica_global_secondary_index_settings_update {
    option.Some(v) -> [
      #(
        "ReplicaGlobalSecondaryIndexSettingsUpdate",
        fn(xs) {
          json.array(
            xs,
            encode_replica_global_secondary_index_settings_update_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case
    input.replica_provisioned_read_capacity_auto_scaling_settings_update
  {
    option.Some(v) -> [
      #(
        "ReplicaProvisionedReadCapacityAutoScalingSettingsUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_provisioned_read_capacity_units {
    option.Some(v) -> [
      #("ReplicaProvisionedReadCapacityUnits", json.int(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_table_class {
    option.Some(v) -> [
      #("ReplicaTableClass", encode_table_class_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_settings_update_struct_top(
  input: ReplicaSettingsUpdate,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  let pairs = case input.replica_global_secondary_index_settings_update {
    option.Some(v) -> [
      #(
        "ReplicaGlobalSecondaryIndexSettingsUpdate",
        fn(xs) {
          json.array(
            xs,
            encode_replica_global_secondary_index_settings_update_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case
    input.replica_provisioned_read_capacity_auto_scaling_settings_update
  {
    option.Some(v) -> [
      #(
        "ReplicaProvisionedReadCapacityAutoScalingSettingsUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_provisioned_read_capacity_units {
    option.Some(v) -> [
      #("ReplicaProvisionedReadCapacityUnits", json.int(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_table_class {
    option.Some(v) -> [
      #("ReplicaTableClass", encode_table_class_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_settings_update_struct() -> decode.Decoder(
  ReplicaSettingsUpdate,
) {
  use <- decode.recursive
  use region_name <- decode.field("RegionName", decode.string)
  use replica_global_secondary_index_settings_update <- decode.optional_field(
    "ReplicaGlobalSecondaryIndexSettingsUpdate",
    option.None,
    decode.optional(
      decode.list(
        decode_replica_global_secondary_index_settings_update_struct(),
      ),
    ),
  )
  use replica_provisioned_read_capacity_auto_scaling_settings_update <- decode.optional_field(
    "ReplicaProvisionedReadCapacityAutoScalingSettingsUpdate",
    option.None,
    decode.optional(decode_auto_scaling_settings_update_struct()),
  )
  use replica_provisioned_read_capacity_units <- decode.optional_field(
    "ReplicaProvisionedReadCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  use replica_table_class <- decode.optional_field(
    "ReplicaTableClass",
    option.None,
    decode.optional(decode_table_class_enum()),
  )
  decode.success(ReplicaSettingsUpdate(
    region_name: region_name,
    replica_global_secondary_index_settings_update: replica_global_secondary_index_settings_update,
    replica_provisioned_read_capacity_auto_scaling_settings_update: replica_provisioned_read_capacity_auto_scaling_settings_update,
    replica_provisioned_read_capacity_units: replica_provisioned_read_capacity_units,
    replica_table_class: replica_table_class,
  ))
}

pub type ReplicaGlobalSecondaryIndexSettingsUpdate {
  ReplicaGlobalSecondaryIndexSettingsUpdate(
    index_name: String,
    provisioned_read_capacity_auto_scaling_settings_update: option.Option(
      AutoScalingSettingsUpdate,
    ),
    provisioned_read_capacity_units: option.Option(Int),
  )
}

pub fn replica_global_secondary_index_settings_update_default(
  index_name index_name: String,
) -> ReplicaGlobalSecondaryIndexSettingsUpdate {
  ReplicaGlobalSecondaryIndexSettingsUpdate(
    index_name: index_name,
    provisioned_read_capacity_auto_scaling_settings_update: option.None,
    provisioned_read_capacity_units: option.None,
  )
}

pub fn encode_replica_global_secondary_index_settings_update_struct(
  input: ReplicaGlobalSecondaryIndexSettingsUpdate,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = case
    input.provisioned_read_capacity_auto_scaling_settings_update
  {
    option.Some(v) -> [
      #(
        "ProvisionedReadCapacityAutoScalingSettingsUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_read_capacity_units {
    option.Some(v) -> [#("ProvisionedReadCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_global_secondary_index_settings_update_struct_top(
  input: ReplicaGlobalSecondaryIndexSettingsUpdate,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = case
    input.provisioned_read_capacity_auto_scaling_settings_update
  {
    option.Some(v) -> [
      #(
        "ProvisionedReadCapacityAutoScalingSettingsUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_read_capacity_units {
    option.Some(v) -> [#("ProvisionedReadCapacityUnits", json.int(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_global_secondary_index_settings_update_struct() -> decode.Decoder(
  ReplicaGlobalSecondaryIndexSettingsUpdate,
) {
  use <- decode.recursive
  use index_name <- decode.field("IndexName", decode.string)
  use provisioned_read_capacity_auto_scaling_settings_update <- decode.optional_field(
    "ProvisionedReadCapacityAutoScalingSettingsUpdate",
    option.None,
    decode.optional(decode_auto_scaling_settings_update_struct()),
  )
  use provisioned_read_capacity_units <- decode.optional_field(
    "ProvisionedReadCapacityUnits",
    option.None,
    decode.optional(decode.int),
  )
  decode.success(ReplicaGlobalSecondaryIndexSettingsUpdate(
    index_name: index_name,
    provisioned_read_capacity_auto_scaling_settings_update: provisioned_read_capacity_auto_scaling_settings_update,
    provisioned_read_capacity_units: provisioned_read_capacity_units,
  ))
}

pub type UpdateGlobalTableSettingsOutput {
  UpdateGlobalTableSettingsOutput(
    global_table_name: option.Option(String),
    replica_settings: option.Option(List(ReplicaSettingsDescription)),
  )
}

pub fn update_global_table_settings_output_default() -> UpdateGlobalTableSettingsOutput {
  UpdateGlobalTableSettingsOutput(
    global_table_name: option.None,
    replica_settings: option.None,
  )
}

pub fn encode_update_global_table_settings_output_struct(
  input: UpdateGlobalTableSettingsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_name {
    option.Some(v) -> [#("GlobalTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replica_settings {
    option.Some(v) -> [
      #(
        "ReplicaSettings",
        fn(xs) { json.array(xs, encode_replica_settings_description_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_global_table_settings_output_struct_top(
  input: UpdateGlobalTableSettingsOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_table_name {
    option.Some(v) -> [#("GlobalTableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.replica_settings {
    option.Some(v) -> [
      #(
        "ReplicaSettings",
        fn(xs) { json.array(xs, encode_replica_settings_description_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_global_table_settings_output_struct() -> decode.Decoder(
  UpdateGlobalTableSettingsOutput,
) {
  use <- decode.recursive
  use global_table_name <- decode.optional_field(
    "GlobalTableName",
    option.None,
    decode.optional(decode.string),
  )
  use replica_settings <- decode.optional_field(
    "ReplicaSettings",
    option.None,
    decode.optional(decode.list(decode_replica_settings_description_struct())),
  )
  decode.success(UpdateGlobalTableSettingsOutput(
    global_table_name: global_table_name,
    replica_settings: replica_settings,
  ))
}

pub type IndexNotFoundException {
  IndexNotFoundException(message: option.Option(String))
}

pub fn index_not_found_exception_default() -> IndexNotFoundException {
  IndexNotFoundException(message: option.None)
}

pub fn encode_index_not_found_exception_struct(
  input: IndexNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_index_not_found_exception_struct_top(
  input: IndexNotFoundException,
) -> json.Json {
  let pairs = []
  let pairs = case input.message {
    option.Some(v) -> [#("message", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_index_not_found_exception_struct() -> decode.Decoder(
  IndexNotFoundException,
) {
  use <- decode.recursive
  use message <- decode.optional_field(
    "message",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(IndexNotFoundException(message: message))
}

pub type UpdateItemInput {
  UpdateItemInput(
    attribute_updates: option.Option(dict.Dict(String, AttributeValueUpdate)),
    condition_expression: option.Option(String),
    conditional_operator: option.Option(ConditionalOperator),
    expected: option.Option(dict.Dict(String, ExpectedAttributeValue)),
    expression_attribute_names: option.Option(dict.Dict(String, String)),
    expression_attribute_values: option.Option(
      dict.Dict(String, AttributeValue),
    ),
    key: dict.Dict(String, AttributeValue),
    return_consumed_capacity: option.Option(ReturnConsumedCapacity),
    return_item_collection_metrics: option.Option(ReturnItemCollectionMetrics),
    return_values: option.Option(ReturnValue),
    return_values_on_condition_check_failure: option.Option(
      ReturnValuesOnConditionCheckFailure,
    ),
    table_name: String,
    update_expression: option.Option(String),
  )
}

pub fn update_item_input_default(
  key key: dict.Dict(String, AttributeValue),
  table_name table_name: String,
) -> UpdateItemInput {
  UpdateItemInput(
    attribute_updates: option.None,
    condition_expression: option.None,
    conditional_operator: option.None,
    expected: option.None,
    expression_attribute_names: option.None,
    expression_attribute_values: option.None,
    key: key,
    return_consumed_capacity: option.None,
    return_item_collection_metrics: option.None,
    return_values: option.None,
    return_values_on_condition_check_failure: option.None,
    table_name: table_name,
    update_expression: option.None,
  )
}

pub fn encode_update_item_input_struct(input: UpdateItemInput) -> json.Json {
  let pairs = []
  let pairs = case input.attribute_updates {
    option.Some(v) -> [
      #(
        "AttributeUpdates",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_update_struct(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.condition_expression {
    option.Some(v) -> [#("ConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.conditional_operator {
    option.Some(v) -> [
      #("ConditionalOperator", encode_conditional_operator_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expected {
    option.Some(v) -> [
      #(
        "Expected",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_expected_attribute_value_struct(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_item_collection_metrics {
    option.Some(v) -> [
      #(
        "ReturnItemCollectionMetrics",
        encode_return_item_collection_metrics_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_values {
    option.Some(v) -> [#("ReturnValues", encode_return_value_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = case input.update_expression {
    option.Some(v) -> [#("UpdateExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_item_input_struct_top(
  input: UpdateItemInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.attribute_updates {
    option.Some(v) -> [
      #(
        "AttributeUpdates",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_update_struct(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.condition_expression {
    option.Some(v) -> [#("ConditionExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.conditional_operator {
    option.Some(v) -> [
      #("ConditionalOperator", encode_conditional_operator_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expected {
    option.Some(v) -> [
      #(
        "Expected",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_expected_attribute_value_struct(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_names {
    option.Some(v) -> [
      #(
        "ExpressionAttributeNames",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) { #(pair.0, json.string(pair.1)) }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.expression_attribute_values {
    option.Some(v) -> [
      #(
        "ExpressionAttributeValues",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.key
    [
      #(
        "Key",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.return_consumed_capacity {
    option.Some(v) -> [
      #("ReturnConsumedCapacity", encode_return_consumed_capacity_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_item_collection_metrics {
    option.Some(v) -> [
      #(
        "ReturnItemCollectionMetrics",
        encode_return_item_collection_metrics_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.return_values {
    option.Some(v) -> [#("ReturnValues", encode_return_value_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.return_values_on_condition_check_failure {
    option.Some(v) -> [
      #(
        "ReturnValuesOnConditionCheckFailure",
        encode_return_values_on_condition_check_failure_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = case input.update_expression {
    option.Some(v) -> [#("UpdateExpression", json.string(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_item_input_struct() -> decode.Decoder(UpdateItemInput) {
  use <- decode.recursive
  use attribute_updates <- decode.optional_field(
    "AttributeUpdates",
    option.None,
    decode.optional(decode.dict(
      decode.string,
      decode_attribute_value_update_struct(),
    )),
  )
  use condition_expression <- decode.optional_field(
    "ConditionExpression",
    option.None,
    decode.optional(decode.string),
  )
  use conditional_operator <- decode.optional_field(
    "ConditionalOperator",
    option.None,
    decode.optional(decode_conditional_operator_enum()),
  )
  use expected <- decode.optional_field(
    "Expected",
    option.None,
    decode.optional(decode.dict(
      decode.string,
      decode_expected_attribute_value_struct(),
    )),
  )
  use expression_attribute_names <- decode.optional_field(
    "ExpressionAttributeNames",
    option.None,
    decode.optional(decode.dict(decode.string, decode.string)),
  )
  use expression_attribute_values <- decode.optional_field(
    "ExpressionAttributeValues",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use key <- decode.field(
    "Key",
    decode.dict(decode.string, decode_attribute_value_union()),
  )
  use return_consumed_capacity <- decode.optional_field(
    "ReturnConsumedCapacity",
    option.None,
    decode.optional(decode_return_consumed_capacity_enum()),
  )
  use return_item_collection_metrics <- decode.optional_field(
    "ReturnItemCollectionMetrics",
    option.None,
    decode.optional(decode_return_item_collection_metrics_enum()),
  )
  use return_values <- decode.optional_field(
    "ReturnValues",
    option.None,
    decode.optional(decode_return_value_enum()),
  )
  use return_values_on_condition_check_failure <- decode.optional_field(
    "ReturnValuesOnConditionCheckFailure",
    option.None,
    decode.optional(decode_return_values_on_condition_check_failure_enum()),
  )
  use table_name <- decode.field("TableName", decode.string)
  use update_expression <- decode.optional_field(
    "UpdateExpression",
    option.None,
    decode.optional(decode.string),
  )
  decode.success(UpdateItemInput(
    attribute_updates: attribute_updates,
    condition_expression: condition_expression,
    conditional_operator: conditional_operator,
    expected: expected,
    expression_attribute_names: expression_attribute_names,
    expression_attribute_values: expression_attribute_values,
    key: key,
    return_consumed_capacity: return_consumed_capacity,
    return_item_collection_metrics: return_item_collection_metrics,
    return_values: return_values,
    return_values_on_condition_check_failure: return_values_on_condition_check_failure,
    table_name: table_name,
    update_expression: update_expression,
  ))
}

pub type AttributeValueUpdate {
  AttributeValueUpdate(
    action: option.Option(AttributeAction),
    value: option.Option(AttributeValue),
  )
}

pub fn attribute_value_update_default() -> AttributeValueUpdate {
  AttributeValueUpdate(action: option.None, value: option.None)
}

pub fn encode_attribute_value_update_struct(
  input: AttributeValueUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.action {
    option.Some(v) -> [#("Action", encode_attribute_action_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.value {
    option.Some(v) -> [#("Value", encode_attribute_value_union(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_attribute_value_update_struct_top(
  input: AttributeValueUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.action {
    option.Some(v) -> [#("Action", encode_attribute_action_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.value {
    option.Some(v) -> [#("Value", encode_attribute_value_union(v)), ..pairs]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_attribute_value_update_struct() -> decode.Decoder(
  AttributeValueUpdate,
) {
  use <- decode.recursive
  use action <- decode.optional_field(
    "Action",
    option.None,
    decode.optional(decode_attribute_action_enum()),
  )
  use value <- decode.optional_field(
    "Value",
    option.None,
    decode.optional(decode_attribute_value_union()),
  )
  decode.success(AttributeValueUpdate(action: action, value: value))
}

pub type AttributeAction {
  AttributeActionAdd
  AttributeActionDelete
  AttributeActionPut
}

pub fn encode_attribute_action_enum(v: AttributeAction) -> json.Json {
  case v {
    AttributeActionAdd -> json.string("ADD")
    AttributeActionDelete -> json.string("DELETE")
    AttributeActionPut -> json.string("PUT")
  }
}

pub fn decode_attribute_action_enum() -> decode.Decoder(AttributeAction) {
  decode.then(decode.string, fn(s) {
    case s {
      "ADD" -> decode.success(AttributeActionAdd)
      "DELETE" -> decode.success(AttributeActionDelete)
      "PUT" -> decode.success(AttributeActionPut)
      _ -> decode.failure(AttributeActionAdd, "unknown enum value")
    }
  })
}

pub type UpdateItemOutput {
  UpdateItemOutput(
    attributes: option.Option(dict.Dict(String, AttributeValue)),
    consumed_capacity: option.Option(ConsumedCapacity),
    item_collection_metrics: option.Option(ItemCollectionMetrics),
  )
}

pub fn update_item_output_default() -> UpdateItemOutput {
  UpdateItemOutput(
    attributes: option.None,
    consumed_capacity: option.None,
    item_collection_metrics: option.None,
  )
}

pub fn encode_update_item_output_struct(input: UpdateItemOutput) -> json.Json {
  let pairs = []
  let pairs = case input.attributes {
    option.Some(v) -> [
      #(
        "Attributes",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_collection_metrics {
    option.Some(v) -> [
      #("ItemCollectionMetrics", encode_item_collection_metrics_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_item_output_struct_top(
  input: UpdateItemOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.attributes {
    option.Some(v) -> [
      #(
        "Attributes",
        fn(d) {
          json.object(
            dict.to_list(d)
            |> list.map(fn(pair) {
              #(pair.0, encode_attribute_value_union(pair.1))
            }),
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.consumed_capacity {
    option.Some(v) -> [
      #("ConsumedCapacity", encode_consumed_capacity_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.item_collection_metrics {
    option.Some(v) -> [
      #("ItemCollectionMetrics", encode_item_collection_metrics_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_item_output_struct() -> decode.Decoder(UpdateItemOutput) {
  use <- decode.recursive
  use attributes <- decode.optional_field(
    "Attributes",
    option.None,
    decode.optional(decode.dict(decode.string, decode_attribute_value_union())),
  )
  use consumed_capacity <- decode.optional_field(
    "ConsumedCapacity",
    option.None,
    decode.optional(decode_consumed_capacity_struct()),
  )
  use item_collection_metrics <- decode.optional_field(
    "ItemCollectionMetrics",
    option.None,
    decode.optional(decode_item_collection_metrics_struct()),
  )
  decode.success(UpdateItemOutput(
    attributes: attributes,
    consumed_capacity: consumed_capacity,
    item_collection_metrics: item_collection_metrics,
  ))
}

pub type UpdateKinesisStreamingDestinationInput {
  UpdateKinesisStreamingDestinationInput(
    stream_arn: String,
    table_name: String,
    update_kinesis_streaming_configuration: option.Option(
      UpdateKinesisStreamingConfiguration,
    ),
  )
}

pub fn update_kinesis_streaming_destination_input_default(
  stream_arn stream_arn: String,
  table_name table_name: String,
) -> UpdateKinesisStreamingDestinationInput {
  UpdateKinesisStreamingDestinationInput(
    stream_arn: stream_arn,
    table_name: table_name,
    update_kinesis_streaming_configuration: option.None,
  )
}

pub fn encode_update_kinesis_streaming_destination_input_struct(
  input: UpdateKinesisStreamingDestinationInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.stream_arn
    [#("StreamArn", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = case input.update_kinesis_streaming_configuration {
    option.Some(v) -> [
      #(
        "UpdateKinesisStreamingConfiguration",
        encode_update_kinesis_streaming_configuration_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_kinesis_streaming_destination_input_struct_top(
  input: UpdateKinesisStreamingDestinationInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.stream_arn
    [#("StreamArn", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = case input.update_kinesis_streaming_configuration {
    option.Some(v) -> [
      #(
        "UpdateKinesisStreamingConfiguration",
        encode_update_kinesis_streaming_configuration_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_kinesis_streaming_destination_input_struct() -> decode.Decoder(
  UpdateKinesisStreamingDestinationInput,
) {
  use <- decode.recursive
  use stream_arn <- decode.field("StreamArn", decode.string)
  use table_name <- decode.field("TableName", decode.string)
  use update_kinesis_streaming_configuration <- decode.optional_field(
    "UpdateKinesisStreamingConfiguration",
    option.None,
    decode.optional(decode_update_kinesis_streaming_configuration_struct()),
  )
  decode.success(UpdateKinesisStreamingDestinationInput(
    stream_arn: stream_arn,
    table_name: table_name,
    update_kinesis_streaming_configuration: update_kinesis_streaming_configuration,
  ))
}

pub type UpdateKinesisStreamingConfiguration {
  UpdateKinesisStreamingConfiguration(
    approximate_creation_date_time_precision: option.Option(
      ApproximateCreationDateTimePrecision,
    ),
  )
}

pub fn update_kinesis_streaming_configuration_default() -> UpdateKinesisStreamingConfiguration {
  UpdateKinesisStreamingConfiguration(
    approximate_creation_date_time_precision: option.None,
  )
}

pub fn encode_update_kinesis_streaming_configuration_struct(
  input: UpdateKinesisStreamingConfiguration,
) -> json.Json {
  let pairs = []
  let pairs = case input.approximate_creation_date_time_precision {
    option.Some(v) -> [
      #(
        "ApproximateCreationDateTimePrecision",
        encode_approximate_creation_date_time_precision_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_kinesis_streaming_configuration_struct_top(
  input: UpdateKinesisStreamingConfiguration,
) -> json.Json {
  let pairs = []
  let pairs = case input.approximate_creation_date_time_precision {
    option.Some(v) -> [
      #(
        "ApproximateCreationDateTimePrecision",
        encode_approximate_creation_date_time_precision_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_kinesis_streaming_configuration_struct() -> decode.Decoder(
  UpdateKinesisStreamingConfiguration,
) {
  use <- decode.recursive
  use approximate_creation_date_time_precision <- decode.optional_field(
    "ApproximateCreationDateTimePrecision",
    option.None,
    decode.optional(decode_approximate_creation_date_time_precision_enum()),
  )
  decode.success(UpdateKinesisStreamingConfiguration(
    approximate_creation_date_time_precision: approximate_creation_date_time_precision,
  ))
}

pub type UpdateKinesisStreamingDestinationOutput {
  UpdateKinesisStreamingDestinationOutput(
    destination_status: option.Option(DestinationStatus),
    stream_arn: option.Option(String),
    table_name: option.Option(String),
    update_kinesis_streaming_configuration: option.Option(
      UpdateKinesisStreamingConfiguration,
    ),
  )
}

pub fn update_kinesis_streaming_destination_output_default() -> UpdateKinesisStreamingDestinationOutput {
  UpdateKinesisStreamingDestinationOutput(
    destination_status: option.None,
    stream_arn: option.None,
    table_name: option.None,
    update_kinesis_streaming_configuration: option.None,
  )
}

pub fn encode_update_kinesis_streaming_destination_output_struct(
  input: UpdateKinesisStreamingDestinationOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.destination_status {
    option.Some(v) -> [
      #("DestinationStatus", encode_destination_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_arn {
    option.Some(v) -> [#("StreamArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.update_kinesis_streaming_configuration {
    option.Some(v) -> [
      #(
        "UpdateKinesisStreamingConfiguration",
        encode_update_kinesis_streaming_configuration_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_kinesis_streaming_destination_output_struct_top(
  input: UpdateKinesisStreamingDestinationOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.destination_status {
    option.Some(v) -> [
      #("DestinationStatus", encode_destination_status_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_arn {
    option.Some(v) -> [#("StreamArn", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.table_name {
    option.Some(v) -> [#("TableName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.update_kinesis_streaming_configuration {
    option.Some(v) -> [
      #(
        "UpdateKinesisStreamingConfiguration",
        encode_update_kinesis_streaming_configuration_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_kinesis_streaming_destination_output_struct() -> decode.Decoder(
  UpdateKinesisStreamingDestinationOutput,
) {
  use <- decode.recursive
  use destination_status <- decode.optional_field(
    "DestinationStatus",
    option.None,
    decode.optional(decode_destination_status_enum()),
  )
  use stream_arn <- decode.optional_field(
    "StreamArn",
    option.None,
    decode.optional(decode.string),
  )
  use table_name <- decode.optional_field(
    "TableName",
    option.None,
    decode.optional(decode.string),
  )
  use update_kinesis_streaming_configuration <- decode.optional_field(
    "UpdateKinesisStreamingConfiguration",
    option.None,
    decode.optional(decode_update_kinesis_streaming_configuration_struct()),
  )
  decode.success(UpdateKinesisStreamingDestinationOutput(
    destination_status: destination_status,
    stream_arn: stream_arn,
    table_name: table_name,
    update_kinesis_streaming_configuration: update_kinesis_streaming_configuration,
  ))
}

pub type UpdateTableInput {
  UpdateTableInput(
    attribute_definitions: option.Option(List(AttributeDefinition)),
    billing_mode: option.Option(BillingMode),
    deletion_protection_enabled: option.Option(Bool),
    global_secondary_index_updates: option.Option(
      List(GlobalSecondaryIndexUpdate),
    ),
    global_table_settings_replication_mode: option.Option(
      GlobalTableSettingsReplicationMode,
    ),
    global_table_witness_updates: option.Option(
      List(GlobalTableWitnessGroupUpdate),
    ),
    multi_region_consistency: option.Option(MultiRegionConsistency),
    on_demand_throughput: option.Option(OnDemandThroughput),
    provisioned_throughput: option.Option(ProvisionedThroughput),
    replica_updates: option.Option(List(ReplicationGroupUpdate)),
    sse_specification: option.Option(SSESpecification),
    stream_specification: option.Option(StreamSpecification),
    table_class: option.Option(TableClass),
    table_name: String,
    warm_throughput: option.Option(WarmThroughput),
  )
}

pub fn update_table_input_default(
  table_name table_name: String,
) -> UpdateTableInput {
  UpdateTableInput(
    attribute_definitions: option.None,
    billing_mode: option.None,
    deletion_protection_enabled: option.None,
    global_secondary_index_updates: option.None,
    global_table_settings_replication_mode: option.None,
    global_table_witness_updates: option.None,
    multi_region_consistency: option.None,
    on_demand_throughput: option.None,
    provisioned_throughput: option.None,
    replica_updates: option.None,
    sse_specification: option.None,
    stream_specification: option.None,
    table_class: option.None,
    table_name: table_name,
    warm_throughput: option.None,
  )
}

pub fn encode_update_table_input_struct(input: UpdateTableInput) -> json.Json {
  let pairs = []
  let pairs = case input.attribute_definitions {
    option.Some(v) -> [
      #(
        "AttributeDefinitions",
        fn(xs) { json.array(xs, encode_attribute_definition_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.billing_mode {
    option.Some(v) -> [#("BillingMode", encode_billing_mode_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.deletion_protection_enabled {
    option.Some(v) -> [#("DeletionProtectionEnabled", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_index_updates {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexUpdates",
        fn(xs) { json.array(xs, encode_global_secondary_index_update_struct) }(
          v,
        ),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_settings_replication_mode {
    option.Some(v) -> [
      #(
        "GlobalTableSettingsReplicationMode",
        encode_global_table_settings_replication_mode_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_witness_updates {
    option.Some(v) -> [
      #(
        "GlobalTableWitnessUpdates",
        fn(xs) {
          json.array(xs, encode_global_table_witness_group_update_struct)
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.multi_region_consistency {
    option.Some(v) -> [
      #("MultiRegionConsistency", encode_multi_region_consistency_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_updates {
    option.Some(v) -> [
      #(
        "ReplicaUpdates",
        fn(xs) { json.array(xs, encode_replication_group_update_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.sse_specification {
    option.Some(v) -> [
      #("SSESpecification", encode_sse_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_specification {
    option.Some(v) -> [
      #("StreamSpecification", encode_stream_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_class {
    option.Some(v) -> [#("TableClass", encode_table_class_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_warm_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_table_input_struct_top(
  input: UpdateTableInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.attribute_definitions {
    option.Some(v) -> [
      #(
        "AttributeDefinitions",
        fn(xs) { json.array(xs, encode_attribute_definition_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.billing_mode {
    option.Some(v) -> [#("BillingMode", encode_billing_mode_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.deletion_protection_enabled {
    option.Some(v) -> [#("DeletionProtectionEnabled", json.bool(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.global_secondary_index_updates {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexUpdates",
        fn(xs) { json.array(xs, encode_global_secondary_index_update_struct) }(
          v,
        ),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_settings_replication_mode {
    option.Some(v) -> [
      #(
        "GlobalTableSettingsReplicationMode",
        encode_global_table_settings_replication_mode_enum(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.global_table_witness_updates {
    option.Some(v) -> [
      #(
        "GlobalTableWitnessUpdates",
        fn(xs) {
          json.array(xs, encode_global_table_witness_group_update_struct)
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.multi_region_consistency {
    option.Some(v) -> [
      #("MultiRegionConsistency", encode_multi_region_consistency_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_updates {
    option.Some(v) -> [
      #(
        "ReplicaUpdates",
        fn(xs) { json.array(xs, encode_replication_group_update_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.sse_specification {
    option.Some(v) -> [
      #("SSESpecification", encode_sse_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.stream_specification {
    option.Some(v) -> [
      #("StreamSpecification", encode_stream_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.table_class {
    option.Some(v) -> [#("TableClass", encode_table_class_enum(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_warm_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_table_input_struct() -> decode.Decoder(UpdateTableInput) {
  use <- decode.recursive
  use attribute_definitions <- decode.optional_field(
    "AttributeDefinitions",
    option.None,
    decode.optional(decode.list(decode_attribute_definition_struct())),
  )
  use billing_mode <- decode.optional_field(
    "BillingMode",
    option.None,
    decode.optional(decode_billing_mode_enum()),
  )
  use deletion_protection_enabled <- decode.optional_field(
    "DeletionProtectionEnabled",
    option.None,
    decode.optional(decode.bool),
  )
  use global_secondary_index_updates <- decode.optional_field(
    "GlobalSecondaryIndexUpdates",
    option.None,
    decode.optional(decode.list(decode_global_secondary_index_update_struct())),
  )
  use global_table_settings_replication_mode <- decode.optional_field(
    "GlobalTableSettingsReplicationMode",
    option.None,
    decode.optional(decode_global_table_settings_replication_mode_enum()),
  )
  use global_table_witness_updates <- decode.optional_field(
    "GlobalTableWitnessUpdates",
    option.None,
    decode.optional(
      decode.list(decode_global_table_witness_group_update_struct()),
    ),
  )
  use multi_region_consistency <- decode.optional_field(
    "MultiRegionConsistency",
    option.None,
    decode.optional(decode_multi_region_consistency_enum()),
  )
  use on_demand_throughput <- decode.optional_field(
    "OnDemandThroughput",
    option.None,
    decode.optional(decode_on_demand_throughput_struct()),
  )
  use provisioned_throughput <- decode.optional_field(
    "ProvisionedThroughput",
    option.None,
    decode.optional(decode_provisioned_throughput_struct()),
  )
  use replica_updates <- decode.optional_field(
    "ReplicaUpdates",
    option.None,
    decode.optional(decode.list(decode_replication_group_update_struct())),
  )
  use sse_specification <- decode.optional_field(
    "SSESpecification",
    option.None,
    decode.optional(decode_sse_specification_struct()),
  )
  use stream_specification <- decode.optional_field(
    "StreamSpecification",
    option.None,
    decode.optional(decode_stream_specification_struct()),
  )
  use table_class <- decode.optional_field(
    "TableClass",
    option.None,
    decode.optional(decode_table_class_enum()),
  )
  use table_name <- decode.field("TableName", decode.string)
  use warm_throughput <- decode.optional_field(
    "WarmThroughput",
    option.None,
    decode.optional(decode_warm_throughput_struct()),
  )
  decode.success(UpdateTableInput(
    attribute_definitions: attribute_definitions,
    billing_mode: billing_mode,
    deletion_protection_enabled: deletion_protection_enabled,
    global_secondary_index_updates: global_secondary_index_updates,
    global_table_settings_replication_mode: global_table_settings_replication_mode,
    global_table_witness_updates: global_table_witness_updates,
    multi_region_consistency: multi_region_consistency,
    on_demand_throughput: on_demand_throughput,
    provisioned_throughput: provisioned_throughput,
    replica_updates: replica_updates,
    sse_specification: sse_specification,
    stream_specification: stream_specification,
    table_class: table_class,
    table_name: table_name,
    warm_throughput: warm_throughput,
  ))
}

pub type GlobalSecondaryIndexUpdate {
  GlobalSecondaryIndexUpdate(
    create: option.Option(CreateGlobalSecondaryIndexAction),
    delete: option.Option(DeleteGlobalSecondaryIndexAction),
    update: option.Option(UpdateGlobalSecondaryIndexAction),
  )
}

pub fn global_secondary_index_update_default() -> GlobalSecondaryIndexUpdate {
  GlobalSecondaryIndexUpdate(
    create: option.None,
    delete: option.None,
    update: option.None,
  )
}

pub fn encode_global_secondary_index_update_struct(
  input: GlobalSecondaryIndexUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.create {
    option.Some(v) -> [
      #("Create", encode_create_global_secondary_index_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.delete {
    option.Some(v) -> [
      #("Delete", encode_delete_global_secondary_index_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.update {
    option.Some(v) -> [
      #("Update", encode_update_global_secondary_index_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_global_secondary_index_update_struct_top(
  input: GlobalSecondaryIndexUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.create {
    option.Some(v) -> [
      #("Create", encode_create_global_secondary_index_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.delete {
    option.Some(v) -> [
      #("Delete", encode_delete_global_secondary_index_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.update {
    option.Some(v) -> [
      #("Update", encode_update_global_secondary_index_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_global_secondary_index_update_struct() -> decode.Decoder(
  GlobalSecondaryIndexUpdate,
) {
  use <- decode.recursive
  use create <- decode.optional_field(
    "Create",
    option.None,
    decode.optional(decode_create_global_secondary_index_action_struct()),
  )
  use delete <- decode.optional_field(
    "Delete",
    option.None,
    decode.optional(decode_delete_global_secondary_index_action_struct()),
  )
  use update <- decode.optional_field(
    "Update",
    option.None,
    decode.optional(decode_update_global_secondary_index_action_struct()),
  )
  decode.success(GlobalSecondaryIndexUpdate(
    create: create,
    delete: delete,
    update: update,
  ))
}

pub type CreateGlobalSecondaryIndexAction {
  CreateGlobalSecondaryIndexAction(
    index_name: String,
    key_schema: List(KeySchemaElement),
    on_demand_throughput: option.Option(OnDemandThroughput),
    projection: Projection,
    provisioned_throughput: option.Option(ProvisionedThroughput),
    warm_throughput: option.Option(WarmThroughput),
  )
}

pub fn create_global_secondary_index_action_default(
  index_name index_name: String,
  key_schema key_schema: List(KeySchemaElement),
  projection projection: Projection,
) -> CreateGlobalSecondaryIndexAction {
  CreateGlobalSecondaryIndexAction(
    index_name: index_name,
    key_schema: key_schema,
    on_demand_throughput: option.None,
    projection: projection,
    provisioned_throughput: option.None,
    warm_throughput: option.None,
  )
}

pub fn encode_create_global_secondary_index_action_struct(
  input: CreateGlobalSecondaryIndexAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.key_schema
    [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.projection
    [#("Projection", encode_projection_struct(v)), ..pairs]
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_warm_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_create_global_secondary_index_action_struct_top(
  input: CreateGlobalSecondaryIndexAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.key_schema
    [
      #(
        "KeySchema",
        fn(xs) { json.array(xs, encode_key_schema_element_struct) }(v),
      ),
      ..pairs
    ]
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.projection
    [#("Projection", encode_projection_struct(v)), ..pairs]
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_warm_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_create_global_secondary_index_action_struct() -> decode.Decoder(
  CreateGlobalSecondaryIndexAction,
) {
  use <- decode.recursive
  use index_name <- decode.field("IndexName", decode.string)
  use key_schema <- decode.field(
    "KeySchema",
    decode.list(decode_key_schema_element_struct()),
  )
  use on_demand_throughput <- decode.optional_field(
    "OnDemandThroughput",
    option.None,
    decode.optional(decode_on_demand_throughput_struct()),
  )
  use projection <- decode.field("Projection", decode_projection_struct())
  use provisioned_throughput <- decode.optional_field(
    "ProvisionedThroughput",
    option.None,
    decode.optional(decode_provisioned_throughput_struct()),
  )
  use warm_throughput <- decode.optional_field(
    "WarmThroughput",
    option.None,
    decode.optional(decode_warm_throughput_struct()),
  )
  decode.success(CreateGlobalSecondaryIndexAction(
    index_name: index_name,
    key_schema: key_schema,
    on_demand_throughput: on_demand_throughput,
    projection: projection,
    provisioned_throughput: provisioned_throughput,
    warm_throughput: warm_throughput,
  ))
}

pub type DeleteGlobalSecondaryIndexAction {
  DeleteGlobalSecondaryIndexAction(index_name: String)
}

pub fn delete_global_secondary_index_action_default(
  index_name index_name: String,
) -> DeleteGlobalSecondaryIndexAction {
  DeleteGlobalSecondaryIndexAction(index_name: index_name)
}

pub fn encode_delete_global_secondary_index_action_struct(
  input: DeleteGlobalSecondaryIndexAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_delete_global_secondary_index_action_struct_top(
  input: DeleteGlobalSecondaryIndexAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_delete_global_secondary_index_action_struct() -> decode.Decoder(
  DeleteGlobalSecondaryIndexAction,
) {
  use <- decode.recursive
  use index_name <- decode.field("IndexName", decode.string)
  decode.success(DeleteGlobalSecondaryIndexAction(index_name: index_name))
}

pub type UpdateGlobalSecondaryIndexAction {
  UpdateGlobalSecondaryIndexAction(
    index_name: String,
    on_demand_throughput: option.Option(OnDemandThroughput),
    provisioned_throughput: option.Option(ProvisionedThroughput),
    warm_throughput: option.Option(WarmThroughput),
  )
}

pub fn update_global_secondary_index_action_default(
  index_name index_name: String,
) -> UpdateGlobalSecondaryIndexAction {
  UpdateGlobalSecondaryIndexAction(
    index_name: index_name,
    on_demand_throughput: option.None,
    provisioned_throughput: option.None,
    warm_throughput: option.None,
  )
}

pub fn encode_update_global_secondary_index_action_struct(
  input: UpdateGlobalSecondaryIndexAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_warm_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_global_secondary_index_action_struct_top(
  input: UpdateGlobalSecondaryIndexAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = case input.on_demand_throughput {
    option.Some(v) -> [
      #("OnDemandThroughput", encode_on_demand_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput {
    option.Some(v) -> [
      #("ProvisionedThroughput", encode_provisioned_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.warm_throughput {
    option.Some(v) -> [
      #("WarmThroughput", encode_warm_throughput_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_global_secondary_index_action_struct() -> decode.Decoder(
  UpdateGlobalSecondaryIndexAction,
) {
  use <- decode.recursive
  use index_name <- decode.field("IndexName", decode.string)
  use on_demand_throughput <- decode.optional_field(
    "OnDemandThroughput",
    option.None,
    decode.optional(decode_on_demand_throughput_struct()),
  )
  use provisioned_throughput <- decode.optional_field(
    "ProvisionedThroughput",
    option.None,
    decode.optional(decode_provisioned_throughput_struct()),
  )
  use warm_throughput <- decode.optional_field(
    "WarmThroughput",
    option.None,
    decode.optional(decode_warm_throughput_struct()),
  )
  decode.success(UpdateGlobalSecondaryIndexAction(
    index_name: index_name,
    on_demand_throughput: on_demand_throughput,
    provisioned_throughput: provisioned_throughput,
    warm_throughput: warm_throughput,
  ))
}

pub type GlobalTableWitnessGroupUpdate {
  GlobalTableWitnessGroupUpdate(
    create: option.Option(CreateGlobalTableWitnessGroupMemberAction),
    delete: option.Option(DeleteGlobalTableWitnessGroupMemberAction),
  )
}

pub fn global_table_witness_group_update_default() -> GlobalTableWitnessGroupUpdate {
  GlobalTableWitnessGroupUpdate(create: option.None, delete: option.None)
}

pub fn encode_global_table_witness_group_update_struct(
  input: GlobalTableWitnessGroupUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.create {
    option.Some(v) -> [
      #(
        "Create",
        encode_create_global_table_witness_group_member_action_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.delete {
    option.Some(v) -> [
      #(
        "Delete",
        encode_delete_global_table_witness_group_member_action_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_global_table_witness_group_update_struct_top(
  input: GlobalTableWitnessGroupUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.create {
    option.Some(v) -> [
      #(
        "Create",
        encode_create_global_table_witness_group_member_action_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.delete {
    option.Some(v) -> [
      #(
        "Delete",
        encode_delete_global_table_witness_group_member_action_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_global_table_witness_group_update_struct() -> decode.Decoder(
  GlobalTableWitnessGroupUpdate,
) {
  use <- decode.recursive
  use create <- decode.optional_field(
    "Create",
    option.None,
    decode.optional(
      decode_create_global_table_witness_group_member_action_struct(),
    ),
  )
  use delete <- decode.optional_field(
    "Delete",
    option.None,
    decode.optional(
      decode_delete_global_table_witness_group_member_action_struct(),
    ),
  )
  decode.success(GlobalTableWitnessGroupUpdate(create: create, delete: delete))
}

pub type CreateGlobalTableWitnessGroupMemberAction {
  CreateGlobalTableWitnessGroupMemberAction(region_name: String)
}

pub fn create_global_table_witness_group_member_action_default(
  region_name region_name: String,
) -> CreateGlobalTableWitnessGroupMemberAction {
  CreateGlobalTableWitnessGroupMemberAction(region_name: region_name)
}

pub fn encode_create_global_table_witness_group_member_action_struct(
  input: CreateGlobalTableWitnessGroupMemberAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_create_global_table_witness_group_member_action_struct_top(
  input: CreateGlobalTableWitnessGroupMemberAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_create_global_table_witness_group_member_action_struct() -> decode.Decoder(
  CreateGlobalTableWitnessGroupMemberAction,
) {
  use <- decode.recursive
  use region_name <- decode.field("RegionName", decode.string)
  decode.success(CreateGlobalTableWitnessGroupMemberAction(
    region_name: region_name,
  ))
}

pub type DeleteGlobalTableWitnessGroupMemberAction {
  DeleteGlobalTableWitnessGroupMemberAction(region_name: String)
}

pub fn delete_global_table_witness_group_member_action_default(
  region_name region_name: String,
) -> DeleteGlobalTableWitnessGroupMemberAction {
  DeleteGlobalTableWitnessGroupMemberAction(region_name: region_name)
}

pub fn encode_delete_global_table_witness_group_member_action_struct(
  input: DeleteGlobalTableWitnessGroupMemberAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_delete_global_table_witness_group_member_action_struct_top(
  input: DeleteGlobalTableWitnessGroupMemberAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_delete_global_table_witness_group_member_action_struct() -> decode.Decoder(
  DeleteGlobalTableWitnessGroupMemberAction,
) {
  use <- decode.recursive
  use region_name <- decode.field("RegionName", decode.string)
  decode.success(DeleteGlobalTableWitnessGroupMemberAction(
    region_name: region_name,
  ))
}

pub type ReplicationGroupUpdate {
  ReplicationGroupUpdate(
    create: option.Option(CreateReplicationGroupMemberAction),
    delete: option.Option(DeleteReplicationGroupMemberAction),
    update: option.Option(UpdateReplicationGroupMemberAction),
  )
}

pub fn replication_group_update_default() -> ReplicationGroupUpdate {
  ReplicationGroupUpdate(
    create: option.None,
    delete: option.None,
    update: option.None,
  )
}

pub fn encode_replication_group_update_struct(
  input: ReplicationGroupUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.create {
    option.Some(v) -> [
      #("Create", encode_create_replication_group_member_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.delete {
    option.Some(v) -> [
      #("Delete", encode_delete_replication_group_member_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.update {
    option.Some(v) -> [
      #("Update", encode_update_replication_group_member_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replication_group_update_struct_top(
  input: ReplicationGroupUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.create {
    option.Some(v) -> [
      #("Create", encode_create_replication_group_member_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.delete {
    option.Some(v) -> [
      #("Delete", encode_delete_replication_group_member_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.update {
    option.Some(v) -> [
      #("Update", encode_update_replication_group_member_action_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replication_group_update_struct() -> decode.Decoder(
  ReplicationGroupUpdate,
) {
  use <- decode.recursive
  use create <- decode.optional_field(
    "Create",
    option.None,
    decode.optional(decode_create_replication_group_member_action_struct()),
  )
  use delete <- decode.optional_field(
    "Delete",
    option.None,
    decode.optional(decode_delete_replication_group_member_action_struct()),
  )
  use update <- decode.optional_field(
    "Update",
    option.None,
    decode.optional(decode_update_replication_group_member_action_struct()),
  )
  decode.success(ReplicationGroupUpdate(
    create: create,
    delete: delete,
    update: update,
  ))
}

pub type CreateReplicationGroupMemberAction {
  CreateReplicationGroupMemberAction(
    global_secondary_indexes: option.Option(List(ReplicaGlobalSecondaryIndex)),
    kms_master_key_id: option.Option(String),
    on_demand_throughput_override: option.Option(OnDemandThroughputOverride),
    provisioned_throughput_override: option.Option(
      ProvisionedThroughputOverride,
    ),
    region_name: String,
    table_class_override: option.Option(TableClass),
  )
}

pub fn create_replication_group_member_action_default(
  region_name region_name: String,
) -> CreateReplicationGroupMemberAction {
  CreateReplicationGroupMemberAction(
    global_secondary_indexes: option.None,
    kms_master_key_id: option.None,
    on_demand_throughput_override: option.None,
    provisioned_throughput_override: option.None,
    region_name: region_name,
    table_class_override: option.None,
  )
}

pub fn encode_create_replication_group_member_action_struct(
  input: CreateReplicationGroupMemberAction,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_replica_global_secondary_index_struct) }(
          v,
        ),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.kms_master_key_id {
    option.Some(v) -> [#("KMSMasterKeyId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #(
        "OnDemandThroughputOverride",
        encode_on_demand_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  let pairs = case input.table_class_override {
    option.Some(v) -> [
      #("TableClassOverride", encode_table_class_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_create_replication_group_member_action_struct_top(
  input: CreateReplicationGroupMemberAction,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_replica_global_secondary_index_struct) }(
          v,
        ),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.kms_master_key_id {
    option.Some(v) -> [#("KMSMasterKeyId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #(
        "OnDemandThroughputOverride",
        encode_on_demand_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  let pairs = case input.table_class_override {
    option.Some(v) -> [
      #("TableClassOverride", encode_table_class_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_create_replication_group_member_action_struct() -> decode.Decoder(
  CreateReplicationGroupMemberAction,
) {
  use <- decode.recursive
  use global_secondary_indexes <- decode.optional_field(
    "GlobalSecondaryIndexes",
    option.None,
    decode.optional(decode.list(decode_replica_global_secondary_index_struct())),
  )
  use kms_master_key_id <- decode.optional_field(
    "KMSMasterKeyId",
    option.None,
    decode.optional(decode.string),
  )
  use on_demand_throughput_override <- decode.optional_field(
    "OnDemandThroughputOverride",
    option.None,
    decode.optional(decode_on_demand_throughput_override_struct()),
  )
  use provisioned_throughput_override <- decode.optional_field(
    "ProvisionedThroughputOverride",
    option.None,
    decode.optional(decode_provisioned_throughput_override_struct()),
  )
  use region_name <- decode.field("RegionName", decode.string)
  use table_class_override <- decode.optional_field(
    "TableClassOverride",
    option.None,
    decode.optional(decode_table_class_enum()),
  )
  decode.success(CreateReplicationGroupMemberAction(
    global_secondary_indexes: global_secondary_indexes,
    kms_master_key_id: kms_master_key_id,
    on_demand_throughput_override: on_demand_throughput_override,
    provisioned_throughput_override: provisioned_throughput_override,
    region_name: region_name,
    table_class_override: table_class_override,
  ))
}

pub type ReplicaGlobalSecondaryIndex {
  ReplicaGlobalSecondaryIndex(
    index_name: String,
    on_demand_throughput_override: option.Option(OnDemandThroughputOverride),
    provisioned_throughput_override: option.Option(
      ProvisionedThroughputOverride,
    ),
  )
}

pub fn replica_global_secondary_index_default(
  index_name index_name: String,
) -> ReplicaGlobalSecondaryIndex {
  ReplicaGlobalSecondaryIndex(
    index_name: index_name,
    on_demand_throughput_override: option.None,
    provisioned_throughput_override: option.None,
  )
}

pub fn encode_replica_global_secondary_index_struct(
  input: ReplicaGlobalSecondaryIndex,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #(
        "OnDemandThroughputOverride",
        encode_on_demand_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_global_secondary_index_struct_top(
  input: ReplicaGlobalSecondaryIndex,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.index_name
    [#("IndexName", json.string(v)), ..pairs]
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #(
        "OnDemandThroughputOverride",
        encode_on_demand_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_global_secondary_index_struct() -> decode.Decoder(
  ReplicaGlobalSecondaryIndex,
) {
  use <- decode.recursive
  use index_name <- decode.field("IndexName", decode.string)
  use on_demand_throughput_override <- decode.optional_field(
    "OnDemandThroughputOverride",
    option.None,
    decode.optional(decode_on_demand_throughput_override_struct()),
  )
  use provisioned_throughput_override <- decode.optional_field(
    "ProvisionedThroughputOverride",
    option.None,
    decode.optional(decode_provisioned_throughput_override_struct()),
  )
  decode.success(ReplicaGlobalSecondaryIndex(
    index_name: index_name,
    on_demand_throughput_override: on_demand_throughput_override,
    provisioned_throughput_override: provisioned_throughput_override,
  ))
}

pub type DeleteReplicationGroupMemberAction {
  DeleteReplicationGroupMemberAction(region_name: String)
}

pub fn delete_replication_group_member_action_default(
  region_name region_name: String,
) -> DeleteReplicationGroupMemberAction {
  DeleteReplicationGroupMemberAction(region_name: region_name)
}

pub fn encode_delete_replication_group_member_action_struct(
  input: DeleteReplicationGroupMemberAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_delete_replication_group_member_action_struct_top(
  input: DeleteReplicationGroupMemberAction,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_delete_replication_group_member_action_struct() -> decode.Decoder(
  DeleteReplicationGroupMemberAction,
) {
  use <- decode.recursive
  use region_name <- decode.field("RegionName", decode.string)
  decode.success(DeleteReplicationGroupMemberAction(region_name: region_name))
}

pub type UpdateReplicationGroupMemberAction {
  UpdateReplicationGroupMemberAction(
    global_secondary_indexes: option.Option(List(ReplicaGlobalSecondaryIndex)),
    kms_master_key_id: option.Option(String),
    on_demand_throughput_override: option.Option(OnDemandThroughputOverride),
    provisioned_throughput_override: option.Option(
      ProvisionedThroughputOverride,
    ),
    region_name: String,
    table_class_override: option.Option(TableClass),
  )
}

pub fn update_replication_group_member_action_default(
  region_name region_name: String,
) -> UpdateReplicationGroupMemberAction {
  UpdateReplicationGroupMemberAction(
    global_secondary_indexes: option.None,
    kms_master_key_id: option.None,
    on_demand_throughput_override: option.None,
    provisioned_throughput_override: option.None,
    region_name: region_name,
    table_class_override: option.None,
  )
}

pub fn encode_update_replication_group_member_action_struct(
  input: UpdateReplicationGroupMemberAction,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_replica_global_secondary_index_struct) }(
          v,
        ),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.kms_master_key_id {
    option.Some(v) -> [#("KMSMasterKeyId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #(
        "OnDemandThroughputOverride",
        encode_on_demand_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  let pairs = case input.table_class_override {
    option.Some(v) -> [
      #("TableClassOverride", encode_table_class_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_replication_group_member_action_struct_top(
  input: UpdateReplicationGroupMemberAction,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_secondary_indexes {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexes",
        fn(xs) { json.array(xs, encode_replica_global_secondary_index_struct) }(
          v,
        ),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.kms_master_key_id {
    option.Some(v) -> [#("KMSMasterKeyId", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.on_demand_throughput_override {
    option.Some(v) -> [
      #(
        "OnDemandThroughputOverride",
        encode_on_demand_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_throughput_override {
    option.Some(v) -> [
      #(
        "ProvisionedThroughputOverride",
        encode_provisioned_throughput_override_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  let pairs = case input.table_class_override {
    option.Some(v) -> [
      #("TableClassOverride", encode_table_class_enum(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_replication_group_member_action_struct() -> decode.Decoder(
  UpdateReplicationGroupMemberAction,
) {
  use <- decode.recursive
  use global_secondary_indexes <- decode.optional_field(
    "GlobalSecondaryIndexes",
    option.None,
    decode.optional(decode.list(decode_replica_global_secondary_index_struct())),
  )
  use kms_master_key_id <- decode.optional_field(
    "KMSMasterKeyId",
    option.None,
    decode.optional(decode.string),
  )
  use on_demand_throughput_override <- decode.optional_field(
    "OnDemandThroughputOverride",
    option.None,
    decode.optional(decode_on_demand_throughput_override_struct()),
  )
  use provisioned_throughput_override <- decode.optional_field(
    "ProvisionedThroughputOverride",
    option.None,
    decode.optional(decode_provisioned_throughput_override_struct()),
  )
  use region_name <- decode.field("RegionName", decode.string)
  use table_class_override <- decode.optional_field(
    "TableClassOverride",
    option.None,
    decode.optional(decode_table_class_enum()),
  )
  decode.success(UpdateReplicationGroupMemberAction(
    global_secondary_indexes: global_secondary_indexes,
    kms_master_key_id: kms_master_key_id,
    on_demand_throughput_override: on_demand_throughput_override,
    provisioned_throughput_override: provisioned_throughput_override,
    region_name: region_name,
    table_class_override: table_class_override,
  ))
}

pub type UpdateTableOutput {
  UpdateTableOutput(table_description: option.Option(TableDescription))
}

pub fn update_table_output_default() -> UpdateTableOutput {
  UpdateTableOutput(table_description: option.None)
}

pub fn encode_update_table_output_struct(
  input: UpdateTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_description {
    option.Some(v) -> [
      #("TableDescription", encode_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_table_output_struct_top(
  input: UpdateTableOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_description {
    option.Some(v) -> [
      #("TableDescription", encode_table_description_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_table_output_struct() -> decode.Decoder(UpdateTableOutput) {
  use <- decode.recursive
  use table_description <- decode.optional_field(
    "TableDescription",
    option.None,
    decode.optional(decode_table_description_struct()),
  )
  decode.success(UpdateTableOutput(table_description: table_description))
}

pub type UpdateTableReplicaAutoScalingInput {
  UpdateTableReplicaAutoScalingInput(
    global_secondary_index_updates: option.Option(
      List(GlobalSecondaryIndexAutoScalingUpdate),
    ),
    provisioned_write_capacity_auto_scaling_update: option.Option(
      AutoScalingSettingsUpdate,
    ),
    replica_updates: option.Option(List(ReplicaAutoScalingUpdate)),
    table_name: String,
  )
}

pub fn update_table_replica_auto_scaling_input_default(
  table_name table_name: String,
) -> UpdateTableReplicaAutoScalingInput {
  UpdateTableReplicaAutoScalingInput(
    global_secondary_index_updates: option.None,
    provisioned_write_capacity_auto_scaling_update: option.None,
    replica_updates: option.None,
    table_name: table_name,
  )
}

pub fn encode_update_table_replica_auto_scaling_input_struct(
  input: UpdateTableReplicaAutoScalingInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_secondary_index_updates {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexUpdates",
        fn(xs) {
          json.array(
            xs,
            encode_global_secondary_index_auto_scaling_update_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_write_capacity_auto_scaling_update {
    option.Some(v) -> [
      #(
        "ProvisionedWriteCapacityAutoScalingUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_updates {
    option.Some(v) -> [
      #(
        "ReplicaUpdates",
        fn(xs) { json.array(xs, encode_replica_auto_scaling_update_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_update_table_replica_auto_scaling_input_struct_top(
  input: UpdateTableReplicaAutoScalingInput,
) -> json.Json {
  let pairs = []
  let pairs = case input.global_secondary_index_updates {
    option.Some(v) -> [
      #(
        "GlobalSecondaryIndexUpdates",
        fn(xs) {
          json.array(
            xs,
            encode_global_secondary_index_auto_scaling_update_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.provisioned_write_capacity_auto_scaling_update {
    option.Some(v) -> [
      #(
        "ProvisionedWriteCapacityAutoScalingUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_updates {
    option.Some(v) -> [
      #(
        "ReplicaUpdates",
        fn(xs) { json.array(xs, encode_replica_auto_scaling_update_struct) }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_update_table_replica_auto_scaling_input_struct() -> decode.Decoder(
  UpdateTableReplicaAutoScalingInput,
) {
  use <- decode.recursive
  use global_secondary_index_updates <- decode.optional_field(
    "GlobalSecondaryIndexUpdates",
    option.None,
    decode.optional(
      decode.list(decode_global_secondary_index_auto_scaling_update_struct()),
    ),
  )
  use provisioned_write_capacity_auto_scaling_update <- decode.optional_field(
    "ProvisionedWriteCapacityAutoScalingUpdate",
    option.None,
    decode.optional(decode_auto_scaling_settings_update_struct()),
  )
  use replica_updates <- decode.optional_field(
    "ReplicaUpdates",
    option.None,
    decode.optional(decode.list(decode_replica_auto_scaling_update_struct())),
  )
  use table_name <- decode.field("TableName", decode.string)
  decode.success(UpdateTableReplicaAutoScalingInput(
    global_secondary_index_updates: global_secondary_index_updates,
    provisioned_write_capacity_auto_scaling_update: provisioned_write_capacity_auto_scaling_update,
    replica_updates: replica_updates,
    table_name: table_name,
  ))
}

pub type GlobalSecondaryIndexAutoScalingUpdate {
  GlobalSecondaryIndexAutoScalingUpdate(
    index_name: option.Option(String),
    provisioned_write_capacity_auto_scaling_update: option.Option(
      AutoScalingSettingsUpdate,
    ),
  )
}

pub fn global_secondary_index_auto_scaling_update_default() -> GlobalSecondaryIndexAutoScalingUpdate {
  GlobalSecondaryIndexAutoScalingUpdate(
    index_name: option.None,
    provisioned_write_capacity_auto_scaling_update: option.None,
  )
}

pub fn encode_global_secondary_index_auto_scaling_update_struct(
  input: GlobalSecondaryIndexAutoScalingUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_write_capacity_auto_scaling_update {
    option.Some(v) -> [
      #(
        "ProvisionedWriteCapacityAutoScalingUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_global_secondary_index_auto_scaling_update_struct_top(
  input: GlobalSecondaryIndexAutoScalingUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_write_capacity_auto_scaling_update {
    option.Some(v) -> [
      #(
        "ProvisionedWriteCapacityAutoScalingUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_global_secondary_index_auto_scaling_update_struct() -> decode.Decoder(
  GlobalSecondaryIndexAutoScalingUpdate,
) {
  use <- decode.recursive
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use provisioned_write_capacity_auto_scaling_update <- decode.optional_field(
    "ProvisionedWriteCapacityAutoScalingUpdate",
    option.None,
    decode.optional(decode_auto_scaling_settings_update_struct()),
  )
  decode.success(GlobalSecondaryIndexAutoScalingUpdate(
    index_name: index_name,
    provisioned_write_capacity_auto_scaling_update: provisioned_write_capacity_auto_scaling_update,
  ))
}

pub type ReplicaAutoScalingUpdate {
  ReplicaAutoScalingUpdate(
    region_name: String,
    replica_global_secondary_index_updates: option.Option(
      List(ReplicaGlobalSecondaryIndexAutoScalingUpdate),
    ),
    replica_provisioned_read_capacity_auto_scaling_update: option.Option(
      AutoScalingSettingsUpdate,
    ),
  )
}

pub fn replica_auto_scaling_update_default(
  region_name region_name: String,
) -> ReplicaAutoScalingUpdate {
  ReplicaAutoScalingUpdate(
    region_name: region_name,
    replica_global_secondary_index_updates: option.None,
    replica_provisioned_read_capacity_auto_scaling_update: option.None,
  )
}

pub fn encode_replica_auto_scaling_update_struct(
  input: ReplicaAutoScalingUpdate,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  let pairs = case input.replica_global_secondary_index_updates {
    option.Some(v) -> [
      #(
        "ReplicaGlobalSecondaryIndexUpdates",
        fn(xs) {
          json.array(
            xs,
            encode_replica_global_secondary_index_auto_scaling_update_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_provisioned_read_capacity_auto_scaling_update {
    option.Some(v) -> [
      #(
        "ReplicaProvisionedReadCapacityAutoScalingUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_auto_scaling_update_struct_top(
  input: ReplicaAutoScalingUpdate,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.region_name
    [#("RegionName", json.string(v)), ..pairs]
  }
  let pairs = case input.replica_global_secondary_index_updates {
    option.Some(v) -> [
      #(
        "ReplicaGlobalSecondaryIndexUpdates",
        fn(xs) {
          json.array(
            xs,
            encode_replica_global_secondary_index_auto_scaling_update_struct,
          )
        }(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  let pairs = case input.replica_provisioned_read_capacity_auto_scaling_update {
    option.Some(v) -> [
      #(
        "ReplicaProvisionedReadCapacityAutoScalingUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_auto_scaling_update_struct() -> decode.Decoder(
  ReplicaAutoScalingUpdate,
) {
  use <- decode.recursive
  use region_name <- decode.field("RegionName", decode.string)
  use replica_global_secondary_index_updates <- decode.optional_field(
    "ReplicaGlobalSecondaryIndexUpdates",
    option.None,
    decode.optional(
      decode.list(
        decode_replica_global_secondary_index_auto_scaling_update_struct(),
      ),
    ),
  )
  use replica_provisioned_read_capacity_auto_scaling_update <- decode.optional_field(
    "ReplicaProvisionedReadCapacityAutoScalingUpdate",
    option.None,
    decode.optional(decode_auto_scaling_settings_update_struct()),
  )
  decode.success(ReplicaAutoScalingUpdate(
    region_name: region_name,
    replica_global_secondary_index_updates: replica_global_secondary_index_updates,
    replica_provisioned_read_capacity_auto_scaling_update: replica_provisioned_read_capacity_auto_scaling_update,
  ))
}

pub type ReplicaGlobalSecondaryIndexAutoScalingUpdate {
  ReplicaGlobalSecondaryIndexAutoScalingUpdate(
    index_name: option.Option(String),
    provisioned_read_capacity_auto_scaling_update: option.Option(
      AutoScalingSettingsUpdate,
    ),
  )
}

pub fn replica_global_secondary_index_auto_scaling_update_default() -> ReplicaGlobalSecondaryIndexAutoScalingUpdate {
  ReplicaGlobalSecondaryIndexAutoScalingUpdate(
    index_name: option.None,
    provisioned_read_capacity_auto_scaling_update: option.None,
  )
}

pub fn encode_replica_global_secondary_index_auto_scaling_update_struct(
  input: ReplicaGlobalSecondaryIndexAutoScalingUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_read_capacity_auto_scaling_update {
    option.Some(v) -> [
      #(
        "ProvisionedReadCapacityAutoScalingUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_replica_global_secondary_index_auto_scaling_update_struct_top(
  input: ReplicaGlobalSecondaryIndexAutoScalingUpdate,
) -> json.Json {
  let pairs = []
  let pairs = case input.index_name {
    option.Some(v) -> [#("IndexName", json.string(v)), ..pairs]
    option.None -> pairs
  }
  let pairs = case input.provisioned_read_capacity_auto_scaling_update {
    option.Some(v) -> [
      #(
        "ProvisionedReadCapacityAutoScalingUpdate",
        encode_auto_scaling_settings_update_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_replica_global_secondary_index_auto_scaling_update_struct() -> decode.Decoder(
  ReplicaGlobalSecondaryIndexAutoScalingUpdate,
) {
  use <- decode.recursive
  use index_name <- decode.optional_field(
    "IndexName",
    option.None,
    decode.optional(decode.string),
  )
  use provisioned_read_capacity_auto_scaling_update <- decode.optional_field(
    "ProvisionedReadCapacityAutoScalingUpdate",
    option.None,
    decode.optional(decode_auto_scaling_settings_update_struct()),
  )
  decode.success(ReplicaGlobalSecondaryIndexAutoScalingUpdate(
    index_name: index_name,
    provisioned_read_capacity_auto_scaling_update: provisioned_read_capacity_auto_scaling_update,
  ))
}

pub type UpdateTableReplicaAutoScalingOutput {
  UpdateTableReplicaAutoScalingOutput(
    table_auto_scaling_description: option.Option(TableAutoScalingDescription),
  )
}

pub fn update_table_replica_auto_scaling_output_default() -> UpdateTableReplicaAutoScalingOutput {
  UpdateTableReplicaAutoScalingOutput(
    table_auto_scaling_description: option.None,
  )
}

pub fn encode_update_table_replica_auto_scaling_output_struct(
  input: UpdateTableReplicaAutoScalingOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_auto_scaling_description {
    option.Some(v) -> [
      #(
        "TableAutoScalingDescription",
        encode_table_auto_scaling_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_table_replica_auto_scaling_output_struct_top(
  input: UpdateTableReplicaAutoScalingOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.table_auto_scaling_description {
    option.Some(v) -> [
      #(
        "TableAutoScalingDescription",
        encode_table_auto_scaling_description_struct(v),
      ),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_table_replica_auto_scaling_output_struct() -> decode.Decoder(
  UpdateTableReplicaAutoScalingOutput,
) {
  use <- decode.recursive
  use table_auto_scaling_description <- decode.optional_field(
    "TableAutoScalingDescription",
    option.None,
    decode.optional(decode_table_auto_scaling_description_struct()),
  )
  decode.success(UpdateTableReplicaAutoScalingOutput(
    table_auto_scaling_description: table_auto_scaling_description,
  ))
}

pub type UpdateTimeToLiveInput {
  UpdateTimeToLiveInput(
    table_name: String,
    time_to_live_specification: TimeToLiveSpecification,
  )
}

pub fn update_time_to_live_input_default(
  table_name table_name: String,
  time_to_live_specification time_to_live_specification: TimeToLiveSpecification,
) -> UpdateTimeToLiveInput {
  UpdateTimeToLiveInput(
    table_name: table_name,
    time_to_live_specification: time_to_live_specification,
  )
}

pub fn encode_update_time_to_live_input_struct(
  input: UpdateTimeToLiveInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.time_to_live_specification
    [
      #("TimeToLiveSpecification", encode_time_to_live_specification_struct(v)),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn encode_update_time_to_live_input_struct_top(
  input: UpdateTimeToLiveInput,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.table_name
    [#("TableName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.time_to_live_specification
    [
      #("TimeToLiveSpecification", encode_time_to_live_specification_struct(v)),
      ..pairs
    ]
  }
  json.object(pairs)
}

pub fn decode_update_time_to_live_input_struct() -> decode.Decoder(
  UpdateTimeToLiveInput,
) {
  use <- decode.recursive
  use table_name <- decode.field("TableName", decode.string)
  use time_to_live_specification <- decode.field(
    "TimeToLiveSpecification",
    decode_time_to_live_specification_struct(),
  )
  decode.success(UpdateTimeToLiveInput(
    table_name: table_name,
    time_to_live_specification: time_to_live_specification,
  ))
}

pub type TimeToLiveSpecification {
  TimeToLiveSpecification(attribute_name: String, enabled: Bool)
}

pub fn time_to_live_specification_default(
  attribute_name attribute_name: String,
  enabled enabled: Bool,
) -> TimeToLiveSpecification {
  TimeToLiveSpecification(attribute_name: attribute_name, enabled: enabled)
}

pub fn encode_time_to_live_specification_struct(
  input: TimeToLiveSpecification,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.attribute_name
    [#("AttributeName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.enabled
    [#("Enabled", json.bool(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn encode_time_to_live_specification_struct_top(
  input: TimeToLiveSpecification,
) -> json.Json {
  let pairs = []
  let pairs = {
    let v = input.attribute_name
    [#("AttributeName", json.string(v)), ..pairs]
  }
  let pairs = {
    let v = input.enabled
    [#("Enabled", json.bool(v)), ..pairs]
  }
  json.object(pairs)
}

pub fn decode_time_to_live_specification_struct() -> decode.Decoder(
  TimeToLiveSpecification,
) {
  use <- decode.recursive
  use attribute_name <- decode.field("AttributeName", decode.string)
  use enabled <- decode.field("Enabled", decode.bool)
  decode.success(TimeToLiveSpecification(
    attribute_name: attribute_name,
    enabled: enabled,
  ))
}

pub type UpdateTimeToLiveOutput {
  UpdateTimeToLiveOutput(
    time_to_live_specification: option.Option(TimeToLiveSpecification),
  )
}

pub fn update_time_to_live_output_default() -> UpdateTimeToLiveOutput {
  UpdateTimeToLiveOutput(time_to_live_specification: option.None)
}

pub fn encode_update_time_to_live_output_struct(
  input: UpdateTimeToLiveOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.time_to_live_specification {
    option.Some(v) -> [
      #("TimeToLiveSpecification", encode_time_to_live_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn encode_update_time_to_live_output_struct_top(
  input: UpdateTimeToLiveOutput,
) -> json.Json {
  let pairs = []
  let pairs = case input.time_to_live_specification {
    option.Some(v) -> [
      #("TimeToLiveSpecification", encode_time_to_live_specification_struct(v)),
      ..pairs
    ]
    option.None -> pairs
  }
  json.object(pairs)
}

pub fn decode_update_time_to_live_output_struct() -> decode.Decoder(
  UpdateTimeToLiveOutput,
) {
  use <- decode.recursive
  use time_to_live_specification <- decode.optional_field(
    "TimeToLiveSpecification",
    option.None,
    decode.optional(decode_time_to_live_specification_struct()),
  )
  decode.success(UpdateTimeToLiveOutput(
    time_to_live_specification: time_to_live_specification,
  ))
}

pub fn encode_batch_execute_statement_input(
  input: BatchExecuteStatementInput,
) -> String {
  json.to_string(encode_batch_execute_statement_input_struct_top(input))
}

pub fn decode_batch_execute_statement_output(
  body: String,
) -> Result(BatchExecuteStatementOutput, String) {
  case json.parse(body, decode_batch_execute_statement_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_batch_execute_statement_request(
  input: BatchExecuteStatementInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_batch_execute_statement_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.BatchExecuteStatement"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_batch_execute_statement_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(BatchExecuteStatementOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_batch_execute_statement_output("{}")
        _ -> decode_batch_execute_statement_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type BatchExecuteStatementError {
  BatchExecuteStatementErrorInternalServerError(value: InternalServerError)
  BatchExecuteStatementErrorRequestLimitExceeded(value: RequestLimitExceeded)
  BatchExecuteStatementErrorThrottlingException(value: ThrottlingException)
  BatchExecuteStatementErrorTransport(reason: String)
  BatchExecuteStatementErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn batch_execute_statement_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(BatchExecuteStatementErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("RequestLimitExceeded", fn(body) {
      case json.parse(body, decode_request_limit_exceeded_struct()) {
        Ok(v) -> Ok(BatchExecuteStatementErrorRequestLimitExceeded(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ThrottlingException", fn(body) {
      case json.parse(body, decode_throttling_exception_struct()) {
        Ok(v) -> Ok(BatchExecuteStatementErrorThrottlingException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_batch_execute_statement_error(
  err: runtime.ClientError,
) -> BatchExecuteStatementError {
  runtime.translate_service_error(
    err,
    batch_execute_statement_error_decoders(),
    fn(reason) { BatchExecuteStatementErrorTransport(reason: reason) },
    fn(et, s, body) {
      BatchExecuteStatementErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_batch_get_item_input(input: BatchGetItemInput) -> String {
  json.to_string(encode_batch_get_item_input_struct_top(input))
}

pub fn decode_batch_get_item_output(
  body: String,
) -> Result(BatchGetItemOutput, String) {
  case json.parse(body, decode_batch_get_item_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_batch_get_item_request(
  input: BatchGetItemInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_batch_get_item_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.BatchGetItem"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_batch_get_item_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(BatchGetItemOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_batch_get_item_output("{}")
        _ -> decode_batch_get_item_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type BatchGetItemError {
  BatchGetItemErrorInternalServerError(value: InternalServerError)
  BatchGetItemErrorInvalidEndpointException(value: InvalidEndpointException)
  BatchGetItemErrorProvisionedThroughputExceededException(
    value: ProvisionedThroughputExceededException,
  )
  BatchGetItemErrorRequestLimitExceeded(value: RequestLimitExceeded)
  BatchGetItemErrorResourceNotFoundException(value: ResourceNotFoundException)
  BatchGetItemErrorThrottlingException(value: ThrottlingException)
  BatchGetItemErrorTransport(reason: String)
  BatchGetItemErrorUnknown(error_type: String, status: Int, body: String)
}

fn batch_get_item_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(BatchGetItemErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(BatchGetItemErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ProvisionedThroughputExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_provisioned_throughput_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(BatchGetItemErrorProvisionedThroughputExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("RequestLimitExceeded", fn(body) {
      case json.parse(body, decode_request_limit_exceeded_struct()) {
        Ok(v) -> Ok(BatchGetItemErrorRequestLimitExceeded(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(BatchGetItemErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ThrottlingException", fn(body) {
      case json.parse(body, decode_throttling_exception_struct()) {
        Ok(v) -> Ok(BatchGetItemErrorThrottlingException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_batch_get_item_error(
  err: runtime.ClientError,
) -> BatchGetItemError {
  runtime.translate_service_error(
    err,
    batch_get_item_error_decoders(),
    fn(reason) { BatchGetItemErrorTransport(reason: reason) },
    fn(et, s, body) {
      BatchGetItemErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_batch_write_item_input(input: BatchWriteItemInput) -> String {
  json.to_string(encode_batch_write_item_input_struct_top(input))
}

pub fn decode_batch_write_item_output(
  body: String,
) -> Result(BatchWriteItemOutput, String) {
  case json.parse(body, decode_batch_write_item_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_batch_write_item_request(
  input: BatchWriteItemInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_batch_write_item_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.BatchWriteItem"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_batch_write_item_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(BatchWriteItemOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_batch_write_item_output("{}")
        _ -> decode_batch_write_item_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type BatchWriteItemError {
  BatchWriteItemErrorInternalServerError(value: InternalServerError)
  BatchWriteItemErrorInvalidEndpointException(value: InvalidEndpointException)
  BatchWriteItemErrorItemCollectionSizeLimitExceededException(
    value: ItemCollectionSizeLimitExceededException,
  )
  BatchWriteItemErrorProvisionedThroughputExceededException(
    value: ProvisionedThroughputExceededException,
  )
  BatchWriteItemErrorReplicatedWriteConflictException(
    value: ReplicatedWriteConflictException,
  )
  BatchWriteItemErrorRequestLimitExceeded(value: RequestLimitExceeded)
  BatchWriteItemErrorResourceNotFoundException(value: ResourceNotFoundException)
  BatchWriteItemErrorThrottlingException(value: ThrottlingException)
  BatchWriteItemErrorTransport(reason: String)
  BatchWriteItemErrorUnknown(error_type: String, status: Int, body: String)
}

fn batch_write_item_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(BatchWriteItemErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(BatchWriteItemErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ItemCollectionSizeLimitExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_item_collection_size_limit_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(BatchWriteItemErrorItemCollectionSizeLimitExceededException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("ProvisionedThroughputExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_provisioned_throughput_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(BatchWriteItemErrorProvisionedThroughputExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ReplicatedWriteConflictException", fn(body) {
      case
        json.parse(body, decode_replicated_write_conflict_exception_struct())
      {
        Ok(v) ->
          Ok(BatchWriteItemErrorReplicatedWriteConflictException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("RequestLimitExceeded", fn(body) {
      case json.parse(body, decode_request_limit_exceeded_struct()) {
        Ok(v) -> Ok(BatchWriteItemErrorRequestLimitExceeded(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(BatchWriteItemErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ThrottlingException", fn(body) {
      case json.parse(body, decode_throttling_exception_struct()) {
        Ok(v) -> Ok(BatchWriteItemErrorThrottlingException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_batch_write_item_error(
  err: runtime.ClientError,
) -> BatchWriteItemError {
  runtime.translate_service_error(
    err,
    batch_write_item_error_decoders(),
    fn(reason) { BatchWriteItemErrorTransport(reason: reason) },
    fn(et, s, body) {
      BatchWriteItemErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_create_backup_input(input: CreateBackupInput) -> String {
  json.to_string(encode_create_backup_input_struct_top(input))
}

pub fn decode_create_backup_output(
  body: String,
) -> Result(CreateBackupOutput, String) {
  case json.parse(body, decode_create_backup_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_create_backup_request(
  input: CreateBackupInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_create_backup_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.CreateBackup"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_create_backup_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(CreateBackupOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_create_backup_output("{}")
        _ -> decode_create_backup_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type CreateBackupError {
  CreateBackupErrorBackupInUseException(value: BackupInUseException)
  CreateBackupErrorContinuousBackupsUnavailableException(
    value: ContinuousBackupsUnavailableException,
  )
  CreateBackupErrorInternalServerError(value: InternalServerError)
  CreateBackupErrorInvalidEndpointException(value: InvalidEndpointException)
  CreateBackupErrorLimitExceededException(value: LimitExceededException)
  CreateBackupErrorTableInUseException(value: TableInUseException)
  CreateBackupErrorTableNotFoundException(value: TableNotFoundException)
  CreateBackupErrorTransport(reason: String)
  CreateBackupErrorUnknown(error_type: String, status: Int, body: String)
}

fn create_backup_error_decoders() {
  [
    #("BackupInUseException", fn(body) {
      case json.parse(body, decode_backup_in_use_exception_struct()) {
        Ok(v) -> Ok(CreateBackupErrorBackupInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ContinuousBackupsUnavailableException", fn(body) {
      case
        json.parse(
          body,
          decode_continuous_backups_unavailable_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(CreateBackupErrorContinuousBackupsUnavailableException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(CreateBackupErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(CreateBackupErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(CreateBackupErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TableInUseException", fn(body) {
      case json.parse(body, decode_table_in_use_exception_struct()) {
        Ok(v) -> Ok(CreateBackupErrorTableInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TableNotFoundException", fn(body) {
      case json.parse(body, decode_table_not_found_exception_struct()) {
        Ok(v) -> Ok(CreateBackupErrorTableNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_create_backup_error(
  err: runtime.ClientError,
) -> CreateBackupError {
  runtime.translate_service_error(
    err,
    create_backup_error_decoders(),
    fn(reason) { CreateBackupErrorTransport(reason: reason) },
    fn(et, s, body) {
      CreateBackupErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_create_global_table_input(
  input: CreateGlobalTableInput,
) -> String {
  json.to_string(encode_create_global_table_input_struct_top(input))
}

pub fn decode_create_global_table_output(
  body: String,
) -> Result(CreateGlobalTableOutput, String) {
  case json.parse(body, decode_create_global_table_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_create_global_table_request(
  input: CreateGlobalTableInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_create_global_table_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.CreateGlobalTable"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_create_global_table_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(CreateGlobalTableOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_create_global_table_output("{}")
        _ -> decode_create_global_table_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type CreateGlobalTableError {
  CreateGlobalTableErrorGlobalTableAlreadyExistsException(
    value: GlobalTableAlreadyExistsException,
  )
  CreateGlobalTableErrorInternalServerError(value: InternalServerError)
  CreateGlobalTableErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  CreateGlobalTableErrorLimitExceededException(value: LimitExceededException)
  CreateGlobalTableErrorTableNotFoundException(value: TableNotFoundException)
  CreateGlobalTableErrorTransport(reason: String)
  CreateGlobalTableErrorUnknown(error_type: String, status: Int, body: String)
}

fn create_global_table_error_decoders() {
  [
    #("GlobalTableAlreadyExistsException", fn(body) {
      case
        json.parse(body, decode_global_table_already_exists_exception_struct())
      {
        Ok(v) ->
          Ok(CreateGlobalTableErrorGlobalTableAlreadyExistsException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(CreateGlobalTableErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(CreateGlobalTableErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(CreateGlobalTableErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TableNotFoundException", fn(body) {
      case json.parse(body, decode_table_not_found_exception_struct()) {
        Ok(v) -> Ok(CreateGlobalTableErrorTableNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_create_global_table_error(
  err: runtime.ClientError,
) -> CreateGlobalTableError {
  runtime.translate_service_error(
    err,
    create_global_table_error_decoders(),
    fn(reason) { CreateGlobalTableErrorTransport(reason: reason) },
    fn(et, s, body) {
      CreateGlobalTableErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_create_table_input(input: CreateTableInput) -> String {
  json.to_string(encode_create_table_input_struct_top(input))
}

pub fn decode_create_table_output(
  body: String,
) -> Result(CreateTableOutput, String) {
  case json.parse(body, decode_create_table_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_create_table_request(
  input: CreateTableInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_create_table_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.CreateTable"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_create_table_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(CreateTableOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_create_table_output("{}")
        _ -> decode_create_table_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type CreateTableError {
  CreateTableErrorInternalServerError(value: InternalServerError)
  CreateTableErrorInvalidEndpointException(value: InvalidEndpointException)
  CreateTableErrorLimitExceededException(value: LimitExceededException)
  CreateTableErrorResourceInUseException(value: ResourceInUseException)
  CreateTableErrorTransport(reason: String)
  CreateTableErrorUnknown(error_type: String, status: Int, body: String)
}

fn create_table_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(CreateTableErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(CreateTableErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(CreateTableErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) -> Ok(CreateTableErrorResourceInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_create_table_error(err: runtime.ClientError) -> CreateTableError {
  runtime.translate_service_error(
    err,
    create_table_error_decoders(),
    fn(reason) { CreateTableErrorTransport(reason: reason) },
    fn(et, s, body) {
      CreateTableErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_delete_backup_input(input: DeleteBackupInput) -> String {
  json.to_string(encode_delete_backup_input_struct_top(input))
}

pub fn decode_delete_backup_output(
  body: String,
) -> Result(DeleteBackupOutput, String) {
  case json.parse(body, decode_delete_backup_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_delete_backup_request(
  input: DeleteBackupInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_delete_backup_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DeleteBackup"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_delete_backup_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DeleteBackupOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_delete_backup_output("{}")
        _ -> decode_delete_backup_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DeleteBackupError {
  DeleteBackupErrorBackupInUseException(value: BackupInUseException)
  DeleteBackupErrorBackupNotFoundException(value: BackupNotFoundException)
  DeleteBackupErrorInternalServerError(value: InternalServerError)
  DeleteBackupErrorInvalidEndpointException(value: InvalidEndpointException)
  DeleteBackupErrorLimitExceededException(value: LimitExceededException)
  DeleteBackupErrorTransport(reason: String)
  DeleteBackupErrorUnknown(error_type: String, status: Int, body: String)
}

fn delete_backup_error_decoders() {
  [
    #("BackupInUseException", fn(body) {
      case json.parse(body, decode_backup_in_use_exception_struct()) {
        Ok(v) -> Ok(DeleteBackupErrorBackupInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("BackupNotFoundException", fn(body) {
      case json.parse(body, decode_backup_not_found_exception_struct()) {
        Ok(v) -> Ok(DeleteBackupErrorBackupNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(DeleteBackupErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(DeleteBackupErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(DeleteBackupErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_delete_backup_error(
  err: runtime.ClientError,
) -> DeleteBackupError {
  runtime.translate_service_error(
    err,
    delete_backup_error_decoders(),
    fn(reason) { DeleteBackupErrorTransport(reason: reason) },
    fn(et, s, body) {
      DeleteBackupErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_delete_item_input(input: DeleteItemInput) -> String {
  json.to_string(encode_delete_item_input_struct_top(input))
}

pub fn decode_delete_item_output(
  body: String,
) -> Result(DeleteItemOutput, String) {
  case json.parse(body, decode_delete_item_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_delete_item_request(
  input: DeleteItemInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_delete_item_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DeleteItem"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_delete_item_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DeleteItemOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_delete_item_output("{}")
        _ -> decode_delete_item_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DeleteItemError {
  DeleteItemErrorConditionalCheckFailedException(
    value: ConditionalCheckFailedException,
  )
  DeleteItemErrorInternalServerError(value: InternalServerError)
  DeleteItemErrorInvalidEndpointException(value: InvalidEndpointException)
  DeleteItemErrorItemCollectionSizeLimitExceededException(
    value: ItemCollectionSizeLimitExceededException,
  )
  DeleteItemErrorProvisionedThroughputExceededException(
    value: ProvisionedThroughputExceededException,
  )
  DeleteItemErrorReplicatedWriteConflictException(
    value: ReplicatedWriteConflictException,
  )
  DeleteItemErrorRequestLimitExceeded(value: RequestLimitExceeded)
  DeleteItemErrorResourceNotFoundException(value: ResourceNotFoundException)
  DeleteItemErrorThrottlingException(value: ThrottlingException)
  DeleteItemErrorTransactionConflictException(
    value: TransactionConflictException,
  )
  DeleteItemErrorTransport(reason: String)
  DeleteItemErrorUnknown(error_type: String, status: Int, body: String)
}

fn delete_item_error_decoders() {
  [
    #("ConditionalCheckFailedException", fn(body) {
      case
        json.parse(body, decode_conditional_check_failed_exception_struct())
      {
        Ok(v) -> Ok(DeleteItemErrorConditionalCheckFailedException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(DeleteItemErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(DeleteItemErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ItemCollectionSizeLimitExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_item_collection_size_limit_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(DeleteItemErrorItemCollectionSizeLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ProvisionedThroughputExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_provisioned_throughput_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(DeleteItemErrorProvisionedThroughputExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ReplicatedWriteConflictException", fn(body) {
      case
        json.parse(body, decode_replicated_write_conflict_exception_struct())
      {
        Ok(v) -> Ok(DeleteItemErrorReplicatedWriteConflictException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("RequestLimitExceeded", fn(body) {
      case json.parse(body, decode_request_limit_exceeded_struct()) {
        Ok(v) -> Ok(DeleteItemErrorRequestLimitExceeded(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(DeleteItemErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ThrottlingException", fn(body) {
      case json.parse(body, decode_throttling_exception_struct()) {
        Ok(v) -> Ok(DeleteItemErrorThrottlingException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TransactionConflictException", fn(body) {
      case json.parse(body, decode_transaction_conflict_exception_struct()) {
        Ok(v) -> Ok(DeleteItemErrorTransactionConflictException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_delete_item_error(err: runtime.ClientError) -> DeleteItemError {
  runtime.translate_service_error(
    err,
    delete_item_error_decoders(),
    fn(reason) { DeleteItemErrorTransport(reason: reason) },
    fn(et, s, body) {
      DeleteItemErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_delete_resource_policy_input(
  input: DeleteResourcePolicyInput,
) -> String {
  json.to_string(encode_delete_resource_policy_input_struct_top(input))
}

pub fn decode_delete_resource_policy_output(
  body: String,
) -> Result(DeleteResourcePolicyOutput, String) {
  case json.parse(body, decode_delete_resource_policy_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_delete_resource_policy_request(
  input: DeleteResourcePolicyInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_delete_resource_policy_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DeleteResourcePolicy"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_delete_resource_policy_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DeleteResourcePolicyOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_delete_resource_policy_output("{}")
        _ -> decode_delete_resource_policy_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DeleteResourcePolicyError {
  DeleteResourcePolicyErrorInternalServerError(value: InternalServerError)
  DeleteResourcePolicyErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  DeleteResourcePolicyErrorLimitExceededException(value: LimitExceededException)
  DeleteResourcePolicyErrorPolicyNotFoundException(
    value: PolicyNotFoundException,
  )
  DeleteResourcePolicyErrorResourceInUseException(value: ResourceInUseException)
  DeleteResourcePolicyErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  DeleteResourcePolicyErrorTransport(reason: String)
  DeleteResourcePolicyErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn delete_resource_policy_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(DeleteResourcePolicyErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(DeleteResourcePolicyErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(DeleteResourcePolicyErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("PolicyNotFoundException", fn(body) {
      case json.parse(body, decode_policy_not_found_exception_struct()) {
        Ok(v) -> Ok(DeleteResourcePolicyErrorPolicyNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) -> Ok(DeleteResourcePolicyErrorResourceInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) ->
          Ok(DeleteResourcePolicyErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_delete_resource_policy_error(
  err: runtime.ClientError,
) -> DeleteResourcePolicyError {
  runtime.translate_service_error(
    err,
    delete_resource_policy_error_decoders(),
    fn(reason) { DeleteResourcePolicyErrorTransport(reason: reason) },
    fn(et, s, body) {
      DeleteResourcePolicyErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_delete_table_input(input: DeleteTableInput) -> String {
  json.to_string(encode_delete_table_input_struct_top(input))
}

pub fn decode_delete_table_output(
  body: String,
) -> Result(DeleteTableOutput, String) {
  case json.parse(body, decode_delete_table_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_delete_table_request(
  input: DeleteTableInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_delete_table_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DeleteTable"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_delete_table_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DeleteTableOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_delete_table_output("{}")
        _ -> decode_delete_table_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DeleteTableError {
  DeleteTableErrorInternalServerError(value: InternalServerError)
  DeleteTableErrorInvalidEndpointException(value: InvalidEndpointException)
  DeleteTableErrorLimitExceededException(value: LimitExceededException)
  DeleteTableErrorResourceInUseException(value: ResourceInUseException)
  DeleteTableErrorResourceNotFoundException(value: ResourceNotFoundException)
  DeleteTableErrorTransport(reason: String)
  DeleteTableErrorUnknown(error_type: String, status: Int, body: String)
}

fn delete_table_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(DeleteTableErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(DeleteTableErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(DeleteTableErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) -> Ok(DeleteTableErrorResourceInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(DeleteTableErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_delete_table_error(err: runtime.ClientError) -> DeleteTableError {
  runtime.translate_service_error(
    err,
    delete_table_error_decoders(),
    fn(reason) { DeleteTableErrorTransport(reason: reason) },
    fn(et, s, body) {
      DeleteTableErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_describe_backup_input(input: DescribeBackupInput) -> String {
  json.to_string(encode_describe_backup_input_struct_top(input))
}

pub fn decode_describe_backup_output(
  body: String,
) -> Result(DescribeBackupOutput, String) {
  case json.parse(body, decode_describe_backup_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_describe_backup_request(
  input: DescribeBackupInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_describe_backup_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DescribeBackup"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_describe_backup_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DescribeBackupOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_describe_backup_output("{}")
        _ -> decode_describe_backup_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DescribeBackupError {
  DescribeBackupErrorBackupNotFoundException(value: BackupNotFoundException)
  DescribeBackupErrorInternalServerError(value: InternalServerError)
  DescribeBackupErrorInvalidEndpointException(value: InvalidEndpointException)
  DescribeBackupErrorTransport(reason: String)
  DescribeBackupErrorUnknown(error_type: String, status: Int, body: String)
}

fn describe_backup_error_decoders() {
  [
    #("BackupNotFoundException", fn(body) {
      case json.parse(body, decode_backup_not_found_exception_struct()) {
        Ok(v) -> Ok(DescribeBackupErrorBackupNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(DescribeBackupErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(DescribeBackupErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_describe_backup_error(
  err: runtime.ClientError,
) -> DescribeBackupError {
  runtime.translate_service_error(
    err,
    describe_backup_error_decoders(),
    fn(reason) { DescribeBackupErrorTransport(reason: reason) },
    fn(et, s, body) {
      DescribeBackupErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_describe_continuous_backups_input(
  input: DescribeContinuousBackupsInput,
) -> String {
  json.to_string(encode_describe_continuous_backups_input_struct_top(input))
}

pub fn decode_describe_continuous_backups_output(
  body: String,
) -> Result(DescribeContinuousBackupsOutput, String) {
  case json.parse(body, decode_describe_continuous_backups_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_describe_continuous_backups_request(
  input: DescribeContinuousBackupsInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_describe_continuous_backups_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DescribeContinuousBackups"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_describe_continuous_backups_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DescribeContinuousBackupsOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_describe_continuous_backups_output("{}")
        _ -> decode_describe_continuous_backups_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DescribeContinuousBackupsError {
  DescribeContinuousBackupsErrorInternalServerError(value: InternalServerError)
  DescribeContinuousBackupsErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  DescribeContinuousBackupsErrorTableNotFoundException(
    value: TableNotFoundException,
  )
  DescribeContinuousBackupsErrorTransport(reason: String)
  DescribeContinuousBackupsErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn describe_continuous_backups_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(DescribeContinuousBackupsErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) ->
          Ok(DescribeContinuousBackupsErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TableNotFoundException", fn(body) {
      case json.parse(body, decode_table_not_found_exception_struct()) {
        Ok(v) ->
          Ok(DescribeContinuousBackupsErrorTableNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_describe_continuous_backups_error(
  err: runtime.ClientError,
) -> DescribeContinuousBackupsError {
  runtime.translate_service_error(
    err,
    describe_continuous_backups_error_decoders(),
    fn(reason) { DescribeContinuousBackupsErrorTransport(reason: reason) },
    fn(et, s, body) {
      DescribeContinuousBackupsErrorUnknown(
        error_type: et,
        status: s,
        body: body,
      )
    },
  )
}

pub fn encode_describe_contributor_insights_input(
  input: DescribeContributorInsightsInput,
) -> String {
  json.to_string(encode_describe_contributor_insights_input_struct_top(input))
}

pub fn decode_describe_contributor_insights_output(
  body: String,
) -> Result(DescribeContributorInsightsOutput, String) {
  case json.parse(body, decode_describe_contributor_insights_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_describe_contributor_insights_request(
  input: DescribeContributorInsightsInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_describe_contributor_insights_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DescribeContributorInsights"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_describe_contributor_insights_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DescribeContributorInsightsOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_describe_contributor_insights_output("{}")
        _ -> decode_describe_contributor_insights_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DescribeContributorInsightsError {
  DescribeContributorInsightsErrorInternalServerError(
    value: InternalServerError,
  )
  DescribeContributorInsightsErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  DescribeContributorInsightsErrorTransport(reason: String)
  DescribeContributorInsightsErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn describe_contributor_insights_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) ->
          Ok(DescribeContributorInsightsErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) ->
          Ok(DescribeContributorInsightsErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_describe_contributor_insights_error(
  err: runtime.ClientError,
) -> DescribeContributorInsightsError {
  runtime.translate_service_error(
    err,
    describe_contributor_insights_error_decoders(),
    fn(reason) { DescribeContributorInsightsErrorTransport(reason: reason) },
    fn(et, s, body) {
      DescribeContributorInsightsErrorUnknown(
        error_type: et,
        status: s,
        body: body,
      )
    },
  )
}

pub fn encode_describe_endpoints_input(
  input: DescribeEndpointsRequest,
) -> String {
  json.to_string(encode_describe_endpoints_request_struct_top(input))
}

pub fn decode_describe_endpoints_output(
  body: String,
) -> Result(DescribeEndpointsResponse, String) {
  case json.parse(body, decode_describe_endpoints_response_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_describe_endpoints_request(
  input: DescribeEndpointsRequest,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_describe_endpoints_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DescribeEndpoints"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_describe_endpoints_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DescribeEndpointsResponse, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_describe_endpoints_output("{}")
        _ -> decode_describe_endpoints_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DescribeEndpointsError {
  DescribeEndpointsErrorTransport(reason: String)
  DescribeEndpointsErrorUnknown(error_type: String, status: Int, body: String)
}

fn describe_endpoints_error_decoders() {
  []
}

fn translate_describe_endpoints_error(
  err: runtime.ClientError,
) -> DescribeEndpointsError {
  runtime.translate_service_error(
    err,
    describe_endpoints_error_decoders(),
    fn(reason) { DescribeEndpointsErrorTransport(reason: reason) },
    fn(et, s, body) {
      DescribeEndpointsErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_describe_export_input(input: DescribeExportInput) -> String {
  json.to_string(encode_describe_export_input_struct_top(input))
}

pub fn decode_describe_export_output(
  body: String,
) -> Result(DescribeExportOutput, String) {
  case json.parse(body, decode_describe_export_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_describe_export_request(
  input: DescribeExportInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_describe_export_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DescribeExport"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_describe_export_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DescribeExportOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_describe_export_output("{}")
        _ -> decode_describe_export_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DescribeExportError {
  DescribeExportErrorExportNotFoundException(value: ExportNotFoundException)
  DescribeExportErrorInternalServerError(value: InternalServerError)
  DescribeExportErrorLimitExceededException(value: LimitExceededException)
  DescribeExportErrorTransport(reason: String)
  DescribeExportErrorUnknown(error_type: String, status: Int, body: String)
}

fn describe_export_error_decoders() {
  [
    #("ExportNotFoundException", fn(body) {
      case json.parse(body, decode_export_not_found_exception_struct()) {
        Ok(v) -> Ok(DescribeExportErrorExportNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(DescribeExportErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(DescribeExportErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_describe_export_error(
  err: runtime.ClientError,
) -> DescribeExportError {
  runtime.translate_service_error(
    err,
    describe_export_error_decoders(),
    fn(reason) { DescribeExportErrorTransport(reason: reason) },
    fn(et, s, body) {
      DescribeExportErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_describe_global_table_input(
  input: DescribeGlobalTableInput,
) -> String {
  json.to_string(encode_describe_global_table_input_struct_top(input))
}

pub fn decode_describe_global_table_output(
  body: String,
) -> Result(DescribeGlobalTableOutput, String) {
  case json.parse(body, decode_describe_global_table_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_describe_global_table_request(
  input: DescribeGlobalTableInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_describe_global_table_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DescribeGlobalTable"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_describe_global_table_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DescribeGlobalTableOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_describe_global_table_output("{}")
        _ -> decode_describe_global_table_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DescribeGlobalTableError {
  DescribeGlobalTableErrorGlobalTableNotFoundException(
    value: GlobalTableNotFoundException,
  )
  DescribeGlobalTableErrorInternalServerError(value: InternalServerError)
  DescribeGlobalTableErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  DescribeGlobalTableErrorTransport(reason: String)
  DescribeGlobalTableErrorUnknown(error_type: String, status: Int, body: String)
}

fn describe_global_table_error_decoders() {
  [
    #("GlobalTableNotFoundException", fn(body) {
      case json.parse(body, decode_global_table_not_found_exception_struct()) {
        Ok(v) ->
          Ok(DescribeGlobalTableErrorGlobalTableNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(DescribeGlobalTableErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(DescribeGlobalTableErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_describe_global_table_error(
  err: runtime.ClientError,
) -> DescribeGlobalTableError {
  runtime.translate_service_error(
    err,
    describe_global_table_error_decoders(),
    fn(reason) { DescribeGlobalTableErrorTransport(reason: reason) },
    fn(et, s, body) {
      DescribeGlobalTableErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_describe_global_table_settings_input(
  input: DescribeGlobalTableSettingsInput,
) -> String {
  json.to_string(encode_describe_global_table_settings_input_struct_top(input))
}

pub fn decode_describe_global_table_settings_output(
  body: String,
) -> Result(DescribeGlobalTableSettingsOutput, String) {
  case json.parse(body, decode_describe_global_table_settings_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_describe_global_table_settings_request(
  input: DescribeGlobalTableSettingsInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_describe_global_table_settings_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DescribeGlobalTableSettings"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_describe_global_table_settings_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DescribeGlobalTableSettingsOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_describe_global_table_settings_output("{}")
        _ -> decode_describe_global_table_settings_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DescribeGlobalTableSettingsError {
  DescribeGlobalTableSettingsErrorGlobalTableNotFoundException(
    value: GlobalTableNotFoundException,
  )
  DescribeGlobalTableSettingsErrorInternalServerError(
    value: InternalServerError,
  )
  DescribeGlobalTableSettingsErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  DescribeGlobalTableSettingsErrorTransport(reason: String)
  DescribeGlobalTableSettingsErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn describe_global_table_settings_error_decoders() {
  [
    #("GlobalTableNotFoundException", fn(body) {
      case json.parse(body, decode_global_table_not_found_exception_struct()) {
        Ok(v) ->
          Ok(DescribeGlobalTableSettingsErrorGlobalTableNotFoundException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) ->
          Ok(DescribeGlobalTableSettingsErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) ->
          Ok(DescribeGlobalTableSettingsErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_describe_global_table_settings_error(
  err: runtime.ClientError,
) -> DescribeGlobalTableSettingsError {
  runtime.translate_service_error(
    err,
    describe_global_table_settings_error_decoders(),
    fn(reason) { DescribeGlobalTableSettingsErrorTransport(reason: reason) },
    fn(et, s, body) {
      DescribeGlobalTableSettingsErrorUnknown(
        error_type: et,
        status: s,
        body: body,
      )
    },
  )
}

pub fn encode_describe_import_input(input: DescribeImportInput) -> String {
  json.to_string(encode_describe_import_input_struct_top(input))
}

pub fn decode_describe_import_output(
  body: String,
) -> Result(DescribeImportOutput, String) {
  case json.parse(body, decode_describe_import_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_describe_import_request(
  input: DescribeImportInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_describe_import_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DescribeImport"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_describe_import_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DescribeImportOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_describe_import_output("{}")
        _ -> decode_describe_import_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DescribeImportError {
  DescribeImportErrorImportNotFoundException(value: ImportNotFoundException)
  DescribeImportErrorTransport(reason: String)
  DescribeImportErrorUnknown(error_type: String, status: Int, body: String)
}

fn describe_import_error_decoders() {
  [
    #("ImportNotFoundException", fn(body) {
      case json.parse(body, decode_import_not_found_exception_struct()) {
        Ok(v) -> Ok(DescribeImportErrorImportNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_describe_import_error(
  err: runtime.ClientError,
) -> DescribeImportError {
  runtime.translate_service_error(
    err,
    describe_import_error_decoders(),
    fn(reason) { DescribeImportErrorTransport(reason: reason) },
    fn(et, s, body) {
      DescribeImportErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_describe_kinesis_streaming_destination_input(
  input: DescribeKinesisStreamingDestinationInput,
) -> String {
  json.to_string(encode_describe_kinesis_streaming_destination_input_struct_top(
    input,
  ))
}

pub fn decode_describe_kinesis_streaming_destination_output(
  body: String,
) -> Result(DescribeKinesisStreamingDestinationOutput, String) {
  case
    json.parse(
      body,
      decode_describe_kinesis_streaming_destination_output_struct(),
    )
  {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_describe_kinesis_streaming_destination_request(
  input: DescribeKinesisStreamingDestinationInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_describe_kinesis_streaming_destination_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DescribeKinesisStreamingDestination"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_describe_kinesis_streaming_destination_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DescribeKinesisStreamingDestinationOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_describe_kinesis_streaming_destination_output("{}")
        _ -> decode_describe_kinesis_streaming_destination_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DescribeKinesisStreamingDestinationError {
  DescribeKinesisStreamingDestinationErrorInternalServerError(
    value: InternalServerError,
  )
  DescribeKinesisStreamingDestinationErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  DescribeKinesisStreamingDestinationErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  DescribeKinesisStreamingDestinationErrorTransport(reason: String)
  DescribeKinesisStreamingDestinationErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn describe_kinesis_streaming_destination_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) ->
          Ok(DescribeKinesisStreamingDestinationErrorInternalServerError(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) ->
          Ok(DescribeKinesisStreamingDestinationErrorInvalidEndpointException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) ->
          Ok(DescribeKinesisStreamingDestinationErrorResourceNotFoundException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_describe_kinesis_streaming_destination_error(
  err: runtime.ClientError,
) -> DescribeKinesisStreamingDestinationError {
  runtime.translate_service_error(
    err,
    describe_kinesis_streaming_destination_error_decoders(),
    fn(reason) {
      DescribeKinesisStreamingDestinationErrorTransport(reason: reason)
    },
    fn(et, s, body) {
      DescribeKinesisStreamingDestinationErrorUnknown(
        error_type: et,
        status: s,
        body: body,
      )
    },
  )
}

pub fn encode_describe_limits_input(input: DescribeLimitsInput) -> String {
  json.to_string(encode_describe_limits_input_struct_top(input))
}

pub fn decode_describe_limits_output(
  body: String,
) -> Result(DescribeLimitsOutput, String) {
  case json.parse(body, decode_describe_limits_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_describe_limits_request(
  input: DescribeLimitsInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_describe_limits_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DescribeLimits"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_describe_limits_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DescribeLimitsOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_describe_limits_output("{}")
        _ -> decode_describe_limits_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DescribeLimitsError {
  DescribeLimitsErrorInternalServerError(value: InternalServerError)
  DescribeLimitsErrorInvalidEndpointException(value: InvalidEndpointException)
  DescribeLimitsErrorTransport(reason: String)
  DescribeLimitsErrorUnknown(error_type: String, status: Int, body: String)
}

fn describe_limits_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(DescribeLimitsErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(DescribeLimitsErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_describe_limits_error(
  err: runtime.ClientError,
) -> DescribeLimitsError {
  runtime.translate_service_error(
    err,
    describe_limits_error_decoders(),
    fn(reason) { DescribeLimitsErrorTransport(reason: reason) },
    fn(et, s, body) {
      DescribeLimitsErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_describe_table_input(input: DescribeTableInput) -> String {
  json.to_string(encode_describe_table_input_struct_top(input))
}

pub fn decode_describe_table_output(
  body: String,
) -> Result(DescribeTableOutput, String) {
  case json.parse(body, decode_describe_table_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_describe_table_request(
  input: DescribeTableInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_describe_table_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DescribeTable"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_describe_table_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DescribeTableOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_describe_table_output("{}")
        _ -> decode_describe_table_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DescribeTableError {
  DescribeTableErrorInternalServerError(value: InternalServerError)
  DescribeTableErrorInvalidEndpointException(value: InvalidEndpointException)
  DescribeTableErrorResourceNotFoundException(value: ResourceNotFoundException)
  DescribeTableErrorTransport(reason: String)
  DescribeTableErrorUnknown(error_type: String, status: Int, body: String)
}

fn describe_table_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(DescribeTableErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(DescribeTableErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(DescribeTableErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_describe_table_error(
  err: runtime.ClientError,
) -> DescribeTableError {
  runtime.translate_service_error(
    err,
    describe_table_error_decoders(),
    fn(reason) { DescribeTableErrorTransport(reason: reason) },
    fn(et, s, body) {
      DescribeTableErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_describe_table_replica_auto_scaling_input(
  input: DescribeTableReplicaAutoScalingInput,
) -> String {
  json.to_string(encode_describe_table_replica_auto_scaling_input_struct_top(
    input,
  ))
}

pub fn decode_describe_table_replica_auto_scaling_output(
  body: String,
) -> Result(DescribeTableReplicaAutoScalingOutput, String) {
  case
    json.parse(body, decode_describe_table_replica_auto_scaling_output_struct())
  {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_describe_table_replica_auto_scaling_request(
  input: DescribeTableReplicaAutoScalingInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_describe_table_replica_auto_scaling_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DescribeTableReplicaAutoScaling"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_describe_table_replica_auto_scaling_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DescribeTableReplicaAutoScalingOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_describe_table_replica_auto_scaling_output("{}")
        _ -> decode_describe_table_replica_auto_scaling_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DescribeTableReplicaAutoScalingError {
  DescribeTableReplicaAutoScalingErrorInternalServerError(
    value: InternalServerError,
  )
  DescribeTableReplicaAutoScalingErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  DescribeTableReplicaAutoScalingErrorTransport(reason: String)
  DescribeTableReplicaAutoScalingErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn describe_table_replica_auto_scaling_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) ->
          Ok(DescribeTableReplicaAutoScalingErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) ->
          Ok(DescribeTableReplicaAutoScalingErrorResourceNotFoundException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_describe_table_replica_auto_scaling_error(
  err: runtime.ClientError,
) -> DescribeTableReplicaAutoScalingError {
  runtime.translate_service_error(
    err,
    describe_table_replica_auto_scaling_error_decoders(),
    fn(reason) { DescribeTableReplicaAutoScalingErrorTransport(reason: reason) },
    fn(et, s, body) {
      DescribeTableReplicaAutoScalingErrorUnknown(
        error_type: et,
        status: s,
        body: body,
      )
    },
  )
}

pub fn encode_describe_time_to_live_input(
  input: DescribeTimeToLiveInput,
) -> String {
  json.to_string(encode_describe_time_to_live_input_struct_top(input))
}

pub fn decode_describe_time_to_live_output(
  body: String,
) -> Result(DescribeTimeToLiveOutput, String) {
  case json.parse(body, decode_describe_time_to_live_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_describe_time_to_live_request(
  input: DescribeTimeToLiveInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_describe_time_to_live_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DescribeTimeToLive"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_describe_time_to_live_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(DescribeTimeToLiveOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_describe_time_to_live_output("{}")
        _ -> decode_describe_time_to_live_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DescribeTimeToLiveError {
  DescribeTimeToLiveErrorInternalServerError(value: InternalServerError)
  DescribeTimeToLiveErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  DescribeTimeToLiveErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  DescribeTimeToLiveErrorTransport(reason: String)
  DescribeTimeToLiveErrorUnknown(error_type: String, status: Int, body: String)
}

fn describe_time_to_live_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(DescribeTimeToLiveErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(DescribeTimeToLiveErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(DescribeTimeToLiveErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_describe_time_to_live_error(
  err: runtime.ClientError,
) -> DescribeTimeToLiveError {
  runtime.translate_service_error(
    err,
    describe_time_to_live_error_decoders(),
    fn(reason) { DescribeTimeToLiveErrorTransport(reason: reason) },
    fn(et, s, body) {
      DescribeTimeToLiveErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_disable_kinesis_streaming_destination_input(
  input: KinesisStreamingDestinationInput,
) -> String {
  json.to_string(encode_kinesis_streaming_destination_input_struct_top(input))
}

pub fn decode_disable_kinesis_streaming_destination_output(
  body: String,
) -> Result(KinesisStreamingDestinationOutput, String) {
  case json.parse(body, decode_kinesis_streaming_destination_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_disable_kinesis_streaming_destination_request(
  input: KinesisStreamingDestinationInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_disable_kinesis_streaming_destination_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.DisableKinesisStreamingDestination"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_disable_kinesis_streaming_destination_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(KinesisStreamingDestinationOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_disable_kinesis_streaming_destination_output("{}")
        _ -> decode_disable_kinesis_streaming_destination_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type DisableKinesisStreamingDestinationError {
  DisableKinesisStreamingDestinationErrorInternalServerError(
    value: InternalServerError,
  )
  DisableKinesisStreamingDestinationErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  DisableKinesisStreamingDestinationErrorLimitExceededException(
    value: LimitExceededException,
  )
  DisableKinesisStreamingDestinationErrorResourceInUseException(
    value: ResourceInUseException,
  )
  DisableKinesisStreamingDestinationErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  DisableKinesisStreamingDestinationErrorTransport(reason: String)
  DisableKinesisStreamingDestinationErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn disable_kinesis_streaming_destination_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) ->
          Ok(DisableKinesisStreamingDestinationErrorInternalServerError(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) ->
          Ok(DisableKinesisStreamingDestinationErrorInvalidEndpointException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) ->
          Ok(DisableKinesisStreamingDestinationErrorLimitExceededException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) ->
          Ok(DisableKinesisStreamingDestinationErrorResourceInUseException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) ->
          Ok(DisableKinesisStreamingDestinationErrorResourceNotFoundException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_disable_kinesis_streaming_destination_error(
  err: runtime.ClientError,
) -> DisableKinesisStreamingDestinationError {
  runtime.translate_service_error(
    err,
    disable_kinesis_streaming_destination_error_decoders(),
    fn(reason) {
      DisableKinesisStreamingDestinationErrorTransport(reason: reason)
    },
    fn(et, s, body) {
      DisableKinesisStreamingDestinationErrorUnknown(
        error_type: et,
        status: s,
        body: body,
      )
    },
  )
}

pub fn encode_enable_kinesis_streaming_destination_input(
  input: KinesisStreamingDestinationInput,
) -> String {
  json.to_string(encode_kinesis_streaming_destination_input_struct_top(input))
}

pub fn decode_enable_kinesis_streaming_destination_output(
  body: String,
) -> Result(KinesisStreamingDestinationOutput, String) {
  case json.parse(body, decode_kinesis_streaming_destination_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_enable_kinesis_streaming_destination_request(
  input: KinesisStreamingDestinationInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_enable_kinesis_streaming_destination_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.EnableKinesisStreamingDestination"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_enable_kinesis_streaming_destination_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(KinesisStreamingDestinationOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_enable_kinesis_streaming_destination_output("{}")
        _ -> decode_enable_kinesis_streaming_destination_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type EnableKinesisStreamingDestinationError {
  EnableKinesisStreamingDestinationErrorInternalServerError(
    value: InternalServerError,
  )
  EnableKinesisStreamingDestinationErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  EnableKinesisStreamingDestinationErrorLimitExceededException(
    value: LimitExceededException,
  )
  EnableKinesisStreamingDestinationErrorResourceInUseException(
    value: ResourceInUseException,
  )
  EnableKinesisStreamingDestinationErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  EnableKinesisStreamingDestinationErrorTransport(reason: String)
  EnableKinesisStreamingDestinationErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn enable_kinesis_streaming_destination_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) ->
          Ok(EnableKinesisStreamingDestinationErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) ->
          Ok(EnableKinesisStreamingDestinationErrorInvalidEndpointException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) ->
          Ok(EnableKinesisStreamingDestinationErrorLimitExceededException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) ->
          Ok(EnableKinesisStreamingDestinationErrorResourceInUseException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) ->
          Ok(EnableKinesisStreamingDestinationErrorResourceNotFoundException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_enable_kinesis_streaming_destination_error(
  err: runtime.ClientError,
) -> EnableKinesisStreamingDestinationError {
  runtime.translate_service_error(
    err,
    enable_kinesis_streaming_destination_error_decoders(),
    fn(reason) {
      EnableKinesisStreamingDestinationErrorTransport(reason: reason)
    },
    fn(et, s, body) {
      EnableKinesisStreamingDestinationErrorUnknown(
        error_type: et,
        status: s,
        body: body,
      )
    },
  )
}

pub fn encode_execute_statement_input(input: ExecuteStatementInput) -> String {
  json.to_string(encode_execute_statement_input_struct_top(input))
}

pub fn decode_execute_statement_output(
  body: String,
) -> Result(ExecuteStatementOutput, String) {
  case json.parse(body, decode_execute_statement_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_execute_statement_request(
  input: ExecuteStatementInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_execute_statement_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.ExecuteStatement"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_execute_statement_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(ExecuteStatementOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_execute_statement_output("{}")
        _ -> decode_execute_statement_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type ExecuteStatementError {
  ExecuteStatementErrorConditionalCheckFailedException(
    value: ConditionalCheckFailedException,
  )
  ExecuteStatementErrorDuplicateItemException(value: DuplicateItemException)
  ExecuteStatementErrorInternalServerError(value: InternalServerError)
  ExecuteStatementErrorItemCollectionSizeLimitExceededException(
    value: ItemCollectionSizeLimitExceededException,
  )
  ExecuteStatementErrorProvisionedThroughputExceededException(
    value: ProvisionedThroughputExceededException,
  )
  ExecuteStatementErrorRequestLimitExceeded(value: RequestLimitExceeded)
  ExecuteStatementErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  ExecuteStatementErrorThrottlingException(value: ThrottlingException)
  ExecuteStatementErrorTransactionConflictException(
    value: TransactionConflictException,
  )
  ExecuteStatementErrorTransport(reason: String)
  ExecuteStatementErrorUnknown(error_type: String, status: Int, body: String)
}

fn execute_statement_error_decoders() {
  [
    #("ConditionalCheckFailedException", fn(body) {
      case
        json.parse(body, decode_conditional_check_failed_exception_struct())
      {
        Ok(v) ->
          Ok(ExecuteStatementErrorConditionalCheckFailedException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("DuplicateItemException", fn(body) {
      case json.parse(body, decode_duplicate_item_exception_struct()) {
        Ok(v) -> Ok(ExecuteStatementErrorDuplicateItemException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(ExecuteStatementErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ItemCollectionSizeLimitExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_item_collection_size_limit_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(ExecuteStatementErrorItemCollectionSizeLimitExceededException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("ProvisionedThroughputExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_provisioned_throughput_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(ExecuteStatementErrorProvisionedThroughputExceededException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("RequestLimitExceeded", fn(body) {
      case json.parse(body, decode_request_limit_exceeded_struct()) {
        Ok(v) -> Ok(ExecuteStatementErrorRequestLimitExceeded(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(ExecuteStatementErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ThrottlingException", fn(body) {
      case json.parse(body, decode_throttling_exception_struct()) {
        Ok(v) -> Ok(ExecuteStatementErrorThrottlingException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TransactionConflictException", fn(body) {
      case json.parse(body, decode_transaction_conflict_exception_struct()) {
        Ok(v) -> Ok(ExecuteStatementErrorTransactionConflictException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_execute_statement_error(
  err: runtime.ClientError,
) -> ExecuteStatementError {
  runtime.translate_service_error(
    err,
    execute_statement_error_decoders(),
    fn(reason) { ExecuteStatementErrorTransport(reason: reason) },
    fn(et, s, body) {
      ExecuteStatementErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_execute_transaction_input(
  input: ExecuteTransactionInput,
) -> String {
  json.to_string(encode_execute_transaction_input_struct_top(input))
}

pub fn decode_execute_transaction_output(
  body: String,
) -> Result(ExecuteTransactionOutput, String) {
  case json.parse(body, decode_execute_transaction_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_execute_transaction_request(
  input: ExecuteTransactionInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_execute_transaction_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.ExecuteTransaction"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_execute_transaction_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(ExecuteTransactionOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_execute_transaction_output("{}")
        _ -> decode_execute_transaction_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type ExecuteTransactionError {
  ExecuteTransactionErrorIdempotentParameterMismatchException(
    value: IdempotentParameterMismatchException,
  )
  ExecuteTransactionErrorInternalServerError(value: InternalServerError)
  ExecuteTransactionErrorProvisionedThroughputExceededException(
    value: ProvisionedThroughputExceededException,
  )
  ExecuteTransactionErrorRequestLimitExceeded(value: RequestLimitExceeded)
  ExecuteTransactionErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  ExecuteTransactionErrorThrottlingException(value: ThrottlingException)
  ExecuteTransactionErrorTransactionCanceledException(
    value: TransactionCanceledException,
  )
  ExecuteTransactionErrorTransactionInProgressException(
    value: TransactionInProgressException,
  )
  ExecuteTransactionErrorTransport(reason: String)
  ExecuteTransactionErrorUnknown(error_type: String, status: Int, body: String)
}

fn execute_transaction_error_decoders() {
  [
    #("IdempotentParameterMismatchException", fn(body) {
      case
        json.parse(
          body,
          decode_idempotent_parameter_mismatch_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(ExecuteTransactionErrorIdempotentParameterMismatchException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(ExecuteTransactionErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ProvisionedThroughputExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_provisioned_throughput_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(ExecuteTransactionErrorProvisionedThroughputExceededException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("RequestLimitExceeded", fn(body) {
      case json.parse(body, decode_request_limit_exceeded_struct()) {
        Ok(v) -> Ok(ExecuteTransactionErrorRequestLimitExceeded(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(ExecuteTransactionErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ThrottlingException", fn(body) {
      case json.parse(body, decode_throttling_exception_struct()) {
        Ok(v) -> Ok(ExecuteTransactionErrorThrottlingException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TransactionCanceledException", fn(body) {
      case json.parse(body, decode_transaction_canceled_exception_struct()) {
        Ok(v) ->
          Ok(ExecuteTransactionErrorTransactionCanceledException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TransactionInProgressException", fn(body) {
      case json.parse(body, decode_transaction_in_progress_exception_struct()) {
        Ok(v) ->
          Ok(ExecuteTransactionErrorTransactionInProgressException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_execute_transaction_error(
  err: runtime.ClientError,
) -> ExecuteTransactionError {
  runtime.translate_service_error(
    err,
    execute_transaction_error_decoders(),
    fn(reason) { ExecuteTransactionErrorTransport(reason: reason) },
    fn(et, s, body) {
      ExecuteTransactionErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_export_table_to_point_in_time_input(
  input: ExportTableToPointInTimeInput,
) -> String {
  json.to_string(encode_export_table_to_point_in_time_input_struct_top(input))
}

pub fn decode_export_table_to_point_in_time_output(
  body: String,
) -> Result(ExportTableToPointInTimeOutput, String) {
  case json.parse(body, decode_export_table_to_point_in_time_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_export_table_to_point_in_time_request(
  input: ExportTableToPointInTimeInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_export_table_to_point_in_time_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.ExportTableToPointInTime"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_export_table_to_point_in_time_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(ExportTableToPointInTimeOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_export_table_to_point_in_time_output("{}")
        _ -> decode_export_table_to_point_in_time_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type ExportTableToPointInTimeError {
  ExportTableToPointInTimeErrorExportConflictException(
    value: ExportConflictException,
  )
  ExportTableToPointInTimeErrorInternalServerError(value: InternalServerError)
  ExportTableToPointInTimeErrorInvalidExportTimeException(
    value: InvalidExportTimeException,
  )
  ExportTableToPointInTimeErrorLimitExceededException(
    value: LimitExceededException,
  )
  ExportTableToPointInTimeErrorPointInTimeRecoveryUnavailableException(
    value: PointInTimeRecoveryUnavailableException,
  )
  ExportTableToPointInTimeErrorTableNotFoundException(
    value: TableNotFoundException,
  )
  ExportTableToPointInTimeErrorTransport(reason: String)
  ExportTableToPointInTimeErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn export_table_to_point_in_time_error_decoders() {
  [
    #("ExportConflictException", fn(body) {
      case json.parse(body, decode_export_conflict_exception_struct()) {
        Ok(v) ->
          Ok(ExportTableToPointInTimeErrorExportConflictException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(ExportTableToPointInTimeErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidExportTimeException", fn(body) {
      case json.parse(body, decode_invalid_export_time_exception_struct()) {
        Ok(v) ->
          Ok(ExportTableToPointInTimeErrorInvalidExportTimeException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) ->
          Ok(ExportTableToPointInTimeErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("PointInTimeRecoveryUnavailableException", fn(body) {
      case
        json.parse(
          body,
          decode_point_in_time_recovery_unavailable_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(
            ExportTableToPointInTimeErrorPointInTimeRecoveryUnavailableException(
              value: v,
            ),
          )
        Error(_) -> Error(Nil)
      }
    }),
    #("TableNotFoundException", fn(body) {
      case json.parse(body, decode_table_not_found_exception_struct()) {
        Ok(v) ->
          Ok(ExportTableToPointInTimeErrorTableNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_export_table_to_point_in_time_error(
  err: runtime.ClientError,
) -> ExportTableToPointInTimeError {
  runtime.translate_service_error(
    err,
    export_table_to_point_in_time_error_decoders(),
    fn(reason) { ExportTableToPointInTimeErrorTransport(reason: reason) },
    fn(et, s, body) {
      ExportTableToPointInTimeErrorUnknown(
        error_type: et,
        status: s,
        body: body,
      )
    },
  )
}

pub fn encode_get_item_input(input: GetItemInput) -> String {
  json.to_string(encode_get_item_input_struct_top(input))
}

pub fn decode_get_item_output(body: String) -> Result(GetItemOutput, String) {
  case json.parse(body, decode_get_item_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_get_item_request(
  input: GetItemInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_get_item_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.GetItem"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_get_item_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(GetItemOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_get_item_output("{}")
        _ -> decode_get_item_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type GetItemError {
  GetItemErrorInternalServerError(value: InternalServerError)
  GetItemErrorInvalidEndpointException(value: InvalidEndpointException)
  GetItemErrorProvisionedThroughputExceededException(
    value: ProvisionedThroughputExceededException,
  )
  GetItemErrorRequestLimitExceeded(value: RequestLimitExceeded)
  GetItemErrorResourceNotFoundException(value: ResourceNotFoundException)
  GetItemErrorThrottlingException(value: ThrottlingException)
  GetItemErrorTransport(reason: String)
  GetItemErrorUnknown(error_type: String, status: Int, body: String)
}

fn get_item_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(GetItemErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(GetItemErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ProvisionedThroughputExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_provisioned_throughput_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(GetItemErrorProvisionedThroughputExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("RequestLimitExceeded", fn(body) {
      case json.parse(body, decode_request_limit_exceeded_struct()) {
        Ok(v) -> Ok(GetItemErrorRequestLimitExceeded(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(GetItemErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ThrottlingException", fn(body) {
      case json.parse(body, decode_throttling_exception_struct()) {
        Ok(v) -> Ok(GetItemErrorThrottlingException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_get_item_error(err: runtime.ClientError) -> GetItemError {
  runtime.translate_service_error(
    err,
    get_item_error_decoders(),
    fn(reason) { GetItemErrorTransport(reason: reason) },
    fn(et, s, body) {
      GetItemErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_get_resource_policy_input(
  input: GetResourcePolicyInput,
) -> String {
  json.to_string(encode_get_resource_policy_input_struct_top(input))
}

pub fn decode_get_resource_policy_output(
  body: String,
) -> Result(GetResourcePolicyOutput, String) {
  case json.parse(body, decode_get_resource_policy_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_get_resource_policy_request(
  input: GetResourcePolicyInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_get_resource_policy_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.GetResourcePolicy"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_get_resource_policy_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(GetResourcePolicyOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_get_resource_policy_output("{}")
        _ -> decode_get_resource_policy_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type GetResourcePolicyError {
  GetResourcePolicyErrorInternalServerError(value: InternalServerError)
  GetResourcePolicyErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  GetResourcePolicyErrorPolicyNotFoundException(value: PolicyNotFoundException)
  GetResourcePolicyErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  GetResourcePolicyErrorTransport(reason: String)
  GetResourcePolicyErrorUnknown(error_type: String, status: Int, body: String)
}

fn get_resource_policy_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(GetResourcePolicyErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(GetResourcePolicyErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("PolicyNotFoundException", fn(body) {
      case json.parse(body, decode_policy_not_found_exception_struct()) {
        Ok(v) -> Ok(GetResourcePolicyErrorPolicyNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(GetResourcePolicyErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_get_resource_policy_error(
  err: runtime.ClientError,
) -> GetResourcePolicyError {
  runtime.translate_service_error(
    err,
    get_resource_policy_error_decoders(),
    fn(reason) { GetResourcePolicyErrorTransport(reason: reason) },
    fn(et, s, body) {
      GetResourcePolicyErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_import_table_input(input: ImportTableInput) -> String {
  json.to_string(encode_import_table_input_struct_top(input))
}

pub fn decode_import_table_output(
  body: String,
) -> Result(ImportTableOutput, String) {
  case json.parse(body, decode_import_table_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_import_table_request(
  input: ImportTableInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_import_table_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.ImportTable"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_import_table_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(ImportTableOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_import_table_output("{}")
        _ -> decode_import_table_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type ImportTableError {
  ImportTableErrorImportConflictException(value: ImportConflictException)
  ImportTableErrorLimitExceededException(value: LimitExceededException)
  ImportTableErrorResourceInUseException(value: ResourceInUseException)
  ImportTableErrorTransport(reason: String)
  ImportTableErrorUnknown(error_type: String, status: Int, body: String)
}

fn import_table_error_decoders() {
  [
    #("ImportConflictException", fn(body) {
      case json.parse(body, decode_import_conflict_exception_struct()) {
        Ok(v) -> Ok(ImportTableErrorImportConflictException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(ImportTableErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) -> Ok(ImportTableErrorResourceInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_import_table_error(err: runtime.ClientError) -> ImportTableError {
  runtime.translate_service_error(
    err,
    import_table_error_decoders(),
    fn(reason) { ImportTableErrorTransport(reason: reason) },
    fn(et, s, body) {
      ImportTableErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_list_backups_input(input: ListBackupsInput) -> String {
  json.to_string(encode_list_backups_input_struct_top(input))
}

pub fn decode_list_backups_output(
  body: String,
) -> Result(ListBackupsOutput, String) {
  case json.parse(body, decode_list_backups_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_list_backups_request(
  input: ListBackupsInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_list_backups_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.ListBackups"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_list_backups_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(ListBackupsOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_list_backups_output("{}")
        _ -> decode_list_backups_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type ListBackupsError {
  ListBackupsErrorInternalServerError(value: InternalServerError)
  ListBackupsErrorInvalidEndpointException(value: InvalidEndpointException)
  ListBackupsErrorTransport(reason: String)
  ListBackupsErrorUnknown(error_type: String, status: Int, body: String)
}

fn list_backups_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(ListBackupsErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(ListBackupsErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_list_backups_error(err: runtime.ClientError) -> ListBackupsError {
  runtime.translate_service_error(
    err,
    list_backups_error_decoders(),
    fn(reason) { ListBackupsErrorTransport(reason: reason) },
    fn(et, s, body) {
      ListBackupsErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_list_contributor_insights_input(
  input: ListContributorInsightsInput,
) -> String {
  json.to_string(encode_list_contributor_insights_input_struct_top(input))
}

pub fn decode_list_contributor_insights_output(
  body: String,
) -> Result(ListContributorInsightsOutput, String) {
  case json.parse(body, decode_list_contributor_insights_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_list_contributor_insights_request(
  input: ListContributorInsightsInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_list_contributor_insights_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.ListContributorInsights"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_list_contributor_insights_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(ListContributorInsightsOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_list_contributor_insights_output("{}")
        _ -> decode_list_contributor_insights_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type ListContributorInsightsError {
  ListContributorInsightsErrorInternalServerError(value: InternalServerError)
  ListContributorInsightsErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  ListContributorInsightsErrorTransport(reason: String)
  ListContributorInsightsErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn list_contributor_insights_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(ListContributorInsightsErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) ->
          Ok(ListContributorInsightsErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_list_contributor_insights_error(
  err: runtime.ClientError,
) -> ListContributorInsightsError {
  runtime.translate_service_error(
    err,
    list_contributor_insights_error_decoders(),
    fn(reason) { ListContributorInsightsErrorTransport(reason: reason) },
    fn(et, s, body) {
      ListContributorInsightsErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_list_exports_input(input: ListExportsInput) -> String {
  json.to_string(encode_list_exports_input_struct_top(input))
}

pub fn decode_list_exports_output(
  body: String,
) -> Result(ListExportsOutput, String) {
  case json.parse(body, decode_list_exports_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_list_exports_request(
  input: ListExportsInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_list_exports_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.ListExports"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_list_exports_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(ListExportsOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_list_exports_output("{}")
        _ -> decode_list_exports_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type ListExportsError {
  ListExportsErrorInternalServerError(value: InternalServerError)
  ListExportsErrorLimitExceededException(value: LimitExceededException)
  ListExportsErrorTransport(reason: String)
  ListExportsErrorUnknown(error_type: String, status: Int, body: String)
}

fn list_exports_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(ListExportsErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(ListExportsErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_list_exports_error(err: runtime.ClientError) -> ListExportsError {
  runtime.translate_service_error(
    err,
    list_exports_error_decoders(),
    fn(reason) { ListExportsErrorTransport(reason: reason) },
    fn(et, s, body) {
      ListExportsErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_list_global_tables_input(input: ListGlobalTablesInput) -> String {
  json.to_string(encode_list_global_tables_input_struct_top(input))
}

pub fn decode_list_global_tables_output(
  body: String,
) -> Result(ListGlobalTablesOutput, String) {
  case json.parse(body, decode_list_global_tables_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_list_global_tables_request(
  input: ListGlobalTablesInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_list_global_tables_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.ListGlobalTables"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_list_global_tables_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(ListGlobalTablesOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_list_global_tables_output("{}")
        _ -> decode_list_global_tables_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type ListGlobalTablesError {
  ListGlobalTablesErrorInternalServerError(value: InternalServerError)
  ListGlobalTablesErrorInvalidEndpointException(value: InvalidEndpointException)
  ListGlobalTablesErrorTransport(reason: String)
  ListGlobalTablesErrorUnknown(error_type: String, status: Int, body: String)
}

fn list_global_tables_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(ListGlobalTablesErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(ListGlobalTablesErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_list_global_tables_error(
  err: runtime.ClientError,
) -> ListGlobalTablesError {
  runtime.translate_service_error(
    err,
    list_global_tables_error_decoders(),
    fn(reason) { ListGlobalTablesErrorTransport(reason: reason) },
    fn(et, s, body) {
      ListGlobalTablesErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_list_imports_input(input: ListImportsInput) -> String {
  json.to_string(encode_list_imports_input_struct_top(input))
}

pub fn decode_list_imports_output(
  body: String,
) -> Result(ListImportsOutput, String) {
  case json.parse(body, decode_list_imports_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_list_imports_request(
  input: ListImportsInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_list_imports_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.ListImports"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_list_imports_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(ListImportsOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_list_imports_output("{}")
        _ -> decode_list_imports_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type ListImportsError {
  ListImportsErrorLimitExceededException(value: LimitExceededException)
  ListImportsErrorTransport(reason: String)
  ListImportsErrorUnknown(error_type: String, status: Int, body: String)
}

fn list_imports_error_decoders() {
  [
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(ListImportsErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_list_imports_error(err: runtime.ClientError) -> ListImportsError {
  runtime.translate_service_error(
    err,
    list_imports_error_decoders(),
    fn(reason) { ListImportsErrorTransport(reason: reason) },
    fn(et, s, body) {
      ListImportsErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_list_tables_input(input: ListTablesInput) -> String {
  json.to_string(encode_list_tables_input_struct_top(input))
}

pub fn decode_list_tables_output(
  body: String,
) -> Result(ListTablesOutput, String) {
  case json.parse(body, decode_list_tables_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_list_tables_request(
  input: ListTablesInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_list_tables_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.ListTables"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_list_tables_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(ListTablesOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_list_tables_output("{}")
        _ -> decode_list_tables_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type ListTablesError {
  ListTablesErrorInternalServerError(value: InternalServerError)
  ListTablesErrorInvalidEndpointException(value: InvalidEndpointException)
  ListTablesErrorTransport(reason: String)
  ListTablesErrorUnknown(error_type: String, status: Int, body: String)
}

fn list_tables_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(ListTablesErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(ListTablesErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_list_tables_error(err: runtime.ClientError) -> ListTablesError {
  runtime.translate_service_error(
    err,
    list_tables_error_decoders(),
    fn(reason) { ListTablesErrorTransport(reason: reason) },
    fn(et, s, body) {
      ListTablesErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_list_tags_of_resource_input(
  input: ListTagsOfResourceInput,
) -> String {
  json.to_string(encode_list_tags_of_resource_input_struct_top(input))
}

pub fn decode_list_tags_of_resource_output(
  body: String,
) -> Result(ListTagsOfResourceOutput, String) {
  case json.parse(body, decode_list_tags_of_resource_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_list_tags_of_resource_request(
  input: ListTagsOfResourceInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_list_tags_of_resource_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.ListTagsOfResource"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_list_tags_of_resource_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(ListTagsOfResourceOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_list_tags_of_resource_output("{}")
        _ -> decode_list_tags_of_resource_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type ListTagsOfResourceError {
  ListTagsOfResourceErrorInternalServerError(value: InternalServerError)
  ListTagsOfResourceErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  ListTagsOfResourceErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  ListTagsOfResourceErrorTransport(reason: String)
  ListTagsOfResourceErrorUnknown(error_type: String, status: Int, body: String)
}

fn list_tags_of_resource_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(ListTagsOfResourceErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(ListTagsOfResourceErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(ListTagsOfResourceErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_list_tags_of_resource_error(
  err: runtime.ClientError,
) -> ListTagsOfResourceError {
  runtime.translate_service_error(
    err,
    list_tags_of_resource_error_decoders(),
    fn(reason) { ListTagsOfResourceErrorTransport(reason: reason) },
    fn(et, s, body) {
      ListTagsOfResourceErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_put_item_input(input: PutItemInput) -> String {
  json.to_string(encode_put_item_input_struct_top(input))
}

pub fn decode_put_item_output(body: String) -> Result(PutItemOutput, String) {
  case json.parse(body, decode_put_item_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_put_item_request(
  input: PutItemInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_put_item_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.PutItem"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_put_item_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(PutItemOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_put_item_output("{}")
        _ -> decode_put_item_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type PutItemError {
  PutItemErrorConditionalCheckFailedException(
    value: ConditionalCheckFailedException,
  )
  PutItemErrorInternalServerError(value: InternalServerError)
  PutItemErrorInvalidEndpointException(value: InvalidEndpointException)
  PutItemErrorItemCollectionSizeLimitExceededException(
    value: ItemCollectionSizeLimitExceededException,
  )
  PutItemErrorProvisionedThroughputExceededException(
    value: ProvisionedThroughputExceededException,
  )
  PutItemErrorReplicatedWriteConflictException(
    value: ReplicatedWriteConflictException,
  )
  PutItemErrorRequestLimitExceeded(value: RequestLimitExceeded)
  PutItemErrorResourceNotFoundException(value: ResourceNotFoundException)
  PutItemErrorThrottlingException(value: ThrottlingException)
  PutItemErrorTransactionConflictException(value: TransactionConflictException)
  PutItemErrorTransport(reason: String)
  PutItemErrorUnknown(error_type: String, status: Int, body: String)
}

fn put_item_error_decoders() {
  [
    #("ConditionalCheckFailedException", fn(body) {
      case
        json.parse(body, decode_conditional_check_failed_exception_struct())
      {
        Ok(v) -> Ok(PutItemErrorConditionalCheckFailedException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(PutItemErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(PutItemErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ItemCollectionSizeLimitExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_item_collection_size_limit_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(PutItemErrorItemCollectionSizeLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ProvisionedThroughputExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_provisioned_throughput_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(PutItemErrorProvisionedThroughputExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ReplicatedWriteConflictException", fn(body) {
      case
        json.parse(body, decode_replicated_write_conflict_exception_struct())
      {
        Ok(v) -> Ok(PutItemErrorReplicatedWriteConflictException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("RequestLimitExceeded", fn(body) {
      case json.parse(body, decode_request_limit_exceeded_struct()) {
        Ok(v) -> Ok(PutItemErrorRequestLimitExceeded(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(PutItemErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ThrottlingException", fn(body) {
      case json.parse(body, decode_throttling_exception_struct()) {
        Ok(v) -> Ok(PutItemErrorThrottlingException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TransactionConflictException", fn(body) {
      case json.parse(body, decode_transaction_conflict_exception_struct()) {
        Ok(v) -> Ok(PutItemErrorTransactionConflictException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_put_item_error(err: runtime.ClientError) -> PutItemError {
  runtime.translate_service_error(
    err,
    put_item_error_decoders(),
    fn(reason) { PutItemErrorTransport(reason: reason) },
    fn(et, s, body) {
      PutItemErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_put_resource_policy_input(
  input: PutResourcePolicyInput,
) -> String {
  json.to_string(encode_put_resource_policy_input_struct_top(input))
}

pub fn decode_put_resource_policy_output(
  body: String,
) -> Result(PutResourcePolicyOutput, String) {
  case json.parse(body, decode_put_resource_policy_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_put_resource_policy_request(
  input: PutResourcePolicyInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_put_resource_policy_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.PutResourcePolicy"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_put_resource_policy_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(PutResourcePolicyOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_put_resource_policy_output("{}")
        _ -> decode_put_resource_policy_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type PutResourcePolicyError {
  PutResourcePolicyErrorInternalServerError(value: InternalServerError)
  PutResourcePolicyErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  PutResourcePolicyErrorLimitExceededException(value: LimitExceededException)
  PutResourcePolicyErrorPolicyNotFoundException(value: PolicyNotFoundException)
  PutResourcePolicyErrorResourceInUseException(value: ResourceInUseException)
  PutResourcePolicyErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  PutResourcePolicyErrorTransport(reason: String)
  PutResourcePolicyErrorUnknown(error_type: String, status: Int, body: String)
}

fn put_resource_policy_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(PutResourcePolicyErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(PutResourcePolicyErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(PutResourcePolicyErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("PolicyNotFoundException", fn(body) {
      case json.parse(body, decode_policy_not_found_exception_struct()) {
        Ok(v) -> Ok(PutResourcePolicyErrorPolicyNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) -> Ok(PutResourcePolicyErrorResourceInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(PutResourcePolicyErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_put_resource_policy_error(
  err: runtime.ClientError,
) -> PutResourcePolicyError {
  runtime.translate_service_error(
    err,
    put_resource_policy_error_decoders(),
    fn(reason) { PutResourcePolicyErrorTransport(reason: reason) },
    fn(et, s, body) {
      PutResourcePolicyErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_query_input(input: QueryInput) -> String {
  json.to_string(encode_query_input_struct_top(input))
}

pub fn decode_query_output(body: String) -> Result(QueryOutput, String) {
  case json.parse(body, decode_query_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_query_request(
  input: QueryInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_query_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.Query"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_query_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(QueryOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_query_output("{}")
        _ -> decode_query_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type QueryError {
  QueryErrorInternalServerError(value: InternalServerError)
  QueryErrorInvalidEndpointException(value: InvalidEndpointException)
  QueryErrorProvisionedThroughputExceededException(
    value: ProvisionedThroughputExceededException,
  )
  QueryErrorRequestLimitExceeded(value: RequestLimitExceeded)
  QueryErrorResourceNotFoundException(value: ResourceNotFoundException)
  QueryErrorThrottlingException(value: ThrottlingException)
  QueryErrorTransport(reason: String)
  QueryErrorUnknown(error_type: String, status: Int, body: String)
}

fn query_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(QueryErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(QueryErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ProvisionedThroughputExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_provisioned_throughput_exceeded_exception_struct(),
        )
      {
        Ok(v) -> Ok(QueryErrorProvisionedThroughputExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("RequestLimitExceeded", fn(body) {
      case json.parse(body, decode_request_limit_exceeded_struct()) {
        Ok(v) -> Ok(QueryErrorRequestLimitExceeded(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(QueryErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ThrottlingException", fn(body) {
      case json.parse(body, decode_throttling_exception_struct()) {
        Ok(v) -> Ok(QueryErrorThrottlingException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_query_error(err: runtime.ClientError) -> QueryError {
  runtime.translate_service_error(
    err,
    query_error_decoders(),
    fn(reason) { QueryErrorTransport(reason: reason) },
    fn(et, s, body) { QueryErrorUnknown(error_type: et, status: s, body: body) },
  )
}

pub fn encode_restore_table_from_backup_input(
  input: RestoreTableFromBackupInput,
) -> String {
  json.to_string(encode_restore_table_from_backup_input_struct_top(input))
}

pub fn decode_restore_table_from_backup_output(
  body: String,
) -> Result(RestoreTableFromBackupOutput, String) {
  case json.parse(body, decode_restore_table_from_backup_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_restore_table_from_backup_request(
  input: RestoreTableFromBackupInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_restore_table_from_backup_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.RestoreTableFromBackup"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_restore_table_from_backup_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(RestoreTableFromBackupOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_restore_table_from_backup_output("{}")
        _ -> decode_restore_table_from_backup_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type RestoreTableFromBackupError {
  RestoreTableFromBackupErrorBackupInUseException(value: BackupInUseException)
  RestoreTableFromBackupErrorBackupNotFoundException(
    value: BackupNotFoundException,
  )
  RestoreTableFromBackupErrorInternalServerError(value: InternalServerError)
  RestoreTableFromBackupErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  RestoreTableFromBackupErrorLimitExceededException(
    value: LimitExceededException,
  )
  RestoreTableFromBackupErrorTableAlreadyExistsException(
    value: TableAlreadyExistsException,
  )
  RestoreTableFromBackupErrorTableInUseException(value: TableInUseException)
  RestoreTableFromBackupErrorTransport(reason: String)
  RestoreTableFromBackupErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn restore_table_from_backup_error_decoders() {
  [
    #("BackupInUseException", fn(body) {
      case json.parse(body, decode_backup_in_use_exception_struct()) {
        Ok(v) -> Ok(RestoreTableFromBackupErrorBackupInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("BackupNotFoundException", fn(body) {
      case json.parse(body, decode_backup_not_found_exception_struct()) {
        Ok(v) ->
          Ok(RestoreTableFromBackupErrorBackupNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(RestoreTableFromBackupErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) ->
          Ok(RestoreTableFromBackupErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(RestoreTableFromBackupErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TableAlreadyExistsException", fn(body) {
      case json.parse(body, decode_table_already_exists_exception_struct()) {
        Ok(v) ->
          Ok(RestoreTableFromBackupErrorTableAlreadyExistsException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TableInUseException", fn(body) {
      case json.parse(body, decode_table_in_use_exception_struct()) {
        Ok(v) -> Ok(RestoreTableFromBackupErrorTableInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_restore_table_from_backup_error(
  err: runtime.ClientError,
) -> RestoreTableFromBackupError {
  runtime.translate_service_error(
    err,
    restore_table_from_backup_error_decoders(),
    fn(reason) { RestoreTableFromBackupErrorTransport(reason: reason) },
    fn(et, s, body) {
      RestoreTableFromBackupErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_restore_table_to_point_in_time_input(
  input: RestoreTableToPointInTimeInput,
) -> String {
  json.to_string(encode_restore_table_to_point_in_time_input_struct_top(input))
}

pub fn decode_restore_table_to_point_in_time_output(
  body: String,
) -> Result(RestoreTableToPointInTimeOutput, String) {
  case json.parse(body, decode_restore_table_to_point_in_time_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_restore_table_to_point_in_time_request(
  input: RestoreTableToPointInTimeInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_restore_table_to_point_in_time_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.RestoreTableToPointInTime"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_restore_table_to_point_in_time_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(RestoreTableToPointInTimeOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_restore_table_to_point_in_time_output("{}")
        _ -> decode_restore_table_to_point_in_time_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type RestoreTableToPointInTimeError {
  RestoreTableToPointInTimeErrorInternalServerError(value: InternalServerError)
  RestoreTableToPointInTimeErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  RestoreTableToPointInTimeErrorInvalidRestoreTimeException(
    value: InvalidRestoreTimeException,
  )
  RestoreTableToPointInTimeErrorLimitExceededException(
    value: LimitExceededException,
  )
  RestoreTableToPointInTimeErrorPointInTimeRecoveryUnavailableException(
    value: PointInTimeRecoveryUnavailableException,
  )
  RestoreTableToPointInTimeErrorTableAlreadyExistsException(
    value: TableAlreadyExistsException,
  )
  RestoreTableToPointInTimeErrorTableInUseException(value: TableInUseException)
  RestoreTableToPointInTimeErrorTableNotFoundException(
    value: TableNotFoundException,
  )
  RestoreTableToPointInTimeErrorTransport(reason: String)
  RestoreTableToPointInTimeErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn restore_table_to_point_in_time_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(RestoreTableToPointInTimeErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) ->
          Ok(RestoreTableToPointInTimeErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidRestoreTimeException", fn(body) {
      case json.parse(body, decode_invalid_restore_time_exception_struct()) {
        Ok(v) ->
          Ok(RestoreTableToPointInTimeErrorInvalidRestoreTimeException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) ->
          Ok(RestoreTableToPointInTimeErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("PointInTimeRecoveryUnavailableException", fn(body) {
      case
        json.parse(
          body,
          decode_point_in_time_recovery_unavailable_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(
            RestoreTableToPointInTimeErrorPointInTimeRecoveryUnavailableException(
              value: v,
            ),
          )
        Error(_) -> Error(Nil)
      }
    }),
    #("TableAlreadyExistsException", fn(body) {
      case json.parse(body, decode_table_already_exists_exception_struct()) {
        Ok(v) ->
          Ok(RestoreTableToPointInTimeErrorTableAlreadyExistsException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TableInUseException", fn(body) {
      case json.parse(body, decode_table_in_use_exception_struct()) {
        Ok(v) -> Ok(RestoreTableToPointInTimeErrorTableInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TableNotFoundException", fn(body) {
      case json.parse(body, decode_table_not_found_exception_struct()) {
        Ok(v) ->
          Ok(RestoreTableToPointInTimeErrorTableNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_restore_table_to_point_in_time_error(
  err: runtime.ClientError,
) -> RestoreTableToPointInTimeError {
  runtime.translate_service_error(
    err,
    restore_table_to_point_in_time_error_decoders(),
    fn(reason) { RestoreTableToPointInTimeErrorTransport(reason: reason) },
    fn(et, s, body) {
      RestoreTableToPointInTimeErrorUnknown(
        error_type: et,
        status: s,
        body: body,
      )
    },
  )
}

pub fn encode_scan_input(input: ScanInput) -> String {
  json.to_string(encode_scan_input_struct_top(input))
}

pub fn decode_scan_output(body: String) -> Result(ScanOutput, String) {
  case json.parse(body, decode_scan_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_scan_request(
  input: ScanInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_scan_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.Scan"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_scan_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(ScanOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_scan_output("{}")
        _ -> decode_scan_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type ScanError {
  ScanErrorInternalServerError(value: InternalServerError)
  ScanErrorInvalidEndpointException(value: InvalidEndpointException)
  ScanErrorProvisionedThroughputExceededException(
    value: ProvisionedThroughputExceededException,
  )
  ScanErrorRequestLimitExceeded(value: RequestLimitExceeded)
  ScanErrorResourceNotFoundException(value: ResourceNotFoundException)
  ScanErrorThrottlingException(value: ThrottlingException)
  ScanErrorTransport(reason: String)
  ScanErrorUnknown(error_type: String, status: Int, body: String)
}

fn scan_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(ScanErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(ScanErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ProvisionedThroughputExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_provisioned_throughput_exceeded_exception_struct(),
        )
      {
        Ok(v) -> Ok(ScanErrorProvisionedThroughputExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("RequestLimitExceeded", fn(body) {
      case json.parse(body, decode_request_limit_exceeded_struct()) {
        Ok(v) -> Ok(ScanErrorRequestLimitExceeded(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(ScanErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ThrottlingException", fn(body) {
      case json.parse(body, decode_throttling_exception_struct()) {
        Ok(v) -> Ok(ScanErrorThrottlingException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_scan_error(err: runtime.ClientError) -> ScanError {
  runtime.translate_service_error(
    err,
    scan_error_decoders(),
    fn(reason) { ScanErrorTransport(reason: reason) },
    fn(et, s, body) { ScanErrorUnknown(error_type: et, status: s, body: body) },
  )
}

pub type TagResourceOutput {
  TagResourceOutput
}

pub fn tag_resource_output_default() -> TagResourceOutput {
  TagResourceOutput
}

pub fn decode_tag_resource_output_struct() -> decode.Decoder(TagResourceOutput) {
  decode.success(TagResourceOutput)
}

pub fn encode_tag_resource_input(input: TagResourceInput) -> String {
  json.to_string(encode_tag_resource_input_struct_top(input))
}

pub fn decode_tag_resource_output(
  body: String,
) -> Result(TagResourceOutput, String) {
  case json.parse(body, decode_tag_resource_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_tag_resource_request(
  input: TagResourceInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_tag_resource_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.TagResource"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_tag_resource_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(TagResourceOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_tag_resource_output("{}")
        _ -> decode_tag_resource_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type TagResourceError {
  TagResourceErrorInternalServerError(value: InternalServerError)
  TagResourceErrorInvalidEndpointException(value: InvalidEndpointException)
  TagResourceErrorLimitExceededException(value: LimitExceededException)
  TagResourceErrorResourceInUseException(value: ResourceInUseException)
  TagResourceErrorResourceNotFoundException(value: ResourceNotFoundException)
  TagResourceErrorTransport(reason: String)
  TagResourceErrorUnknown(error_type: String, status: Int, body: String)
}

fn tag_resource_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(TagResourceErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(TagResourceErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(TagResourceErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) -> Ok(TagResourceErrorResourceInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(TagResourceErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_tag_resource_error(err: runtime.ClientError) -> TagResourceError {
  runtime.translate_service_error(
    err,
    tag_resource_error_decoders(),
    fn(reason) { TagResourceErrorTransport(reason: reason) },
    fn(et, s, body) {
      TagResourceErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_transact_get_items_input(input: TransactGetItemsInput) -> String {
  json.to_string(encode_transact_get_items_input_struct_top(input))
}

pub fn decode_transact_get_items_output(
  body: String,
) -> Result(TransactGetItemsOutput, String) {
  case json.parse(body, decode_transact_get_items_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_transact_get_items_request(
  input: TransactGetItemsInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_transact_get_items_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.TransactGetItems"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_transact_get_items_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(TransactGetItemsOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_transact_get_items_output("{}")
        _ -> decode_transact_get_items_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type TransactGetItemsError {
  TransactGetItemsErrorInternalServerError(value: InternalServerError)
  TransactGetItemsErrorInvalidEndpointException(value: InvalidEndpointException)
  TransactGetItemsErrorProvisionedThroughputExceededException(
    value: ProvisionedThroughputExceededException,
  )
  TransactGetItemsErrorRequestLimitExceeded(value: RequestLimitExceeded)
  TransactGetItemsErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  TransactGetItemsErrorThrottlingException(value: ThrottlingException)
  TransactGetItemsErrorTransactionCanceledException(
    value: TransactionCanceledException,
  )
  TransactGetItemsErrorTransport(reason: String)
  TransactGetItemsErrorUnknown(error_type: String, status: Int, body: String)
}

fn transact_get_items_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(TransactGetItemsErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(TransactGetItemsErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ProvisionedThroughputExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_provisioned_throughput_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(TransactGetItemsErrorProvisionedThroughputExceededException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("RequestLimitExceeded", fn(body) {
      case json.parse(body, decode_request_limit_exceeded_struct()) {
        Ok(v) -> Ok(TransactGetItemsErrorRequestLimitExceeded(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(TransactGetItemsErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ThrottlingException", fn(body) {
      case json.parse(body, decode_throttling_exception_struct()) {
        Ok(v) -> Ok(TransactGetItemsErrorThrottlingException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TransactionCanceledException", fn(body) {
      case json.parse(body, decode_transaction_canceled_exception_struct()) {
        Ok(v) -> Ok(TransactGetItemsErrorTransactionCanceledException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_transact_get_items_error(
  err: runtime.ClientError,
) -> TransactGetItemsError {
  runtime.translate_service_error(
    err,
    transact_get_items_error_decoders(),
    fn(reason) { TransactGetItemsErrorTransport(reason: reason) },
    fn(et, s, body) {
      TransactGetItemsErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_transact_write_items_input(
  input: TransactWriteItemsInput,
) -> String {
  json.to_string(encode_transact_write_items_input_struct_top(input))
}

pub fn decode_transact_write_items_output(
  body: String,
) -> Result(TransactWriteItemsOutput, String) {
  case json.parse(body, decode_transact_write_items_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_transact_write_items_request(
  input: TransactWriteItemsInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_transact_write_items_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.TransactWriteItems"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_transact_write_items_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(TransactWriteItemsOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_transact_write_items_output("{}")
        _ -> decode_transact_write_items_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type TransactWriteItemsError {
  TransactWriteItemsErrorIdempotentParameterMismatchException(
    value: IdempotentParameterMismatchException,
  )
  TransactWriteItemsErrorInternalServerError(value: InternalServerError)
  TransactWriteItemsErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  TransactWriteItemsErrorProvisionedThroughputExceededException(
    value: ProvisionedThroughputExceededException,
  )
  TransactWriteItemsErrorRequestLimitExceeded(value: RequestLimitExceeded)
  TransactWriteItemsErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  TransactWriteItemsErrorThrottlingException(value: ThrottlingException)
  TransactWriteItemsErrorTransactionCanceledException(
    value: TransactionCanceledException,
  )
  TransactWriteItemsErrorTransactionInProgressException(
    value: TransactionInProgressException,
  )
  TransactWriteItemsErrorTransport(reason: String)
  TransactWriteItemsErrorUnknown(error_type: String, status: Int, body: String)
}

fn transact_write_items_error_decoders() {
  [
    #("IdempotentParameterMismatchException", fn(body) {
      case
        json.parse(
          body,
          decode_idempotent_parameter_mismatch_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(TransactWriteItemsErrorIdempotentParameterMismatchException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(TransactWriteItemsErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(TransactWriteItemsErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ProvisionedThroughputExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_provisioned_throughput_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(TransactWriteItemsErrorProvisionedThroughputExceededException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("RequestLimitExceeded", fn(body) {
      case json.parse(body, decode_request_limit_exceeded_struct()) {
        Ok(v) -> Ok(TransactWriteItemsErrorRequestLimitExceeded(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(TransactWriteItemsErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ThrottlingException", fn(body) {
      case json.parse(body, decode_throttling_exception_struct()) {
        Ok(v) -> Ok(TransactWriteItemsErrorThrottlingException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TransactionCanceledException", fn(body) {
      case json.parse(body, decode_transaction_canceled_exception_struct()) {
        Ok(v) ->
          Ok(TransactWriteItemsErrorTransactionCanceledException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TransactionInProgressException", fn(body) {
      case json.parse(body, decode_transaction_in_progress_exception_struct()) {
        Ok(v) ->
          Ok(TransactWriteItemsErrorTransactionInProgressException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_transact_write_items_error(
  err: runtime.ClientError,
) -> TransactWriteItemsError {
  runtime.translate_service_error(
    err,
    transact_write_items_error_decoders(),
    fn(reason) { TransactWriteItemsErrorTransport(reason: reason) },
    fn(et, s, body) {
      TransactWriteItemsErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub type UntagResourceOutput {
  UntagResourceOutput
}

pub fn untag_resource_output_default() -> UntagResourceOutput {
  UntagResourceOutput
}

pub fn decode_untag_resource_output_struct() -> decode.Decoder(
  UntagResourceOutput,
) {
  decode.success(UntagResourceOutput)
}

pub fn encode_untag_resource_input(input: UntagResourceInput) -> String {
  json.to_string(encode_untag_resource_input_struct_top(input))
}

pub fn decode_untag_resource_output(
  body: String,
) -> Result(UntagResourceOutput, String) {
  case json.parse(body, decode_untag_resource_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_untag_resource_request(
  input: UntagResourceInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_untag_resource_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.UntagResource"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_untag_resource_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(UntagResourceOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_untag_resource_output("{}")
        _ -> decode_untag_resource_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type UntagResourceError {
  UntagResourceErrorInternalServerError(value: InternalServerError)
  UntagResourceErrorInvalidEndpointException(value: InvalidEndpointException)
  UntagResourceErrorLimitExceededException(value: LimitExceededException)
  UntagResourceErrorResourceInUseException(value: ResourceInUseException)
  UntagResourceErrorResourceNotFoundException(value: ResourceNotFoundException)
  UntagResourceErrorTransport(reason: String)
  UntagResourceErrorUnknown(error_type: String, status: Int, body: String)
}

fn untag_resource_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(UntagResourceErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(UntagResourceErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(UntagResourceErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) -> Ok(UntagResourceErrorResourceInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(UntagResourceErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_untag_resource_error(
  err: runtime.ClientError,
) -> UntagResourceError {
  runtime.translate_service_error(
    err,
    untag_resource_error_decoders(),
    fn(reason) { UntagResourceErrorTransport(reason: reason) },
    fn(et, s, body) {
      UntagResourceErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_update_continuous_backups_input(
  input: UpdateContinuousBackupsInput,
) -> String {
  json.to_string(encode_update_continuous_backups_input_struct_top(input))
}

pub fn decode_update_continuous_backups_output(
  body: String,
) -> Result(UpdateContinuousBackupsOutput, String) {
  case json.parse(body, decode_update_continuous_backups_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_update_continuous_backups_request(
  input: UpdateContinuousBackupsInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_update_continuous_backups_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.UpdateContinuousBackups"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_update_continuous_backups_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(UpdateContinuousBackupsOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_update_continuous_backups_output("{}")
        _ -> decode_update_continuous_backups_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type UpdateContinuousBackupsError {
  UpdateContinuousBackupsErrorContinuousBackupsUnavailableException(
    value: ContinuousBackupsUnavailableException,
  )
  UpdateContinuousBackupsErrorInternalServerError(value: InternalServerError)
  UpdateContinuousBackupsErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  UpdateContinuousBackupsErrorTableNotFoundException(
    value: TableNotFoundException,
  )
  UpdateContinuousBackupsErrorTransport(reason: String)
  UpdateContinuousBackupsErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn update_continuous_backups_error_decoders() {
  [
    #("ContinuousBackupsUnavailableException", fn(body) {
      case
        json.parse(
          body,
          decode_continuous_backups_unavailable_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(UpdateContinuousBackupsErrorContinuousBackupsUnavailableException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(UpdateContinuousBackupsErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) ->
          Ok(UpdateContinuousBackupsErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TableNotFoundException", fn(body) {
      case json.parse(body, decode_table_not_found_exception_struct()) {
        Ok(v) ->
          Ok(UpdateContinuousBackupsErrorTableNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_update_continuous_backups_error(
  err: runtime.ClientError,
) -> UpdateContinuousBackupsError {
  runtime.translate_service_error(
    err,
    update_continuous_backups_error_decoders(),
    fn(reason) { UpdateContinuousBackupsErrorTransport(reason: reason) },
    fn(et, s, body) {
      UpdateContinuousBackupsErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_update_contributor_insights_input(
  input: UpdateContributorInsightsInput,
) -> String {
  json.to_string(encode_update_contributor_insights_input_struct_top(input))
}

pub fn decode_update_contributor_insights_output(
  body: String,
) -> Result(UpdateContributorInsightsOutput, String) {
  case json.parse(body, decode_update_contributor_insights_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_update_contributor_insights_request(
  input: UpdateContributorInsightsInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_update_contributor_insights_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.UpdateContributorInsights"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_update_contributor_insights_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(UpdateContributorInsightsOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_update_contributor_insights_output("{}")
        _ -> decode_update_contributor_insights_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type UpdateContributorInsightsError {
  UpdateContributorInsightsErrorInternalServerError(value: InternalServerError)
  UpdateContributorInsightsErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  UpdateContributorInsightsErrorTransport(reason: String)
  UpdateContributorInsightsErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn update_contributor_insights_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(UpdateContributorInsightsErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) ->
          Ok(UpdateContributorInsightsErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_update_contributor_insights_error(
  err: runtime.ClientError,
) -> UpdateContributorInsightsError {
  runtime.translate_service_error(
    err,
    update_contributor_insights_error_decoders(),
    fn(reason) { UpdateContributorInsightsErrorTransport(reason: reason) },
    fn(et, s, body) {
      UpdateContributorInsightsErrorUnknown(
        error_type: et,
        status: s,
        body: body,
      )
    },
  )
}

pub fn encode_update_global_table_input(
  input: UpdateGlobalTableInput,
) -> String {
  json.to_string(encode_update_global_table_input_struct_top(input))
}

pub fn decode_update_global_table_output(
  body: String,
) -> Result(UpdateGlobalTableOutput, String) {
  case json.parse(body, decode_update_global_table_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_update_global_table_request(
  input: UpdateGlobalTableInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_update_global_table_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.UpdateGlobalTable"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_update_global_table_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(UpdateGlobalTableOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_update_global_table_output("{}")
        _ -> decode_update_global_table_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type UpdateGlobalTableError {
  UpdateGlobalTableErrorGlobalTableNotFoundException(
    value: GlobalTableNotFoundException,
  )
  UpdateGlobalTableErrorInternalServerError(value: InternalServerError)
  UpdateGlobalTableErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  UpdateGlobalTableErrorReplicaAlreadyExistsException(
    value: ReplicaAlreadyExistsException,
  )
  UpdateGlobalTableErrorReplicaNotFoundException(
    value: ReplicaNotFoundException,
  )
  UpdateGlobalTableErrorTableNotFoundException(value: TableNotFoundException)
  UpdateGlobalTableErrorTransport(reason: String)
  UpdateGlobalTableErrorUnknown(error_type: String, status: Int, body: String)
}

fn update_global_table_error_decoders() {
  [
    #("GlobalTableNotFoundException", fn(body) {
      case json.parse(body, decode_global_table_not_found_exception_struct()) {
        Ok(v) ->
          Ok(UpdateGlobalTableErrorGlobalTableNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(UpdateGlobalTableErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(UpdateGlobalTableErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ReplicaAlreadyExistsException", fn(body) {
      case json.parse(body, decode_replica_already_exists_exception_struct()) {
        Ok(v) ->
          Ok(UpdateGlobalTableErrorReplicaAlreadyExistsException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ReplicaNotFoundException", fn(body) {
      case json.parse(body, decode_replica_not_found_exception_struct()) {
        Ok(v) -> Ok(UpdateGlobalTableErrorReplicaNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TableNotFoundException", fn(body) {
      case json.parse(body, decode_table_not_found_exception_struct()) {
        Ok(v) -> Ok(UpdateGlobalTableErrorTableNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_update_global_table_error(
  err: runtime.ClientError,
) -> UpdateGlobalTableError {
  runtime.translate_service_error(
    err,
    update_global_table_error_decoders(),
    fn(reason) { UpdateGlobalTableErrorTransport(reason: reason) },
    fn(et, s, body) {
      UpdateGlobalTableErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_update_global_table_settings_input(
  input: UpdateGlobalTableSettingsInput,
) -> String {
  json.to_string(encode_update_global_table_settings_input_struct_top(input))
}

pub fn decode_update_global_table_settings_output(
  body: String,
) -> Result(UpdateGlobalTableSettingsOutput, String) {
  case json.parse(body, decode_update_global_table_settings_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_update_global_table_settings_request(
  input: UpdateGlobalTableSettingsInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_update_global_table_settings_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.UpdateGlobalTableSettings"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_update_global_table_settings_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(UpdateGlobalTableSettingsOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_update_global_table_settings_output("{}")
        _ -> decode_update_global_table_settings_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type UpdateGlobalTableSettingsError {
  UpdateGlobalTableSettingsErrorGlobalTableNotFoundException(
    value: GlobalTableNotFoundException,
  )
  UpdateGlobalTableSettingsErrorIndexNotFoundException(
    value: IndexNotFoundException,
  )
  UpdateGlobalTableSettingsErrorInternalServerError(value: InternalServerError)
  UpdateGlobalTableSettingsErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  UpdateGlobalTableSettingsErrorLimitExceededException(
    value: LimitExceededException,
  )
  UpdateGlobalTableSettingsErrorReplicaNotFoundException(
    value: ReplicaNotFoundException,
  )
  UpdateGlobalTableSettingsErrorResourceInUseException(
    value: ResourceInUseException,
  )
  UpdateGlobalTableSettingsErrorTransport(reason: String)
  UpdateGlobalTableSettingsErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn update_global_table_settings_error_decoders() {
  [
    #("GlobalTableNotFoundException", fn(body) {
      case json.parse(body, decode_global_table_not_found_exception_struct()) {
        Ok(v) ->
          Ok(UpdateGlobalTableSettingsErrorGlobalTableNotFoundException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("IndexNotFoundException", fn(body) {
      case json.parse(body, decode_index_not_found_exception_struct()) {
        Ok(v) ->
          Ok(UpdateGlobalTableSettingsErrorIndexNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(UpdateGlobalTableSettingsErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) ->
          Ok(UpdateGlobalTableSettingsErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) ->
          Ok(UpdateGlobalTableSettingsErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ReplicaNotFoundException", fn(body) {
      case json.parse(body, decode_replica_not_found_exception_struct()) {
        Ok(v) ->
          Ok(UpdateGlobalTableSettingsErrorReplicaNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) ->
          Ok(UpdateGlobalTableSettingsErrorResourceInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_update_global_table_settings_error(
  err: runtime.ClientError,
) -> UpdateGlobalTableSettingsError {
  runtime.translate_service_error(
    err,
    update_global_table_settings_error_decoders(),
    fn(reason) { UpdateGlobalTableSettingsErrorTransport(reason: reason) },
    fn(et, s, body) {
      UpdateGlobalTableSettingsErrorUnknown(
        error_type: et,
        status: s,
        body: body,
      )
    },
  )
}

pub fn encode_update_item_input(input: UpdateItemInput) -> String {
  json.to_string(encode_update_item_input_struct_top(input))
}

pub fn decode_update_item_output(
  body: String,
) -> Result(UpdateItemOutput, String) {
  case json.parse(body, decode_update_item_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_update_item_request(
  input: UpdateItemInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_update_item_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.UpdateItem"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_update_item_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(UpdateItemOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_update_item_output("{}")
        _ -> decode_update_item_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type UpdateItemError {
  UpdateItemErrorConditionalCheckFailedException(
    value: ConditionalCheckFailedException,
  )
  UpdateItemErrorInternalServerError(value: InternalServerError)
  UpdateItemErrorInvalidEndpointException(value: InvalidEndpointException)
  UpdateItemErrorItemCollectionSizeLimitExceededException(
    value: ItemCollectionSizeLimitExceededException,
  )
  UpdateItemErrorProvisionedThroughputExceededException(
    value: ProvisionedThroughputExceededException,
  )
  UpdateItemErrorReplicatedWriteConflictException(
    value: ReplicatedWriteConflictException,
  )
  UpdateItemErrorRequestLimitExceeded(value: RequestLimitExceeded)
  UpdateItemErrorResourceNotFoundException(value: ResourceNotFoundException)
  UpdateItemErrorThrottlingException(value: ThrottlingException)
  UpdateItemErrorTransactionConflictException(
    value: TransactionConflictException,
  )
  UpdateItemErrorTransport(reason: String)
  UpdateItemErrorUnknown(error_type: String, status: Int, body: String)
}

fn update_item_error_decoders() {
  [
    #("ConditionalCheckFailedException", fn(body) {
      case
        json.parse(body, decode_conditional_check_failed_exception_struct())
      {
        Ok(v) -> Ok(UpdateItemErrorConditionalCheckFailedException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(UpdateItemErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(UpdateItemErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ItemCollectionSizeLimitExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_item_collection_size_limit_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(UpdateItemErrorItemCollectionSizeLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ProvisionedThroughputExceededException", fn(body) {
      case
        json.parse(
          body,
          decode_provisioned_throughput_exceeded_exception_struct(),
        )
      {
        Ok(v) ->
          Ok(UpdateItemErrorProvisionedThroughputExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ReplicatedWriteConflictException", fn(body) {
      case
        json.parse(body, decode_replicated_write_conflict_exception_struct())
      {
        Ok(v) -> Ok(UpdateItemErrorReplicatedWriteConflictException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("RequestLimitExceeded", fn(body) {
      case json.parse(body, decode_request_limit_exceeded_struct()) {
        Ok(v) -> Ok(UpdateItemErrorRequestLimitExceeded(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(UpdateItemErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ThrottlingException", fn(body) {
      case json.parse(body, decode_throttling_exception_struct()) {
        Ok(v) -> Ok(UpdateItemErrorThrottlingException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("TransactionConflictException", fn(body) {
      case json.parse(body, decode_transaction_conflict_exception_struct()) {
        Ok(v) -> Ok(UpdateItemErrorTransactionConflictException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_update_item_error(err: runtime.ClientError) -> UpdateItemError {
  runtime.translate_service_error(
    err,
    update_item_error_decoders(),
    fn(reason) { UpdateItemErrorTransport(reason: reason) },
    fn(et, s, body) {
      UpdateItemErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_update_kinesis_streaming_destination_input(
  input: UpdateKinesisStreamingDestinationInput,
) -> String {
  json.to_string(encode_update_kinesis_streaming_destination_input_struct_top(
    input,
  ))
}

pub fn decode_update_kinesis_streaming_destination_output(
  body: String,
) -> Result(UpdateKinesisStreamingDestinationOutput, String) {
  case
    json.parse(
      body,
      decode_update_kinesis_streaming_destination_output_struct(),
    )
  {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_update_kinesis_streaming_destination_request(
  input: UpdateKinesisStreamingDestinationInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_update_kinesis_streaming_destination_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.UpdateKinesisStreamingDestination"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_update_kinesis_streaming_destination_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(UpdateKinesisStreamingDestinationOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_update_kinesis_streaming_destination_output("{}")
        _ -> decode_update_kinesis_streaming_destination_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type UpdateKinesisStreamingDestinationError {
  UpdateKinesisStreamingDestinationErrorInternalServerError(
    value: InternalServerError,
  )
  UpdateKinesisStreamingDestinationErrorInvalidEndpointException(
    value: InvalidEndpointException,
  )
  UpdateKinesisStreamingDestinationErrorLimitExceededException(
    value: LimitExceededException,
  )
  UpdateKinesisStreamingDestinationErrorResourceInUseException(
    value: ResourceInUseException,
  )
  UpdateKinesisStreamingDestinationErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  UpdateKinesisStreamingDestinationErrorTransport(reason: String)
  UpdateKinesisStreamingDestinationErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn update_kinesis_streaming_destination_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) ->
          Ok(UpdateKinesisStreamingDestinationErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) ->
          Ok(UpdateKinesisStreamingDestinationErrorInvalidEndpointException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) ->
          Ok(UpdateKinesisStreamingDestinationErrorLimitExceededException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) ->
          Ok(UpdateKinesisStreamingDestinationErrorResourceInUseException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) ->
          Ok(UpdateKinesisStreamingDestinationErrorResourceNotFoundException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_update_kinesis_streaming_destination_error(
  err: runtime.ClientError,
) -> UpdateKinesisStreamingDestinationError {
  runtime.translate_service_error(
    err,
    update_kinesis_streaming_destination_error_decoders(),
    fn(reason) {
      UpdateKinesisStreamingDestinationErrorTransport(reason: reason)
    },
    fn(et, s, body) {
      UpdateKinesisStreamingDestinationErrorUnknown(
        error_type: et,
        status: s,
        body: body,
      )
    },
  )
}

pub fn encode_update_table_input(input: UpdateTableInput) -> String {
  json.to_string(encode_update_table_input_struct_top(input))
}

pub fn decode_update_table_output(
  body: String,
) -> Result(UpdateTableOutput, String) {
  case json.parse(body, decode_update_table_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_update_table_request(
  input: UpdateTableInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_update_table_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.UpdateTable"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_update_table_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(UpdateTableOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_update_table_output("{}")
        _ -> decode_update_table_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type UpdateTableError {
  UpdateTableErrorInternalServerError(value: InternalServerError)
  UpdateTableErrorInvalidEndpointException(value: InvalidEndpointException)
  UpdateTableErrorLimitExceededException(value: LimitExceededException)
  UpdateTableErrorResourceInUseException(value: ResourceInUseException)
  UpdateTableErrorResourceNotFoundException(value: ResourceNotFoundException)
  UpdateTableErrorTransport(reason: String)
  UpdateTableErrorUnknown(error_type: String, status: Int, body: String)
}

fn update_table_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(UpdateTableErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(UpdateTableErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(UpdateTableErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) -> Ok(UpdateTableErrorResourceInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(UpdateTableErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_update_table_error(err: runtime.ClientError) -> UpdateTableError {
  runtime.translate_service_error(
    err,
    update_table_error_decoders(),
    fn(reason) { UpdateTableErrorTransport(reason: reason) },
    fn(et, s, body) {
      UpdateTableErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

pub fn encode_update_table_replica_auto_scaling_input(
  input: UpdateTableReplicaAutoScalingInput,
) -> String {
  json.to_string(encode_update_table_replica_auto_scaling_input_struct_top(
    input,
  ))
}

pub fn decode_update_table_replica_auto_scaling_output(
  body: String,
) -> Result(UpdateTableReplicaAutoScalingOutput, String) {
  case
    json.parse(body, decode_update_table_replica_auto_scaling_output_struct())
  {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_update_table_replica_auto_scaling_request(
  input: UpdateTableReplicaAutoScalingInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_update_table_replica_auto_scaling_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.UpdateTableReplicaAutoScaling"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_update_table_replica_auto_scaling_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(UpdateTableReplicaAutoScalingOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_update_table_replica_auto_scaling_output("{}")
        _ -> decode_update_table_replica_auto_scaling_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type UpdateTableReplicaAutoScalingError {
  UpdateTableReplicaAutoScalingErrorInternalServerError(
    value: InternalServerError,
  )
  UpdateTableReplicaAutoScalingErrorLimitExceededException(
    value: LimitExceededException,
  )
  UpdateTableReplicaAutoScalingErrorResourceInUseException(
    value: ResourceInUseException,
  )
  UpdateTableReplicaAutoScalingErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  UpdateTableReplicaAutoScalingErrorTransport(reason: String)
  UpdateTableReplicaAutoScalingErrorUnknown(
    error_type: String,
    status: Int,
    body: String,
  )
}

fn update_table_replica_auto_scaling_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) ->
          Ok(UpdateTableReplicaAutoScalingErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) ->
          Ok(UpdateTableReplicaAutoScalingErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) ->
          Ok(UpdateTableReplicaAutoScalingErrorResourceInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) ->
          Ok(UpdateTableReplicaAutoScalingErrorResourceNotFoundException(
            value: v,
          ))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_update_table_replica_auto_scaling_error(
  err: runtime.ClientError,
) -> UpdateTableReplicaAutoScalingError {
  runtime.translate_service_error(
    err,
    update_table_replica_auto_scaling_error_decoders(),
    fn(reason) { UpdateTableReplicaAutoScalingErrorTransport(reason: reason) },
    fn(et, s, body) {
      UpdateTableReplicaAutoScalingErrorUnknown(
        error_type: et,
        status: s,
        body: body,
      )
    },
  )
}

pub fn encode_update_time_to_live_input(
  input: UpdateTimeToLiveInput,
) -> String {
  json.to_string(encode_update_time_to_live_input_struct_top(input))
}

pub fn decode_update_time_to_live_output(
  body: String,
) -> Result(UpdateTimeToLiveOutput, String) {
  case json.parse(body, decode_update_time_to_live_output_struct()) {
    Ok(v) -> Ok(v)
    Error(_) -> Error("decode failed")
  }
}

pub fn build_update_time_to_live_request(
  input: UpdateTimeToLiveInput,
) -> #(String, String, dict.Dict(String, String), BitArray) {
  let body_str = encode_update_time_to_live_input(input)
  let body = bit_array.from_string(body_str)
  let headers =
    dict.from_list([
      #("Content-Type", "application/x-amz-json-1.0"),
      #("Content-Length", int.to_string(bit_array.byte_size(body))),
      #("X-Amz-Target", "DynamoDB_20120810.UpdateTimeToLive"),
    ])
  #("POST", "/", headers, body)
}

pub fn parse_update_time_to_live_response(
  _code: Int,
  _headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(UpdateTimeToLiveOutput, String) {
  case bit_array.to_string(body) {
    Ok(text) ->
      case text {
        "" -> decode_update_time_to_live_output("{}")
        _ -> decode_update_time_to_live_output(text)
      }
    Error(_) -> Error("non-utf8 body")
  }
}

pub type UpdateTimeToLiveError {
  UpdateTimeToLiveErrorInternalServerError(value: InternalServerError)
  UpdateTimeToLiveErrorInvalidEndpointException(value: InvalidEndpointException)
  UpdateTimeToLiveErrorLimitExceededException(value: LimitExceededException)
  UpdateTimeToLiveErrorResourceInUseException(value: ResourceInUseException)
  UpdateTimeToLiveErrorResourceNotFoundException(
    value: ResourceNotFoundException,
  )
  UpdateTimeToLiveErrorTransport(reason: String)
  UpdateTimeToLiveErrorUnknown(error_type: String, status: Int, body: String)
}

fn update_time_to_live_error_decoders() {
  [
    #("InternalServerError", fn(body) {
      case json.parse(body, decode_internal_server_error_struct()) {
        Ok(v) -> Ok(UpdateTimeToLiveErrorInternalServerError(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("InvalidEndpointException", fn(body) {
      case json.parse(body, decode_invalid_endpoint_exception_struct()) {
        Ok(v) -> Ok(UpdateTimeToLiveErrorInvalidEndpointException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("LimitExceededException", fn(body) {
      case json.parse(body, decode_limit_exceeded_exception_struct()) {
        Ok(v) -> Ok(UpdateTimeToLiveErrorLimitExceededException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceInUseException", fn(body) {
      case json.parse(body, decode_resource_in_use_exception_struct()) {
        Ok(v) -> Ok(UpdateTimeToLiveErrorResourceInUseException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
    #("ResourceNotFoundException", fn(body) {
      case json.parse(body, decode_resource_not_found_exception_struct()) {
        Ok(v) -> Ok(UpdateTimeToLiveErrorResourceNotFoundException(value: v))
        Error(_) -> Error(Nil)
      }
    }),
  ]
}

fn translate_update_time_to_live_error(
  err: runtime.ClientError,
) -> UpdateTimeToLiveError {
  runtime.translate_service_error(
    err,
    update_time_to_live_error_decoders(),
    fn(reason) { UpdateTimeToLiveErrorTransport(reason: reason) },
    fn(et, s, body) {
      UpdateTimeToLiveErrorUnknown(error_type: et, status: s, body: body)
    },
  )
}

/// Invoke BatchExecuteStatement. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `BatchExecuteStatementError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `BatchExecuteStatementErrorTransport` variant.
pub fn batch_execute_statement(
  client: Client,
  input: BatchExecuteStatementInput,
) -> Result(BatchExecuteStatementOutput, BatchExecuteStatementError) {
  case
    runtime.invoke(
      client.config,
      build_batch_execute_statement_request(input),
      parse_batch_execute_statement_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_batch_execute_statement_error(err))
  }
}

/// Invoke BatchGetItem. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `BatchGetItemError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `BatchGetItemErrorTransport` variant.
pub fn batch_get_item(
  client: Client,
  input: BatchGetItemInput,
) -> Result(BatchGetItemOutput, BatchGetItemError) {
  case
    runtime.invoke(
      client.config,
      build_batch_get_item_request(input),
      parse_batch_get_item_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_batch_get_item_error(err))
  }
}

/// Invoke BatchWriteItem. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `BatchWriteItemError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `BatchWriteItemErrorTransport` variant.
pub fn batch_write_item(
  client: Client,
  input: BatchWriteItemInput,
) -> Result(BatchWriteItemOutput, BatchWriteItemError) {
  case
    runtime.invoke(
      client.config,
      build_batch_write_item_request(input),
      parse_batch_write_item_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_batch_write_item_error(err))
  }
}

/// Invoke CreateBackup. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `CreateBackupError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `CreateBackupErrorTransport` variant.
pub fn create_backup(
  client: Client,
  input: CreateBackupInput,
) -> Result(CreateBackupOutput, CreateBackupError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_create_backup_endpoint_params(input),
      build_create_backup_request(input),
      parse_create_backup_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_create_backup_error(err))
  }
}

fn build_create_backup_endpoint_params(
  input: CreateBackupInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke CreateGlobalTable. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `CreateGlobalTableError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `CreateGlobalTableErrorTransport` variant.
pub fn create_global_table(
  client: Client,
  input: CreateGlobalTableInput,
) -> Result(CreateGlobalTableOutput, CreateGlobalTableError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_create_global_table_endpoint_params(input),
      build_create_global_table_request(input),
      parse_create_global_table_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_create_global_table_error(err))
  }
}

fn build_create_global_table_endpoint_params(
  input: CreateGlobalTableInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(
      params,
      "ResourceArn",
      endpoints.StringVal(input.global_table_name),
    )
  params
}

/// Invoke CreateTable. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `CreateTableError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `CreateTableErrorTransport` variant.
pub fn create_table(
  client: Client,
  input: CreateTableInput,
) -> Result(CreateTableOutput, CreateTableError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_create_table_endpoint_params(input),
      build_create_table_request(input),
      parse_create_table_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_create_table_error(err))
  }
}

fn build_create_table_endpoint_params(
  input: CreateTableInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke DeleteBackup. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DeleteBackupError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DeleteBackupErrorTransport` variant.
pub fn delete_backup(
  client: Client,
  input: DeleteBackupInput,
) -> Result(DeleteBackupOutput, DeleteBackupError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_delete_backup_endpoint_params(input),
      build_delete_backup_request(input),
      parse_delete_backup_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_delete_backup_error(err))
  }
}

fn build_delete_backup_endpoint_params(
  input: DeleteBackupInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.backup_arn))
  params
}

/// Invoke DeleteItem. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DeleteItemError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DeleteItemErrorTransport` variant.
pub fn delete_item(
  client: Client,
  input: DeleteItemInput,
) -> Result(DeleteItemOutput, DeleteItemError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_delete_item_endpoint_params(input),
      build_delete_item_request(input),
      parse_delete_item_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_delete_item_error(err))
  }
}

fn build_delete_item_endpoint_params(
  input: DeleteItemInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke DeleteResourcePolicy. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DeleteResourcePolicyError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DeleteResourcePolicyErrorTransport` variant.
pub fn delete_resource_policy(
  client: Client,
  input: DeleteResourcePolicyInput,
) -> Result(DeleteResourcePolicyOutput, DeleteResourcePolicyError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_delete_resource_policy_endpoint_params(input),
      build_delete_resource_policy_request(input),
      parse_delete_resource_policy_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_delete_resource_policy_error(err))
  }
}

fn build_delete_resource_policy_endpoint_params(
  input: DeleteResourcePolicyInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.resource_arn))
  params
}

/// Invoke DeleteTable. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DeleteTableError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DeleteTableErrorTransport` variant.
pub fn delete_table(
  client: Client,
  input: DeleteTableInput,
) -> Result(DeleteTableOutput, DeleteTableError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_delete_table_endpoint_params(input),
      build_delete_table_request(input),
      parse_delete_table_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_delete_table_error(err))
  }
}

fn build_delete_table_endpoint_params(
  input: DeleteTableInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke DescribeBackup. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DescribeBackupError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DescribeBackupErrorTransport` variant.
pub fn describe_backup(
  client: Client,
  input: DescribeBackupInput,
) -> Result(DescribeBackupOutput, DescribeBackupError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_describe_backup_endpoint_params(input),
      build_describe_backup_request(input),
      parse_describe_backup_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_describe_backup_error(err))
  }
}

fn build_describe_backup_endpoint_params(
  input: DescribeBackupInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.backup_arn))
  params
}

/// Invoke DescribeContinuousBackups. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DescribeContinuousBackupsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DescribeContinuousBackupsErrorTransport` variant.
pub fn describe_continuous_backups(
  client: Client,
  input: DescribeContinuousBackupsInput,
) -> Result(DescribeContinuousBackupsOutput, DescribeContinuousBackupsError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_describe_continuous_backups_endpoint_params(input),
      build_describe_continuous_backups_request(input),
      parse_describe_continuous_backups_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_describe_continuous_backups_error(err))
  }
}

fn build_describe_continuous_backups_endpoint_params(
  input: DescribeContinuousBackupsInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke DescribeContributorInsights. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DescribeContributorInsightsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DescribeContributorInsightsErrorTransport` variant.
pub fn describe_contributor_insights(
  client: Client,
  input: DescribeContributorInsightsInput,
) -> Result(DescribeContributorInsightsOutput, DescribeContributorInsightsError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_describe_contributor_insights_endpoint_params(input),
      build_describe_contributor_insights_request(input),
      parse_describe_contributor_insights_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_describe_contributor_insights_error(err))
  }
}

fn build_describe_contributor_insights_endpoint_params(
  input: DescribeContributorInsightsInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke DescribeEndpoints. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DescribeEndpointsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DescribeEndpointsErrorTransport` variant.
pub fn describe_endpoints(
  client: Client,
  input: DescribeEndpointsRequest,
) -> Result(DescribeEndpointsResponse, DescribeEndpointsError) {
  case
    runtime.invoke(
      client.config,
      build_describe_endpoints_request(input),
      parse_describe_endpoints_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_describe_endpoints_error(err))
  }
}

/// Invoke DescribeExport. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DescribeExportError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DescribeExportErrorTransport` variant.
pub fn describe_export(
  client: Client,
  input: DescribeExportInput,
) -> Result(DescribeExportOutput, DescribeExportError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_describe_export_endpoint_params(input),
      build_describe_export_request(input),
      parse_describe_export_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_describe_export_error(err))
  }
}

fn build_describe_export_endpoint_params(
  input: DescribeExportInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.export_arn))
  params
}

/// Invoke DescribeGlobalTable. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DescribeGlobalTableError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DescribeGlobalTableErrorTransport` variant.
pub fn describe_global_table(
  client: Client,
  input: DescribeGlobalTableInput,
) -> Result(DescribeGlobalTableOutput, DescribeGlobalTableError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_describe_global_table_endpoint_params(input),
      build_describe_global_table_request(input),
      parse_describe_global_table_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_describe_global_table_error(err))
  }
}

fn build_describe_global_table_endpoint_params(
  input: DescribeGlobalTableInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(
      params,
      "ResourceArn",
      endpoints.StringVal(input.global_table_name),
    )
  params
}

/// Invoke DescribeGlobalTableSettings. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DescribeGlobalTableSettingsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DescribeGlobalTableSettingsErrorTransport` variant.
pub fn describe_global_table_settings(
  client: Client,
  input: DescribeGlobalTableSettingsInput,
) -> Result(DescribeGlobalTableSettingsOutput, DescribeGlobalTableSettingsError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_describe_global_table_settings_endpoint_params(input),
      build_describe_global_table_settings_request(input),
      parse_describe_global_table_settings_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_describe_global_table_settings_error(err))
  }
}

fn build_describe_global_table_settings_endpoint_params(
  input: DescribeGlobalTableSettingsInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(
      params,
      "ResourceArn",
      endpoints.StringVal(input.global_table_name),
    )
  params
}

/// Invoke DescribeImport. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DescribeImportError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DescribeImportErrorTransport` variant.
pub fn describe_import(
  client: Client,
  input: DescribeImportInput,
) -> Result(DescribeImportOutput, DescribeImportError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_describe_import_endpoint_params(input),
      build_describe_import_request(input),
      parse_describe_import_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_describe_import_error(err))
  }
}

fn build_describe_import_endpoint_params(
  input: DescribeImportInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.import_arn))
  params
}

/// Invoke DescribeKinesisStreamingDestination. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DescribeKinesisStreamingDestinationError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DescribeKinesisStreamingDestinationErrorTransport` variant.
pub fn describe_kinesis_streaming_destination(
  client: Client,
  input: DescribeKinesisStreamingDestinationInput,
) -> Result(
  DescribeKinesisStreamingDestinationOutput,
  DescribeKinesisStreamingDestinationError,
) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_describe_kinesis_streaming_destination_endpoint_params(input),
      build_describe_kinesis_streaming_destination_request(input),
      parse_describe_kinesis_streaming_destination_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) ->
      Error(translate_describe_kinesis_streaming_destination_error(err))
  }
}

fn build_describe_kinesis_streaming_destination_endpoint_params(
  input: DescribeKinesisStreamingDestinationInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke DescribeLimits. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DescribeLimitsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DescribeLimitsErrorTransport` variant.
pub fn describe_limits(
  client: Client,
  input: DescribeLimitsInput,
) -> Result(DescribeLimitsOutput, DescribeLimitsError) {
  case
    runtime.invoke(
      client.config,
      build_describe_limits_request(input),
      parse_describe_limits_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_describe_limits_error(err))
  }
}

/// Invoke DescribeTable. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DescribeTableError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DescribeTableErrorTransport` variant.
pub fn describe_table(
  client: Client,
  input: DescribeTableInput,
) -> Result(DescribeTableOutput, DescribeTableError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_describe_table_endpoint_params(input),
      build_describe_table_request(input),
      parse_describe_table_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_describe_table_error(err))
  }
}

fn build_describe_table_endpoint_params(
  input: DescribeTableInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke DescribeTableReplicaAutoScaling. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DescribeTableReplicaAutoScalingError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DescribeTableReplicaAutoScalingErrorTransport` variant.
pub fn describe_table_replica_auto_scaling(
  client: Client,
  input: DescribeTableReplicaAutoScalingInput,
) -> Result(
  DescribeTableReplicaAutoScalingOutput,
  DescribeTableReplicaAutoScalingError,
) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_describe_table_replica_auto_scaling_endpoint_params(input),
      build_describe_table_replica_auto_scaling_request(input),
      parse_describe_table_replica_auto_scaling_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) ->
      Error(translate_describe_table_replica_auto_scaling_error(err))
  }
}

fn build_describe_table_replica_auto_scaling_endpoint_params(
  input: DescribeTableReplicaAutoScalingInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke DescribeTimeToLive. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DescribeTimeToLiveError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DescribeTimeToLiveErrorTransport` variant.
pub fn describe_time_to_live(
  client: Client,
  input: DescribeTimeToLiveInput,
) -> Result(DescribeTimeToLiveOutput, DescribeTimeToLiveError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_describe_time_to_live_endpoint_params(input),
      build_describe_time_to_live_request(input),
      parse_describe_time_to_live_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_describe_time_to_live_error(err))
  }
}

fn build_describe_time_to_live_endpoint_params(
  input: DescribeTimeToLiveInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke DisableKinesisStreamingDestination. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `DisableKinesisStreamingDestinationError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `DisableKinesisStreamingDestinationErrorTransport` variant.
pub fn disable_kinesis_streaming_destination(
  client: Client,
  input: KinesisStreamingDestinationInput,
) -> Result(
  KinesisStreamingDestinationOutput,
  DisableKinesisStreamingDestinationError,
) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_disable_kinesis_streaming_destination_endpoint_params(input),
      build_disable_kinesis_streaming_destination_request(input),
      parse_disable_kinesis_streaming_destination_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) ->
      Error(translate_disable_kinesis_streaming_destination_error(err))
  }
}

fn build_disable_kinesis_streaming_destination_endpoint_params(
  input: KinesisStreamingDestinationInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke EnableKinesisStreamingDestination. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `EnableKinesisStreamingDestinationError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `EnableKinesisStreamingDestinationErrorTransport` variant.
pub fn enable_kinesis_streaming_destination(
  client: Client,
  input: KinesisStreamingDestinationInput,
) -> Result(
  KinesisStreamingDestinationOutput,
  EnableKinesisStreamingDestinationError,
) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_enable_kinesis_streaming_destination_endpoint_params(input),
      build_enable_kinesis_streaming_destination_request(input),
      parse_enable_kinesis_streaming_destination_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) ->
      Error(translate_enable_kinesis_streaming_destination_error(err))
  }
}

fn build_enable_kinesis_streaming_destination_endpoint_params(
  input: KinesisStreamingDestinationInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke ExecuteStatement. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `ExecuteStatementError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `ExecuteStatementErrorTransport` variant.
pub fn execute_statement(
  client: Client,
  input: ExecuteStatementInput,
) -> Result(ExecuteStatementOutput, ExecuteStatementError) {
  case
    runtime.invoke(
      client.config,
      build_execute_statement_request(input),
      parse_execute_statement_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_execute_statement_error(err))
  }
}

/// Invoke ExecuteTransaction. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `ExecuteTransactionError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `ExecuteTransactionErrorTransport` variant.
pub fn execute_transaction(
  client: Client,
  input: ExecuteTransactionInput,
) -> Result(ExecuteTransactionOutput, ExecuteTransactionError) {
  case
    runtime.invoke(
      client.config,
      build_execute_transaction_request(input),
      parse_execute_transaction_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_execute_transaction_error(err))
  }
}

/// Invoke ExportTableToPointInTime. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `ExportTableToPointInTimeError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `ExportTableToPointInTimeErrorTransport` variant.
pub fn export_table_to_point_in_time(
  client: Client,
  input: ExportTableToPointInTimeInput,
) -> Result(ExportTableToPointInTimeOutput, ExportTableToPointInTimeError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_export_table_to_point_in_time_endpoint_params(input),
      build_export_table_to_point_in_time_request(input),
      parse_export_table_to_point_in_time_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_export_table_to_point_in_time_error(err))
  }
}

fn build_export_table_to_point_in_time_endpoint_params(
  input: ExportTableToPointInTimeInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_arn))
  params
}

/// Invoke GetItem. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `GetItemError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `GetItemErrorTransport` variant.
pub fn get_item(
  client: Client,
  input: GetItemInput,
) -> Result(GetItemOutput, GetItemError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_get_item_endpoint_params(input),
      build_get_item_request(input),
      parse_get_item_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_get_item_error(err))
  }
}

fn build_get_item_endpoint_params(
  input: GetItemInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke GetResourcePolicy. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `GetResourcePolicyError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `GetResourcePolicyErrorTransport` variant.
pub fn get_resource_policy(
  client: Client,
  input: GetResourcePolicyInput,
) -> Result(GetResourcePolicyOutput, GetResourcePolicyError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_get_resource_policy_endpoint_params(input),
      build_get_resource_policy_request(input),
      parse_get_resource_policy_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_get_resource_policy_error(err))
  }
}

fn build_get_resource_policy_endpoint_params(
  input: GetResourcePolicyInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.resource_arn))
  params
}

/// Invoke ImportTable. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `ImportTableError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `ImportTableErrorTransport` variant.
pub fn import_table(
  client: Client,
  input: ImportTableInput,
) -> Result(ImportTableOutput, ImportTableError) {
  case
    runtime.invoke(
      client.config,
      build_import_table_request(input),
      parse_import_table_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_import_table_error(err))
  }
}

/// Invoke ListBackups. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `ListBackupsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `ListBackupsErrorTransport` variant.
pub fn list_backups(
  client: Client,
  input: ListBackupsInput,
) -> Result(ListBackupsOutput, ListBackupsError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_list_backups_endpoint_params(input),
      build_list_backups_request(input),
      parse_list_backups_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_list_backups_error(err))
  }
}

fn build_list_backups_endpoint_params(
  input: ListBackupsInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params = case input.table_name {
    option.Some(v) -> dict.insert(params, "ResourceArn", endpoints.StringVal(v))
    option.None -> params
  }
  params
}

/// Invoke ListContributorInsights. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `ListContributorInsightsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `ListContributorInsightsErrorTransport` variant.
pub fn list_contributor_insights(
  client: Client,
  input: ListContributorInsightsInput,
) -> Result(ListContributorInsightsOutput, ListContributorInsightsError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_list_contributor_insights_endpoint_params(input),
      build_list_contributor_insights_request(input),
      parse_list_contributor_insights_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_list_contributor_insights_error(err))
  }
}

fn build_list_contributor_insights_endpoint_params(
  input: ListContributorInsightsInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params = case input.table_name {
    option.Some(v) -> dict.insert(params, "ResourceArn", endpoints.StringVal(v))
    option.None -> params
  }
  params
}

/// Invoke ListExports. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `ListExportsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `ListExportsErrorTransport` variant.
pub fn list_exports(
  client: Client,
  input: ListExportsInput,
) -> Result(ListExportsOutput, ListExportsError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_list_exports_endpoint_params(input),
      build_list_exports_request(input),
      parse_list_exports_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_list_exports_error(err))
  }
}

fn build_list_exports_endpoint_params(
  input: ListExportsInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params = case input.table_arn {
    option.Some(v) -> dict.insert(params, "ResourceArn", endpoints.StringVal(v))
    option.None -> params
  }
  params
}

/// Invoke ListGlobalTables. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `ListGlobalTablesError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `ListGlobalTablesErrorTransport` variant.
pub fn list_global_tables(
  client: Client,
  input: ListGlobalTablesInput,
) -> Result(ListGlobalTablesOutput, ListGlobalTablesError) {
  case
    runtime.invoke(
      client.config,
      build_list_global_tables_request(input),
      parse_list_global_tables_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_list_global_tables_error(err))
  }
}

/// Invoke ListImports. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `ListImportsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `ListImportsErrorTransport` variant.
pub fn list_imports(
  client: Client,
  input: ListImportsInput,
) -> Result(ListImportsOutput, ListImportsError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_list_imports_endpoint_params(input),
      build_list_imports_request(input),
      parse_list_imports_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_list_imports_error(err))
  }
}

fn build_list_imports_endpoint_params(
  input: ListImportsInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params = case input.table_arn {
    option.Some(v) -> dict.insert(params, "ResourceArn", endpoints.StringVal(v))
    option.None -> params
  }
  params
}

/// Invoke ListTables. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `ListTablesError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `ListTablesErrorTransport` variant.
pub fn list_tables(
  client: Client,
  input: ListTablesInput,
) -> Result(ListTablesOutput, ListTablesError) {
  case
    runtime.invoke(
      client.config,
      build_list_tables_request(input),
      parse_list_tables_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_list_tables_error(err))
  }
}

/// Invoke ListTagsOfResource. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `ListTagsOfResourceError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `ListTagsOfResourceErrorTransport` variant.
pub fn list_tags_of_resource(
  client: Client,
  input: ListTagsOfResourceInput,
) -> Result(ListTagsOfResourceOutput, ListTagsOfResourceError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_list_tags_of_resource_endpoint_params(input),
      build_list_tags_of_resource_request(input),
      parse_list_tags_of_resource_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_list_tags_of_resource_error(err))
  }
}

fn build_list_tags_of_resource_endpoint_params(
  input: ListTagsOfResourceInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.resource_arn))
  params
}

/// Invoke PutItem. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `PutItemError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `PutItemErrorTransport` variant.
pub fn put_item(
  client: Client,
  input: PutItemInput,
) -> Result(PutItemOutput, PutItemError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_put_item_endpoint_params(input),
      build_put_item_request(input),
      parse_put_item_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_put_item_error(err))
  }
}

fn build_put_item_endpoint_params(
  input: PutItemInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke PutResourcePolicy. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `PutResourcePolicyError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `PutResourcePolicyErrorTransport` variant.
pub fn put_resource_policy(
  client: Client,
  input: PutResourcePolicyInput,
) -> Result(PutResourcePolicyOutput, PutResourcePolicyError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_put_resource_policy_endpoint_params(input),
      build_put_resource_policy_request(input),
      parse_put_resource_policy_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_put_resource_policy_error(err))
  }
}

fn build_put_resource_policy_endpoint_params(
  input: PutResourcePolicyInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.resource_arn))
  params
}

/// Invoke Query. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `QueryError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `QueryErrorTransport` variant.
pub fn query(
  client: Client,
  input: QueryInput,
) -> Result(QueryOutput, QueryError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_query_endpoint_params(input),
      build_query_request(input),
      parse_query_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_query_error(err))
  }
}

fn build_query_endpoint_params(
  input: QueryInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke RestoreTableFromBackup. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `RestoreTableFromBackupError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `RestoreTableFromBackupErrorTransport` variant.
pub fn restore_table_from_backup(
  client: Client,
  input: RestoreTableFromBackupInput,
) -> Result(RestoreTableFromBackupOutput, RestoreTableFromBackupError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_restore_table_from_backup_endpoint_params(input),
      build_restore_table_from_backup_request(input),
      parse_restore_table_from_backup_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_restore_table_from_backup_error(err))
  }
}

fn build_restore_table_from_backup_endpoint_params(
  input: RestoreTableFromBackupInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(
      params,
      "ResourceArn",
      endpoints.StringVal(input.target_table_name),
    )
  params
}

/// Invoke RestoreTableToPointInTime. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `RestoreTableToPointInTimeError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `RestoreTableToPointInTimeErrorTransport` variant.
pub fn restore_table_to_point_in_time(
  client: Client,
  input: RestoreTableToPointInTimeInput,
) -> Result(RestoreTableToPointInTimeOutput, RestoreTableToPointInTimeError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_restore_table_to_point_in_time_endpoint_params(input),
      build_restore_table_to_point_in_time_request(input),
      parse_restore_table_to_point_in_time_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_restore_table_to_point_in_time_error(err))
  }
}

fn build_restore_table_to_point_in_time_endpoint_params(
  input: RestoreTableToPointInTimeInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(
      params,
      "ResourceArn",
      endpoints.StringVal(input.target_table_name),
    )
  params
}

/// Invoke Scan. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `ScanError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `ScanErrorTransport` variant.
pub fn scan(client: Client, input: ScanInput) -> Result(ScanOutput, ScanError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_scan_endpoint_params(input),
      build_scan_request(input),
      parse_scan_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_scan_error(err))
  }
}

fn build_scan_endpoint_params(
  input: ScanInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke TagResource. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `TagResourceError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `TagResourceErrorTransport` variant.
pub fn tag_resource(
  client: Client,
  input: TagResourceInput,
) -> Result(TagResourceOutput, TagResourceError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_tag_resource_endpoint_params(input),
      build_tag_resource_request(input),
      parse_tag_resource_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_tag_resource_error(err))
  }
}

fn build_tag_resource_endpoint_params(
  input: TagResourceInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.resource_arn))
  params
}

/// Invoke TransactGetItems. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `TransactGetItemsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `TransactGetItemsErrorTransport` variant.
pub fn transact_get_items(
  client: Client,
  input: TransactGetItemsInput,
) -> Result(TransactGetItemsOutput, TransactGetItemsError) {
  case
    runtime.invoke(
      client.config,
      build_transact_get_items_request(input),
      parse_transact_get_items_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_transact_get_items_error(err))
  }
}

/// Invoke TransactWriteItems. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `TransactWriteItemsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `TransactWriteItemsErrorTransport` variant.
pub fn transact_write_items(
  client: Client,
  input: TransactWriteItemsInput,
) -> Result(TransactWriteItemsOutput, TransactWriteItemsError) {
  case
    runtime.invoke(
      client.config,
      build_transact_write_items_request(input),
      parse_transact_write_items_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_transact_write_items_error(err))
  }
}

/// Invoke UntagResource. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `UntagResourceError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `UntagResourceErrorTransport` variant.
pub fn untag_resource(
  client: Client,
  input: UntagResourceInput,
) -> Result(UntagResourceOutput, UntagResourceError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_untag_resource_endpoint_params(input),
      build_untag_resource_request(input),
      parse_untag_resource_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_untag_resource_error(err))
  }
}

fn build_untag_resource_endpoint_params(
  input: UntagResourceInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.resource_arn))
  params
}

/// Invoke UpdateContinuousBackups. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `UpdateContinuousBackupsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `UpdateContinuousBackupsErrorTransport` variant.
pub fn update_continuous_backups(
  client: Client,
  input: UpdateContinuousBackupsInput,
) -> Result(UpdateContinuousBackupsOutput, UpdateContinuousBackupsError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_update_continuous_backups_endpoint_params(input),
      build_update_continuous_backups_request(input),
      parse_update_continuous_backups_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_update_continuous_backups_error(err))
  }
}

fn build_update_continuous_backups_endpoint_params(
  input: UpdateContinuousBackupsInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke UpdateContributorInsights. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `UpdateContributorInsightsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `UpdateContributorInsightsErrorTransport` variant.
pub fn update_contributor_insights(
  client: Client,
  input: UpdateContributorInsightsInput,
) -> Result(UpdateContributorInsightsOutput, UpdateContributorInsightsError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_update_contributor_insights_endpoint_params(input),
      build_update_contributor_insights_request(input),
      parse_update_contributor_insights_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_update_contributor_insights_error(err))
  }
}

fn build_update_contributor_insights_endpoint_params(
  input: UpdateContributorInsightsInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke UpdateGlobalTable. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `UpdateGlobalTableError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `UpdateGlobalTableErrorTransport` variant.
pub fn update_global_table(
  client: Client,
  input: UpdateGlobalTableInput,
) -> Result(UpdateGlobalTableOutput, UpdateGlobalTableError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_update_global_table_endpoint_params(input),
      build_update_global_table_request(input),
      parse_update_global_table_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_update_global_table_error(err))
  }
}

fn build_update_global_table_endpoint_params(
  input: UpdateGlobalTableInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(
      params,
      "ResourceArn",
      endpoints.StringVal(input.global_table_name),
    )
  params
}

/// Invoke UpdateGlobalTableSettings. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `UpdateGlobalTableSettingsError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `UpdateGlobalTableSettingsErrorTransport` variant.
pub fn update_global_table_settings(
  client: Client,
  input: UpdateGlobalTableSettingsInput,
) -> Result(UpdateGlobalTableSettingsOutput, UpdateGlobalTableSettingsError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_update_global_table_settings_endpoint_params(input),
      build_update_global_table_settings_request(input),
      parse_update_global_table_settings_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_update_global_table_settings_error(err))
  }
}

fn build_update_global_table_settings_endpoint_params(
  input: UpdateGlobalTableSettingsInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(
      params,
      "ResourceArn",
      endpoints.StringVal(input.global_table_name),
    )
  params
}

/// Invoke UpdateItem. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `UpdateItemError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `UpdateItemErrorTransport` variant.
pub fn update_item(
  client: Client,
  input: UpdateItemInput,
) -> Result(UpdateItemOutput, UpdateItemError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_update_item_endpoint_params(input),
      build_update_item_request(input),
      parse_update_item_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_update_item_error(err))
  }
}

fn build_update_item_endpoint_params(
  input: UpdateItemInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke UpdateKinesisStreamingDestination. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `UpdateKinesisStreamingDestinationError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `UpdateKinesisStreamingDestinationErrorTransport` variant.
pub fn update_kinesis_streaming_destination(
  client: Client,
  input: UpdateKinesisStreamingDestinationInput,
) -> Result(
  UpdateKinesisStreamingDestinationOutput,
  UpdateKinesisStreamingDestinationError,
) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_update_kinesis_streaming_destination_endpoint_params(input),
      build_update_kinesis_streaming_destination_request(input),
      parse_update_kinesis_streaming_destination_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) ->
      Error(translate_update_kinesis_streaming_destination_error(err))
  }
}

fn build_update_kinesis_streaming_destination_endpoint_params(
  input: UpdateKinesisStreamingDestinationInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke UpdateTable. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `UpdateTableError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `UpdateTableErrorTransport` variant.
pub fn update_table(
  client: Client,
  input: UpdateTableInput,
) -> Result(UpdateTableOutput, UpdateTableError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_update_table_endpoint_params(input),
      build_update_table_request(input),
      parse_update_table_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_update_table_error(err))
  }
}

fn build_update_table_endpoint_params(
  input: UpdateTableInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke UpdateTableReplicaAutoScaling. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `UpdateTableReplicaAutoScalingError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `UpdateTableReplicaAutoScalingErrorTransport` variant.
pub fn update_table_replica_auto_scaling(
  client: Client,
  input: UpdateTableReplicaAutoScalingInput,
) -> Result(
  UpdateTableReplicaAutoScalingOutput,
  UpdateTableReplicaAutoScalingError,
) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_update_table_replica_auto_scaling_endpoint_params(input),
      build_update_table_replica_auto_scaling_request(input),
      parse_update_table_replica_auto_scaling_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_update_table_replica_auto_scaling_error(err))
  }
}

fn build_update_table_replica_auto_scaling_endpoint_params(
  input: UpdateTableReplicaAutoScalingInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

/// Invoke UpdateTimeToLive. Signs the request with SigV4 and dispatches via the configured
/// HTTP transport. Service errors come back as typed `UpdateTimeToLiveError`
/// variants; transport, decode, and credentials failures all collapse
/// into the generic `UpdateTimeToLiveErrorTransport` variant.
pub fn update_time_to_live(
  client: Client,
  input: UpdateTimeToLiveInput,
) -> Result(UpdateTimeToLiveOutput, UpdateTimeToLiveError) {
  case
    runtime.invoke_with_endpoint_params(
      client.config,
      build_update_time_to_live_endpoint_params(input),
      build_update_time_to_live_request(input),
      parse_update_time_to_live_response,
    )
  {
    Ok(out) -> Ok(out)
    Error(err) -> Error(translate_update_time_to_live_error(err))
  }
}

fn build_update_time_to_live_endpoint_params(
  input: UpdateTimeToLiveInput,
) -> dict.Dict(String, endpoints.Value) {
  let params = dict.new()
  let params =
    dict.insert(params, "ResourceArn", endpoints.StringVal(input.table_name))
  params
}

pub fn paginate_list_tables(
  client: Client,
  input: ListTablesInput,
  acc: acc,
  reducer: fn(acc, List(String)) -> acc,
) -> Result(acc, ListTablesError) {
  let step = fn(cursor) {
    let input = case cursor {
      option.Some(_) ->
        ListTablesInput(..input, exclusive_start_table_name: cursor)
      option.None -> input
    }
    case list_tables(client, input) {
      Ok(out) ->
        Ok(#(option.unwrap(out.table_names, []), out.last_evaluated_table_name))
      Error(e) -> Error(e)
    }
  }
  pagination.fold(acc: acc, step: step, reducer: reducer)
}

pub fn paginate_query(
  client: Client,
  input: QueryInput,
  acc: acc,
  reducer: fn(acc, List(dict.Dict(String, AttributeValue))) -> acc,
) -> Result(acc, QueryError) {
  let step = fn(cursor) {
    let input = case cursor {
      option.Some(_) -> QueryInput(..input, exclusive_start_key: cursor)
      option.None -> input
    }
    case query(client, input) {
      Ok(out) -> Ok(#(option.unwrap(out.items, []), out.last_evaluated_key))
      Error(e) -> Error(e)
    }
  }
  pagination.fold(acc: acc, step: step, reducer: reducer)
}

pub fn paginate_scan(
  client: Client,
  input: ScanInput,
  acc: acc,
  reducer: fn(acc, List(dict.Dict(String, AttributeValue))) -> acc,
) -> Result(acc, ScanError) {
  let step = fn(cursor) {
    let input = case cursor {
      option.Some(_) -> ScanInput(..input, exclusive_start_key: cursor)
      option.None -> input
    }
    case scan(client, input) {
      Ok(out) -> Ok(#(option.unwrap(out.items, []), out.last_evaluated_key))
      Error(e) -> Error(e)
    }
  }
  pagination.fold(acc: acc, step: step, reducer: reducer)
}

pub fn wait_until_table_not_exists(
  client: Client,
  input: DescribeTableInput,
  max_attempts: Int,
) -> Result(Nil, waiter.WaiterError(DescribeTableError)) {
  waiter.wait(
    step: fn(_attempt) {
      case describe_table(client, input) {
        Ok(_) -> waiter.Continue
        Error(e) ->
          case e {
            DescribeTableErrorResourceNotFoundException(_) -> waiter.Settled
            _ -> waiter.Continue
          }
      }
    },
    max_attempts: max_attempts,
    min_delay_ms: 20_000,
    max_delay_ms: 120_000,
  )
}

pub fn parse_internal_server_error_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "InternalServerError")
}

pub fn parse_request_limit_exceeded_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "RequestLimitExceeded")
}

pub fn parse_throttling_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "ThrottlingException")
}

pub fn parse_invalid_endpoint_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "InvalidEndpointException")
}

pub fn parse_provisioned_throughput_exceeded_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(
    headers,
    body,
    "ProvisionedThroughputExceededException",
  )
}

pub fn parse_resource_not_found_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "ResourceNotFoundException")
}

pub fn parse_item_collection_size_limit_exceeded_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(
    headers,
    body,
    "ItemCollectionSizeLimitExceededException",
  )
}

pub fn parse_replicated_write_conflict_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(
    headers,
    body,
    "ReplicatedWriteConflictException",
  )
}

pub fn parse_backup_in_use_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "BackupInUseException")
}

pub fn parse_continuous_backups_unavailable_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(
    headers,
    body,
    "ContinuousBackupsUnavailableException",
  )
}

pub fn parse_limit_exceeded_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "LimitExceededException")
}

pub fn parse_table_in_use_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "TableInUseException")
}

pub fn parse_table_not_found_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "TableNotFoundException")
}

pub fn parse_global_table_already_exists_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(
    headers,
    body,
    "GlobalTableAlreadyExistsException",
  )
}

pub fn parse_resource_in_use_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "ResourceInUseException")
}

pub fn parse_backup_not_found_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "BackupNotFoundException")
}

pub fn parse_conditional_check_failed_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(
    headers,
    body,
    "ConditionalCheckFailedException",
  )
}

pub fn parse_transaction_conflict_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(
    headers,
    body,
    "TransactionConflictException",
  )
}

pub fn parse_policy_not_found_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "PolicyNotFoundException")
}

pub fn parse_export_not_found_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "ExportNotFoundException")
}

pub fn parse_global_table_not_found_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(
    headers,
    body,
    "GlobalTableNotFoundException",
  )
}

pub fn parse_import_not_found_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "ImportNotFoundException")
}

pub fn parse_duplicate_item_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "DuplicateItemException")
}

pub fn parse_idempotent_parameter_mismatch_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(
    headers,
    body,
    "IdempotentParameterMismatchException",
  )
}

pub fn parse_transaction_canceled_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(
    headers,
    body,
    "TransactionCanceledException",
  )
}

pub fn parse_transaction_in_progress_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(
    headers,
    body,
    "TransactionInProgressException",
  )
}

pub fn parse_export_conflict_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "ExportConflictException")
}

pub fn parse_invalid_export_time_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "InvalidExportTimeException")
}

pub fn parse_point_in_time_recovery_unavailable_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(
    headers,
    body,
    "PointInTimeRecoveryUnavailableException",
  )
}

pub fn parse_import_conflict_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "ImportConflictException")
}

pub fn parse_table_already_exists_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "TableAlreadyExistsException")
}

pub fn parse_invalid_restore_time_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "InvalidRestoreTimeException")
}

pub fn parse_replica_already_exists_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(
    headers,
    body,
    "ReplicaAlreadyExistsException",
  )
}

pub fn parse_replica_not_found_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "ReplicaNotFoundException")
}

pub fn parse_index_not_found_exception_response(
  _code: Int,
  headers: dict.Dict(String, String),
  body: BitArray,
) -> Result(Nil, String) {
  runtime.check_error_type_matches(headers, body, "IndexNotFoundException")
}