A simple and efficient packet frame encoder/decoder

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
0
down vote

favorite












I have written a simple packet-framing class, for converting un-encoded 'packets' into encoded/delimited 'frames,' to be sent over a P2P serial connection. The functionality is based on the RFC 1662 "Point-to-Point" protocol, and the general design was inspired by the article "Framing in Serial Communications" by Eli Bendersky.



One notable departure from the design in the article: this implementation has opted to use a single 'frame terminator' byte at the end, rather than separate 'begin/end' bytes.



The code leverages template arguments and standard iterator; users can choose to use whichever standard container is appropriate for their environment. In particular, it is an ideal utility for use in a (C++11-compatible) embedded environment - a fixed-size array with standard 'inserter' iterator support can be used.



#pragma once
#include <cstdint>

// The simple_frame_encoding class provides packet/frame encoding and decoding, using a simple
// framing strategy with the following rules:
//
// - The end of an input packet is suffixed with the "frame separator" reserved byte.
// - Any occurrences of incidental 'reserved bytes' within the input packet are escaped:
// - The reserved byte is prefixed with the "escape" reserved byte (signaling that the next byte must be decoded).
// - The reserved byte is XOR'd using the "XOR encode" byte.
//
// When decoding, the reserve strategy is employed:
// - Append bytes to the decoded packet
// - When the 'escape' is encountered, make sure the next byte is 'decoded' (XOR) before appending
// - The frame is complete once the 'frame separator' is encountered
template<std::uint8_t FrameSeparator, std::uint8_t Escape, std::uint8_t XorEncode>
class simple_frame_encoding final
public:

// Ensure none of the 'reserved' bytes (separator, escape) conflict with encoded versions of the same
static_assert((FrameSeparator ^ XorEncode) != FrameSeparator, "Encoded byte conflict: the encoded 'FrameSeparator' byte is equal to the unencoded 'FrameSeparator' byte");
static_assert((FrameSeparator ^ XorEncode) != Escape, "Encoded byte conflict: the encoded 'FrameSeparator' byte is equal to the unencoded 'Escape' byte");
static_assert((Escape ^ XorEncode) != FrameSeparator, "Encoded byte conflict: the encoded 'Escape' byte is equal to the unencoded 'FrameSeparator' byte");
static_assert((Escape ^ XorEncode) != Escape, "Encoded byte conflict: the encoded 'Escape' byte is equal to the unencoded 'Escape' byte");

simple_frame_encoding() = default;
~simple_frame_encoding() = default;

// Iterate over the specified packet range, encoding the contents
// and inserting the resulting 'encoded' frame bytes in the 'output' inserter.
template<typename TInputIter, typename TInserter>
void encode(TInputIter first, TInputIter last, TInserter output)
// Append each byte to the encoded packet;
// ensure any 'reserved' bytes are XOR'd, and prepended with an escape character
while (first != last)
if (is_reserved(*first))
*output++ = Escape;
*output++ = (*first ^= XorEncode);

else
*output++ = *first;

first++;


// Append the frame separator, after the contents
*output++ = FrameSeparator;


// Frame decoding occurs over a stream of individual bytes, and tracks internal state;
// the decoder class encapsulates the current frame-decoding state into a self-contained class.
// The decoder is fed with individual 'encoded' bytes, automatically decoding
// them and inserting them into a 'decoded' packet structure, as appropriate.
class decoder
public:
// Decode the next byte, appending the result to the output iterator.
// Return true if the packet is 'complete.'
template<typename TInserter>
bool decode_next_byte(std::uint8_t byte, TInserter output)
// If we encounter the 'escape' byte, mark the next byte for decoding
// and return *without* appending
if (byte == Escape)
decode_next_byte_ = true;
return false;


// If we encounter the 'separator' byte, then the packet is done!
// Return true and reset the state.
if (byte == FrameSeparator)
reset();
return true;


// If the previous byte was an 'escape' char,
// decode this byte before adding it to the packet
if (decode_next_byte_)
byte ^= XorEncode;
decode_next_byte_ = false;


