messagepack 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.adoc +773 -0
- data/Rakefile +8 -0
- data/docs/Gemfile +7 -0
- data/docs/README.md +85 -0
- data/docs/_config.yml +137 -0
- data/docs/_guides/index.adoc +14 -0
- data/docs/_guides/io-streaming.adoc +226 -0
- data/docs/_guides/migration.adoc +218 -0
- data/docs/_guides/performance.adoc +189 -0
- data/docs/_pages/buffer.adoc +85 -0
- data/docs/_pages/extension-types.adoc +117 -0
- data/docs/_pages/factory-pattern.adoc +115 -0
- data/docs/_pages/index.adoc +20 -0
- data/docs/_pages/serialization.adoc +159 -0
- data/docs/_pages/streaming.adoc +97 -0
- data/docs/_pages/symbol-extension.adoc +69 -0
- data/docs/_pages/timestamp-extension.adoc +88 -0
- data/docs/_references/api.adoc +360 -0
- data/docs/_references/extensions.adoc +198 -0
- data/docs/_references/format.adoc +301 -0
- data/docs/_references/index.adoc +14 -0
- data/docs/_tutorials/extension-types.adoc +170 -0
- data/docs/_tutorials/getting-started.adoc +165 -0
- data/docs/_tutorials/index.adoc +14 -0
- data/docs/_tutorials/thread-safety.adoc +157 -0
- data/docs/index.adoc +77 -0
- data/docs/lychee.toml +42 -0
- data/lib/messagepack/bigint.rb +131 -0
- data/lib/messagepack/buffer.rb +534 -0
- data/lib/messagepack/core_ext.rb +34 -0
- data/lib/messagepack/error.rb +24 -0
- data/lib/messagepack/extensions/base.rb +55 -0
- data/lib/messagepack/extensions/registry.rb +154 -0
- data/lib/messagepack/extensions/symbol.rb +38 -0
- data/lib/messagepack/extensions/timestamp.rb +110 -0
- data/lib/messagepack/extensions/value.rb +38 -0
- data/lib/messagepack/factory.rb +349 -0
- data/lib/messagepack/format.rb +99 -0
- data/lib/messagepack/packer.rb +702 -0
- data/lib/messagepack/symbol.rb +4 -0
- data/lib/messagepack/time.rb +29 -0
- data/lib/messagepack/timestamp.rb +4 -0
- data/lib/messagepack/unpacker.rb +1418 -0
- data/lib/messagepack/version.rb +5 -0
- data/lib/messagepack.rb +81 -0
- metadata +94 -0
data/Rakefile
ADDED
data/docs/Gemfile
ADDED
data/docs/README.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# MessagePack Documentation
|
|
2
|
+
|
|
3
|
+
This directory contains the documentation site for the MessagePack Ruby gem, built with Jekyll and the just-the-docs theme.
|
|
4
|
+
|
|
5
|
+
## Building locally
|
|
6
|
+
|
|
7
|
+
### Prerequisites
|
|
8
|
+
|
|
9
|
+
- Ruby 3.3 or higher
|
|
10
|
+
- Bundler
|
|
11
|
+
|
|
12
|
+
### Install dependencies
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
cd docs
|
|
16
|
+
bundle install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Build the site
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
bundle exec jekyll build
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The built site will be in `_site/`.
|
|
26
|
+
|
|
27
|
+
### Serve locally
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
bundle exec jekyll serve
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Visit `http://localhost:4000/messagepack/` to view the site.
|
|
34
|
+
|
|
35
|
+
## Running link checker
|
|
36
|
+
|
|
37
|
+
Install lychee:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# macOS
|
|
41
|
+
brew install lychee
|
|
42
|
+
|
|
43
|
+
# Or with cargo
|
|
44
|
+
cargo install lychee
|
|
45
|
+
|
|
46
|
+
# Or use Docker
|
|
47
|
+
docker run -v $(pwd):/work lycheeverse/lychee ./docs
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Run link checker:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Build the site first
|
|
54
|
+
bundle exec jekyll build
|
|
55
|
+
|
|
56
|
+
# Check links
|
|
57
|
+
lychee --config lychee.toml _site/**/*.html
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Documentation structure
|
|
61
|
+
|
|
62
|
+
- `index.adoc` - Main entry point
|
|
63
|
+
- `_pages/` - Core topics (fundamental concepts)
|
|
64
|
+
- `_tutorials/` - Step-by-step learning guides
|
|
65
|
+
- `_guides/` - Task-oriented documentation
|
|
66
|
+
- `_references/` - Technical specifications and API docs
|
|
67
|
+
|
|
68
|
+
## Adding new documentation
|
|
69
|
+
|
|
70
|
+
1. Create new `.adoc` file in the appropriate collection directory
|
|
71
|
+
2. Add YAML front matter with `title`, `parent`, and `nav_order`
|
|
72
|
+
3. Follow the template structure:
|
|
73
|
+
- Purpose section
|
|
74
|
+
- References section
|
|
75
|
+
- Concepts section
|
|
76
|
+
- Examples section
|
|
77
|
+
4. Update the collection's index.adoc to include the new page
|
|
78
|
+
|
|
79
|
+
## CI/CD
|
|
80
|
+
|
|
81
|
+
Documentation is automatically built and deployed to GitHub Pages:
|
|
82
|
+
- On push to `main` branch
|
|
83
|
+
- When files in `docs/` change
|
|
84
|
+
|
|
85
|
+
Links are automatically checked with lychee on every push and PR.
|
data/docs/_config.yml
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Site settings
|
|
2
|
+
title: MessagePack Ruby
|
|
3
|
+
description: >-
|
|
4
|
+
Pure Ruby implementation of the MessagePack binary serialization format
|
|
5
|
+
baseurl: "/messagepack"
|
|
6
|
+
url: "https://lutaml.github.io"
|
|
7
|
+
|
|
8
|
+
# Theme
|
|
9
|
+
theme: just-the-docs
|
|
10
|
+
remote_theme: just-the-docs/just-the-docs@v0.7.0
|
|
11
|
+
|
|
12
|
+
# Color scheme
|
|
13
|
+
color_scheme: light
|
|
14
|
+
|
|
15
|
+
# Search
|
|
16
|
+
search_enabled: true
|
|
17
|
+
search:
|
|
18
|
+
heading_level: 2
|
|
19
|
+
previews: 3
|
|
20
|
+
preview_words_before: 5
|
|
21
|
+
preview_words_after: 10
|
|
22
|
+
tokenizer_separator: /[\s/]+/
|
|
23
|
+
rel_url: true
|
|
24
|
+
button: false
|
|
25
|
+
|
|
26
|
+
# Heading anchors
|
|
27
|
+
heading_anchors: true
|
|
28
|
+
|
|
29
|
+
# Aux links for the upper right navigation
|
|
30
|
+
aux_links:
|
|
31
|
+
"GitHub":
|
|
32
|
+
- "https://github.com/lutaml/messagepack"
|
|
33
|
+
"RubyGems":
|
|
34
|
+
- "https://rubygems.org/gems/messagepack"
|
|
35
|
+
|
|
36
|
+
# Makes Aux links open in a new tab
|
|
37
|
+
aux_links_new_tab: true
|
|
38
|
+
|
|
39
|
+
# Back to top link
|
|
40
|
+
back_to_top: true
|
|
41
|
+
back_to_top_text: "Back to top"
|
|
42
|
+
|
|
43
|
+
# Footer content
|
|
44
|
+
footer_content: >-
|
|
45
|
+
Copyright © 2025 Ribose. Distributed by an
|
|
46
|
+
<a href="https://github.com/lutaml/messagepack/blob/main/LICENSE">MIT license</a>.
|
|
47
|
+
|
|
48
|
+
# Footer last edit timestamp
|
|
49
|
+
last_edit_timestamp: true
|
|
50
|
+
last_edit_time_format: "%b %e %Y at %I:%M %p"
|
|
51
|
+
|
|
52
|
+
# Navigation structure
|
|
53
|
+
nav_sort: order
|
|
54
|
+
|
|
55
|
+
# Collections for organizing content
|
|
56
|
+
collections:
|
|
57
|
+
pages:
|
|
58
|
+
permalink: "/:path/"
|
|
59
|
+
output: true
|
|
60
|
+
tutorials:
|
|
61
|
+
permalink: "/:collection/:path/"
|
|
62
|
+
output: true
|
|
63
|
+
guides:
|
|
64
|
+
permalink: "/:collection/:path/"
|
|
65
|
+
output: true
|
|
66
|
+
references:
|
|
67
|
+
permalink: "/:collection/:path/"
|
|
68
|
+
output: true
|
|
69
|
+
|
|
70
|
+
# Just the Docs collection configuration
|
|
71
|
+
just_the_docs:
|
|
72
|
+
collections:
|
|
73
|
+
pages:
|
|
74
|
+
name: Core topics
|
|
75
|
+
nav_fold: false
|
|
76
|
+
tutorials:
|
|
77
|
+
name: Tutorials
|
|
78
|
+
nav_fold: true
|
|
79
|
+
guides:
|
|
80
|
+
name: Guides
|
|
81
|
+
nav_fold: true
|
|
82
|
+
references:
|
|
83
|
+
name: References
|
|
84
|
+
nav_fold: true
|
|
85
|
+
|
|
86
|
+
# Plugins
|
|
87
|
+
plugins:
|
|
88
|
+
- jekyll-asciidoc
|
|
89
|
+
- jekyll-seo-tag
|
|
90
|
+
- jekyll-sitemap
|
|
91
|
+
|
|
92
|
+
# AsciiDoc configuration
|
|
93
|
+
asciidoc: {}
|
|
94
|
+
asciidoctor:
|
|
95
|
+
attributes:
|
|
96
|
+
- source-highlighter=rouge
|
|
97
|
+
- rouge-style=github
|
|
98
|
+
- icons=font
|
|
99
|
+
- sectanchors=true
|
|
100
|
+
- idprefix=
|
|
101
|
+
- idseparator=-
|
|
102
|
+
- experimental=true
|
|
103
|
+
|
|
104
|
+
include:
|
|
105
|
+
- '*.adoc'
|
|
106
|
+
|
|
107
|
+
# Exclude from processing
|
|
108
|
+
exclude:
|
|
109
|
+
- Gemfile
|
|
110
|
+
- Gemfile.lock
|
|
111
|
+
- _site
|
|
112
|
+
- node_modules
|
|
113
|
+
- vendor/bundle/
|
|
114
|
+
- vendor/cache/
|
|
115
|
+
- vendor/gems/
|
|
116
|
+
- vendor/ruby/
|
|
117
|
+
|
|
118
|
+
# Enable code copy button
|
|
119
|
+
enable_copy_code_button: true
|
|
120
|
+
|
|
121
|
+
# Callouts
|
|
122
|
+
callouts_level: quiet
|
|
123
|
+
callouts:
|
|
124
|
+
highlight:
|
|
125
|
+
color: yellow
|
|
126
|
+
important:
|
|
127
|
+
title: Important
|
|
128
|
+
color: blue
|
|
129
|
+
new:
|
|
130
|
+
title: New
|
|
131
|
+
color: green
|
|
132
|
+
note:
|
|
133
|
+
title: Note
|
|
134
|
+
color: purple
|
|
135
|
+
warning:
|
|
136
|
+
title: Warning
|
|
137
|
+
color: red
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Guides
|
|
3
|
+
nav_order: 1
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
== Purpose
|
|
7
|
+
|
|
8
|
+
Guides provide task-oriented documentation for specific use cases.
|
|
9
|
+
|
|
10
|
+
== Guides
|
|
11
|
+
|
|
12
|
+
* link:../guides/performance[Performance optimization] - Techniques for maximizing performance
|
|
13
|
+
* link:../guides/io-streaming[IO streaming] - Working with files and network streams
|
|
14
|
+
* link:../guides/migration[Migration guide] - Migrating from other MessagePack implementations
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: IO streaming
|
|
3
|
+
nav_order: 2
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
== Purpose
|
|
7
|
+
|
|
8
|
+
This guide explains how to work with IO objects and network streams using
|
|
9
|
+
MessagePack.
|
|
10
|
+
|
|
11
|
+
== References
|
|
12
|
+
|
|
13
|
+
* link:../pages/streaming[Streaming] - Streaming unpacker concepts
|
|
14
|
+
* link:../pages/buffer[Buffer management] - Buffer IO integration
|
|
15
|
+
|
|
16
|
+
== Concepts
|
|
17
|
+
|
|
18
|
+
=== IO-based unpacking
|
|
19
|
+
|
|
20
|
+
The unpacker can work directly with IO objects:
|
|
21
|
+
|
|
22
|
+
* Automatically reads data as needed
|
|
23
|
+
* Efficient chunked buffering
|
|
24
|
+
* Suitable for files and network sockets
|
|
25
|
+
|
|
26
|
+
=== Streaming unpacker
|
|
27
|
+
|
|
28
|
+
Feed data incrementally:
|
|
29
|
+
|
|
30
|
+
* Parse incomplete data
|
|
31
|
+
* Handle chunked responses
|
|
32
|
+
* Process multiple objects from stream
|
|
33
|
+
|
|
34
|
+
== Working with files
|
|
35
|
+
|
|
36
|
+
=== Writing to files
|
|
37
|
+
|
|
38
|
+
[source,ruby]
|
|
39
|
+
----
|
|
40
|
+
data = { name: "Alice", items: [1, 2, 3] }
|
|
41
|
+
|
|
42
|
+
# Pack and write
|
|
43
|
+
File.open("output.msgpack", "wb") do |file|
|
|
44
|
+
packed = Messagepack.pack(data)
|
|
45
|
+
file.write(packed)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Or use pack with IO directly
|
|
49
|
+
File.open("output.msgpack", "wb") do |file|
|
|
50
|
+
Messagepack.pack(data, file)
|
|
51
|
+
end
|
|
52
|
+
----
|
|
53
|
+
|
|
54
|
+
=== Reading from files
|
|
55
|
+
|
|
56
|
+
[source,ruby]
|
|
57
|
+
----
|
|
58
|
+
# Read and unpack
|
|
59
|
+
data = File.read("output.msgpack", encoding: Encoding::BINARY)
|
|
60
|
+
result = Messagepack.unpack(data)
|
|
61
|
+
|
|
62
|
+
# Or use unpack with IO directly
|
|
63
|
+
File.open("output.msgpack", "rb") do |file|
|
|
64
|
+
result = Messagepack.unpack(file)
|
|
65
|
+
end
|
|
66
|
+
----
|
|
67
|
+
|
|
68
|
+
=== Processing large files
|
|
69
|
+
|
|
70
|
+
[source,ruby]
|
|
71
|
+
----
|
|
72
|
+
# For files with multiple objects, use streaming
|
|
73
|
+
unpacker = Messagepack::Unpacker.new(File.open("large.msgpack", "rb"))
|
|
74
|
+
|
|
75
|
+
while obj = unpacker.read
|
|
76
|
+
process(obj)
|
|
77
|
+
end
|
|
78
|
+
----
|
|
79
|
+
|
|
80
|
+
== Network streaming
|
|
81
|
+
|
|
82
|
+
=== TCP server example
|
|
83
|
+
|
|
84
|
+
[source,ruby]
|
|
85
|
+
----
|
|
86
|
+
require 'socket'
|
|
87
|
+
require 'messagepack'
|
|
88
|
+
|
|
89
|
+
server = TCPServer.new(2000)
|
|
90
|
+
|
|
91
|
+
loop do
|
|
92
|
+
client = server.accept
|
|
93
|
+
unpacker = Messagepack::Unpacker.new(client)
|
|
94
|
+
|
|
95
|
+
while obj = unpacker.read
|
|
96
|
+
# Process each message
|
|
97
|
+
response = handle_message(obj)
|
|
98
|
+
|
|
99
|
+
# Send response
|
|
100
|
+
packed = Messagepack.pack(response)
|
|
101
|
+
client.write(packed)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
client.close
|
|
105
|
+
end
|
|
106
|
+
----
|
|
107
|
+
|
|
108
|
+
=== TCP client example
|
|
109
|
+
|
|
110
|
+
[source,ruby]
|
|
111
|
+
----
|
|
112
|
+
require 'socket'
|
|
113
|
+
require 'messagepack'
|
|
114
|
+
|
|
115
|
+
socket = TCPSocket.new('localhost', 2000)
|
|
116
|
+
|
|
117
|
+
# Send request
|
|
118
|
+
request = { action: "ping", data: "hello" }
|
|
119
|
+
socket.write(Messagepack.pack(request))
|
|
120
|
+
|
|
121
|
+
# Read response
|
|
122
|
+
unpacker = Messagepack::Unpacker.new(socket)
|
|
123
|
+
response = unpacker.read
|
|
124
|
+
|
|
125
|
+
puts response.inspect
|
|
126
|
+
socket.close
|
|
127
|
+
----
|
|
128
|
+
|
|
129
|
+
=== HTTP streaming
|
|
130
|
+
|
|
131
|
+
[source,ruby]
|
|
132
|
+
----
|
|
133
|
+
require 'net/http'
|
|
134
|
+
require 'messagepack'
|
|
135
|
+
|
|
136
|
+
uri = URI('http://example.com/stream')
|
|
137
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
138
|
+
|
|
139
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
|
140
|
+
http.request(request) do |response|
|
|
141
|
+
unpacker = Messagepack::Unpacker.new
|
|
142
|
+
|
|
143
|
+
response.read_body do |chunk|
|
|
144
|
+
unpacker.feed(chunk)
|
|
145
|
+
|
|
146
|
+
while obj = unpacker.read
|
|
147
|
+
process(obj)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
----
|
|
152
|
+
|
|
153
|
+
== WebSocket streaming
|
|
154
|
+
|
|
155
|
+
[source,ruby]
|
|
156
|
+
----
|
|
157
|
+
# Using websocket-client-simple gem
|
|
158
|
+
require 'websocket-client-simple'
|
|
159
|
+
require 'messagepack'
|
|
160
|
+
|
|
161
|
+
ws = WebSocket::Client::Simple.connect('ws://example.com/stream')
|
|
162
|
+
|
|
163
|
+
unpacker = Messagepack::Unpacker.new
|
|
164
|
+
|
|
165
|
+
ws.on :message do |msg|
|
|
166
|
+
unpacker.feed(msg.data)
|
|
167
|
+
|
|
168
|
+
while obj = unpacker.read
|
|
169
|
+
puts "Received: #{obj.inspect}"
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
ws.on :open do
|
|
174
|
+
# Send MessagePack data
|
|
175
|
+
ws.send(Messagepack.pack({type: "subscribe", channel: "updates"}))
|
|
176
|
+
end
|
|
177
|
+
----
|
|
178
|
+
|
|
179
|
+
== Error handling
|
|
180
|
+
|
|
181
|
+
=== Handling incomplete data
|
|
182
|
+
|
|
183
|
+
[source,ruby]
|
|
184
|
+
----
|
|
185
|
+
unpacker = Messagepack::Unpacker.new
|
|
186
|
+
|
|
187
|
+
unpacker.feed(partial_data)
|
|
188
|
+
obj = unpacker.read
|
|
189
|
+
|
|
190
|
+
if obj
|
|
191
|
+
puts "Got object: #{obj.inspect}"
|
|
192
|
+
else
|
|
193
|
+
puts "Need more data"
|
|
194
|
+
end
|
|
195
|
+
----
|
|
196
|
+
|
|
197
|
+
=== Handling malformed data
|
|
198
|
+
|
|
199
|
+
[source,ruby]
|
|
200
|
+
----
|
|
201
|
+
begin
|
|
202
|
+
result = Messagepack.unpack(invalid_data)
|
|
203
|
+
rescue Messagepack::MalformedFormatError => e
|
|
204
|
+
puts "Invalid MessagePack: #{e.message}"
|
|
205
|
+
rescue Messagepack::UnpackError => e
|
|
206
|
+
puts "Unpack error: #{e.message}"
|
|
207
|
+
end
|
|
208
|
+
----
|
|
209
|
+
|
|
210
|
+
=== Handling IO errors
|
|
211
|
+
|
|
212
|
+
[source,ruby]
|
|
213
|
+
----
|
|
214
|
+
begin
|
|
215
|
+
File.open("data.msgpack", "rb") do |file|
|
|
216
|
+
unpacker = Messagepack::Unpacker.new(file)
|
|
217
|
+
while obj = unpacker.read
|
|
218
|
+
process(obj)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
rescue Errno::ENOENT
|
|
222
|
+
puts "File not found"
|
|
223
|
+
rescue IOError => e
|
|
224
|
+
puts "IO error: #{e.message}"
|
|
225
|
+
end
|
|
226
|
+
----
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Migration guide
|
|
3
|
+
nav_order: 3
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
== Purpose
|
|
7
|
+
|
|
8
|
+
This guide helps you migrate from other MessagePack implementations to the
|
|
9
|
+
pure Ruby MessagePack library.
|
|
10
|
+
|
|
11
|
+
== References
|
|
12
|
+
|
|
13
|
+
* link:../pages/serialization[Serialization] - Core API
|
|
14
|
+
* link:../references/api[API reference] - Complete API documentation
|
|
15
|
+
|
|
16
|
+
== From msgpack-ruby (C extension)
|
|
17
|
+
|
|
18
|
+
The pure Ruby implementation aims for API compatibility with msgpack-ruby.
|
|
19
|
+
|
|
20
|
+
=== Module name
|
|
21
|
+
|
|
22
|
+
[source,ruby]
|
|
23
|
+
----
|
|
24
|
+
# msgpack-ruby
|
|
25
|
+
MessagePack.pack(data)
|
|
26
|
+
|
|
27
|
+
# messagepack (pure Ruby)
|
|
28
|
+
Messagepack.pack(data)
|
|
29
|
+
----
|
|
30
|
+
|
|
31
|
+
The pure Ruby version uses `Messagepack` (single word) instead of `MessagePack`.
|
|
32
|
+
|
|
33
|
+
=== Compatible APIs
|
|
34
|
+
|
|
35
|
+
Most core APIs are compatible:
|
|
36
|
+
|
|
37
|
+
[source,ruby]
|
|
38
|
+
----
|
|
39
|
+
# These work the same in both
|
|
40
|
+
Messagepack.pack(data)
|
|
41
|
+
Messagepack.unpack(data)
|
|
42
|
+
Messagepack.load(data)
|
|
43
|
+
Messagepack.dump(data)
|
|
44
|
+
----
|
|
45
|
+
|
|
46
|
+
=== Extension types
|
|
47
|
+
|
|
48
|
+
Extension type registration is similar:
|
|
49
|
+
|
|
50
|
+
[source,ruby]
|
|
51
|
+
----
|
|
52
|
+
# msgpack-ruby
|
|
53
|
+
factory = MessagePack::Factory.new
|
|
54
|
+
factory.register_type(0x01, MyClass, ...)
|
|
55
|
+
|
|
56
|
+
# messagepack (pure Ruby)
|
|
57
|
+
factory = Messagepack::Factory.new
|
|
58
|
+
factory.register_type(0x01, MyClass, ...)
|
|
59
|
+
----
|
|
60
|
+
|
|
61
|
+
=== Differences
|
|
62
|
+
|
|
63
|
+
* **Performance**: C extension is faster for most operations
|
|
64
|
+
* **Dependencies**: Pure Ruby has no C dependencies
|
|
65
|
+
* **Portability**: Pure Ruby works on any Ruby implementation
|
|
66
|
+
|
|
67
|
+
=== Migration steps
|
|
68
|
+
|
|
69
|
+
1. Update Gemfile:
|
|
70
|
+
|
|
71
|
+
[source,ruby]
|
|
72
|
+
----
|
|
73
|
+
# Remove
|
|
74
|
+
gem 'msgpack'
|
|
75
|
+
|
|
76
|
+
# Add
|
|
77
|
+
gem 'messagepack'
|
|
78
|
+
----
|
|
79
|
+
|
|
80
|
+
2. Update require statements:
|
|
81
|
+
|
|
82
|
+
[source,ruby]
|
|
83
|
+
----
|
|
84
|
+
# Change
|
|
85
|
+
require 'msgpack'
|
|
86
|
+
|
|
87
|
+
# To
|
|
88
|
+
require 'messagepack'
|
|
89
|
+
----
|
|
90
|
+
|
|
91
|
+
3. Update constant references:
|
|
92
|
+
|
|
93
|
+
[source,ruby]
|
|
94
|
+
----
|
|
95
|
+
# Change
|
|
96
|
+
MessagePack::Factory
|
|
97
|
+
MessagePack::Unpacker
|
|
98
|
+
|
|
99
|
+
# To
|
|
100
|
+
Messagepack::Factory
|
|
101
|
+
Messagepack::Unpacker
|
|
102
|
+
----
|
|
103
|
+
|
|
104
|
+
== From JSON serialization
|
|
105
|
+
|
|
106
|
+
MessagePack is a binary alternative to JSON.
|
|
107
|
+
|
|
108
|
+
=== Encoding data
|
|
109
|
+
|
|
110
|
+
[source,ruby]
|
|
111
|
+
----
|
|
112
|
+
# JSON
|
|
113
|
+
require 'json'
|
|
114
|
+
JSON.generate({name: "Alice"})
|
|
115
|
+
|
|
116
|
+
# MessagePack
|
|
117
|
+
require 'messagepack'
|
|
118
|
+
Messagepack.pack({name: "Alice"})
|
|
119
|
+
----
|
|
120
|
+
|
|
121
|
+
=== Decoding data
|
|
122
|
+
|
|
123
|
+
[source,ruby]
|
|
124
|
+
----
|
|
125
|
+
# JSON
|
|
126
|
+
JSON.parse('{"name":"Alice"}')
|
|
127
|
+
|
|
128
|
+
# MessagePack
|
|
129
|
+
Messagepack.unpack(binary_string)
|
|
130
|
+
----
|
|
131
|
+
|
|
132
|
+
=== Type differences
|
|
133
|
+
|
|
134
|
+
[source,ruby]
|
|
135
|
+
----
|
|
136
|
+
# JSON only supports these types
|
|
137
|
+
null, true, false, number, string, array, object
|
|
138
|
+
|
|
139
|
+
# MessagePack supports additional types
|
|
140
|
+
nil, boolean, integer, float, string, binary, array, map,
|
|
141
|
+
timestamp, extension types
|
|
142
|
+
----
|
|
143
|
+
|
|
144
|
+
=== Migration pattern
|
|
145
|
+
|
|
146
|
+
[source,ruby]
|
|
147
|
+
----
|
|
148
|
+
# Before (JSON)
|
|
149
|
+
class Cache
|
|
150
|
+
def save(key, value)
|
|
151
|
+
File.write("cache/#{key}", JSON.generate(value))
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def load(key)
|
|
155
|
+
JSON.parse(File.read("cache/#{key}"))
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# After (MessagePack)
|
|
160
|
+
class Cache
|
|
161
|
+
def save(key, value)
|
|
162
|
+
File.write("cache/#{key}", Messagepack.pack(value), mode: 'wb')
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def load(key)
|
|
166
|
+
Messagepack.unpack(File.read("cache/#{key}", encoding: Encoding::BINARY))
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
----
|
|
170
|
+
|
|
171
|
+
== Compatibility mode
|
|
172
|
+
|
|
173
|
+
For compatibility with older MessagePack implementations:
|
|
174
|
+
|
|
175
|
+
[source,ruby]
|
|
176
|
+
----
|
|
177
|
+
# Use compatibility mode to avoid bin/str8 types
|
|
178
|
+
binary = Messagepack.pack(data, compatibility_mode: true)
|
|
179
|
+
----
|
|
180
|
+
|
|
181
|
+
This ensures:
|
|
182
|
+
* Binary data uses str16/str32 instead of bin8/bin16/bin32
|
|
183
|
+
* Strings use str16/str32 instead of str8
|
|
184
|
+
|
|
185
|
+
== Testing your migration
|
|
186
|
+
|
|
187
|
+
=== Verify serialization
|
|
188
|
+
|
|
189
|
+
[source,ruby]
|
|
190
|
+
----
|
|
191
|
+
# Test that data round-trips correctly
|
|
192
|
+
def test_serialization(data)
|
|
193
|
+
binary = Messagepack.pack(data)
|
|
194
|
+
result = Messagepack.unpack(binary)
|
|
195
|
+
result == data
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Test various types
|
|
199
|
+
test_serialization(nil)
|
|
200
|
+
test_serialization(true)
|
|
201
|
+
test_serialization(42)
|
|
202
|
+
test_serialization(3.14)
|
|
203
|
+
test_serialization("hello")
|
|
204
|
+
test_serialization([1, 2, 3])
|
|
205
|
+
test_serialization({a: 1, b: 2})
|
|
206
|
+
----
|
|
207
|
+
|
|
208
|
+
=== Compare with old implementation
|
|
209
|
+
|
|
210
|
+
[source,ruby]
|
|
211
|
+
----
|
|
212
|
+
# Verify compatibility by comparing outputs
|
|
213
|
+
old_binary = OldImpl.pack(data)
|
|
214
|
+
new_binary = Messagepack.pack(data)
|
|
215
|
+
|
|
216
|
+
# Results should be identical for standard types
|
|
217
|
+
# (extension types may differ)
|
|
218
|
+
----
|