/// Hard resource limits applied while parsing and rendering.
///
/// Defaults are sized generously against the Telegram fixture corpus
/// (17.2k real files: p99 input ~748 KB, max ~1.7 MB) while still bounding
/// hostile input. Corpus-backed caps are kept at least 4x above the observed
/// maxima where real files had non-zero examples. Every limit maps to an
/// [`crate::error::Limit`] error —
/// exceeding one is a clean `Err`, never a crash or an OOM spiral.
#[derive(Debug, Clone, Copy)]
pub struct Limits {
  /// Maximum input size in bytes.
  pub max_input_bytes: usize,
  /// Maximum JSON nesting depth (objects + arrays combined).
  pub max_nesting_depth: usize,
  /// Maximum number of layers across the composition and all precomps.
  pub max_layers: usize,
  /// Maximum number of shape elements in a single layer.
  pub max_shapes_per_layer: usize,
  /// Maximum number of paint elements in a single layer.
  pub max_paints_per_layer: usize,
  /// Maximum cumulative geometry-source items observed by paints in one layer.
  pub max_paint_source_items_per_layer: usize,
  /// Maximum focal radial gradient paints in one layer.
  pub max_focal_radial_gradients_per_layer: usize,
  /// Maximum focal radial gradient paints after precomp reference expansion.
  pub max_focal_radial_gradient_expansion: usize,
  /// Maximum shape layers containing at least one retained paint.
  pub max_painted_shape_layers: usize,
  /// Maximum retained solid layers across root and asset layers.
  pub max_solid_layers: usize,
  /// Maximum keyframes for a single animated property.
  pub max_keyframes: usize,
  /// Maximum authored vertices in a single path or mask.
  pub max_path_points: usize,
  /// Maximum absolute authored coordinate/tangent magnitude in paths.
  pub max_path_coordinate_abs: f32,
  /// Maximum masks in a single layer.
  pub max_masks_per_layer: usize,
  /// Maximum retained masks across root and asset layers.
  pub max_masks: usize,
  /// Maximum authored vertices in a single mask path.
  pub max_mask_path_points: usize,
  /// Maximum dash entries in a single stroke.
  pub max_dash_elements: usize,
  /// Maximum dashed strokes in one shape group.
  pub max_dashed_strokes_per_group: usize,
  /// Maximum gradient strokes in one shape group.
  pub max_gradient_strokes_per_group: usize,
  /// Maximum source segment span before a round-join dashed stroke in one group.
  pub max_dashed_path_segment_span: f32,
  /// Maximum floats retained in a single gradient stop table.
  pub max_gradient_stop_values: usize,
  /// Maximum Fitzpatrick metadata entries parsed when requested by options.
  pub max_fitz_entries: usize,
  /// Maximum expanded precomp-layer references in the asset graph.
  pub max_precomp_expansion: usize,
  /// Maximum parent-chain depth in one layer list.
  pub max_parent_chain_depth: usize,
  /// Maximum sum of parent-chain depths in one layer list.
  pub max_parent_chain_total_depth: usize,
  /// Maximum generated polystar points.
  pub max_polystar_points: f32,
  /// Maximum copies for a single repeater.
  pub max_repeater_copies: f32,
  /// Maximum round-corners modifiers in one layer.
  pub max_round_corners_per_layer: usize,
  /// Maximum trim modifiers in one layer.
  pub max_trims_per_layer: usize,
  /// Maximum estimated dash pieces generated by one shape group.
  pub max_dashed_piece_estimate_per_group: usize,
  /// Maximum compounded repeater copies in one shape group.
  pub max_repeater_product_per_group: usize,
  /// Maximum number of assets (precomps).
  pub max_assets: usize,
  /// Maximum composition width/height in points, and render size in pixels.
  pub max_dimension: u32,
}

impl Default for Limits {
  fn default() -> Self {
    Self {
      max_input_bytes: 16 << 20, // 16 MiB
      max_nesting_depth: 128,
      max_layers: 2304,
      max_shapes_per_layer: 10_000,
      max_paints_per_layer: 2560,
      max_paint_source_items_per_layer: 4096,
      max_focal_radial_gradients_per_layer: 160,
      max_focal_radial_gradient_expansion: 512,
      max_painted_shape_layers: 2048,
      max_solid_layers: 256,
      max_keyframes: 2048,
      max_path_points: 4096,
      max_path_coordinate_abs: 140_000.0,
      max_masks_per_layer: 16,
      max_masks: 256,
      max_mask_path_points: 128,
      max_dash_elements: 32,
      max_dashed_strokes_per_group: 128,
      max_gradient_strokes_per_group: 24,
      max_dashed_path_segment_span: 5000.0,
      max_gradient_stop_values: 1024,
      max_fitz_entries: 16,
      max_precomp_expansion: 4096,
      max_parent_chain_depth: 128,
      max_parent_chain_total_depth: 16_384,
      max_polystar_points: 128.0,
      max_repeater_copies: 64.0,
      max_round_corners_per_layer: 8,
      max_trims_per_layer: 320,
      max_dashed_piece_estimate_per_group: 2048,
      max_repeater_product_per_group: 4096,
      max_assets: 256,
      max_dimension: 8192,
    }
  }
}
