/**
 * The `TxChunk` module provides a transactional collection backed by an
 * immutable {@link Chunk}. A `TxChunk<A>` stores the current chunk in a
 * {@link TxRef}, so reads and updates are tracked by Effect transactions and
 * committed atomically.
 *
 * **Mental model**
 *
 * - A `TxChunk` is mutable at the reference level, but every stored value is a
 *   persistent `Chunk`
 * - Single operations such as {@link append}, {@link drop}, or {@link get} run
 *   as transactions on their own
 * - Wrap several operations in `Effect.tx` when they must observe one
 *   consistent snapshot and commit or retry together
 * - If a transaction reads a `TxChunk` and another transaction changes it
 *   before commit, the transaction retries instead of publishing a stale write
 *
 * **Common tasks**
 *
 * - Create collections: {@link empty}, {@link make}, {@link fromIterable}
 * - Replace or transform contents: {@link set}, {@link update}, {@link modify}
 * - Add values: {@link append}, {@link prepend}, {@link appendAll},
 *   {@link prependAll}
 * - Keep or remove ranges: {@link take}, {@link drop}, {@link slice},
 *   {@link filter}
 * - Inspect contents: {@link get}, {@link size}, {@link isEmpty},
 *   {@link isNonEmpty}
 *
 * **Gotchas**
 *
 * - `get` returns the current immutable `Chunk`, not a live mutable view
 * - Operations such as {@link append}, {@link drop}, and {@link filter} update
 *   the stored chunk; they do not return a new `TxChunk`
 * - Use `TxQueue` instead when producers should wait, drop, or slide based on
 *   queue capacity
 *
 * **See also**
 *
 * - {@link TxRef} for the lower-level transactional reference used internally
 * - {@link Chunk} for immutable chunk operations
 * - `TxQueue` for transactional producer/consumer queues
 *
 * @since 4.0.0
 */
import * as Chunk from "./Chunk.js";
import * as Effect from "./Effect.js";
import { format } from "./Formatter.js";
import { dual } from "./Function.js";
import { NodeInspectSymbol, toJson } from "./Inspectable.js";
import { pipeArguments } from "./Pipeable.js";
import * as TxRef from "./TxRef.js";
const TypeId = "~effect/transactions/TxChunk";
const TxChunkProto = {
  [NodeInspectSymbol]() {
    return this.toJSON();
  },
  toString() {
    return `TxChunk(${format(toJson(this.ref))})`;
  },
  toJSON() {
    return {
      _id: "TxChunk",
      ref: toJson(this.ref)
    };
  },
  pipe() {
    return pipeArguments(this, arguments);
  }
};
/**
 * Creates a new `TxChunk` with the specified initial chunk.
 *
 * **Details**
 *
 * This function returns a new TxChunk reference containing the provided initial chunk. No existing
 * TxChunk instances are modified.
 *
 * **Example** (Creating a TxChunk from a chunk)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   // Create a TxChunk with initial values
 *   const initialChunk = Chunk.fromIterable([1, 2, 3])
 *   const txChunk = yield* TxChunk.make(initialChunk)
 *
 *   // Read the value - automatically transactional
 *   const result = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(result)) // [1, 2, 3]
 * })
 * ```
 *
 * @category constructors
 * @since 4.0.0
 */
export const make = initial => Effect.map(TxRef.make(initial), ref => makeUnsafe(ref));
/**
 * Creates a new empty `TxChunk`.
 *
 * **Details**
 *
 * This function returns a new TxChunk reference that is initially empty. No existing TxChunk
 * instances are modified.
 *
 * **Example** (Creating an empty TxChunk)
 *
 * ```ts
 * import { Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   // Create an empty TxChunk
 *   const txChunk = yield* TxChunk.empty<number>()
 *
 *   // Check if it's empty - automatically transactional
 *   const isEmpty = yield* TxChunk.isEmpty(txChunk)
 *   console.log(isEmpty) // true
 *
 *   // Add elements - automatically transactional
 *   yield* TxChunk.append(txChunk, 42)
 *
 *   const isStillEmpty = yield* TxChunk.isEmpty(txChunk)
 *   console.log(isStillEmpty) // false
 * })
 * ```
 *
 * @category constructors
 * @since 4.0.0
 */
