///|
/// Application policy for the zero-dependency upload pipeline.
pub(all) struct UploadPolicy {
  parser_limits : @model.Limits
  allow_legacy_mixed : Bool
  max_file_bytes : Int64
  max_field_bytes : Int64
  max_total_payload_bytes : Int64
  max_file_count : Int
  max_field_count : Int
} derive(Debug, Eq)

///|
pub fn default_upload_policy() -> UploadPolicy {
  {
    parser_limits: @model.default_limits(),
    allow_legacy_mixed: true,
    max_file_bytes: 1073741824L,
    max_field_bytes: 1048576L,
    max_total_payload_bytes: 1073741824L,
    max_file_count: 64,
    max_field_count: 128,
  }
}

///|
pub(all) enum UploadPartKind {
  Field
  File
} derive(Debug, Eq)

///|
/// Metadata supplied to application-owned storage callbacks.
pub(all) struct UploadPart {
  meta : @model.PartMeta
  kind : UploadPartKind
  depth : Int
  parent_part_index : Int?
} derive(Debug, Eq)

///|
pub(all) struct UploadProgress {
  wire_bytes : Int64
  payload_bytes : Int64
  fields_completed : Int
  files_completed : Int
  active_part : UploadPart?
} derive(Debug, Eq)

///|
pub(all) struct UploadReceipt {
  wire_bytes : Int64
  payload_bytes : Int64
  fields_completed : Int
  files_completed : Int
} derive(Debug, Eq)

///|
pub(all) suberror UploadError {
  InvalidPolicy(reason~ : String)
  Protocol(error~ : @model.MultipartError)
  Mixed(error~ : @mixed.MixedError)
  SinkFailed(operation~ : String)
  PartTooLarge(part_index~ : Int, limit~ : Int64, observed~ : Int64)
  TotalPayloadTooLarge(limit~ : Int64, observed~ : Int64)
  PartCountExceeded(kind~ : UploadPartKind, limit~ : Int, observed~ : Int)
  UnexpectedEvent(reason~ : String)
  Aborted(reason~ : String)
} derive(Debug, Eq)