// If we reach this point, simply append the byte to the packet in progress...
*output++ = byte;
return false;


void reset()
decode_next_byte_ = false;

private:
bool decode_next_byte_ = false;
;

// Create and return an instance of a frame decoder, for the current encoding
decoder create_decoder()
return decoder();


protected:
// Determine if a given byte is reserved by the FrameSeparator or Escape characters
static bool is_reserved(std::uint8_t byte)
return byte == FrameSeparator
;

// Default frame encoding, effectively matching RFC 1662, the point-to-point protocol.
using default_simple_frame_encoding = simple_frame_encoding<0x7E, 0x7D, 0x20>;


When decoding: the decode_next_packet function will return true when the frame delimiter was found. This indicates the packet is 'complete' and should be dispatched to the next layer of application code.



Users are left to clear their own 'in progress' packet buffer, prior to receiving the next byte.



Example usage when encoding a packet to be sent over the wire:



auto packet = vector<uint8_t> 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F ;
vector<uint8_t> frame;

auto encoding = default_simple_frame_encoding();
encoding.encode(begin(packet), end(packet), back_inserter(frame));

serialPort.send(frame);


Example usage, when receiving a stream of frame-encoded bytes:



auto encoding = default_simple_frame_encoding();
auto decoder = encoding.create_decoder();
uint8_t nextByte = 0;
static_buffer packet;
while (serialPort.waitNextByte(nextByte))
if(decoder.decode_next_byte(nextByte, back_inserter(packet))
dispatch_completed_packet(packet);
packet.clear();




I am looking for any and all criticisms on style, efficiency, reusability, and readability.







share|improve this question



























    up vote
    0
    down vote

    favorite












    I have written a simple packet-framing class, for converting un-encoded 'packets' into encoded/delimited 'frames,' to be sent over a P2P serial connection. The functionality is based on the RFC 1662 "Point-to-Point" protocol, and the general design was inspired by the article "Framing in Serial Communications" by Eli Bendersky.



    One notable departure from the design in the article: this implementation has opted to use a single 'frame terminator' byte at the end, rather than separate 'begin/end' bytes.



    The code leverages template arguments and standard iterator; users can choose to use whichever standard container is appropriate for their environment. In particular, it is an ideal utility for use in a (C++11-compatible) embedded environment - a fixed-size array with standard 'inserter' iterator support can be used.



    #pragma once
    #include <cstdint>

    // The simple_frame_encoding class provides packet/frame encoding and decoding, using a simple
    // framing strategy with the following rules:
    //
    // - The end of an input packet is suffixed with the "frame separator" reserved byte.
    // - Any occurrences of incidental 'reserved bytes' within the input packet are escaped:
    // - The reserved byte is prefixed with the "escape" reserved byte (signaling that the next byte must be decoded).
    // - The reserved byte is XOR'd using the "XOR encode" byte.
    //
    // When decoding, the reserve strategy is employed:
    // - Append bytes to the decoded packet
    // - When the 'escape' is encountered, make sure the next byte is 'decoded' (XOR) before appending
    // - The frame is complete once the 'frame separator' is encountered
    template<std::uint8_t FrameSeparator, std::uint8_t Escape, std::uint8_t XorEncode>
    class simple_frame_encoding final
    public:

    // Ensure none of the 'reserved' bytes (separator, escape) conflict with encoded versions of the same
    static_assert((FrameSeparator ^ XorEncode) != FrameSeparator, "Encoded byte conflict: the encoded 'FrameSeparator' byte is equal to the unencoded 'FrameSeparator' byte");
    static_assert((FrameSeparator ^ XorEncode) != Escape, "Encoded byte conflict: the encoded 'FrameSeparator' byte is equal to the unencoded 'Escape' byte");
    static_assert((Escape ^ XorEncode) != FrameSeparator, "Encoded byte conflict: the encoded 'Escape' byte is equal to the unencoded 'FrameSeparator' byte");
    static_assert((Escape ^ XorEncode) != Escape, "Encoded byte conflict: the encoded 'Escape' byte is equal to the unencoded 'Escape' byte");

    simple_frame_encoding() = default;
    ~simple_frame_encoding() = default;

    // Iterate over the specified packet range, encoding the contents
    // and inserting the resulting 'encoded' frame bytes in the 'output' inserter.
    template<typename TInputIter, typename TInserter>
    void encode(TInputIter first, TInputIter last, TInserter output)
    // Append each byte to the encoded packet;
    // ensure any 'reserved' bytes are XOR'd, and prepended with an escape character
    while (first != last)
    if (is_reserved(*first))
    *output++ = Escape;
    *output++ = (*first ^= XorEncode);

    else
    *output++ = *first;

    first++;


    // Append the frame separator, after the contents
    *output++ = FrameSeparator;


    // Frame decoding occurs over a stream of individual bytes, and tracks internal state;
    // the decoder class encapsulates the current frame-decoding state into a self-contained class.
    // The decoder is fed with individual 'encoded' bytes, automatically decoding
    // them and inserting them into a 'decoded' packet structure, as appropriate.
    class decoder
    public:
    // Decode the next byte, appending the result to the output iterator.
    // Return true if the packet is 'complete.'
    template<typename TInserter>
    bool decode_next_byte(std::uint8_t byte, TInserter output)
    // If we encounter the 'escape' byte, mark the next byte for decoding
    // and return *without* appending
    if (byte == Escape)
    decode_next_byte_ = true;
    return false;


    // If we encounter the 'separator' byte, then the packet is done!
    // Return true and reset the state.
    if (byte == FrameSeparator)
    reset();
    return true;


    // If the previous byte was an 'escape' char,
    // decode this byte before adding it to the packet
    if (decode_next_byte_)
    byte ^= XorEncode;
    decode_next_byte_ = false;


    // If we reach this point, simply append the byte to the packet in progress...
    *output++ = byte;
    return false;


    void reset()
    decode_next_byte_ = false;

    private:
    bool decode_next_byte_ = false;
    ;

    // Create and return an instance of a frame decoder, for the current encoding
    decoder create_decoder()
    return decoder();


    protected:
    // Determine if a given byte is reserved by the FrameSeparator or Escape characters
    static bool is_reserved(std::uint8_t byte)
    return byte == FrameSeparator
    ;

    // Default frame encoding, effectively matching RFC 1662, the point-to-point protocol.
    using default_simple_frame_encoding = simple_frame_encoding<0x7E, 0x7D, 0x20>;


    When decoding: the decode_next_packet function will return true when the frame delimiter was found. This indicates the packet is 'complete' and should be dispatched to the next layer of application code.



    Users are left to clear their own 'in progress' packet buffer, prior to receiving the next byte.



    Example usage when encoding a packet to be sent over the wire:



    auto packet = vector<uint8_t> 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F ;
    vector<uint8_t> frame;

    auto encoding = default_simple_frame_encoding();
    encoding.encode(begin(packet), end(packet), back_inserter(frame));

    serialPort.send(frame);


    Example usage, when receiving a stream of frame-encoded bytes:



    auto encoding = default_simple_frame_encoding();
    auto decoder = encoding.create_decoder();
    uint8_t nextByte = 0;
    static_buffer packet;
    while (serialPort.waitNextByte(nextByte))
    if(decoder.decode_next_byte(nextByte, back_inserter(packet))
    dispatch_completed_packet(packet);
    packet.clear();




    I am looking for any and all criticisms on style, efficiency, reusability, and readability.







    share|improve this question























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I have written a simple packet-framing class, for converting un-encoded 'packets' into encoded/delimited 'frames,' to be sent over a P2P serial connection. The functionality is based on the RFC 1662 "Point-to-Point" protocol, and the general design was inspired by the article "Framing in Serial Communications" by Eli Bendersky.



      One notable departure from the design in the article: this implementation has opted to use a single 'frame terminator' byte at the end, rather than separate 'begin/end' bytes.



      The code leverages template arguments and standard iterator; users can choose to use whichever standard container is appropriate for their environment. In particular, it is an ideal utility for use in a (C++11-compatible) embedded environment - a fixed-size array with standard 'inserter' iterator support can be used.



      #pragma once
      #include <cstdint>

      // The simple_frame_encoding class provides packet/frame encoding and decoding, using a simple
      // framing strategy with the following rules:
      //
      // - The end of an input packet is suffixed with the "frame separator" reserved byte.
      // - Any occurrences of incidental 'reserved bytes' within the input packet are escaped:
      // - The reserved byte is prefixed with the "escape" reserved byte (signaling that the next byte must be decoded).
      // - The reserved byte is XOR'd using the "XOR encode" byte.
      //
      // When decoding, the reserve strategy is employed:
      // - Append bytes to the decoded packet
      // - When the 'escape' is encountered, make sure the next byte is 'decoded' (XOR) before appending
      // - The frame is complete once the 'frame separator' is encountered
      template<std::uint8_t FrameSeparator, std::uint8_t Escape, std::uint8_t XorEncode>
      class simple_frame_encoding final
      public:

      // Ensure none of the 'reserved' bytes (separator, escape) conflict with encoded versions of the same
      static_assert((FrameSeparator ^ XorEncode) != FrameSeparator, "Encoded byte conflict: the encoded 'FrameSeparator' byte is equal to the unencoded 'FrameSeparator' byte");
      static_assert((FrameSeparator ^ XorEncode) != Escape, "Encoded byte conflict: the encoded 'FrameSeparator' byte is equal to the unencoded 'Escape' byte");
      static_assert((Escape ^ XorEncode) != FrameSeparator, "Encoded byte conflict: the encoded 'Escape' byte is equal to the unencoded 'FrameSeparator' byte");
      static_assert((Escape ^ XorEncode) != Escape, "Encoded byte conflict: the encoded 'Escape' byte is equal to the unencoded 'Escape' byte");

      simple_frame_encoding() = default;
      ~simple_frame_encoding() = default;

      // Iterate over the specified packet range, encoding the contents
      // and inserting the resulting 'encoded' frame bytes in the 'output' inserter.
      template<typename TInputIter, typename TInserter>
      void encode(TInputIter first, TInputIter last, TInserter output)
      // Append each byte to the encoded packet;
      // ensure any 'reserved' bytes are XOR'd, and prepended with an escape character
      while (first != last)
      if (is_reserved(*first))
      *output++ = Escape;
      *output++ = (*first ^= XorEncode);

      else
      *output++ = *first;

      first++;


      // Append the frame separator, after the contents
      *output++ = FrameSeparator;


      // Frame decoding occurs over a stream of individual bytes, and tracks internal state;
      // the decoder class encapsulates the current frame-decoding state into a self-contained class.
      // The decoder is fed with individual 'encoded' bytes, automatically decoding
      // them and inserting them into a 'decoded' packet structure, as appropriate.
      class decoder
      public:
      // Decode the next byte, appending the result to the output iterator.
      // Return true if the packet is 'complete.'
      template<typename TInserter>
      bool decode_next_byte(std::uint8_t byte, TInserter output)
      // If we encounter the 'escape' byte, mark the next byte for decoding
      // and return *without* appending
      if (byte == Escape)
      decode_next_byte_ = true;
      return false;


      // If we encounter the 'separator' byte, then the packet is done!
      // Return true and reset the state.
      if (byte == FrameSeparator)
      reset();
      return true;


      // If the previous byte was an 'escape' char,
      // decode this byte before adding it to the packet
      if (decode_next_byte_)
      byte ^= XorEncode;
      decode_next_byte_ = false;


      // If we reach this point, simply append the byte to the packet in progress...
      *output++ = byte;
      return false;


      void reset()
      decode_next_byte_ = false;

      private:
      bool decode_next_byte_ = false;
      ;

      // Create and return an instance of a frame decoder, for the current encoding
      decoder create_decoder()
      return decoder();


      protected:
      // Determine if a given byte is reserved by the FrameSeparator or Escape characters
      static bool is_reserved(std::uint8_t byte)
      return byte == FrameSeparator
      ;

      // Default frame encoding, effectively matching RFC 1662, the point-to-point protocol.
      using default_simple_frame_encoding = simple_frame_encoding<0x7E, 0x7D, 0x20>;


      When decoding: the decode_next_packet function will return true when the frame delimiter was found. This indicates the packet is 'complete' and should be dispatched to the next layer of application code.



      Users are left to clear their own 'in progress' packet buffer, prior to receiving the next byte.



      Example usage when encoding a packet to be sent over the wire:



      auto packet = vector<uint8_t> 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F ;
      vector<uint8_t> frame;

      auto encoding = default_simple_frame_encoding();
      encoding.encode(begin(packet), end(packet), back_inserter(frame));

      serialPort.send(frame);


      Example usage, when receiving a stream of frame-encoded bytes:



      auto encoding = default_simple_frame_encoding();
      auto decoder = encoding.create_decoder();
      uint8_t nextByte = 0;
      static_buffer packet;
      while (serialPort.waitNextByte(nextByte))
      if(decoder.decode_next_byte(nextByte, back_inserter(packet))
      dispatch_completed_packet(packet);
      packet.clear();




      I am looking for any and all criticisms on style, efficiency, reusability, and readability.







      share|improve this question













      I have written a simple packet-framing class, for converting un-encoded 'packets' into encoded/delimited 'frames,' to be sent over a P2P serial connection. The functionality is based on the RFC 1662 "Point-to-Point" protocol, and the general design was inspired by the article "Framing in Serial Communications" by Eli Bendersky.



      One notable departure from the design in the article: this implementation has opted to use a single 'frame terminator' byte at the end, rather than separate 'begin/end' bytes.



      The code leverages template arguments and standard iterator; users can choose to use whichever standard container is appropriate for their environment. In particular, it is an ideal utility for use in a (C++11-compatible) embedded environment - a fixed-size array with standard 'inserter' iterator support can be used.



      #pragma once
      #include <cstdint>

      // The simple_frame_encoding class provides packet/frame encoding and decoding, using a simple
      // framing strategy with the following rules:
      //
      // - The end of an input packet is suffixed with the "frame separator" reserved byte.
      // - Any occurrences of incidental 'reserved bytes' within the input packet are escaped:
      // - The reserved byte is prefixed with the "escape" reserved byte (signaling that the next byte must be decoded).
      // - The reserved byte is XOR'd using the "XOR encode" byte.
      //
      // When decoding, the reserve strategy is employed:
      // - Append bytes to the decoded packet
      // - When the 'escape' is encountered, make sure the next byte is 'decoded' (XOR) before appending
      // - The frame is complete once the 'frame separator' is encountered
      template<std::uint8_t FrameSeparator, std::uint8_t Escape, std::uint8_t XorEncode>
      class simple_frame_encoding final
      public:

      // Ensure none of the 'reserved' bytes (separator, escape) conflict with encoded versions of the same
      static_assert((FrameSeparator ^ XorEncode) != FrameSeparator, "Encoded byte conflict: the encoded 'FrameSeparator' byte is equal to the unencoded 'FrameSeparator' byte");
      static_assert((FrameSeparator ^ XorEncode) != Escape, "Encoded byte conflict: the encoded 'FrameSeparator' byte is equal to the unencoded 'Escape' byte");
      static_assert((Escape ^ XorEncode) != FrameSeparator, "Encoded byte conflict: the encoded 'Escape' byte is equal to the unencoded 'FrameSeparator' byte");
      static_assert((Escape ^ XorEncode) != Escape, "Encoded byte conflict: the encoded 'Escape' byte is equal to the unencoded 'Escape' byte");

      simple_frame_encoding() = default;
      ~simple_frame_encoding() = default;

      // Iterate over the specified packet range, encoding the contents
      // and inserting the resulting 'encoded' frame bytes in the 'output' inserter.
      template<typename TInputIter, typename TInserter>
      void encode(TInputIter first, TInputIter last, TInserter output)
      // Append each byte to the encoded packet;
      // ensure any 'reserved' bytes are XOR'd, and prepended with an escape character
      while (first != last)
      if (is_reserved(*first))
      *output++ = Escape;
      *output++ = (*first ^= XorEncode);

      else
      *output++ = *first;

      first++;


      // Append the frame separator, after the contents
      *output++ = FrameSeparator;


      // Frame decoding occurs over a stream of individual bytes, and tracks internal state;
      // the decoder class encapsulates the current frame-decoding state into a self-contained class.
      // The decoder is fed with individual 'encoded' bytes, automatically decoding
      // them and inserting them into a 'decoded' packet structure, as appropriate.
      class decoder
      public:
      // Decode the next byte, appending the result to the output iterator.
      // Return true if the packet is 'complete.'
      template<typename TInserter>
      bool decode_next_byte(std::uint8_t byte, TInserter output)
      // If we encounter the 'escape' byte, mark the next byte for decoding
      // and return *without* appending
      if (byte == Escape)
      decode_next_byte_ = true;
      return false;


      // If we encounter the 'separator' byte, then the packet is done!
      // Return true and reset the state.
      if (byte == FrameSeparator)
      reset();
      return true;


      // If the previous byte was an 'escape' char,
      // decode this byte before adding it to the packet
      if (decode_next_byte_)
      byte ^= XorEncode;
      decode_next_byte_ = false;


      // If we reach this point, simply append the byte to the packet in progress...
      *output++ = byte;
      return false;


      void reset()
      decode_next_byte_ = false;

      private:
      bool decode_next_byte_ = false;
      ;

      // Create and return an instance of a frame decoder, for the current encoding
      decoder create_decoder()
      return decoder();


      protected:
      // Determine if a given byte is reserved by the FrameSeparator or Escape characters
      static bool is_reserved(std::uint8_t byte)
      return byte == FrameSeparator
      ;

      // Default frame encoding, effectively matching RFC 1662, the point-to-point protocol.
      using default_simple_frame_encoding = simple_frame_encoding<0x7E, 0x7D, 0x20>;


      When decoding: the decode_next_packet function will return true when the frame delimiter was found. This indicates the packet is 'complete' and should be dispatched to the next layer of application code.



      Users are left to clear their own 'in progress' packet buffer, prior to receiving the next byte.



      Example usage when encoding a packet to be sent over the wire:



      auto packet = vector<uint8_t> 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F ;
      vector<uint8_t> frame;

      auto encoding = default_simple_frame_encoding();
      encoding.encode(begin(packet), end(packet), back_inserter(frame));

      serialPort.send(frame);


      Example usage, when receiving a stream of frame-encoded bytes:



      auto encoding = default_simple_frame_encoding();
      auto decoder = encoding.create_decoder();
      uint8_t nextByte = 0;
      static_buffer packet;
      while (serialPort.waitNextByte(nextByte))
      if(decoder.decode_next_byte(nextByte, back_inserter(packet))
      dispatch_completed_packet(packet);
      packet.clear();




      I am looking for any and all criticisms on style, efficiency, reusability, and readability.









      share|improve this question












      share|improve this question




      share|improve this question








      edited Aug 2 at 21:43









      Sam Onela

      5,72961543




      5,72961543









      asked Aug 2 at 18:21









      BTownTKD

      1013




      1013

























          active

          oldest

          votes











          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f200846%2fa-simple-and-efficient-packet-frame-encoder-decoder%23new-answer', 'question_page');

          );

          Post as a guest



































          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes










           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f200846%2fa-simple-and-efficient-packet-frame-encoder-decoder%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Python Lists

          Aion

          JavaScript Array Iteration Methods