/**
 * The `Pipeable` module defines the shared interface and implementation helpers
 * for values that support Effect-style method chaining with `.pipe(...)`.
 *
 * A `Pipeable` value can pass itself through a sequence of unary functions from
 * left to right, so code can be written as `value.pipe(f, g, h)` instead of
 * deeply nesting calls. This is the method form used by many Effect data types
 * to compose transformations, validations, and effectful operations while
 * keeping the original value as the starting point of the pipeline.
 *
 * **Common tasks**
 *
 * - Type values that expose a `.pipe(...)` method with the {@link Pipeable} interface
 * - Implement a custom `.pipe(...)` method with {@link pipeArguments}
 * - Reuse the standard implementation through {@link Prototype}, {@link Class}, or {@link Mixin}
 *
 * **Gotchas**
 *
 * - Each function receives the result of the previous function, not the original value
 * - The overloads preserve precise types for long pipelines, but very long chains may be easier to read when split
 *
 * @since 2.0.0
 */
/**
 * Applies a `pipe` method's variadic arguments to an initial value from left
 * to right.
 *
 * **When to use**
 *
 * Use to implement a custom `.pipe(...)` method from JavaScript's `arguments`
 * object.
 *
 * **Details**
 *
 * This helper is intended for implementing `Pipeable.pipe` methods that
 * receive JavaScript's `arguments` object. With no functions it returns the
 * original value; otherwise it feeds each result into the next function.
 *
 * **Example** (Implementing a pipe method)
 *
 * ```ts
 * import { Pipeable } from "effect"
 *
 * class NumberBox {
 *   constructor(readonly value: number) {}
 *
 *   pipe(..._fns: ReadonlyArray<(value: number) => number>): number {
 *     return Pipeable.pipeArguments(this.value, arguments) as number
 *   }
 * }
 *
 * const result = new NumberBox(5).pipe(
 *   (n) => n + 2,
 *   (n) => n * 3
 * )
 * console.log(result) // 21
 * ```
 *
 * @category combinators
 * @since 2.0.0
 */
export const pipeArguments = (self, args) => {
  switch (args.length) {
    case 0:
      return self;
    case 1:
      return args[0](self);
    case 2:
      return args[1](args[0](self));
    case 3:
      return args[2](args[1](args[0](self)));
    case 4:
      return args[3](args[2](args[1](args[0](self))));
    case 5:
      return args[4](args[3](args[2](args[1](args[0](self)))));
    case 6:
      return args[5](args[4](args[3](args[2](args[1](args[0](self))))));
    case 7:
      return args[6](args[5](args[4](args[3](args[2](args[1](args[0](self)))))));
    case 8:
      return args[7](args[6](args[5](args[4](args[3](args[2](args[1](args[0](self))))))));
    case 9:
      return args[8](args[7](args[6](args[5](args[4](args[3](args[2](args[1](args[0](self)))))))));
    default:
      {
        let ret = self;
        for (let i = 0, len = args.length; i < len; i++) {
          ret = args[i](ret);
        }
        return ret;
      }
  }
};
/**
 * Reusable prototype that implements `Pipeable.pipe`.
 *
 * **When to use**
 *
 * Use when classes or object prototypes can reuse this value when they need the
 * standard pipe implementation backed by `pipeArguments`.
 *
 * @category prototypes
 * @since 3.15.0
 */
export const Prototype = {
  pipe() {
    return pipeArguments(this, arguments);
  }
};
/**
 * Provides a base constructor whose instances implement the standard `Pipeable.pipe`
 * method.
 *
 * **When to use**
 *
 * Use when extend or compose this constructor when defining a class that should support
 * Effect-style method chaining through `.pipe(...)`.
 *
 * @category constructors
 * @since 3.15.0
 */
export const Class = /*#__PURE__*/function () {
  function PipeableBase() {}
  PipeableBase.prototype = Prototype;
  return PipeableBase;
}();
/**
 * Returns a subclass of the provided class that adds the standard `pipe`
 * method.
 *
 * **When to use**
 *
 * Use to add pipe support to an existing class without extending a base class
 * or modifying its prototype.
 *
 * **Details**
 *
 * The original constructor and instance members are preserved, and the added
 * method delegates to `pipeArguments`.
 *
 * @see {@link Prototype} for a reusable prototype object
 * @see {@link Class} for a base constructor to extend
 * @category constructors
 * @since 4.0.0
 */
export const Mixin = klass => class extends klass {
  pipe() {
    return pipeArguments(this, arguments);
  }
};
//# sourceMappingURL=Pipeable.js.map