anchor.diff:      overlapping_blocks => blocks(),
       count => non_neg_integer(),
       skip_local => boolean()}.
  +% Definition of blocks sequence list - see get_overlapping_blocks_sequence/2 funstion doc
  +-type blocks_sequences() :: [{ConsistentBlocksRange :: blocks(), OverlappingBlocks :: blocks()}].
  +-type getting_sequence_block_result() :: #{
  +    action := finish | start_new_sequence,
  +    remaining_blocks_to_split := blocks(),
  +    blocks_to_split_sequence := blocks(),
  +    existing_blocks_overlapping_with_sequenc := blocks()
  +}.
   
   -export_type([block/0, blocks/0, blocks_tree/0, stored_blocks/0, get_doc_opts/0]).
   
  
positive.code:     set_blocks/2, set_final_blocks/2, update_blocks/2, clear_blocks/2]).
  %% Blocks API
  -export([get_location_size/2, get_blocks_range/1, get_blocks_range/2]).
  
  %%%===================================================================
  %%% Location getters/setters
  
negative.code:             Location#file_location{blocks = lists:sublist(Blocks, Num)}}};
          Error ->
              Error
      end.
  
  -spec get_block_seqences(blocks_tree(), gb_sets:iter(), non_neg_integer(), blocks()) -> blocks_sequences().
  get_block_seqences(ExistingBlocksTree, ExistingBlocksIterator, HoleSizeLimit, BlocksToSplitIntoSequences) ->
      #{
          blocks_to_split_sequence := BlocksToSplitSequence,
          existing_blocks_overlapping_with_sequenc := BlocksOverlappingWithSequence
      } = Answer = get_single_blocks_sequence(BlocksToSplitIntoSequences, [], % arguments connected with input sequence
      ExistingBlocksIterator, [], [], % arguments connected with existing blocks
      0, HoleSizeLimit), % arguments connected with whole size control
  
      SequenceDescription = {BlocksToSplitSequence, BlocksOverlappingWithSequence},
      case Answer of
          #{action := finish, remaining_blocks_to_split := []} ->
              [SequenceDescription];
          #{action := finish, remaining_blocks_to_split := RemainingBlocksToSplit} ->
              [SequenceDescription, {RemainingBlocksToSplit, []}];
          #{action := start_new_sequence, remaining_blocks_to_split := [#file_block{offset = Offset} | _] = NewBlocksToSplitIntoSequences} ->
              ExistingBlocksNextIterator = gb_sets:iterator_from(#file_block{offset = Offset, size = 0}, ExistingBlocksTree),
              [SequenceDescription | get_block_seqences(ExistingBlocksTree, ExistingBlocksNextIterator, HoleSizeLimit, NewBlocksToSplitIntoSequences)]
      end.
  
  -spec get_single_blocks_sequence(blocks(), blocks(), gb_sets:iter(), blocks(), blocks(),
      non_neg_integer(), non_neg_integer()) -> getting_sequence_block_result().
  get_single_blocks_sequence([], BlocksInCurrentSequence, % arguments connected with input sequence
      _ExistingBlocksIterator, ExistingBlocksOverlappingWithCurrentSequence, _SkippedExistingBlocks, % arguments connected with existing blocks
      _CurrentHoleSize, _HoleSizeLimit % arguments connected with whole size control
  ) ->
      #{action => finish, remaining_blocks_to_split => [],
          blocks_to_split_sequence => lists:reverse(BlocksInCurrentSequence),
          existing_blocks_overlapping_with_sequenc => ExistingBlocksOverlappingWithCurrentSequence};
  get_single_blocks_sequence([Block | BlocksToSplitIntoSequencesTail], BlocksInCurrentSequence, % arguments connected with input sequence
      _ExistingBlocksIterator, ExistingBlocksOverlappingWithCurrentSequence, _SkippedExistingBlocks, % arguments connected with existing blocks
      HoleSizeLimit, HoleSizeLimit % arguments connected with whole size control
  ) ->
      #{action => start_new_sequence, remaining_blocks_to_split => BlocksToSplitIntoSequencesTail,
          blocks_to_split_sequence => lists:reverse([Block | BlocksInCurrentSequence]),
          existing_blocks_overlapping_with_sequenc => ExistingBlocksOverlappingWithCurrentSequence};
  get_single_blocks_sequence([Block | BlocksToSplitIntoSequencesTail] = BlocksToSplitIntoSequences, BlocksInCurrentSequence, % arguments connected with input sequence
      ExistingBlocksIterator, ExistingBlocksOverlappingWithCurrentSequence, SkippedExistingBlocks, % arguments connected with existing blocks
      CurrentHoleSize, HoleSizeLimit % arguments connected with whole size control
  ) ->
      case gb_sets:next(ExistingBlocksIterator) of
          none ->
              #{action => finish, remaining_blocks_to_split => BlocksToSplitIntoSequencesTail,
                  blocks_to_split_sequence => lists:reverse([Block | BlocksInCurrentSequence]),
                  existing_blocks_overlapping_with_sequenc => ExistingBlocksOverlappingWithCurrentSequence};
          {ExistingBlock, ExistingBlocksNextIterator} ->
              {NewBlocksToSplitIntoSequences, NewBlocksInCurrentSequence,
                  NewExistingOverlappingBlocks, NewSkippedExistingBlocks,
                  NewCurrentHoleSize} =
                  add_blocks_to_sequence(BlocksToSplitIntoSequences, BlocksInCurrentSequence,
                      ExistingBlock, SkippedExistingBlocks,
                      CurrentHoleSize),
              get_single_blocks_sequence(NewBlocksToSplitIntoSequences, NewBlocksInCurrentSequence,
                  ExistingBlocksNextIterator, ExistingBlocksOverlappingWithCurrentSequence ++ NewExistingOverlappingBlocks, NewSkippedExistingBlocks,
                  NewCurrentHoleSize, HoleSizeLimit)
      end.
  
  -spec add_blocks_to_sequence(blocks(), blocks(), block(), blocks(), non_neg_integer()) ->
      {blocks(), blocks(), blocks(), blocks(), non_neg_integer()}.
  add_blocks_to_sequence([], BlocksInCurrentSequence, % arguments connected with input sequence
      _ExistingBlock, SkippedExistingBlocks, % arguments connected with existing blocks
      CurrentHoleSize % argument connected with whole size control
  ) ->
      {[], BlocksInCurrentSequence, [], SkippedExistingBlocks, CurrentHoleSize};
  add_blocks_to_sequence(BlocksToSplitIntoSequences, BlocksInCurrentSequence, % arguments connected with input sequence
      ExistingBlock, SkippedExistingBlocks, % arguments connected with existing blocks
      CurrentHoleSize % argument connected with whole size control
  ) ->
      [#file_block{offset = Offset, size = Size} = Block | BlocksToSplitIntoSequencesTail] = BlocksToSplitIntoSequences,
      End = Offset + Size,
      #file_block{offset = ExistingBlockEnd, size = ExistingBlockSize} = ExistingBlock,
      ExistingBlockOffset = ExistingBlockEnd - ExistingBlockSize,
  
      case {ExistingBlockOffset =< End, ExistingBlockEnd < Offset} of
          {true, true} ->
              {BlocksToSplitIntoSequences, BlocksInCurrentSequence,
                  [], SkippedExistingBlocks ++ [#file_block{offset = ExistingBlockOffset, size = ExistingBlockSize}],
                  CurrentHoleSize + 1};
          {true, false} ->
              {BlocksToSplitIntoSequences, BlocksInCurrentSequence,
                      SkippedExistingBlocks ++ [#file_block{offset = ExistingBlockOffset, size = ExistingBlockSize}], [],
                  0};
          _ ->
              add_blocks_to_sequence(BlocksToSplitIntoSequencesTail, [Block | BlocksInCurrentSequence],
                  ExistingBlock, SkippedExistingBlocks,
                  CurrentHoleSize)
      end.