clj-commons / gloss

speaks in bytes, so you don't have to
Eclipse Public License 1.0
483 stars 57 forks source link

Seeming bug when reading from buffer not starting at 0 #63

Closed oskarkv closed 1 year ago

oskarkv commented 1 year ago

I'm using gloss from 5cc3fb6166dfbb05f1590d46f0a1601496acf697

I have this code:

(def edn-codec (gloss/compile-frame
                (gloss/finite-frame :int32
                                    (gloss/string :utf-8))
                pr-str
                #(do (println "Got this:" %) (edn/read-string %))))

(defn encode [data]
  (glio/encode edn-codec data))

(defn decode [buffer-seq]
  (glio/decode edn-codec buffer-seq false))

(def testb (doto (ByteBuffer/allocate 40)
             (.putInt (int 5))
             (.put (byte 34))
             (.put (byte 97))
             (.put (byte 98))
             (.put (byte 99))
             (.put (byte 34))
             (.flip)))

(println "result:" (decode (list testb)))

And it works as expected, it prints:

Got this: "abc"
result: abc

So far, so good. But if I try the following buffer instead

(def testb (doto (ByteBuffer/allocate 40)
             (.put (byte 97))
             (.put (byte 97))
             (.put (byte 97))
             (.put (byte 97))
             (.putInt (int 5))
             (.put (byte 34))
             (.put (byte 97))
             (.put (byte 98))
             (.put (byte 99))
             (.put (byte 34))
             (.flip)
             (.position 4)))

it doesn't work as I expect. I expect it to have the same result as the first buffer, but it doesn't. This is printed:

Got this: \0\0\0"abc"
result: \0\0\0

So, it almost works. If I increase the (int 5) to (int 6) it says Insufficient bytes to decode frame., so it reads the 5 and uses it as the length, but then also includes those bytes in the result, before calling the post-decode function. Is that really how it's supposed to work?

KingMob commented 1 year ago

Yeah, looks like a bug. I think it's because when primitive-codec is returning the remaining bytes, it does so by calling rewind-bytes and then drop-bytes. Unfortunately, rewind-bytes sets the position to 0, breaking stuff.

On top of that SingleBufferSequence's drop-bytes- fn was ALSO ignoring position... I think I have a fix. See #64