export const empty = () => Effect.map(TxRef.make(Chunk.empty()), ref => makeUnsafe(ref));
/**
 * Creates a new `TxChunk` from an iterable.
 *
 * **Details**
 *
 * This function returns a new TxChunk reference containing elements from the provided iterable. No
 * existing TxChunk instances are modified.
 *
 * **Example** (Creating from an iterable)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   // Create TxChunk from array
 *   const txChunk = yield* TxChunk.fromIterable([1, 2, 3, 4, 5])
 *
 *   // Read the contents - automatically transactional
 *   const chunk = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(chunk)) // [1, 2, 3, 4, 5]
 *
 *   // Multi-step atomic modification - use explicit transaction
 *   yield* Effect.tx(
 *     Effect.gen(function*() {
 *       yield* TxChunk.append(txChunk, 6)
 *       yield* TxChunk.prepend(txChunk, 0)
 *     })
 *   )
 *
 *   const updated = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(updated)) // [0, 1, 2, 3, 4, 5, 6]
 * })
 * ```
 *
 * @category constructors
 * @since 4.0.0
 */
export const fromIterable = iterable => Effect.map(TxRef.make(Chunk.fromIterable(iterable)), ref => makeUnsafe(ref));
/**
 * Creates a new `TxChunk` with the specified TxRef.
 *
 * **Details**
 *
 * This function returns a new TxChunk reference wrapping the provided TxRef. No existing TxChunk
 * instances are modified.
 *
 * **Example** (Wrapping an existing TxRef)
 *
 * ```ts
 * import { Chunk, TxChunk, TxRef } from "effect"
 *
 * // Create a TxChunk from an existing TxRef (advanced usage)
 * const ref = TxRef.makeUnsafe(Chunk.fromIterable([1, 2, 3]))
 * const txChunk = TxChunk.makeUnsafe(ref)
 * ```
 *
 * @category constructors
 * @since 4.0.0
 */
