Skip to content

Instantly share code, notes, and snippets.

@kschiess
Created June 19, 2012 15:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kschiess/2954735 to your computer and use it in GitHub Desktop.
Save kschiess/2954735 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'
HEADER = 0x61
FOOTER = 0x62
DLE = 0xAB
def after_dle(x)
x
end
# 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.
decoder = Fiber.new do |target|
loop do
byte = Fiber.yield
frame = ''
if byte == HEADER
loop do
byte = Fiber.yield
case byte
when FOOTER
target.resume(frame)
break
when DLE
byte = Fiber.yield
frame += after_dle(byte).to_s(16)
else
frame += byte.to_s(16)
end
end
end
end
end
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
@kschiess
Copy link
Author

Frame received: 99afd1.
Frame received: ab14.

@floere
Copy link

floere commented Jun 20, 2012

Extremely elegantly decoupled. Like it a lot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment