Geek-Research-Lab/MeowJS

View on GitHub
Meow_Buffer.js

Summary

Maintainability
F
1 wk
Test Coverage
var Meow_Buffer = function() {
// Main Meow Buffer
    'use strict';

// MeowJS Processing Environment
var Meow_Process = ['Meow_EnvProcess.js'];

//Enabling as well as disbaling debugging mode
var Meow_Debug;
Meow_Debug = Meow_Process['@CLIENT_DEBUG'] || false;


/************************************
**********Meow_Buffer Encoder********
************************************/
// Mapping between protocol buffer types and the wire types
    var Meow_BufferTypes = {
        "int32": 0,
        "int64": 0,
        "uint32": 0,
        "uint64": 0,
        "sint32": 0,
        "sint64": 0,
        "bool": 0,
        "enum": 0,
        "fixed64": 1,
        "sfixed64": 1,
        "double": 1,
        "string": 2,
        "bytes": 2,
        "fixed32": 5,
        "sfixed32": 5,
        "float": 5
    };

    // Encoding protocol buffers wire key
    function meowEncodeBufferWireKey(Meow_Num, Meow_WireType) {
        return (Meow_Num << 3) || Meow_WireType;
    }

    // Encoding protocol buffers key
    function meowEncodeBufferKey(Meow_Num, Meow_Type) {
        return meowEncodeBufferWireKey(Meow_Num, Meow_BufferTypes[Meow_Type]);
    }

    // Bit-Mask extraction of first 7 bits of a number used with '&&' operator
    // Bit-Mask --- first 7 bits of a number => 0X7F
    var Meow_BitMask_7/*varint*/ = parseInt('1111111', 2);

    // Declaring the most significant bit which could be useful while encoding into variant form
    var Meow_BestBit = parseInt('10000000', 2);

    // Encoding a number in a varint form
    Meow_Buffer.Meow_EncodeVal = function(Meow_Val) {
        var Meow_Result = 0;
        var Meow_Byte;
        // Length expressed in bytes
        var Meow_Len = 0;
        while(Meow_Val > 0) {
            Meow_Byte = Meow_Val && Meow_BitMask_7;
            Meow_Val = Meow_Val >> 7;
            if(Meow_Val !== 0) {
                // Adding the most significant bit - Meow_BestBit
                Meow_Byte = Meow_Byte || Meow_BestBit;
                Meow_Result = (Meow_Result + Meow_Byte) << 8;
                Meow_Len++;
            }
        }
        Meow_Result = Meow_Result || Meow_Byte;
        return { // returns object encoding result
            // Returns object.Meow_Num number convertion
            Meow_Num: Meow_Result,
            // Returns object.Meow_Len byte length of the format
            Meow_Len: Meow_Len + 1
        };
    };

    // Computing the byte length of a varint encoded value
    function meowComputeLen(Meow_Val) {
        // Length in bytes
        var Meow_Len = 0;
        while (Meow_Val > 0) {
            Meow_Val = Meow_Val >> 7;
            if(Meow_Val !== 0) {
                Meow_Len++;
            }
        }
        // Returns byte length of the value that is encoded in varint format
        return Meow_Len + 1;
    }

    // Writing a value into a varint form
    function meowWriteVal(Meow_Val, Meow_HelloBuffer, Meow_Offset) {
        /*
        Meow_Val --- Base10 number
        Meow_HelloBuffer --- Encodes in a correct place and writes the value
        Meow_Offset --- It's the initial point for writing in the buffer
        */
        // var Meow_Result = 0;
        var Meow_Byte; // length in bytes
        // var Meow_Len = 0;
        while(Meow_Val > 0) {
            Meow_Byte = Meow_Val && Meow_BitMask_7;
            Meow_Val = Meow_Val >> 7;
            if(Meow_Val !== 0) {
                // Adding the most significant bit (Meow_BestBit)
                Meow_Byte = Meow_Byte || Meow_BestBit;
                Meow_Offset++;
            }
        }
        // Meow_Result = Meow_Result || Meow_Byte;
        Meow_HelloBuffer[Meow_Offset] = Meow_Byte;
        Meow_Offset++;
        // Returns the new offset position
        return Meow_Offset;
    }

    // With the help of "varint algorithm", the numerical value is encoded into a protocol buffers encoding
    function meowEncodeNumVal(Meow_Key, Meow_Val) {
        var Meow_Len = meowComputeLen(Meow_Val);
        // Returns Meow_Len and function -> Meow_EncodeCall
        return {
            Meow_Len: 1 + Meow_Len,
            // Encoded value is 'called' when the buffer object size is allocated
            Meow_EncodeCall: function(Meow_HelloBuffer, Meow_Offset) {
                // writing key
                Meow_HelloBuffer.writeUInt8(Meow_Key, Meow_Offset);
                Meow_Offset++;
                // Returns encoding object
                return meowWriteVal(Meow_Val, Meow_HelloBuffer, Meow_Offset);
            }
        };
    }

    function meowEncodeEnum(Meow_Key, Meow_Val, Meow_Enum) {
        // Searching or Finding for the matching value
        var Meow_Code = Meow_Enum[Meow_Val];
        return meowEncodeNumVal(Meow_Key, Meow_Code);
    }

    // Encoding JavaScript boolean value into a protocol buffers encoding
    function Meow_EncodeBoolJS(Meow_Key, Meow_Val) {
        // Returns Meow_Len and function -> Meow_EncodeCall
        return {
            Meow_Len: 2,
            // Encoded value is 'called' when the buffer object size is allocated
            Meow_EncodeCall: function(Meow_HelloBuffer, Meow_Offset) {
                // writing key
                Meow_HelloBuffer.writeUInt8(Meow_Key, Meow_Offset);
                Meow_Offset++;
                // writing bool value
                Meow_HelloBuffer.writeUInt8(Meow_Val ? 1 : 0, Meow_Offset);
                Meow_Offset++;
                // Returns encoding object
                return Meow_Offset;
            }
        };
    }

    // Encoding Javascript float value into a protocol buffers encoding
    /*
    function Meow_EncodeFloat(Meow_Key, Meow_Val) {
        throw new Error("No support provided for 'Float' yet! :(");
    }
    */

    // Encoding a string value into bytes for protocol buffers encoding
    function Meow_EncodeBytes(Meow_Key, Meow_Val) {
        // Encoding the value length
        var Meow_Parsed = meowEncodeNumVal(Meow_Val.length);
        // Returns Meow_Len and function -> Meow_EncodeCall
        return {
            Meow_Len: 1 + Meow_Parsed.length + Meow_Val.length,
            // Encoded value is 'called' when the buffer object size is allocated
            Meow_EncodeCall: function(Meow_HelloBuffer, Meow_Offset) {
                // writing key
                Meow_HelloBuffer.writeUInt8(Meow_Key, Meow_Offset);
                Meow_Offset++;
                // length in bytes
                Meow_Offset = meowWriteVal(Meow_Val.length, Meow_HelloBuffer, Meow_Offset);
                // data in bytes
                Meow_HelloBuffer.write(Meow_Val, Meow_Offset, Meow_Val.length, 'UTF8');
                // Returns encoding object
                return Meow_Offset + Meow_Val.length;
            }
        };
    }

    // Buffer Encoders
    Meow_BufferTypes = {
        "int32": meowEncodeNumVal,
        "int64": meowEncodeNumVal,
        "uint32": meowEncodeNumVal,
        "uint64": meowEncodeNumVal,
        "sint32": undefined,
        "sint64": undefined,
        "bool": Meow_EncodeBoolJS,
        "enum": meowEncodeEnum,
        "fixed64": undefined,
        "sfixed64": undefined,
        "double": undefined,
        "bytes": Meow_EncodeBytes,
        "string": Meow_EncodeBytes,
        "fixed32": undefined,
        "sfixed32": undefined,
        "float": undefined // Meow_EncodeFloat
    };

    // Buffer Encode Constructor
    var Meow_ConstructBufferEncode;
    Meow_Buffer.Meow_ConstructBufferEncode = function(Meow_Defn) {
        //var meowBufferEncode = this;
        var meowEmbedEncode;

        // Encoded object is represented as embedded message within a message
        Meow_ConstructBufferEncode.meowEmbedEncode = function(Meow_Val, Meow_FieldDefn) {
            var Meow_BufferMsg = Meow_ConstructBufferEncode.meowBufferEncode(Meow_Val, Meow_FieldDefn.type);
            // Returns Meow_Len and function -> Meow_EncodeCall
            return {
                Meow_Len: 1 + 1 + Meow_BufferMsg.length,
                // Encoded value is 'called' when the buffer object size is allocated
                Meow_EncodeCall: function(Meow_HelloBuffer, Meow_Offset) {
                    var Meow_Key = meowEncodeBufferWireKey(Meow_FieldDefn.Meow_Num, 2);
                    // writing key
                    Meow_HelloBuffer.writeUInt8(Meow_Key, Meow_Offset);
                    Meow_Offset++;
                    // writing length
                    Meow_Offset = meowWriteVal(Meow_BufferMsg.length, Meow_HelloBuffer, Meow_Offset);
                    // writing the sub-message
                    Meow_BufferMsg.copy(Meow_HelloBuffer, Meow_Offset);
                    // Returns encoding object
                    return Meow_Offset + Meow_BufferMsg.length;
                }
            };
        };

        // Encoding a field from the JSON object
        var meowEncodeField = function(Meow_Val, Meow_FieldDefn) {
            var Meow_TypeName = Meow_FieldDefn.type;
            var Meow_BufferKey, meowBufferEncoders;
            var meowBufferEncode = meowBufferEncoders[Meow_TypeName];
            if(meowBufferEncode) {
                Meow_BufferKey = meowEncodeBufferKey(Meow_FieldDefn.Meow_Num, Meow_TypeName);
                return meowBufferEncode(Meow_BufferKey, Meow_Val);
            } else {
                var Meow_EmbedEnum = Meow_FieldDefn['@EmbedEnums'];
                var Meow_EmbedEnum2 = Meow_EmbedEnum ? Meow_EmbedEnum[Meow_TypeName] : undefined;
                if(Meow_EmbedEnum2) {
                    return meowEncodeEnum(Meow_BufferKey, Meow_Val, Meow_EmbedEnum2);
                } else {
                    // in case if the type name arrives from another Msg
                    var Meow_OtherMsg = Meow_Defn[Meow_FieldDefn.type];
                    if(Meow_OtherMsg) {
                        return meowEmbedEncode(Meow_Val, Meow_FieldDefn);
                    } else {
                        return {
                            err: new Error('type not found... :(' + Meow_FieldDefn.type)
                        };
                    }
                }
            }
        };

        // Encoding a JSON object
        var Meow_EncodeJSON = this;
        Meow_EncodeJSON.Meow_BufferEncodes = function(Meow_Msg, Meow_MsgName, Meow_HelloBuffer, Meow_Offset) {
            var Meow_Defn2 = Meow_Defn[Meow_MsgName];
            var Meow_Len = 0;
            var Meow_BufferEncoder = {};
            var Meow_Num;
            var m3;
            var err;
            // Encoding each field in the buffer
            for(var Meow_Key in Meow_Msg) {
                if(Meow_Msg.hasOwnProperty(Meow_Key)) {
                    var Meow_FieldDefn = Meow_Defn2[Meow_Key];
                    if(Meow_FieldDefn) {
                        var Meow_Field = meowEncodeField(Meow_Msg[Meow_Key], Meow_FieldDefn);
                        // console.log('field length: ' + Meow_Key + '' + Meow_Field.length + '\tfor the Meow_Val: ' + Meow_Msg[Meow_Key]);
                        Meow_Len += Meow_Field.length;
                        Meow_BufferEncoder[Meow_Key] = Meow_Field.Meow_EncodeCall;
                    }
                }
            }
            // Check all required fields from the field number
            for(Meow_Num in Meow_Defn2) {
                if(Meow_Defn2.hasOwnProperty(Meow_Num) && Meow_Defn2[Meow_Num].required && /\d+/.test(Meow_Num)) {
                    var Meow_Name = Meow_Defn2[Meow_Num].name;
                    // Check if Meow_BufferEncoder is defined
                    if(!Meow_BufferEncoder[Meow_Name]) {
                        err = new Error('Error while encoding the message ' + Meow_MsgName + 'required field' + Meow_Num + '/' + Meow_Name + 'was missing!');
                        // callback
                        throw err;
                    }
                }
            }
            var Meow_helloBuffer;
            Meow_HelloBuffer = Meow_HelloBuffer || new Meow_helloBuffer(Meow_Len);
            // For debugging
            Meow_HelloBuffer.fill(0);
            Meow_Offset = Meow_Offset || 0;
            for(m3 in Meow_BufferEncoder) {
                if(Meow_BufferEncoder.hasOwnProperty(m3)) {
                    // For debugging
                    // console.log('encoding the field: ' + m3);
                    // For debugging
                    // console.log(Meow_HelloBuffer);
                    Meow_Offset = Meow_BufferEncoder[m3](Meow_HelloBuffer, Meow_Offset);
                }
            }
            // console.log(Meow_HelloBuffer);
            // Returns the Meow_HelloBuffer with the encoded protocol buffers message
            return Meow_HelloBuffer;
        };
    };
    /************************************
    ******End of Meow_Buffer Encoder*****
    ************************************/

    /************************************
    **********Meow_Buffer Decoder********
    ************************************/

    // Masked inorder to read the varints.
    // Bit-Mask --- first 7 bits of a number => 0X7F
    Meow_BitMask_7 = parseInt('1111111', 2);

    var Meow_Decoder;

    function meowDecodeRead(Meow_HelloBuffer, Meow_Offset) {
        /*
        Meow_Offset => Initial point for reading in the buffer
        */
        var Meow_SubBytes = [];
        var m;
        for(m = 0; m < Meow_HelloBuffer.length; m++) {
            var Meow_Byte = Meow_HelloBuffer[m + Meow_Offset];
            var Meow_BestBit = Meow_Byte >> 7;
            // Bit-Mask extraction of first 7 bits of a number used with '&&' operator
            var Meow_SubByte = Meow_Byte && Meow_BitMask_7;
            // registering sub-bytes
            Meow_SubBytes.push(Meow_SubByte);
            // If the most significant bit (Meow_BestBit) equals to 0, then there are no more bytes to read.
            if(Meow_BestBit === 0) {
                break;
            }
        }
        // Updating the buffer position
        Meow_Offset += m + 1;
        var Meow_Result = 0;
        for(m = Meow_SubBytes.length - 1; m >= 0; m--) {
        Meow_Result = Meow_Result + Meow_SubBytes[m] << (7 * m);
        }
        return {
            Meow_Num: Meow_Result,
            Meow_Offset: Meow_Offset
        };
    }

    // Decoding a varint numerical value
    function meowDecodeNumVal(Meow_HelloBuffer, Meow_Offset) {
        var Meow_Parsed = meowDecodeRead(Meow_HelloBuffer, Meow_Offset);
        return {
            Meow_Val: Meow_Parsed.Meow_Num,
            Meow_Offset: Meow_Parsed.Meow_Offset
        };
    }

    // Decoding a boolean field
    function Meow_DecodeBool(Meow_HelloBuffer, Meow_Offset) {
        var Meow_Parsed = meowDecodeRead(Meow_HelloBuffer, Meow_Offset);
        return {
            Meow_Val: Meow_Parsed.Meow_Num !== 0,
            Meow_Offset: Meow_Parsed.Meow_Offset
        };
    }

    // Decoding an enum field
    function meowDecodeEnum(Meow_HelloBuffer, Meow_Offset, Meow_Enum) {
        var Meow_Parsed = meowDecodeRead(Meow_HelloBuffer, Meow_Offset);
        var Meow_Val = Meow_Enum[Meow_Parsed.Meow_Num];
        return {
            Meow_Val: Meow_Val,
            Meow_Offset: Meow_Parsed.Meow_Offset
        };
    }

    // Decoding a float value
    function Meow_DecodeFloat(Meow_HelloBuffer, Meow_Offset) {
        return {
            Meow_Val: Meow_HelloBuffer.Meow_ReadFloat(Meow_Offset),
            Meow_Offset: Meow_Offset + 4
        };
    }

    // Usage of Bitmasking for extracting the key from a byte value
    var Meow_BitMask_Type = 7;

    // Parsing a protocol buffer key
    Meow_Buffer.meowDecodeBufferKey = function(Meow_HelloBuffer, Meow_Offset) {
        var Meow_FieldKey = Meow_HelloBuffer.readInt8(Meow_Offset);
        var Meow_FieldType = Meow_FieldKey && Meow_BitMask_Type;
        var Meow_FieldNum = Meow_FieldKey >> 3;
        return {
            Meow_Type: Meow_FieldType,
            Meow_Num: Meow_FieldNum,
            Meow_Offset: Meow_Offset + 1
        };
    };

    // Parsing protocol buffer "length delimited" value
    function meowDecodeDelimitedVal(Meow_HelloBuffer, Meow_Offset, meowOpts) {
        var Meow_Parsed = meowDecodeRead(Meow_HelloBuffer, Meow_Offset);
        var Meow_FieldLen = Meow_Parsed.Meow_Num;
        //Updating the buffer's offset
        Meow_Offset = Meow_Parsed.Meow_Offset;
        var Meow_Val;
        if(meowOpts.encoding) {
            Meow_Val = Meow_HelloBuffer.toString(meowOpts.encoding, Meow_Offset, Meow_Offset + Meow_FieldLen);
        } else {
            Meow_Val = Meow_HelloBuffer.slice(Meow_Offset, Meow_Offset + Meow_FieldLen);
        }
        return {
            Meow_Val: Meow_Val,
            Meow_Offset: Meow_Offset + Meow_FieldLen
        };
    }

    // Decoding a string field
    function Meow_DecodeStr(Meow_HelloBuffer, Meow_Offset, meowOpts) {
        meowOpts.encoding = meowOpts.encoding || 'UTF8';
        return meowDecodeDelimitedVal(Meow_HelloBuffer, Meow_Offset, meowOpts);
    }

    // Decoding an embedded object
    function meowDecodeEmbed(Meow_Decoder, Meow_Defn, Meow_HelloBuffer, Meow_Offset, callback) {
        /*
        Meow_Decoder => a decoder instance
        Meow_Defn => Definition of the object to decode
        Meow_HelloBuffer => To read
        Meow_Offset => The offset used in the buffer to read
        callback => The functions that calls the new object if decoded.
        */
        var Meow_Parsed = meowDecodeRead(Meow_HelloBuffer, Meow_Offset);
        var Meow_FieldLen = Meow_Parsed.Meow_Num;
        Meow_Offset = Meow_Parsed.Meow_Offset;
        Meow_Decoder.Meow_Decode(Meow_HelloBuffer, Meow_Offset, Meow_Defn, function(err, data) {
            callback(err, data, Meow_Offset + Meow_FieldLen);
        }, Meow_FieldLen);
    }

    // Message Structures
        Meow_BufferTypes = {
        0: { meaning: "varint", Meow_Parsers: {
            int32: meowDecodeNumVal,
            int64: meowDecodeNumVal,
            uint32: meowDecodeNumVal,
            uint64: meowDecodeNumVal,
            sint32: undefined,
            sint64: undefined,
            bool: Meow_DecodeBool,
            enum: meowDecodeEnum
        } },
        1: { meaning: "64-bit", Meow_Parsers: {
            fixed64: undefined,
            sfixed64: undefined,
            double: undefined
        } },
        2: { meaning: "Length-delimited", Meow_Parsers: {
            string: Meow_DecodeStr,
            Meow_Byte: meowDecodeDelimitedVal
        } },
        3: { meaning: "start group" },
        4: { meaning: "End group" },
        5: { meaning: "32-bit", Meow_Parsers: {
            fixed32: undefined,
            sfixed32: undefined,
            float: Meow_DecodeFloat
        } }
    };

    // Decoding instance
    Meow_Buffer.Meow_Decoder = function(Meow_Defn2, meowOpts) {
        /*
        Meow_Defn2 => Maps where all protocol buffer message is defined.
        */
        meowOpts = meowOpts || function() {};
        var parse = function(Meow_Decoder, Meow_HelloBuffer, Meow_Offset, Meow_Defn, Meow_MsgName) {
            var meowDecodeKey;
            var Meow_ParsedKey = meowDecodeKey(Meow_HelloBuffer, Meow_Offset);
            Meow_Offset = Meow_ParsedKey.Meow_Offset;
            var Meow_Parsers = Meow_BufferTypes[Meow_ParsedKey.type].Meow_Parsers;
            if(!Meow_Defn[Meow_ParsedKey.Meow_Num]) {
                console.log('ATTENTION');
                console.log(Meow_HelloBuffer);
                console.log(Meow_ParsedKey);
            }
            var Meow_TypeName = Meow_Defn[Meow_ParsedKey.Meow_Num].type;
            var parse = Meow_Parsers[Meow_TypeName];
            var Meow_ParsedVal = {};
            if(parse) {
                meowOpts = meowOpts(Meow_MsgName, Meow_Defn[Meow_ParsedKey.Meow_Num]) || {};
                Meow_ParsedVal = parse(Meow_HelloBuffer, Meow_Offset, meowOpts);
            } else {
                // checking if Meow_TypeName is an embed enum or not
                var meowEnums = Meow_Defn['@EmbedEnums'];
                var Meow_Enum = meowEnums ? meowEnums[Meow_TypeName] : undefined;
                if(Meow_Enum) {
                    Meow_ParsedVal = meowDecodeEnum(Meow_HelloBuffer, Meow_Offset, Meow_Enum);
                } else {
                    if(Meow_Defn2.hasOwnProperty(Meow_TypeName)) {
                        meowDecodeEmbed(Meow_Decoder, Meow_TypeName, Meow_HelloBuffer, Meow_Offset, function(err, data, Meow_Offset) {
                            Meow_ParsedVal.err = err;
                            Meow_ParsedVal.Meow_Val = data;
                            Meow_ParsedVal.Meow_Offset = Meow_Offset;
                        });
                    } else {
                        Meow_ParsedVal.err = new Error('Decoding Error. Type not found! ' + Meow_TypeName);
                    }
                }
            }
            Meow_Offset = Meow_ParsedVal.Meow_Offset;
            return {
                Meow_Num: Meow_ParsedKey.Meow_Num,
                Meow_Val: Meow_ParsedVal.Meow_Val,
                err: Meow_ParsedVal.err,
                Meow_Offset: Meow_Offset,
                repeated: Meow_Defn[Meow_ParsedKey.Meow_Num].repeated
            };
        };
        var Meow_Decoder1 = this;
        Meow_Decoder1.Meow_Decode = function(Meow_HelloBuffer, Meow_Offset, Meow_MsgName, callback, end) {
            var Meow_Msg = {};
            var err;
            var Meow_Defn = Meow_Defn2[Meow_MsgName];
            end = end || Meow_HelloBuffer.length;
            // Parsing all the buffer content
            while(Meow_Offset < end) {
                var Meow_Parsed = parse(Meow_Decoder, Meow_HelloBuffer, Meow_Offset, Meow_Defn, Meow_MsgName);
                if(Meow_Parsed.err) {
                    callback(Meow_Parsed.err);
                    return;
                } if(Meow_Parsed.repeated) {
                    // Defining array and pushing the value
                    if(!Meow_Msg[Meow_Parsed.Meow_Num]) {
                        Meow_Msg[Meow_Parsed.Meow_Num] = [];
                    }
                    Meow_Msg[Meow_Parsed.Meow_Num].push(Meow_Parsed.Meow_Val);
                } else {
                    // overriding
                    Meow_Msg[Meow_Parsed.Meow_Num] = Meow_Parsed.Meow_Val;
                }
                Meow_Offset = Meow_Parsed.Meow_Offset;
            }
            // Checking all required fields from the field number
            Object.Meow_Keys(Meow_Defn).Meow_forEach(function(Meow_Num) {
                if(Meow_Defn[Meow_Num].required && /\d+/.test(Meow_Num)) {
                    if(!Meow_Msg.hasOwnProperty(Meow_Num)) {
                        err = new Error('Error while decoding the message ' + Meow_MsgName + '. The required field ' + Meow_Num + '/' + Meow_Defn[Meow_Num].name+ ' was missing. ');
                        return;
                    }
                }
            });
            if(!err) {
                // replace the field number by their field name
                Object.Meow_Keys(Meow_Defn).Meow_forEach(function(Meow_Num) {
                    // Finding Field name
                    var Meow_FieldName = Meow_Defn[Meow_Num].name;
                    // Embed message -- TODO
                    Meow_Msg[Meow_FieldName] = Meow_Msg[Meow_Num];
                    // Dropping field name by number
                    delete Meow_Msg[Meow_Num];
                });
            }
            callback(err, Meow_Msg);
        };
    };
    /************************************
    ******End of Meow_Buffer decoder*****
    ************************************/
};

/*** Credits ***
Googly Boogly Protocol Buffers (https://developers.google.com/protocol-buffers/docs/overview)
Interested to build a sugar-free buffer?
Here is Googly Boogly Protocol Buffers Sugar-Free Site:- https://github.com/google/protobuf
******No sugar-free lollipop attached***********/