Hyperlinkv0.8.0-beta.28

Schema

Source effect/Schema.ts:10790138 lines
export interface BigDecimal extends declare<BigDecimal_.BigDecimal> {
  readonly "Rebuild": BigDecimal
}

const BigDecimalString = String.annotate({ expected: "a string that will be decoded as a BigDecimal" })

const bigDecimalDefaultMaxScale = 20
const bigDecimalInvalidOrderedConstraintsError = "Unable to derive an arbitrary for the ordered BigDecimal constraints"

function bigDecimalScaleValueAtScale(bd: BigDecimal_.BigDecimal, scale: number): bigint {
  return BigDecimal_.scale(bd, scale).value
}

function bigDecimalMinValueAtScale(
  minimum: BigDecimal_.BigDecimal,
  scale: number,
  excluded: boolean
): bigint {
  return excluded
    ? bigDecimalScaleValueAtScale(BigDecimal_.floor(minimum, scale), scale) + globalThis.BigInt(1)
    : bigDecimalScaleValueAtScale(BigDecimal_.ceil(minimum, scale), scale)
}

function bigDecimalMaxValueAtScale(
  maximum: BigDecimal_.BigDecimal,
  scale: number,
  excluded: boolean
): bigint {
  return excluded
    ? bigDecimalScaleValueAtScale(BigDecimal_.ceil(maximum, scale), scale) - globalThis.BigInt(1)
    : bigDecimalScaleValueAtScale(BigDecimal_.floor(maximum, scale), scale)
}

function bigDecimalMaxScale(ordered: Annotations.ToArbitrary.OrderedConstraint<BigDecimal_.BigDecimal>): number {
  return Math.max(
    bigDecimalDefaultMaxScale,
    ordered.minimum?.scale ?? 0,
    ordered.maximum?.scale ?? 0,
    ordered.exclusiveMinimum && ordered.minimum !== undefined ? ordered.minimum.scale + 1 : 0,
    ordered.exclusiveMaximum && ordered.maximum !== undefined ? ordered.maximum.scale + 1 : 0
  )
}

function bigDecimalValueConstraintsAtScale(
  ordered: Annotations.ToArbitrary.OrderedConstraint<BigDecimal_.BigDecimal>,
  scale: number
): FastCheck.BigIntConstraints | undefined {
  const constraints: FastCheck.BigIntConstraints = {}
  if (ordered.minimum !== undefined) {
    constraints.min = bigDecimalMinValueAtScale(ordered.minimum, scale, ordered.exclusiveMinimum === true)
  }
  if (ordered.maximum !== undefined) {
    constraints.max = bigDecimalMaxValueAtScale(ordered.maximum, scale, ordered.exclusiveMaximum === true)
  }
  if (constraints.min !== undefined && constraints.max !== undefined && constraints.min > constraints.max) {
    return undefined
  }
  return constraints
}

function bigDecimalScaleConstraints(
  ordered: Annotations.ToArbitrary.OrderedConstraint<BigDecimal_.BigDecimal>
): FastCheck.IntegerConstraints {
  const max = bigDecimalMaxScale(ordered)
  if (bigDecimalValueConstraintsAtScale(ordered, max) === undefined) {
    throw new globalThis.Error(bigDecimalInvalidOrderedConstraintsError)
  }

  let min = 0
  let high = max
  while (min < high) {
    const scale = min + Math.floor((high - min) / 2)
    if (bigDecimalValueConstraintsAtScale(ordered, scale) === undefined) {
      min = scale + 1
    } else {
      high = scale
    }
  }
  return { min, max }
}

/**
 * Schema for `BigDecimal` values.
 *
 * **When to use**
 *
 * Use when you already have Effect decimal instances and need schema
 * validation, formatting, equivalence, and JSON string serialization.
 *
 * **Details**
 *
 * Default JSON serializer:
 *
 * - encodes `BigDecimal` as a `string`
 *
 * @see {@link BigDecimalFromString} for parsing string input into a BigDecimal
 *
 * @category BigDecimal
 * @since 3.10.0
 */
export const BigDecimal: BigDecimal = declare(
  BigDecimal_.isBigDecimal,
  {
    typeConstructor: {
      _tag: "effect/BigDecimal"
    },
    generation: {
      runtime: `Schema.BigDecimal`,
      Type: `BigDecimal.BigDecimal`,
      importDeclaration: `import * as BigDecimal from "effect/BigDecimal"`
    },
    expected: "BigDecimal",
    toCodecJson: () =>
      link<BigDecimal_.BigDecimal>()(
        BigDecimalString,
        SchemaTransformation.bigDecimalFromString
      ),
    toArbitrary: () => (fc, ctx) => {
      const ordered = ctx.constraint?.ordered?.order === BigDecimal_.Order
        ? ctx.constraint.ordered as Annotations.ToArbitrary.OrderedConstraint<BigDecimal_.BigDecimal>
        : undefined
      if (ordered === undefined) {
        return fc.tuple(fc.bigInt(), fc.integer({ min: 0, max: bigDecimalDefaultMaxScale }))
          .map(([value, scale]) => BigDecimal_.make(value, scale))
      }

      return fc.integer(bigDecimalScaleConstraints(ordered)).chain((scale) => {
        const constraints = bigDecimalValueConstraintsAtScale(ordered, scale)
        if (constraints === undefined) {
          throw new globalThis.Error(bigDecimalInvalidOrderedConstraintsError)
        }
        return fc.bigInt(constraints).map((value) => BigDecimal_.make(value, scale))
      })
    },
    toFormatter: () => (bd) => BigDecimal_.format(bd),
    toEquivalence: () => BigDecimal_.Equivalence
  }
)
Referenced by 2 symbols