ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: "matz (Yukihiro Matsumoto)" <noreply@ruby-lang.org>
To: ruby-core@ruby-lang.org
Subject: [ruby-core:105766] [Ruby master Feature#18254] Add an `offset` parameter to String#unpack and String#unpack1
Date: Mon, 25 Oct 2021 02:08:45 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-94280.20211025020844.7941@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-18254.20211018080403.7941@ruby-lang.org

Issue #18254 has been updated by matz (Yukihiro Matsumoto).


Sounds reasonable. Accepted.

Matz.


----------------------------------------
Feature #18254: Add an `offset` parameter to String#unpack and String#unpack1
https://bugs.ruby-lang.org/issues/18254#change-94280

* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
----------------------------------------
When working with binary protocols it's common to have to first unpack some kind of header or type prefix, and then based on that unpack another part of the string.

For instance here's [a code snippet from Dalli, the most common Memcached client](https://github.com/petergoldstein/dalli/blob/76b79d78cda13562da17bc99f92edcedf1873994/lib/dalli/protocol/binary.rb#L156-L184):

```ruby
while buf.bytesize - pos >= 24
  header = buf.slice(pos, 24)
  (key_length, _, body_length, cas) = header.unpack(KV_HEADER)

  if key_length == 0
    # all done!
    @multi_buffer = nil
    @position = nil
    @inprogress = false
    break

  elsif buf.bytesize - pos >= 24 + body_length
    flags = buf.slice(pos + 24, 4).unpack1("N")
    key = buf.slice(pos + 24 + 4, key_length)
    value = buf.slice(pos + 24 + 4 + key_length, body_length - key_length - 4) if body_length - key_length - 4 > 0

    pos = pos + 24 + body_length

    begin
      values[key] = [deserialize(value, flags), cas]
    rescue DalliError
    end

  else
    # not enough data yet, wait for more
    break
  end
end
@position = pos
```

### Proposal

If `unpack` and `unpack1` had an `offset:` parameter, it would allow this kind of code to extract the fields it needs without allocating and copying as much strings, e.g.:

```ruby
flags = buf.slice(pos + 24, 4).unpack1("N")
```

could be:

```ruby
buf.unpack1("N", offset: pos + 24)
```




-- 
https://bugs.ruby-lang.org/

  parent reply	other threads:[~2021-10-25  2:08 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-18  8:04 [ruby-core:105660] [Ruby master Feature#18254] Add an `offset` parameter to String#unpack and String#unpack1 byroot (Jean Boussier)
2021-10-18  8:24 ` [ruby-core:105661] " znz (Kazuhiro NISHIYAMA)
2021-10-18  8:32 ` [ruby-core:105662] " byroot (Jean Boussier)
2021-10-18 14:26 ` [ruby-core:105663] " byroot (Jean Boussier)
2021-10-25  2:08 ` matz (Yukihiro Matsumoto) [this message]
2021-10-25  2:36 ` [ruby-core:105769] " mame (Yusuke Endoh)
2021-10-25  5:39 ` [ruby-core:105774] " nobu (Nobuyoshi Nakada)
2021-10-25  6:56 ` [ruby-core:105775] " byroot (Jean Boussier)
2021-10-25  9:26 ` [ruby-core:105783] " duerst
2021-10-25  9:41 ` [ruby-core:105784] " byroot (Jean Boussier)
2021-10-25 14:34 ` [ruby-core:105788] " byroot (Jean Boussier)
2021-10-25 16:55 ` [ruby-core:105792] " mame (Yusuke Endoh)
2021-10-25 17:36 ` [ruby-core:105794] " byroot (Jean Boussier)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-94280.20211025020844.7941@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).