{"version":3,"file":"index.mjs","names":["CONFIGS","options","getUpgrade","options","getUpgrade","options","getUpgrade","options","getUpgrade","options","getUpgrade","options","getUpgrade","options","getUpgrade","CONFIGS","CONFIGS","options","getUpgrade","options","getUpgrade","options","getUpgrade"],"sources":["../src/round.ts","../src/internal/lerp.ts","../src/internal/parsers/parse-aero.ts","../src/internal/parsers/parse-anti-roll-bar.ts","../src/internal/parsers/parse-brake-pressure.ts","../src/internal/parsers/parse-bump-rebound.ts","../src/internal/parsers/parse-camber-toe.ts","../src/internal/parsers/parse-caster.ts","../src/internal/parsers/parse-default.ts","../src/internal/parsers/parse-default-optional.ts","../src/internal/parsers/parse-differential.ts","../src/internal/parsers/parse-drivetrain-swap.ts","../src/internal/parsers/parse-engine-swap.ts","../src/internal/parsers/parse-final-drive.ts","../src/internal/parsers/parse-gear-ratios.ts","../src/internal/parsers/parse-intercooler.ts","../src/internal/parsers/parse-ordinal.ts","../src/internal/parsers/parse-percent.ts","../src/internal/parsers/parse-restrictor-plate.ts","../src/internal/parsers/parse-ride-height.ts","../src/internal/parsers/parse-spring-stiffness.ts","../src/internal/parsers/parse-springs-and-dampers.ts","../src/internal/parsers/parse-stock-non-stock.ts","../src/internal/parsers/parse-transmission.ts","../src/internal/parsers/parse-turbo.ts","../src/internal/parsers/parse-tyre-pressure.ts","../src/internal/to-bytes.ts","../src/parse.ts"],"sourcesContent":["import { RoundingMode } from './enums';\n\nconst STEP: Record<RoundingMode, number> = {\n  [RoundingMode.Whole]: 1,\n  [RoundingMode.DoubleDigit]: 0.01,\n  [RoundingMode.SingleDigit]: 0.1,\n  [RoundingMode.Half]: 0.5,\n};\n\nconst DECIMALS: Record<RoundingMode, number> = {\n  [RoundingMode.Whole]: 0,\n  [RoundingMode.DoubleDigit]: 2,\n  [RoundingMode.SingleDigit]: 1,\n  [RoundingMode.Half]: 1,\n};\n\n/**\n * Rounds a number to the nearest step.\n *\n * @param value The number to round.\n * @param mode The rounding mode (whole, double-digit, single digit, half).\n *\n * @returns The rounded number.\n *\n * @throws Error If the value is not finite.\n */\nexport function round(value: number, mode: RoundingMode): number {\n  if (!Number.isFinite(value)) {\n    throw new Error(`Cannot round non-finite value: ${value}`);\n  }\n  const step = STEP[mode];\n  const rounded = Math.round(value / step) * step;\n  return Number(rounded.toFixed(DECIMALS[mode]));\n}\n","import type { RoundingMode } from '../enums';\nimport { round } from '../round';\nimport type { ValueRange } from '../types';\n\n/**\n * Linear interpolation between two values (Round to 2 decimal places).\n *\n * @param value The value to interpolate between 0 and 1.\n * @param range The range of values to interpolate between.\n * @param mode The rounding mode to use.\n *\n * @returns The interpolated value.\n *\n * @throws RangeError If the value is not between 0 and 1.\n */\nexport function lerp(\n  value: number,\n  range: ValueRange,\n  mode: RoundingMode,\n): number {\n  if (value < 0 || value > 1)\n    throw new RangeError(\n      `Value must be between 0 and 1, got ${value} instead.`,\n    );\n  return round(range.min + value * (range.max - range.min), mode);\n}\n","import { Position, RoundingMode, UnitSystem } from '../../enums';\nimport type { Configuration, TuningField } from '../../types';\nimport { lerp } from '../lerp';\n\nconst CONFIGS = {\n  [UnitSystem.Imperial]: {\n    unit: 'lb',\n  },\n  [UnitSystem.Metric]: {\n    unit: 'kgf',\n  },\n};\n\n/**\n * Parse aero from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n * @param config The configuration containing the unit system and aero range (optional).\n * @param position The position of the aero (front or rear).\n *\n * @returns The parsed aero as a {@link TuningField} object.\n *\n * @throws RangeError If the raw float value is not between 0 and 1.\n */\nexport function parseAero(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n  config: Configuration,\n  position: Position,\n): TuningField {\n  const raw = view.getFloat32(byteOffset, true);\n  let { unit } = CONFIGS[config.unitSystem];\n  let roundingMode = RoundingMode.SingleDigit;\n  let range =\n    position === Position.Front ? config.aero?.front : config.aero?.rear;\n  if (!range) {\n    unit = '%';\n    range = { min: 0.0, max: 100.0 };\n    roundingMode = RoundingMode.Whole;\n  }\n  const value = lerp(raw, range, roundingMode);\n  return { raw, value, unit, range };\n}\n","import { RoundingMode } from '../../enums';\nimport type { TuningField } from '../../types';\nimport { lerp } from '../lerp';\n\n/**\n * Parse an anti-roll bar stiffness from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed anti-roll bar stiffness as a {@link TuningField} object.\n *\n * @throws RangeError If the raw float value is not between 0 and 1.\n */\nexport function parseAntiRollBar(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): TuningField {\n  const raw = view.getFloat32(byteOffset, true);\n  const unit = null;\n  const range = { min: 1.0, max: 65.0 };\n  const value = lerp(raw, range, RoundingMode.SingleDigit);\n  return { raw, value, unit, range };\n}\n","import { RoundingMode } from '../../enums';\nimport type { TuningField } from '../../types';\nimport { lerp } from '../lerp';\n\n/**\n * Parse brake pressure from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed brake pressure as a {@link TuningField} object.\n *\n * @throws RangeError If the raw float value is not between 0 and 1.\n */\nexport function parseBrakePressure(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): TuningField {\n  const raw = view.getFloat32(byteOffset, true);\n  const unit = null;\n  const range = { min: 0.0, max: 200.0 };\n  const value = lerp(raw, range, RoundingMode.Whole);\n  return { raw, value, unit, range };\n}\n","import { RoundingMode } from '../../enums';\nimport type { TuningField } from '../../types';\nimport { lerp } from '../lerp';\n\n/**\n * Parse a bump or rebound stiffness from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed bump or rebound stiffness as a {@link TuningField} object.\n *\n * @throws RangeError If the raw float value is not between 0 and 1.\n */\nexport function parseBumpRebound(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): TuningField {\n  const raw = view.getFloat32(byteOffset, true);\n  const unit = null;\n  const range = { min: 1.0, max: 20.0 };\n  const value = lerp(raw, range, RoundingMode.SingleDigit);\n  return { raw, value, unit, range };\n}\n","import { RoundingMode } from '../../enums';\nimport type { TuningField } from '../../types';\nimport { lerp } from '../lerp';\n\n/**\n * Parse a camber or toe angle from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed camber or toe angle as a {@link TuningField} object.\n *\n * @throws RangeError If the raw float value is not between 0 and 1.\n */\nexport function parseCamberToe(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): TuningField {\n  const raw = view.getFloat32(byteOffset, true);\n  const unit = '°';\n  const range = { min: -5, max: 5 };\n  const value = lerp(raw, range, RoundingMode.SingleDigit);\n  return { raw, value, unit, range };\n}\n","import { RoundingMode } from '../../enums';\nimport type { TuningField } from '../../types';\nimport { lerp } from '../lerp';\n\n/**\n * Parse a caster angle from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed caster angle as a {@link TuningField} object.\n *\n * @throws RangeError If the raw float value is not between 0 and 1.\n */\nexport function parseCaster(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): TuningField {\n  const raw = view.getFloat32(byteOffset, true);\n  const unit = '°';\n  const range = { min: 1.0, max: 7.0 };\n  const value = lerp(raw, range, RoundingMode.SingleDigit);\n  return { raw, value, unit, range };\n}\n","import type { UpgradeField } from '../../types';\n\nconst options = ['Stock', 'Street', 'Sport', 'Race'];\n\n/**\n * Get the upgrade name from the raw upgrade ID.\n */\nfunction getUpgrade(raw: number): string | null {\n  switch (raw % 100) {\n    case 0:\n      return 'Stock';\n    case 1:\n      return 'Street';\n    case 2:\n      return 'Sport';\n    case 3:\n      return 'Race';\n    default:\n      return null;\n  }\n}\n\n/**\n * Parse an arbitrary upgrade grade from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed upgrade grade.\n *\n * @throws RangeError If the upgrade ID is invalid.\n */\nexport function parseDefault(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): UpgradeField {\n  const raw = view.getInt32(byteOffset, true);\n  const selected = getUpgrade(raw);\n  if (selected === null) throw new RangeError('Invalid upgrade ID');\n  return { raw, selected, options };\n}\n","import type { UpgradeField } from '../../types';\n\nconst options = ['Stock', 'Street', 'Sport', 'Race'];\n\n/**\n * Get the upgrade name from the raw upgrade ID.\n */\nfunction getUpgrade(raw: number): string | null | undefined {\n  switch (raw % 100) {\n    case -1:\n      return null;\n    case 0:\n      return 'Stock';\n    case 1:\n      return 'Street';\n    case 2:\n      return 'Sport';\n    case 3:\n      return 'Race';\n    default:\n      return undefined;\n  }\n}\n\n/**\n * Parse an arbitrary upgrade grade (stock, street, sport, race) from a binary Forza tuning file.\n * This version allows for an upgrade to be null (optional).\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed upgrade grade.\n *\n * @throws RangeError If the upgrade ID is invalid.\n */\nexport function parseDefaultOptional(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): UpgradeField | null {\n  const raw = view.getInt32(byteOffset, true);\n  const selected = getUpgrade(raw);\n  if (selected === undefined) throw new RangeError('Invalid upgrade ID');\n  if (selected === null) return null;\n  return { raw, selected, options };\n}\n","import type { UpgradeField } from '../../types';\n\nconst options = [\n  'Stock',\n  'Street',\n  'Sport',\n  'Race',\n  'Rally',\n  'Drift',\n  'Off-Road',\n];\n\n/**\n * Get the upgrade name from the raw upgrade ID.\n */\nfunction getUpgrade(raw: number): string | null {\n  switch (raw % 100) {\n    case 0:\n      return 'Stock';\n    case 1:\n      return 'Street';\n    case 2:\n      return 'Sport';\n    case 3:\n      return 'Race';\n    case 4:\n      return 'Rally';\n    case 5:\n      return 'Drift (Rally if FWD)';\n    case 6:\n    case 7:\n      return 'Off-Road';\n    default:\n      return null;\n  }\n}\n\n/**\n * Parse the differential upgrade from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed differential upgrade.\n *\n * @throws RangeError If the upgrade ID is invalid.\n */\nexport function parseDifferential(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): UpgradeField {\n  const raw = view.getInt32(byteOffset, true);\n  const selected = getUpgrade(raw);\n  if (selected === null) throw new RangeError('Invalid upgrade ID');\n  return { raw, selected, options };\n}\n","import type { UpgradeField } from '../../types';\n\nconst options = ['Stock', 'RWD', 'AWD'];\n\n/**\n * Get the upgrade name from the raw upgrade ID.\n */\nfunction getUpgrade(raw: number): string | null {\n  switch (raw % 100) {\n    case 0:\n      return 'Stock';\n    case 1:\n      return 'RWD (AWD if only option)';\n    case 2:\n      return 'AWD';\n    default:\n      return null;\n  }\n}\n\n/**\n * Parse the drivetrain swap upgrade from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed drivetrain swap upgrade.\n *\n * @throws RangeError If the upgrade ID is invalid.\n */\nexport function parseDrivetrainSwap(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): UpgradeField {\n  const raw = view.getInt32(byteOffset, true);\n  const selected = getUpgrade(raw);\n  if (selected === null) throw new RangeError('Invalid upgrade ID');\n  return { raw, selected, options };\n}\n","import type { UpgradeField } from '../../types';\n\nconst options = [\n  'Stock',\n  '1st Non-Stock',\n  '2nd Non-Stock',\n  '3rd Non-Stock',\n  '4th Non-Stock',\n  '5th Non-Stock',\n  '6th Non-Stock',\n  '7th Non-Stock',\n  '8th Non-Stock',\n  '9th Non-Stock',\n];\n\n/**\n * Get the upgrade name from the raw upgrade ID.\n */\nfunction getUpgrade(raw: number): string | null {\n  switch (raw % 100) {\n    case 0:\n      return 'Stock';\n    case 1:\n      return '1st Non-Stock';\n    case 2:\n      return '2nd Non-Stock';\n    case 3:\n      return '3rd Non-Stock';\n    case 4:\n      return '4th Non-Stock';\n    case 5:\n      return '5th Non-Stock';\n    case 6:\n      return '6th Non-Stock';\n    case 7:\n      return '7th Non-Stock';\n    case 8:\n      return '8th Non-Stock';\n    case 9:\n      return '9th Non-Stock';\n    default:\n      return null;\n  }\n}\n\n/**\n * Parse the engine swap upgrade from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed engine swap upgrade.\n *\n * @throws RangeError If the upgrade ID is invalid.\n */\nexport function parseEngineSwap(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): UpgradeField {\n  const raw = view.getInt32(byteOffset, true);\n  const selected = getUpgrade(raw);\n  if (selected === null) throw new RangeError('Invalid upgrade ID');\n  return { raw, selected, options };\n}\n","import { RoundingMode } from '../../enums';\nimport type { TuningField } from '../../types';\nimport { lerp } from '../lerp';\n\n/**\n * Parses the final drive ratio from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed final drive ratio as a {@link TuningField} object.\n *\n * @throws RangeError If the raw float value is not between 0 and 1.\n */\nexport function parseFinalDrive(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): TuningField {\n  const raw = view.getFloat32(byteOffset, true);\n  const unit = null;\n  const range = { min: 2.2, max: 6.1 };\n  const value = lerp(raw, range, RoundingMode.DoubleDigit);\n  return { raw, value, unit, range };\n}\n","import { RoundingMode } from '../../enums';\nimport type { TuningField } from '../../types';\nimport { lerp } from '../lerp';\n\n/**\n * Parses gear ratios from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset of the first gear ratio float.\n *\n * @returns An array with a maximum of 10 {@link TuningField} objects, each representing a gear ratio.\n *\n * @throws RangeError If any raw float value is not between 0 and 1.\n */\nexport function parseGearRatios(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): TuningField[] {\n  const tuningFields: TuningField[] = [];\n  const unit = null;\n  const range = { min: 0.48, max: 6.0 };\n  for (let i = 0; i < 10; i++) {\n    const raw = view.getFloat32(byteOffset + i * 4, true);\n    if (raw === -1) continue;\n    if (raw < 0 || raw > 1) throw new RangeError('Invalid gear ratio');\n    const value = lerp(raw, range, RoundingMode.DoubleDigit);\n    tuningFields.push({ raw, value, unit, range });\n  }\n  return tuningFields;\n}\n","import type { UpgradeField } from '../../types';\n\nconst options = ['No Intercooler', 'Stock', 'Street', 'Sport', 'Race'];\n\n/**\n * Get the upgrade name from the raw upgrade ID.\n */\nfunction getUpgrade(raw: number): string | null {\n  switch (raw % 100) {\n    case -1:\n      return 'No Intercooler';\n    case 0:\n      return 'Stock (Street if No Intercooler possible)';\n    case 1:\n      return 'Street (Sport if No Intercooler possible)';\n    case 2:\n      return 'Sport (Race if No Intercooler possible)';\n    case 3:\n      return 'Race';\n    default:\n      return null;\n  }\n}\n\n/**\n * Parse the intercooler upgrade from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed intercooler upgrade.\n *\n * @throws RangeError If the upgrade ID is invalid.\n */\nexport function parseIntercooler(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): UpgradeField {\n  const raw = view.getInt32(byteOffset, true);\n  const selected = getUpgrade(raw);\n  if (selected === null) throw new RangeError('Invalid upgrade ID');\n  return { raw, selected, options };\n}\n","/**\n * Parse the car ordinal from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The car ordinal.\n */\nexport function parseOrdinal(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): number {\n  return view.getInt32(byteOffset, true);\n}\n","import { RoundingMode } from '../../enums';\nimport type { TuningField } from '../../types';\nimport { lerp } from '../lerp';\n\n/**\n * Parse a float value to per cent from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed float value as a {@link TuningField} object.\n *\n * @throws RangeError If the raw float value is not between 0 and 1.\n */\nexport function parsePercent(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): TuningField {\n  const raw = view.getFloat32(byteOffset, true);\n  const range = { min: 0.0, max: 100.0 };\n  const unit = '%';\n  const value = lerp(raw, range, RoundingMode.Whole);\n  return { raw, value, unit, range };\n}\n","import type { UpgradeField } from '../../types';\n\nconst options = ['Stock', 'No Restrictor Plate', 'Remove Restrictor'];\n\n/**\n * Get the upgrade name from the raw upgrade ID.\n */\nfunction getUpgrade(raw: number): string | null | undefined {\n  switch (raw % 100) {\n    case -1:\n      return null;\n    case 0:\n      return 'Stock';\n    case 1:\n      return 'No Restrictor Plate';\n    case 2:\n      return 'Remove Restrictor';\n    default:\n      return undefined;\n  }\n}\n\n/**\n * Parse the restrictor plate upgrade from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed restrictor plate upgrade.\n *\n * @throws RangeError If the upgrade ID is invalid.\n */\nexport function parseRestrictorPlate(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): UpgradeField | null {\n  const raw = view.getInt32(byteOffset, true);\n  const selected = getUpgrade(raw);\n  if (selected === undefined) throw new RangeError('Invalid upgrade ID');\n  if (selected === null) return null;\n  return { raw, selected, options };\n}\n","import { Position, RoundingMode, UnitSystem } from '../../enums';\nimport type { Configuration, TuningField } from '../../types';\nimport { lerp } from '../lerp';\n\nconst CONFIGS = {\n  [UnitSystem.Imperial]: {\n    unit: 'in',\n  },\n  [UnitSystem.Metric]: {\n    unit: 'cm',\n  },\n};\n\n/**\n * Parse ride height from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n * @param config The configuration containing the unit system and ride height range (optional).\n * @param position The position of the spring (front or rear).\n *\n * @returns The parsed ride height as a {@link TuningField} object.\n *\n * @throws RangeError If the raw float value is not between 0 and 1.\n */\nexport function parseRideHeight(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n  config: Configuration,\n  position: Position,\n) {\n  const raw = view.getFloat32(byteOffset, true);\n  let { unit } = CONFIGS[config.unitSystem];\n  let roundingMode = RoundingMode.SingleDigit;\n  let range =\n    position === Position.Front\n      ? config.springs?.rideHeight?.front\n      : config.springs?.rideHeight?.rear;\n  if (!range) {\n    unit = '%';\n    range = { min: 0.0, max: 100.0 };\n    roundingMode = RoundingMode.Whole;\n  }\n  const value = lerp(raw, range, roundingMode);\n  return { raw, value, unit, range };\n}\n","import { Position, RoundingMode, UnitSystem } from '../../enums';\nimport type { Configuration, TuningField } from '../../types';\nimport { lerp } from '../lerp';\n\nconst CONFIGS = {\n  [UnitSystem.Imperial]: {\n    unit: 'lb/in',\n  },\n  [UnitSystem.Metric]: {\n    unit: 'kgf/mm',\n  },\n};\n\n/**\n * Parse spring stiffness from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n * @param config The configuration containing the unit system and spring stiffness range (optional).\n * @param position The position of the spring (front or rear).\n *\n * @returns The parsed spring stiffness as a {@link TuningField} object.\n *\n * @throws RangeError If the raw float value is not between 0 and 1.\n */\nexport function parseSpringStiffness(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n  config: Configuration,\n  position: Position,\n) {\n  const raw = view.getFloat32(byteOffset, true);\n  let { unit } = CONFIGS[config.unitSystem];\n  let roundingMode = RoundingMode.SingleDigit;\n  let range =\n    position === Position.Front\n      ? config.springs?.stiffness?.front\n      : config.springs?.stiffness?.rear;\n  if (!range) {\n    unit = '%';\n    range = { min: 0.0, max: 100.0 };\n    roundingMode = RoundingMode.Whole;\n  }\n  const value = lerp(raw, range, roundingMode);\n  return { raw, value, unit, range };\n}\n","import type { UpgradeField } from '../../types';\n\nconst options = [\n  'Stock',\n  'Street',\n  'Sport',\n  'Race',\n  'Rally',\n  'Drift',\n  'Off-Road',\n];\n\n/**\n * Get the upgrade name from the raw upgrade ID.\n */\nfunction getUpgrade(raw: number): string | null {\n  switch (raw % 100) {\n    case 0:\n      return 'Stock';\n    case 1:\n      return 'Street';\n    case 2:\n      return 'Sport';\n    case 3:\n      return 'Race';\n    case 4:\n      return 'Rally';\n    case 5:\n      return 'Drift';\n    case 6:\n      return 'Off-Road';\n    default:\n      return null;\n  }\n}\n\n/**\n * Parse the springs and dampers upgrade from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed springs and dampers upgrade.\n *\n * @throws RangeError If the upgrade ID is invalid.\n */\nexport function parseSpringsAndDampers(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): UpgradeField {\n  const raw = view.getInt32(byteOffset, true);\n  const selected = getUpgrade(raw);\n  if (selected === null) throw new RangeError('Invalid upgrade ID');\n  return { raw, selected, options };\n}\n","import type { UpgradeField } from '../../types';\n\nconst options = ['Stock', 'Non-Stock'];\n\n/**\n * Get the upgrade name from the raw upgrade ID.\n */\nfunction getUpgrade(raw: number): string {\n  switch (raw % 1000) {\n    case 0:\n      return 'Stock';\n    default:\n      return 'Non-Stock';\n  }\n}\n\n/**\n * Parse an arbitrary upgrade grade (stock, non-stock) from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed upgrade grade.\n */\nexport function parseStockNonStock(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): UpgradeField {\n  const raw = view.getInt32(byteOffset, true);\n  const selected = getUpgrade(raw);\n  return { raw, selected, options };\n}\n","import type { UpgradeField } from '../../types';\n\nconst options = [\n  'Stock',\n  'Street',\n  'Sport',\n  'Race',\n  'Race: 6-Speed',\n  'Race: 7-Speed',\n  'Race: 8-Speed',\n  'Race: 9-Speed',\n  'Race: 10-Speed',\n  'Drift: 4-Speed',\n];\n\n/**\n * Get the upgrade name from the raw upgrade ID.\n */\nfunction getUpgrade(raw: number, numGears: number): string | null {\n  switch (raw % 100) {\n    case 0:\n      return 'Stock';\n    case 1:\n      return 'Street';\n    case 2:\n      return 'Sport';\n    case 3:\n      return 'Race';\n    case 4:\n    case 5:\n    case 6:\n    case 7:\n      return `Race: ${numGears}-Speed`;\n    case 8:\n      return `Drift: 4-Speed`;\n    default:\n      return null;\n  }\n}\n\n/**\n * Parse the transmission upgrade from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n * @param numGears The number of gears in the car.\n *\n * @returns The parsed transmission upgrade.\n *\n * @throws RangeError If the upgrade ID is invalid.\n */\nexport function parseTransmission(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n  numGears: number,\n): UpgradeField {\n  const raw = view.getInt32(byteOffset, true);\n  const selected = getUpgrade(raw, numGears);\n  if (selected === null) throw new RangeError('Invalid upgrade ID');\n  return { raw, selected, options };\n}\n","import type { UpgradeField } from '../../types';\n\nconst options = ['Stock', 'Street', 'Sport', 'Race', 'Race with Anti-Lag'];\n\n/**\n * Get the upgrade name from the raw upgrade ID.\n */\nfunction getUpgrade(raw: number): string | null | undefined {\n  switch (raw % 100) {\n    case -1:\n      return null;\n    case 0:\n      return 'Stock';\n    case 1:\n      return 'Street (Race w/ Anti-Lag if only option)';\n    case 2:\n      return 'Sport';\n    case 3:\n      return 'Race';\n    case 4:\n      return 'Race with Anti-Lag';\n    default:\n      return undefined;\n  }\n}\n\n/**\n * Parse the turbo upgrade from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n *\n * @returns The parsed turbo upgrade.\n *\n * @throws RangeError If the upgrade ID is invalid.\n */\nexport function parseTurbo(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n): UpgradeField | null {\n  const raw = view.getInt32(byteOffset, true);\n  const selected = getUpgrade(raw);\n  if (selected === undefined) throw new RangeError('Invalid upgrade ID');\n  if (selected === null) return null;\n  return { raw, selected, options };\n}\n","import { RoundingMode, UnitSystem } from '../../enums';\nimport type { Configuration, TuningField } from '../../types';\nimport { lerp } from '../lerp';\n\nconst CONFIGS = {\n  [UnitSystem.Imperial]: {\n    range: { min: 15.0, max: 55.0 },\n    unit: 'psi',\n    roundingMode: RoundingMode.Half,\n  },\n  [UnitSystem.Metric]: {\n    range: { min: 1.0, max: 3.8 },\n    unit: 'bar',\n    roundingMode: RoundingMode.SingleDigit,\n  },\n};\n\n/**\n * Parse tyre pressure from a binary Forza tuning file.\n *\n * @param view The DataView to read from.\n * @param byteOffset The byte offset to read from.\n * @param config The configuration containing the unit system.\n *\n * @returns The parsed tyre pressure as a {@link TuningField} object.\n *\n * @throws RangeError If the raw float value is not between 0 and 1.\n */\nexport function parseTyrePressure(\n  view: DataView<ArrayBufferLike>,\n  byteOffset: number,\n  config: Configuration,\n): TuningField {\n  const { range, unit, roundingMode } = CONFIGS[config.unitSystem];\n  const raw = view.getFloat32(byteOffset, true);\n  const value = lerp(raw, range, roundingMode);\n  return { raw, value, unit, range };\n}\n","import type { BinaryInput } from '../types.js';\n\n/**\n * Normalize any supported {@link BinaryInput} into a {@link Uint8Array}.\n *\n * @param input The input to normalize.\n *\n * @returns The normalized input.\n *\n * @throws TypeError If the input is not supported.\n */\nexport async function toBytes(input: BinaryInput): Promise<Uint8Array> {\n  if (input instanceof Uint8Array) {\n    return input;\n  }\n\n  if (input instanceof ArrayBuffer) {\n    return new Uint8Array(input);\n  }\n\n  if (typeof Blob !== 'undefined' && input instanceof Blob) {\n    const buffer = await input.arrayBuffer();\n    return new Uint8Array(buffer);\n  }\n\n  throw new TypeError(\n    'Unsupported input: expected an ArrayBuffer, Uint8Array, Blob, or File.',\n  );\n}\n","import { Position, UnitSystem } from './enums';\nimport { parseAero } from './internal/parsers/parse-aero';\nimport { parseAntiRollBar } from './internal/parsers/parse-anti-roll-bar';\nimport { parseBrakePressure } from './internal/parsers/parse-brake-pressure';\nimport { parseBumpRebound } from './internal/parsers/parse-bump-rebound';\nimport { parseCamberToe } from './internal/parsers/parse-camber-toe';\nimport { parseCaster } from './internal/parsers/parse-caster';\nimport { parseDefault } from './internal/parsers/parse-default';\nimport { parseDefaultOptional } from './internal/parsers/parse-default-optional';\nimport { parseDifferential } from './internal/parsers/parse-differential';\nimport { parseDrivetrainSwap } from './internal/parsers/parse-drivetrain-swap';\nimport { parseEngineSwap } from './internal/parsers/parse-engine-swap';\nimport { parseFinalDrive } from './internal/parsers/parse-final-drive';\nimport { parseGearRatios } from './internal/parsers/parse-gear-ratios';\nimport { parseIntercooler } from './internal/parsers/parse-intercooler';\nimport { parseOrdinal } from './internal/parsers/parse-ordinal';\nimport { parsePercent } from './internal/parsers/parse-percent';\nimport { parseRestrictorPlate } from './internal/parsers/parse-restrictor-plate';\nimport { parseRideHeight } from './internal/parsers/parse-ride-height';\nimport { parseSpringStiffness } from './internal/parsers/parse-spring-stiffness';\nimport { parseSpringsAndDampers } from './internal/parsers/parse-springs-and-dampers';\nimport { parseStockNonStock } from './internal/parsers/parse-stock-non-stock';\nimport { parseTransmission } from './internal/parsers/parse-transmission';\nimport { parseTurbo } from './internal/parsers/parse-turbo';\nimport { parseTyrePressure } from './internal/parsers/parse-tyre-pressure';\nimport { toBytes } from './internal/to-bytes.js';\nimport type { BinaryInput, Configuration, ForzaTune } from './types.js';\n\n/**\n * Parse a binary Forza tuning file into a typed {@link ForzaTune} object.\n *\n * Accepts `File`, `Blob`, `fetch` response (`await res.arrayBuffer()`), or `fs.readFile()` in\n * Node.js (`Uint8Array`).\n *\n * @example Browser\n * ```ts\n * import { parse } from 'forza-tuning-parser';\n *\n * dropZone.addEventListener('drop', async (e) => {\n *   const file = e.dataTransfer!.files[0];\n *   const tune = await parse(file);\n * });\n * ```\n *\n * @example Node.js\n * ```ts\n * import { readFile } from 'node:fs/promises';\n * import { parse } from 'forza-tuning-parser';\n *\n * const tune = await parse(await readFile('my.tune'));\n * ```\n *\n * @throws {TypeError} if `input` is not a supported binary type.\n */\nexport async function parse(\n  input: BinaryInput,\n  config: Configuration = { unitSystem: UnitSystem.Imperial },\n): Promise<ForzaTune> {\n  const bytes = await toBytes(input);\n  const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n  const tuning = {\n    tyrePressure: {\n      front: parseTyrePressure(view, 0x1ce, config),\n      rear: parseTyrePressure(view, 0x1fa, config),\n    },\n    gearing: {\n      finalDrive: parseFinalDrive(view, 0x1a6),\n      ratios: parseGearRatios(view, 0x22e),\n    },\n    alignment: {\n      camber: {\n        front: parseCamberToe(view, 0x1d2),\n        rear: parseCamberToe(view, 0x1fe),\n      },\n      toe: {\n        front: parseCamberToe(view, 0x1d6),\n        rear: parseCamberToe(view, 0x202),\n      },\n      caster: parseCaster(view, 0x1da),\n    },\n    antiRollBars: {\n      front: parseAntiRollBar(view, 0x1e2),\n      rear: parseAntiRollBar(view, 0x20e),\n    },\n    springs: {\n      stiffness: {\n        front: parseSpringStiffness(view, 0x1de, config, Position.Front),\n        rear: parseSpringStiffness(view, 0x20a, config, Position.Rear),\n      },\n      rideHeight: {\n        front: parseRideHeight(view, 0x1e6, config, Position.Front),\n        rear: parseRideHeight(view, 0x212, config, Position.Rear),\n      },\n    },\n    damping: {\n      reboundStiffness: {\n        front: parseBumpRebound(view, 0x1ee),\n        rear: parseBumpRebound(view, 0x21a),\n      },\n      bumpStiffness: {\n        front: parseBumpRebound(view, 0x1ea),\n        rear: parseBumpRebound(view, 0x216),\n      },\n    },\n    aero: {\n      front: parseAero(view, 0x19e, config, Position.Front),\n      rear: parseAero(view, 0x1a2, config, Position.Rear),\n    },\n    brakes: {\n      balance: parsePercent(view, 0x1ae),\n      pressure: parseBrakePressure(view, 0x1aa),\n    },\n    differential: {\n      front: {\n        acceleration: parsePercent(view, 0x1f2),\n        deceleration: parsePercent(view, 0x1f6),\n      },\n      rear: {\n        acceleration: parsePercent(view, 0x21e),\n        deceleration: parsePercent(view, 0x222),\n      },\n      balance: parsePercent(view, 0x1b6),\n    },\n  };\n  return {\n    ordinal: parseOrdinal(view, 0x2),\n    engine: {\n      camshaft: parseDefault(view, 0x3e),\n      valves: parseDefault(view, 0x42),\n      displacement: parseDefault(view, 0x46),\n      pistons: parseDefault(view, 0x4a),\n      fuelSystemOrCarburetor: parseDefault(view, 0x4e),\n      ignition: parseDefault(view, 0x52),\n      exhaust: parseDefault(view, 0x56),\n      intake: parseDefault(view, 0x5a),\n      flywheel: parseDefault(view, 0x5e),\n      intakeManifold: parseDefaultOptional(view, 0x62),\n      restrictorPlate: parseRestrictorPlate(view, 0x66),\n      oilCooling: parseDefault(view, 0x6a),\n      singleTurbo: parseTurbo(view, 0x6e),\n      twinTurbo: parseTurbo(view, 0x72),\n      centrifugalSupercharger: parseDefaultOptional(view, 0x7a),\n      supercharger: parseDefaultOptional(view, 0x7e),\n      intercooler: parseIntercooler(view, 0x82),\n    },\n    platform: {\n      brakes: parseDefault(view, 0x1e),\n      springsAndDampers: parseSpringsAndDampers(view, 0x22),\n      frontAntiRollBar: parseDefault(view, 0x26),\n      rearAntiRollBar: parseDefault(view, 0x2a),\n      weightReduction: parseDefault(view, 0xae),\n      chassisReinforcement: parseDefault(view, 0x32),\n    },\n    drivetrain: {\n      clutch: parseDefault(view, 0x86),\n      transmission: parseTransmission(view, 0x8a, tuning.gearing.ratios.length),\n      driveline: parseDefault(view, 0x8e),\n      differential: parseDifferential(view, 0x92),\n    },\n    conversions: {\n      engineSwap: parseEngineSwap(view, 0xe),\n      drivetrainSwap: parseDrivetrainSwap(view, 0x12),\n      bodySwap: parseStockNonStock(view, 0x16),\n    },\n    tuning,\n  };\n}\n"],"mappings":"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"}