code: def _decompose_and_get_unitary(val: Union['cirq.Operation', 'cirq.Gate']
                                 ) -> np.ndarray:
      
      from cirq.protocols.apply_unitary import apply_unitary, ApplyUnitaryArgs
      from cirq.protocols.decompose import (decompose_once,
                                            decompose_once_with_qubits)
      from cirq import Gate, LineQubit, Operation
  
      if isinstance(val, Operation):
          qubits = val.qubits
          decomposed_val = decompose_once(val, default=None)
      elif isinstance(val, Gate):
          # Since gates don't know about qubits, we need to create some
          qubits = tuple(LineQubit.range(val.num_qubits()))
          decomposed_val = decompose_once_with_qubits(val,
                                                      qubits,
                                                      default=None)
  
      if decomposed_val is not None:
          # Calculate the resulting unitary (if it exists)
          n = len(qubits)
          state = np.eye(1 << n, dtype=np.complex128)
          state.shape = (2,) * (2 * n)
          buffer = np.zeros(state.shape, dtype=np.complex128)
          qubit_map = {q: i for i, q in enumerate(qubits)}
          result = state
          for op in decomposed_val:
              indices = [qubit_map[q] for q in op.qubits]
              result = apply_unitary(
                  unitary_value=op,
                  args=ApplyUnitaryArgs(state, buffer, indices),
                  default=None)
              if result is None:
                  return None
              if result is buffer:
                  buffer = state
              state = result
          if result is not None:
              return result.reshape((1 << n, 1 << n))
docs: Try to decompose a cirq.Operation or cirq.Gate, and return its unitary
      if it exists.
  
      Returns:
          If `val` can be decomposed into unitaries, calculate the resulting
          unitary and return it. If it doesn't exist, None is returned.