y-crdt / yrb-actioncable

An ActionCable companion for Y.js clients.
https://y-crdt.github.io/yrb-actioncable/
MIT License
47 stars 5 forks source link

Y::Lib0::Decoding.read_var_uint8_array should increment decoder's `pos` #108

Closed hoshinotsuyoshi closed 5 months ago

hoshinotsuyoshi commented 5 months ago

Problem

I encountered an issue while using Y::Lib0::Decoding.read_var_uint8_array, where pos does not change, preventing successful sequential reading of strings.

I suspect the solution might involve adapting and fixing the part decoder.pos += len from https://github.com/dmonad/lib0/blob/616c7cc61c0bc03d1419bb347977259673ca8aa3/decoding.js#L104.

js:

https://github.com/dmonad/lib0/blob/616c7cc61c0bc03d1419bb347977259673ca8aa3/decoding.js#L104

export const readUint8Array = (decoder, len) => {
  const view = new Uint8Array(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len)
  decoder.pos += len
  return view
}

ruby:

https://github.com/y-crdt/yrb-actioncable/blob/358efdce316042d4261ced4caaed29e8a4b85252/gems/yrb-actioncable/lib/y/lib0/decoding.rb#L29-L31

      def self.read_uint8_array(decoder, size)
        view = Buffer.create_uint8_array_view_from_buffer(decoder.arr, decoder.pos + 0, size)
      end

demo

doc = Y::Doc.new
text = doc.get_text("text")
text << "content"
p doc.diff
# => [1, 1, 219, 249, 254, 144, 12, 0, 4, 1, 4, 116, 101, 120, 116, 7, 99, 111, 110, 116, 101, 110, 116, 0]

decoder = Y::Lib0::Decoding::Decoder.new(doc.diff)

Y::Lib0::Decoding.read_var_uint(decoder) #=> 1 (numOfStateUpdates)
Y::Lib0::Decoding.read_var_uint(decoder) #=> 1 (numberOfStructs)
Y::Lib0::Decoding.read_var_uint(decoder) #=> 3256859867 (client)
Y::Lib0::Decoding.read_var_uint(decoder) #=> 0 (clock)
Y::Lib0::Decoding.read_var_uint(decoder) #=> 4 (info(String))
Y::Lib0::Decoding.read_var_uint(decoder) #=> 1 (parent info)

# first, read "text"
array = Y::Lib0::Decoding.read_var_uint8_array(decoder)

p array
#=> [116, 101, 120, 116]
p array.pack("C*")
#=> "text"

# **Problem**
# **Now, we should increment `pos` manually**
decoder.pos += array.size

# Now, we can read next content  "content"
array = Y::Lib0::Decoding.read_var_uint8_array(decoder)

p array
#=> [99, 111, 110, 116, 101, 110, 116]
p array.pack("C*")
#=> "content"