class Plumb::Pipeline

def around(callable = nil, &block)

def around(callable = nil, &block)
  around_blocks << (callable || block)
  self
end

def around(callable = nil, &block)

def around(callable = nil, &block)
  @around_blocks << (callable || block)
  self
end

def around_blocks

def around_blocks
  @around_blocks ||= []
end

def call(result)

def call(result)
  @type.call(result)
end

def configure(&setup)

def configure(&setup)
  case setup.arity
  when 1
    setup.call(self)
  when 0
    instance_eval(&setup)
  else
    raise ArgumentError, 'setup block must have arity of 0 or 1'
  end
end

def inherited(subclass)

def inherited(subclass)
  around_blocks.each { |block| subclass.around(block) }
  super
end

def initialize(type: Types::Any, freeze_after: true, &setup)

def initialize(type: Types::Any, freeze_after: true, &setup)
  @type = type
  @children = [type].freeze
  @around_blocks = self.class.around_blocks.dup
  return unless block_given?
  configure(&setup)
  freeze if freeze_after
end

def is_a_step?(callable)

def is_a_step?(callable)
  return false unless callable.respond_to?(:call)
  true
end

def prepare_step(callable) = callable

def prepare_step(callable) = callable

def step(callable = nil, &block)

def step(callable = nil, &block)
  callable ||= block
  unless is_a_step?(callable)
    raise ArgumentError,
          "#step expects an interface #call(Result) Result, but got #{callable.inspect}"
  end
  callable = prepare_step(callable)
  callable = @around_blocks.reverse.reduce(callable) { |cl, bl| AroundStep.new(cl, bl) } if @around_blocks.any?
  @type >>= callable
  self
end