///|
/// Constants refer to the reaction written in `reaction`, with dimensionless
/// activities. A secondary species uses log(a_s) = log_k + sum(nu log(a_i)).
pub(all) struct ThermoRecord {
  id : String
  reaction : String
  source_reaction : String
  log_k : Double
  source_lines : String
  derivation : String
} derive(Debug, ToJson, FromJson)

///|
/// A fixed dataset and the approximation used to apply it in this solver.
/// The source is molal; this release uses c/(1 mol/L), with m approximately c
/// for dilute water and unit solvent activity. No temperature extrapolation.
pub(all) struct ThermodynamicData {
  adaptation_notice : String
  version : String
  reference_url : String
  reference_sha256 : String
  source_standard_state : String
  solver_standard_state : String
  reference_temperature_k : Double
  min_temperature_k : Double
  max_temperature_k : Double
  pressure_atm : Double
  license : String
  license_url : String
  limitations : String
  records : Array[ThermoRecord]
} derive(Debug, ToJson, FromJson)

///|
pub(all) struct IterationRecord {
  outer_iteration : Int32
  inner_iterations : Int32
  ionic_strength : Double
  max_scaled_residual : Double
  max_log_gamma_error : Double
} derive(Debug, ToJson, FromJson)

///|
fn thermo_record(data : ThermodynamicData, id : String) -> ThermoRecord? {
  for record in data.records {
    if record.id == id {
      return Some(record)
    }
  }
  None
}

///|
fn finite(value : Double) -> Bool {
  value == value && value.abs() < 1.0e300
}