Giter Club home page Giter Club logo

Comments (8)

dmendel avatar dmendel commented on May 29, 2024

I'm not sure if BinData is the right tool for what you want.

BinData is used to read/write/modify a well defined structured-binary-format. Your description indicates that you just want some sort of serialization mechanism and don't really care about the underlying binary representation. Yaml or Marshal might suit you better.

from bindata.

madprogrammer avatar madprogrammer commented on May 29, 2024

Well, actually I do care about underlying binary representation as I'm trying to write a network protocol client, whose protocol is similar to the Minecraft NBT example code. I am just trying to make the resulting object more comfortable to work with from Ruby code. Consider this definition in BinData format:

class MyString < BinData::Primitive
    endian :big
    int16 :len, :value => lambda { data.length }
    string :data, :read_length => :len

    def get
        self.data
    end

    def set(v)
        self.data = v
    end
end

class Term < BinData::Record; end

class MyArray < BinData::Record
    endian :big
    int16 :len, :value => lambda { data.length }
    array :data, :type => :term, :initial_length => :len
end

class MyObject < BinData::Record
    endian :big
    int16 :len, :value => lambda { items.length }
    array :items, :initial_length => :len do
        my_string :tag
        term :item
    end
end

class Term < BinData::Record
    endian :big
    uint8  :type
    choice :payload, :selection => :type do
        int8        1
        int8        2
        int16       3
        int32       4
        int64       5
        float       6
        double      7
        my_string   8
        my_array    9
        my_object   10
    end
end

The resulting object parsed using this definition will look something like the following:

{
    :type=>10, // object
    :payload=> {
        :len=>3,
        :items=>[
            {:tag=>"a", :item=>{:type=>3, :payload=>1}},
            {:tag=>"c", :item=>{:type=>2, :payload=>0}},
            {:tag=>"p",
                :item=>{
                    :type=>10, // object
                    :payload=>{
                        :len=>4,
                        :items=>[
                            {:tag=>"key1", :item=>{:type=>8, :payload=>"value1"}}, // string
                            {:tag=>"key2", :item=>{:type=>8, :payload=>"value2"}}  // string
                        ]
                    }
                }
            }
        ]
    }
}

This is a well-defined structured binary format. However, in such form it's not very convenient to manipulate the objects. Since in the definition above MyObject actually looks like a Hash, it would be easier if it was possible to manipulate the key-value pairs as Hash in Ruby, not as Array. For some of the Term choice types, it is also possible to derive type information from Ruby class (e.g. String value can be unambiguously mapped to choice (tag id) 8.

So, what I want to achieve here is MyObject being represented as Hash in Ruby, and it's len property being automatically managed according to the number of keys. The Hash interface should transparently allow access to the internal items array, with tag being the hash key.

from bindata.

dmendel avatar dmendel commented on May 29, 2024

Okay, I understand now.

So if I have code like

foo = MyObject.new
foo["a"] = 3

what is the type of the term? It could be 1, 2, 3, 4, 5, 6 or 7.

from bindata.

madprogrammer avatar madprogrammer commented on May 29, 2024

In case of ambiguous types (like numeric types) you could perhaps do something like:

foo["a"] = Term.new(4, 424242)

Other types could be assigned without such ambiguity:

foo["b"] = "some string"
bar = MyObject.new
bar["a"] = "other string"
foo["c"] = bar
foo["d"] = ["array", Term(4, 8888)]

A possible upper layer of abstraction (not a part of BinData) could also have knowledge of which keys contain which types of values. Reading values could also be implemented as reading Hash-like object:

foo["b"]
=> "some string"
foo["a"]
=> 3

from bindata.

dmendel avatar dmendel commented on May 29, 2024

I think you've answered your own question. You can implement some syntactic sugar so a Record appears like a Hash.

class MyObject < BinData::Primitive

Don't use Primitive. MyObject is compound, not primitive.

Take your original attempt and derive from Record, rather than Primitive.

Instead of defining get and set, define [] and []=. You may need to define other methods from Hash if you use them on the ruby side.

Your [] code will look like your get method.

Your []= method will likely contain a large case statement that converts the ruby object into a Term and then appends (or replaces) to the items array.

from bindata.

madprogrammer avatar madprogrammer commented on May 29, 2024

Thanks. I will try to implement it in the way you suggested, I just thought there might be some built-in support for what I am trying to do.

from bindata.

madprogrammer avatar madprogrammer commented on May 29, 2024

Apparently overriding [] and []= in BinData::Record breaks the implementation in BinData::Struct. Just found it when trying to serialize a nested MyObject. Will see if there's any way around it.

from bindata.

madprogrammer avatar madprogrammer commented on May 29, 2024

Everything works now. Closing question.

from bindata.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.