export const makeUnsafe = ref => {
  const txChunk = Object.create(TxChunkProto);
  txChunk[TypeId] = TypeId;
  txChunk.ref = ref;
  return txChunk;
};
/**
 * Modifies the value of the `TxChunk` using the provided function.
 *
 * **Details**
 *
 * This function mutates the original TxChunk by updating its internal state. It does not return a
 * new TxChunk reference.
 *
 * **Example** (Modifying while returning a value)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([1, 2, 3])
 *
 *   // Modify and return both old size and new chunk
 *   const oldSize = yield* TxChunk.modify(txChunk, (chunk) => [
 *     Chunk.size(chunk), // return value (old size)
 *     Chunk.append(chunk, 4) // new value
 *   ])
 *
 *   console.log(oldSize) // 3
 *
 *   const newChunk = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(newChunk)) // [1, 2, 3, 4]
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const modify = /*#__PURE__*/dual(2, (self, f) => TxRef.modify(self.ref, f));
/**
 * Updates the value of the `TxChunk` using the provided function.
 *
 * **Details**
 *
 * This function mutates the original TxChunk by updating its internal state. It does not return a
 * new TxChunk reference.
 *
 * **Example** (Updating the stored chunk)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([1, 2, 3])
 *
 *   // Update the chunk by reversing it atomically
 *   yield* TxChunk.update(txChunk, (chunk) => Chunk.reverse(chunk))
 *
 *   const result = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(result)) // [3, 2, 1]
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const update = /*#__PURE__*/dual(2, (self, f) => TxRef.update(self.ref, f));
/**
 * Reads the current chunk from the `TxChunk`.
 *
 * **Example** (Reading the current chunk)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([1, 2, 3])
 *
 *   // Read the current value within a transaction
 *   const chunk = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(chunk)) // [1, 2, 3]
 *
 *   // The value is tracked for conflict detection
 *   const size = Chunk.size(chunk)
 *   console.log(size) // 3
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const get = self => TxRef.get(self.ref);
/**
 * Sets the value of the `TxChunk`.
 *
 * **Details**
 *
 * This function mutates the original TxChunk by replacing its internal state with the provided
 * chunk. It does not return a new TxChunk reference.
 *
 * **Example** (Replacing the stored chunk)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([1, 2, 3])
 *
 *   // Replace the entire chunk content
 *   const newChunk = Chunk.fromIterable([10, 20, 30, 40])
 *   yield* TxChunk.set(txChunk, newChunk)
 *
 *   const result = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(result)) // [10, 20, 30, 40]
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const set = /*#__PURE__*/dual(2, (self, chunk) => TxRef.set(self.ref, chunk));
/**
 * Appends an element to the end of the `TxChunk`.
 *
 * **Details**
 *
 * This function mutates the original TxChunk by adding the element to the end. It does not return a
 * new TxChunk reference.
 *
 * **Example** (Appending an element)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([1, 2, 3])
 *
 *   // Add element to the end atomically
 *   yield* TxChunk.append(txChunk, 4)
 *
 *   const result = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(result)) // [1, 2, 3, 4]
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const append = /*#__PURE__*/dual(2, (self, element) => update(self, current => Chunk.append(current, element)));
/**
 * Prepends an element to the beginning of the `TxChunk`.
 *
 * **Details**
 *
 * This function mutates the original TxChunk by adding the element to the beginning. It does not
 * return a new TxChunk reference.
 *
 * **Example** (Prepending an element)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([2, 3, 4])
 *
 *   // Add element to the beginning atomically
 *   yield* TxChunk.prepend(txChunk, 1)
 *
 *   const result = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(result)) // [1, 2, 3, 4]
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const prepend = /*#__PURE__*/dual(2, (self, element) => update(self, current => Chunk.prepend(current, element)));
/**
 * Gets the size of the `TxChunk`.
 *
 * **Example** (Getting the size)
 *
 * ```ts
 * import { Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([1, 2, 3, 4, 5])
 *
 *   // Get the current size - automatically transactional
 *   const currentSize = yield* TxChunk.size(txChunk)
 *   console.log(currentSize) // 5
 *
 *   // Size is tracked for conflict detection
 *   yield* TxChunk.append(txChunk, 6)
 *   const newSize = yield* TxChunk.size(txChunk)
 *   console.log(newSize) // 6
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const size = self => modify(self, current => [Chunk.size(current), current]);
/**
 * Checks whether the `TxChunk` is empty.
 *
 * **Example** (Checking for an empty chunk)
 *
 * ```ts
 * import { Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const emptyChunk = yield* TxChunk.empty<number>()
 *   const nonEmptyChunk = yield* TxChunk.fromIterable([1, 2, 3])
 *
 *   // Check if chunks are empty - automatically transactional
 *   const isEmpty1 = yield* TxChunk.isEmpty(emptyChunk)
 *   const isEmpty2 = yield* TxChunk.isEmpty(nonEmptyChunk)
 *
 *   console.log(isEmpty1) // true
 *   console.log(isEmpty2) // false
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const isEmpty = self => modify(self, current => [Chunk.isEmpty(current), current]);
/**
 * Checks whether the `TxChunk` is non-empty.
 *
 * **Example** (Checking for a non-empty chunk)
 *
 * ```ts
 * import { Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const emptyChunk = yield* TxChunk.empty<number>()
 *   const nonEmptyChunk = yield* TxChunk.fromIterable([1, 2, 3])
 *
 *   // Check if chunks are non-empty - automatically transactional
 *   const isNonEmpty1 = yield* TxChunk.isNonEmpty(emptyChunk)
 *   const isNonEmpty2 = yield* TxChunk.isNonEmpty(nonEmptyChunk)
 *
 *   console.log(isNonEmpty1) // false
 *   console.log(isNonEmpty2) // true
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const isNonEmpty = self => modify(self, current => [Chunk.isNonEmpty(current), current]);
/**
 * Takes the first `n` elements from the `TxChunk`.
 *
 * **Details**
 *
 * This function mutates the original TxChunk by keeping only the first n elements. It does not
 * return a new TxChunk reference.
 *
 * **Example** (Taking leading elements)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([1, 2, 3, 4, 5])
 *
 *   // Take only the first 3 elements - automatically transactional
 *   yield* TxChunk.take(txChunk, 3)
 *
 *   const result = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(result)) // [1, 2, 3]
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const take = /*#__PURE__*/dual(2, (self, n) => update(self, current => Chunk.take(current, n)));
/**
 * Drops the first `n` elements from the `TxChunk`.
 *
 * **Details**
 *
 * This function mutates the original TxChunk by removing the first n elements. It does not return a
 * new TxChunk reference.
 *
 * **Example** (Dropping leading elements)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([1, 2, 3, 4, 5])
 *
 *   // Drop the first 2 elements - automatically transactional
 *   yield* TxChunk.drop(txChunk, 2)
 *
 *   const result = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(result)) // [3, 4, 5]
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const drop = /*#__PURE__*/dual(2, (self, n) => update(self, current => Chunk.drop(current, n)));
/**
 * Takes a slice of the `TxChunk` from `start` to `end` (exclusive).
 *
 * **Details**
 *
 * This function mutates the original TxChunk by keeping only the elements in the specified range. It
 * does not return a new TxChunk reference.
 *
 * **Example** (Taking a slice)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([1, 2, 3, 4, 5, 6, 7])
 *
 *   // Take elements from index 2 to 5 (exclusive) - automatically transactional
 *   yield* TxChunk.slice(txChunk, 2, 5)
 *
 *   const result = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(result)) // [3, 4, 5]
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const slice = /*#__PURE__*/dual(3, (self, start, end) => update(self, current => Chunk.take(Chunk.drop(current, start), end - start)));
/**
 * Maps each element of the `TxChunk` using a function that returns the same
 * element type.
 *
 * **Details**
 *
 * This function mutates the original `TxChunk` by transforming each element in place. It does not
 * return a new `TxChunk` reference.
 *
 * **Example** (Mapping elements)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([1, 2, 3, 4])
 *
 *   // Transform each element atomically (must maintain same type)
 *   yield* TxChunk.map(txChunk, (n) => n * 2)
 *
 *   const result = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(result)) // [2, 4, 6, 8]
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const map = /*#__PURE__*/dual(2, (self, f) => update(self, current => Chunk.map(current, f)));
/**
 * Filters the `TxChunk` keeping only elements that satisfy the predicate.
 *
 * **Details**
 *
 * This function mutates the original TxChunk by removing elements that don't match the predicate. It
 * does not return a new TxChunk reference.
 *
 * **Example** (Filtering elements)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([1, 2, 3, 4, 5, 6])
 *
 *   // Keep only even numbers atomically
 *   yield* TxChunk.filter(txChunk, (n) => n % 2 === 0)
 *
 *   const result = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(result)) // [2, 4, 6]
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const filter = /*#__PURE__*/dual(2, (self, predicate) => update(self, current => Chunk.filter(current, predicate)));
/**
 * Concatenates another chunk to the end of the `TxChunk`.
 *
 * **Details**
 *
 * This function mutates the original TxChunk by appending all elements from the other chunk. It does
 * not return a new TxChunk reference.
 *
 * **Example** (Appending another chunk)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([1, 2, 3])
 *   const otherChunk = Chunk.fromIterable([4, 5, 6])
 *
 *   // Append all elements from another chunk atomically
 *   yield* TxChunk.appendAll(txChunk, otherChunk)
 *
 *   const result = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(result)) // [1, 2, 3, 4, 5, 6]
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const appendAll = /*#__PURE__*/dual(2, (self, other) => update(self, current => Chunk.appendAll(current, other)));
/**
 * Concatenates another chunk to the beginning of the `TxChunk`.
 *
 * **Details**
 *
 * This function mutates the original TxChunk by prepending all elements from the other chunk. It
 * does not return a new TxChunk reference.
 *
 * **Example** (Prepending another chunk)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk = yield* TxChunk.fromIterable([4, 5, 6])
 *   const otherChunk = Chunk.fromIterable([1, 2, 3])
 *
 *   // Prepend all elements from another chunk atomically
 *   yield* TxChunk.prependAll(txChunk, otherChunk)
 *
 *   const result = yield* TxChunk.get(txChunk)
 *   console.log(Chunk.toReadonlyArray(result)) // [1, 2, 3, 4, 5, 6]
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const prependAll = /*#__PURE__*/dual(2, (self, other) => update(self, current => Chunk.prependAll(current, other)));
/**
 * Concatenates another `TxChunk` to the end of this `TxChunk`.
 *
 * **Details**
 *
 * This function mutates the original TxChunk by appending all elements from the other TxChunk. It
 * does not return a new TxChunk reference.
 *
 * **Example** (Concatenating TxChunks)
 *
 * ```ts
 * import { Chunk, Effect, TxChunk } from "effect"
 *
 * const program = Effect.gen(function*() {
 *   const txChunk1 = yield* TxChunk.fromIterable([1, 2, 3])
 *   const txChunk2 = yield* TxChunk.fromIterable([4, 5, 6])
 *
 *   // Concatenate atomically within a transaction
 *   yield* TxChunk.concat(txChunk1, txChunk2)
 *
 *   const result = yield* TxChunk.get(txChunk1)
 *   console.log(Chunk.toReadonlyArray(result)) // [1, 2, 3, 4, 5, 6]
 *
 *   // Original txChunk2 is unchanged
 *   const original = yield* TxChunk.get(txChunk2)
 *   console.log(Chunk.toReadonlyArray(original)) // [4, 5, 6]
 * })
 * ```
 *
 * @category combinators
 * @since 4.0.0
 */
export const concat = /*#__PURE__*/dual(2, (self, other) => Effect.gen(function* () {
  const otherChunk = yield* get(other);
  yield* appendAll(self, otherChunk);
}).pipe(Effect.tx));
//# sourceMappingURL=TxChunk.js.map