Module: CoRE::CoAP::Coding

Included in:
CoRE::CoAP
Defined in:
lib/core/coap/coding.rb

Constant Summary collapse

BIN =
Encoding::BINARY
UTF8 =
Encoding::UTF_8
UNRESERVED =

Alphanumerics, '_', '-', '.', '~'

'\w\-\.~'
SUB_DELIM =
"!$&'()*+,;="
SUB_DELIM_NO_AMP =
SUB_DELIM.delete('&')
PATH_UNENCODED =
"#{UNRESERVED}#{SUB_DELIM}:@"
PATH_ENCODED_RE =
/[^#{PATH_UNENCODED}]/mn
QUERY_UNENCODED =
"#{UNRESERVED}#{SUB_DELIM_NO_AMP}:@/?"
QUERY_ENCODED_RE =
/[^#{QUERY_UNENCODED}]/mn

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object

Also extend on include.


21
22
23
# File 'lib/core/coap/coding.rb', line 21

def self.included(base)
  base.send :extend, Coding
end

Instance Method Details

#number_of_bits_up_to(n) ⇒ Object

n must be 2**k Returns k


74
75
76
77
# File 'lib/core/coap/coding.rb', line 74

def number_of_bits_up_to(n)
#       Math.frexp(n-1)[1]
  Math.log2(n).floor
end

#o256_decode(str) ⇒ Object


61
62
63
64
65
66
67
68
69
70
# File 'lib/core/coap/coding.rb', line 61

def o256_decode(str)
  num = 0

  str.each_byte do |b|
    num <<= 8
    num += b + 1
  end

  num
end

#o256_encode(num) ⇒ Object

Byte strings lexicographically goedelized as numbers (one+256 coding)


49
50
51
52
53
54
55
56
57
58
59
# File 'lib/core/coap/coding.rb', line 49

def o256_encode(num)
  str = empty_buffer

  while num > 0
    num -= 1
    str << (num & 0xFF)
    num >>= 8
  end

  str.reverse
end

#path_decode(path) ⇒ Object


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/core/coap/coding.rb', line 117

def path_decode(path)
  # Needs -1 to avoid eating trailing slashes!
  a = path.split('/', -1) 

  return a if a.empty?

  if a[0] != ''
    raise ArgumentError, "Path #{path.inspect} not starting with /"
  end

  # Special case for '/'
  return [] if a[1] == '' 

  a[1..-1].map { |el| percent_decode(el) }
end

#path_encode(uri_elements) ⇒ Object


99
100
101
102
# File 'lib/core/coap/coding.rb', line 99

def path_encode(uri_elements)
  return '/' if uri_elements.nil? || uri_elements.empty?
  '/' + uri_elements.map { |el| uri_encode_element(el, PATH_ENCODED_RE) }.join('/')
end

#percent_decode(el) ⇒ Object


113
114
115
# File 'lib/core/coap/coding.rb', line 113

def percent_decode(el)
  el.gsub(/%(..)/) { $1.to_i(16).chr(BIN) }.force_encoding(UTF8)
end

#query_decode(query) ⇒ Object


133
134
135
136
137
138
139
140
141
142
143
# File 'lib/core/coap/coding.rb', line 133

def query_decode(query)
  return [] if query.empty?

  query = query[1..-1] if query[0] == '?'

  a = query.split('&', -1).map do |el|
    el.gsub(/%(..)/) { $1.to_i(16).chr(BIN) }.force_encoding(UTF8)
  end

  a
end

#query_encode(query_elements) ⇒ Object


104
105
106
107
# File 'lib/core/coap/coding.rb', line 104

def query_encode(query_elements)
  return '' if query_elements.nil? || query_elements.empty?
  '?' + query_elements.map { |el| uri_encode_element(el, QUERY_ENCODED_RE) }.join('&')
end

#scheme_and_authority_decode(s) ⇒ Object


91
92
93
94
95
96
97
# File 'lib/core/coap/coding.rb', line 91

def scheme_and_authority_decode(s)
  if s =~ %r{\A(?:coap://)((?:\[|%5B)([^\]]*)(?:\]|%5D)|([^:/]*))(:(\d+))?(/.*)?\z}i
    host = $2 || $3       # Should check syntax...
    port = $5 || CoAP::PORT
    [$6, host, port.to_i]
  end
end

#scheme_and_authority_encode(host, port) ⇒ Object


79
80
81
82
83
84
85
86
87
88
89
# File 'lib/core/coap/coding.rb', line 79

def scheme_and_authority_encode(host, port)
  unless host =~ /\[.*\]/
    host = "[#{host}]" if host =~ /:/
  end

  port = Integer(port)

  scheme_and_authority = "coap://#{host}"
  scheme_and_authority << ":#{port}" unless port == CoAP::PORT
  scheme_and_authority
end

#uri_encode_element(el, re) ⇒ Object


109
110
111
# File 'lib/core/coap/coding.rb', line 109

def uri_encode_element(el, re)
  el.dup.force_encoding(BIN).gsub(re) { |x| "%%%02X" % x.ord }
end

#vlb_decode(s) ⇒ Object


42
43
44
45
46
# File 'lib/core/coap/coding.rb', line 42

def vlb_decode(s)
  n = 0
  s.each_byte { |b| n <<= 8; n += b }
  n
end

#vlb_encode(n) ⇒ Object

The variable-length binary (vlb) numbers defined in CoRE-CoAP Appendix A.


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/core/coap/coding.rb', line 26

def vlb_encode(n)
  n = Integer(n)
  v = empty_buffer

  if n < 0
    raise ArgumentError, "Can't encode negative number #{n}."
  end

  while n > 0
    v << (n & 0xFF)
    n >>= 8
  end

  v.reverse!
end