Module: RText::MessageHelper

Includes:
JsonInterface
Included in:
Frontend::Connector, Service
Defined in:
lib/rtext/message_helper.rb

Instance Method Summary collapse

Methods included from JsonInterface

#json_to_object, #object_to_json, set_j2o_converter, set_o2j_converter

Instance Method Details

#each_json_object_string(object, &block) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/rtext/message_helper.rb', line 68

def each_json_object_string(object, &block)
  if object.is_a?(Hash)
    object.each_pair do |k, v|
      # don't call block for hash keys
      each_json_object_string(v, &block)
    end
  elsif object.is_a?(Array)
    object.each do |v|
      each_json_object_string(v, &block)
    end
  elsif object.is_a?(String)
    yield(object)
  else
    # ignore
  end
end

#escape_all_strings(obj) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/rtext/message_helper.rb', line 41

def escape_all_strings(obj)
  each_json_object_string(obj) do |s|
    s.force_encoding("binary")
    bytes = s.bytes.to_a
    s.clear
    bytes.each do |b|
      if b >= 128 || b == 0x25 # %
        s << "%#{b.to_s(16)}".force_encoding("binary")
      else
        s << b.chr("binary")
      end
    end
    # there are no non ascii-7-bit characters left
    s.force_encoding("utf-8")
  end
end

#extract_message(data) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/rtext/message_helper.rb', line 18

def extract_message(data)
  # interpret input data as binary
  data.force_encoding("binary")
  obj = nil
  if data =~ /^(\d+)\{/
    length_length = $1.size
    length = $1.to_i
    if data.size >= length_length + length
      data.slice!(0..(length_length-1))
      json = data.slice!(0..length-1)
      # there shouldn't be any non ascii-7-bit characters, transcode just to be sure
      # encode from binary to utf-8 with :undef => :replace turns all non-ascii-7-bit bytes
      # into the replacement character (\uFFFD)
      json.encode!("utf-8", :undef => :replace)
      obj = json_to_object(json)
    end
  end
  if obj
    unescape_all_strings(obj)
  end
  obj
end

#serialize_message(obj) ⇒ Object



8
9
10
11
12
13
14
15
16
# File 'lib/rtext/message_helper.rb', line 8

def serialize_message(obj)
  escape_all_strings(obj)
  json = object_to_json(obj)
  # the JSON method outputs data in UTF-8 encoding
  # the RText protocol expects message lengths measured in bytes
  # there shouldn't be any non-ascii-7-bit characters, though, so json.size would also be ok
  json.prepend(json.bytesize.to_s) 
  json
end

#unescape_all_strings(obj) ⇒ Object



58
59
60
61
62
63
64
65
66
# File 'lib/rtext/message_helper.rb', line 58

def unescape_all_strings(obj)
  each_json_object_string(obj) do |s|
    # change encoding back to binary 
    # there could still be replacement characters (\uFFFD), turn them into "?"
    s.encode!("binary", :undef => :replace)
    s.gsub!(/%[0-9a-fA-F][0-9a-fA-F]/){|m| m[1..2].to_i(16).chr("binary")}
    s.force_encoding("binary")
  end
end