Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save floere/2958016 to your computer and use it in GitHub Desktop.
Save floere/2958016 to your computer and use it in GitHub Desktop.
Coroutines are excellent for encoding state machines. See http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/
# Encoding: UTF-8
#
require 'fiber'
# This accepts generated frames and prints them.
#
target = Fiber.new do
loop do
frame = Fiber.yield
puts "Frame received: #{frame}."
end
end
target.resume
# This decodes frames and transfers control to the return value of the
# first yield, which should be a fiber that handles results.
#
def decoder_with_options options = {}
header = options[:header] || 0x61
footer = options[:footer] || 0x62
dle = options[:dle] || 0xAB
after_dle = options[:after_dle] || (->(x) { x.to_s(16) })
payload = options[:payload] || (->(x) { x.to_s(16) })
Fiber.new do |target|
loop do
part = Fiber.yield
frame = ''
if part == header
loop do
part = Fiber.yield
case part
when footer
target.resume frame
break
when dle
part = Fiber.yield
frame += after_dle[part]
else
frame += payload[part]
end
end
end
end
end
end
decoder = decoder_with_options header: "61",
footer: "62",
dle: "AB",
after_dle: ->(x) { x },
payload: ->(x) { x }
decoder.resume(target)
["70", "24",
"61", "99", "AF", "D1", "62",
"56", "62",
"61", "AB", "AB", "14", "62",
"7"].each do |thing|
decoder.resume thing
end
decoder = decoder_with_options
decoder.resume target
[0x70, 0x24,
0x61, 0x99, 0xAF, 0xD1, 0x62,
0x56, 0x62,
0x61, 0xAB, 0xAB, 0x14, 0x62,
0x7].each do |byte|
decoder.resume byte
end
parts = [0x70, 0x24,
0x61, 0x99, 0xAF, 0xD1, 0x62,
0x56, 0x62,
0x61, 0xAB, 0xAB, 0x14, 0x62,
0x7]
100.times { decoder.resume parts.sample }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment