/**
 * Yields its wrapped value exactly once through an `IterableIterator`.
 *
 * **When to use**
 *
 * Use to implement `[Symbol.iterator]()` on Effect-like types so they can be
 * `yield*`-ed inside generator functions, such as `Effect.gen` and
 * `Option.gen`.
 *
 * **Details**
 *
 * The first call to `next()` returns `{ value: self, done: false }`. Every
 * subsequent call returns `{ value: a, done: true }` where `a` is the argument
 * passed to `next()`. `[Symbol.iterator]()` returns a **new** `SingleShotGen`
 * wrapping the same value, so the outer type can be iterated multiple times.
 *
 * **Example** (Yielding a wrapped value in a generator)
 *
 * ```ts
 * import { Utils } from "effect"
 *
 * const gen = new Utils.SingleShotGen<string, number>("hello")
 *
 * // First call yields the wrapped value
 * console.log(gen.next(0))
 * // { value: "hello", done: false }
 *
 * // Second call signals completion with the provided value
 * console.log(gen.next(42))
 * // { value: 42, done: true }
 * ```
 *
 * @see {@link Gen} for the type-level signature that relies on `SingleShotGen`
 * @category constructors
 * @since 2.0.0
 */
export class SingleShotGen {
  called = false;
  self;
  constructor(self) {
    this.self = self;
  }
  /**
   * Yields the stored value once, then completes with the value sent back in.
   *
   * **When to use**
   *
   * Use to advance a `SingleShotGen` through its single yield and completion
   * step.
   *
   * @since 2.0.0
   */
  next(a) {
    return this.called ? {
      value: a,
      done: true
    } : (this.called = true, {
      value: this.self,
      done: false
    });
  }
  /**
   * Creates a fresh single-shot iterator over the stored value.
   *
   * **When to use**
   *
   * Use to iterate the wrapped value again without reusing the consumed
   * iterator state.
   *
   * @since 2.0.0
   */
  [Symbol.iterator]() {
    return new SingleShotGen(this.self);
  }
}
const InternalTypeId = "~effect/Utils/internal";
const standard = {
  [InternalTypeId]: body => {
    return body();
  }
};
const forced = {
  [InternalTypeId]: body => {
    try {
      return body();
    } finally {
      //
    }
  }
};
const isNotOptimizedAway = /*#__PURE__*/standard[InternalTypeId](() => new Error().stack)?.includes(InternalTypeId) === true;
/** @internal */
export const internalCall = isNotOptimizedAway ? standard[InternalTypeId] : forced[InternalTypeId];
//# sourceMappingURL=Utils.js.map