All files / src/codec/edges ops.ts

100% Statements 35/35
100% Branches 11/11
100% Functions 6/6
100% Lines 35/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 891x                 1x 172x 172x 172x             1x 1x 41x               1x 1431x 1431x 1431x 1431x         1431x 1431x 1431x 1431x 1431x 1431x 1431x 1431x 1431x             1x 1x 1431x             1x   1x 1x             1x   1x 1x               1x   1x 1x 1x  
import {Array, Equivalence, HashMap, HashSet, Option, pipe, Tuple} from 'effect'
import type {NonEmptyArray} from 'effect/Array'
import type {EdgeList, EdgeMap, TreeEdge} from './types.js'
 
/**
 * A tree edge for the root node: parent is `None`.
 * @category internal
 * @function
 */
export const rootTreeEdge = <A>(child: A): [A, Option.Option<A>] => [
  child,
  Option.none(),
]
 
/**
 * Set a parent on a non-root tree edge.
 * @category internal
 * @function
 */
export const setParent: <A>(a: A) => (edge: TreeEdge<A>) => TreeEdge<A> =
  a =>
  ([head]) => [head, Option.some(a)]
 
/**
 * Assert the edge map has a single root and return a pair of the root and its
 * possibly empty list of children.
 * @category internal
 * @function
 */
export const getMapChildren = <A>({
  roots,
  toChildren,
}: EdgeMap<A>): [A, A[]] => {
  const [root] = HashSet.values(roots)
  /* v8 ignore next 2 */
  if (root === undefined) throw new Error('Edge map |roots|=0')
  if (HashSet.size(roots) !== 1) throw new Error('Edge map |roots|≠1')
 
  return [
    root,
    pipe(
      toChildren,
      HashMap.get(root),
      Option.getOrElse(() => []),
    ),
  ]
}
 
/**
 * Sets the roots of the edge map to a single root.
 * @category internal
 * @function
 */
export const setMapRoot =
  <A>(map: EdgeMap<A>) =>
  (root: A): EdgeMap<A> => ({...map, roots: HashSet.fromIterable([root])})
 
/**
 * Given an equivalence of `A`, return an equivalence of `TreeEdge<A>`.
 * @category internal
 * @function
 */
export const getEdgeEquivalence: <A>(
  equalsA: Equivalence.Equivalence<A>,
) => Equivalence.Equivalence<TreeEdge<A>> = equalsA =>
  Tuple.getEquivalence(equalsA, Option.getEquivalence(equalsA))
 
/**
 * Given an equivalence of `A`, return an equivalence of `EdgeList<A>`.
 * @category internal
 * @function
 */
export const getEdgeListEquivalence: <A>(
  equalsA: Equivalence.Equivalence<A>,
) => Equivalence.Equivalence<EdgeList<A>> = equalsA =>
  pipe(equalsA, getEdgeEquivalence, Array.getEquivalence)
 
/**
 * Convert a numeric edge list into a list of numeric pairs.
 * Root node edge will appear as `[1, 0]`.
 * @category internal
 * @function
 */
export const numeric: (
  edges: EdgeList<number>,
) => NonEmptyArray<[number, number]> = Array.map(
  Tuple.mapSecond(Option.getOrElse(() => 0)),
)