class ReeString::TruncateBytes

def call(str, truncate_at, **opts)

def call(str, truncate_at, **opts)
  str = str.dup
  omission = opts[:omission] || DEFAULT_OMISSION
  case
  when str.bytesize <= truncate_at
    str
  when omission.bytesize > truncate_at
    raise ArgumentError, "Omission #{omission.inspect} is #{omission.bytesize}, larger than the truncation length of #{truncate_at} bytes"
  when omission.bytesize == truncate_at
    omission.dup
  else
    String.new.tap do |cut|
      cut_at = truncate_at - omission.bytesize
      str.each_grapheme_cluster do |grapheme|
        if cut.bytesize + grapheme.bytesize <= cut_at
          cut << grapheme
        else
          break
        end
      end
      cut << omission
    end
  end
end