Class: Acrofill::Serializer

Inherits:
Object
  • Object
show all
Defined in:
lib/acrofill/serializer.rb

Overview

Serializes Ruby values (as produced by pdf-reader) back into PDF syntax. References are renumbered through the map supplied by the Writer.

Constant Summary collapse

REGULAR_NAME_CHAR =

PDF "regular characters": printable ASCII minus whitespace, the delimiters ( ) < > [ ] { } / % and the name-escape character #.

%r{[!-~&&[^()<>\[\]{}/%#]]}
REGULAR_NAME =
/\A#{REGULAR_NAME_CHAR.source}+\z/
MAX_DEPTH =
200

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(oid_map) ⇒ Serializer

Returns a new instance of Serializer.



22
23
24
# File 'lib/acrofill/serializer.rb', line 22

def initialize(oid_map)
  @oid_map = oid_map
end

Class Method Details

.format_number(num) ⇒ Object



13
14
15
16
17
18
19
20
# File 'lib/acrofill/serializer.rb', line 13

def self.format_number(num)
  # PDF has no syntax for infinity/NaN, and #to_i on them raises;
  # a non-finite number can only come from malformed input, so clamp.
  return '0' unless num.finite?
  return num.to_i.to_s if num == num.to_i

  format('%.5f', num).sub(/\.?0+\z/, '')
end

Instance Method Details

#serialize(obj, depth = 0) ⇒ Object

Raises:



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/acrofill/serializer.rb', line 26

def serialize(obj, depth = 0)
  # Bound recursion: a pathologically nested array/dict from malformed
  # input would otherwise overflow the stack.
  raise Error, 'object nesting too deep' if depth > MAX_DEPTH

  case obj
  when PDF::Reader::Reference
    oid = @oid_map[obj.id]
    oid ? "#{oid} 0 R" : 'null'
  when Hash then serialize_dict(obj, depth)
  when Array then "[#{obj.map { |el| serialize(el, depth + 1) }.join(' ')}]"
  when Symbol then serialize_name(obj)
  when String then serialize_string(obj)
  when Integer then obj.to_s
  when Float then self.class.format_number(obj)
  when TrueClass then 'true'
  when FalseClass then 'false'
  when NilClass then 'null'
  else
    raise Error, "cannot serialize #{obj.class}"
  end
end