///|
/// Limits for in-memory form fields. File bodies are never accepted by the
/// collector; route them through `PartSinkAdapter` instead.
pub(all) struct FieldCollectorLimits {
  max_fields : Int
  max_field_bytes : Int64
  max_total_field_bytes : Int64
} derive(Debug, Eq)

///|
pub fn default_field_collector_limits() -> FieldCollectorLimits {
  { max_fields: 64, max_field_bytes: 65536L, max_total_field_bytes: 262144L }
}

///|
/// A completed small text or binary form field.
pub(all) struct FormField {
  meta : @model.PartMeta
  value : Bytes
} derive(Debug, Eq)

///|
/// A decoded text field. Decoding is explicit so binary field consumers can
/// continue using `FormField.value` without an implicit UTF-8 conversion.
pub(all) struct DecodedField {
  name : String
  value : String
  content_type : String?
} derive(Debug, Eq)

///|
/// Failures at the collector and transport-adapter boundary.
pub(all) suberror FormError {
  InvalidCollectorLimits(reason~ : String)
  UnexpectedEvent(reason~ : String)
  FilePartRejected(part_index~ : Int)
  FieldLimitExceeded(limit~ : Int64, observed~ : Int64)
  FieldCountExceeded(limit~ : Int, observed~ : Int)
  InvalidTextEncoding(field_name~ : String, charset~ : String)
  SinkFailed(reason~ : String)
  SourceFailed(reason~ : String)
  Protocol(error~ : @model.MultipartError)
} derive(Debug, Eq)