y-rb 0.1.3 → 0.1.4.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile DELETED
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
5
- require "yard"
6
- require "rubocop/rake_task"
7
- require "thermite/tasks"
8
-
9
- RSpec::Core::RakeTask.new(:spec)
10
-
11
- RuboCop::RakeTask.new
12
-
13
- task default: %i[spec rubocop]
14
-
15
- desc "Compile the y-rb crate"
16
- task :compile do
17
- # MacOS: ARM + x64
18
- `cargo build --release --target=aarch64-apple-darwin`
19
- `cargo build --release --target=x86_64-apple-darwin`
20
-
21
- # Copy to target folder
22
- `cp target/aarch64-apple-darwin/release/liby_rb.dylib target/release/`
23
- end
24
-
25
- task :clean do
26
- `cargo clean`
27
- end
28
-
29
- task test: :spec
30
-
31
- task :docs do
32
- `yard server --reload`
33
- end
34
-
35
- RuboCop::RakeTask.new
36
-
37
- YARD::Rake::YardocTask.new
38
-
39
- Thermite::Tasks.new
data/bin/console DELETED
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require "bundler/setup"
5
- require "y/rb"
6
-
7
- # You can add fixtures and/or initialization code here to make experimenting
8
- # with your gem easier. You can also use a different console, if you like.
9
-
10
- # (If you use this, don't forget to add pry to your Gemfile!)
11
- # require "pry"
12
- # Pry.start
13
-
14
- require "irb"
15
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
data/build/Dockerfile DELETED
@@ -1,18 +0,0 @@
1
- ARG CROSS_BASE_IMAGE
2
- FROM $CROSS_BASE_IMAGE
3
-
4
- ENV RUBY_VERSION=3.1.2
5
-
6
- RUN apt-get update -yq && apt-get install -yq build-essential gnupg2 openssl ruby ruby-dev
7
- RUN curl -sSL https://rvm.io/pkuczynski.asc | gpg2 --import -
8
- RUN curl -L https://get.rvm.io | bash -s stable
9
- RUN /bin/bash -l -c "rvm requirements"
10
- RUN /bin/bash -l -c "rvm install 3.1.2"
11
- RUN /bin/bash -l -c "rvm install 3.0.4"
12
- RUN /bin/bash -l -c "rvm install 2.7.6"
13
- RUN /bin/bash -l -c "rvm install 2.6.10"
14
-
15
- COPY build/entrypoint.sh /
16
- RUN chmod +x "/entrypoint.sh"
17
-
18
- ENTRYPOINT ["/entrypoint.sh"]
data/build/build.rb DELETED
@@ -1,105 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require "active_support/core_ext/string"
5
- require "fileutils"
6
- require "minitar"
7
- require "zlib"
8
-
9
- require_relative "../lib/y/version"
10
-
11
- RUBIES = %w[2.6.10 2.7.6 3.0.4 3.1.2].freeze
12
-
13
- # darwin20 = mac os 11.x
14
- # darwin21 = mac os 12.x
15
- # darwin22 = mac os 13.x
16
- TARGETS = {
17
- "aarch64-apple-darwin": {
18
- cpu: "arm64",
19
- os: "darwin21"
20
- },
21
- "aarch64-unknown-linux-gnu": {
22
- cpu: "arm64",
23
- os: "linux"
24
- },
25
- "aarch64-unknown-linux-musl": {
26
- cpu: "arm64",
27
- os: "linux-musl",
28
- env: {
29
- "RUSTFLAGS" => "\"-C target-feature=-crt-static\""
30
- }
31
- },
32
- "x86_64-unknown-linux-gnu": {
33
- cpu: "x86_64",
34
- os: "linux"
35
- },
36
- "x86_64-unknown-linux-musl": {
37
- cpu: "x86_64",
38
- os: "linux-musl",
39
- env: {
40
- "RUSTFLAGS" => "\"-C target-feature=-crt-static\""
41
- }
42
- }
43
- }.freeze
44
-
45
- def build_lib(target, options, ruby_version) # rubocop:disable Metrics/MethodLength
46
- env_vars = if !options.nil? && options.key?(:env)
47
- target_env = target.to_s.underscore.upcase
48
- options[:env]
49
- .map { |env, value| "CARGO_TARGET_#{target_env}_#{env}=#{value}" }
50
- .join(" ")
51
- else
52
- ""
53
- end
54
-
55
- cmd = [
56
- "cargo clean",
57
- "#{env_vars} RUBY_VERSION=#{ruby_version} cross build --target=#{target} --release"
58
- ].join(" && ")
59
-
60
- `#{cmd}`
61
- end
62
-
63
- def copy_lib(target)
64
- path = "#{__dir__}/../target/#{target}/release"
65
-
66
- file = Dir["#{path}/*{dylib,so}"].first
67
-
68
- extension = File.extname(file)
69
- dest = "#{path}/y_rb#{extension}"
70
-
71
- FileUtils.cp(file, dest)
72
-
73
- dest
74
- end
75
-
76
- # Build
77
-
78
- FileUtils.rm_rf "#{__dir__}/out"
79
-
80
- TARGETS.each do |target, options|
81
- RUBIES.each do |ruby_version|
82
- puts "Build: target=#{target}, ruby=#{ruby_version}"
83
-
84
- version = Gem::Version.new(ruby_version)
85
- version_segments = version.canonical_segments
86
- ruby_version_string = "#{version_segments[0]}#{version_segments[1]}"
87
-
88
- build_lib(target, options, ruby_version)
89
- file = copy_lib(target)
90
-
91
- raise "Build failed" if file.nil?
92
-
93
- extension = File.extname(file)
94
- dir = "#{__dir__}/out/y_rb-#{Y::VERSION}-ruby#{ruby_version_string}-#{options[:os]}-#{options[:cpu]}"
95
- FileUtils.mkdir_p(dir)
96
- FileUtils.cp(file, "#{dir}/y_rb#{extension}")
97
-
98
- archive = "#{dir}/y_rb-#{Y::VERSION}-ruby#{ruby_version_string}-#{options[:os]}-#{options[:cpu]}.tar.gz"
99
- Zlib::GzipWriter.open(archive) do |tgz|
100
- Dir.chdir(dir) do
101
- Archive::Tar::Minitar.pack(".", tgz)
102
- end
103
- end
104
- end
105
- end
data/build/entrypoint.sh DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- /bin/bash -l -c "rvm --default use $RUBY_VERSION" && exec "$@"
data/docs/decisions.md DELETED
@@ -1,64 +0,0 @@
1
- # Decision log
2
-
3
- ## 2022-05-12
4
-
5
- ### Transactions do not always commit automatically
6
-
7
- In `yrs`, the lifetime of a transaction is determined automatically. This can
8
- lead to an interesting situation in Ruby, where we attach a listener to receive
9
- changes, never commit a transaction explicitly and where the transaction gets
10
- dropped automatically. I believe we still maintain a pointer to the transaction
11
- that no longer exists, and therefore we receive a segfault.
12
-
13
- ## 2022-05-12
14
-
15
- ### Add event-driven approach to receive changes
16
-
17
- It is not clear if this ends up being the final API to receive changes, but
18
- it is the one that is supported in one or the other way across all `yrs`
19
- implementations. It might be beneficial to add a synchronous API in the future,
20
- but this isn't supported right away. All common styles of closure like behavior
21
- are supported: `Proc`, `Lambda` and `Block`.
22
-
23
- ## 2022-05-09
24
-
25
- ### Supported operations on data types are either read-only or mutable
26
-
27
- In a meeting with the wider `y-crdt` group on May 6th, 2022, it became clear
28
- that the cost of creating a new instance of a data type is common operation in
29
- many languages (Python, Ruby, …), but it is not something we should to support.
30
- This pattern leads to all sort of problems, mostly because it contradicts the
31
- common usage pattern of replicating changes between two or more clients.
32
-
33
- Instead, the API should be explicit about this fact and should not make it too
34
- easy to do that.
35
-
36
- ## 2022-05-06
37
-
38
- ### Transactions are implicit by default
39
-
40
- The developer should not be exposed to transactions until they need to
41
- change the default logic in any way. If someone creates a structure and inserts,
42
- removes, this should be part of the same transaction until stated otherwise.
43
-
44
- ### Synchronisation happens at the document level
45
-
46
- It might be interesting to sync at a more granular level, but for the sake of
47
- simplicity, the first iteration of this library will only support
48
- synchronization of the complete document.
49
-
50
- ## 2022-05-05
51
-
52
- ### No direct exposure of internal API
53
-
54
- The internal API (`y-crdt`) is subject to constant changes and does not
55
- necessarily offer an idiomatic Ruby interface. Therefore, the public API of
56
- `y-rb` does not follow the `y-crdt` API, but prefers familiar Ruby idioms when
57
- possible and might even require libraries where it makes sense (e.g. `nokogiri` for XML).
58
-
59
- ### Rutie is a temporary dependency
60
-
61
- The Ruby<->Rust binding feels immature. But it is not the goal of this project
62
- to fix this immediately. The long-term vision is to replace this part by
63
- something more lightweight and opinionated that could be part of the Rust
64
- codebase of this project.
data/docs/examples.md DELETED
@@ -1,16 +0,0 @@
1
- # Examples
2
-
3
- > Usage patterns
4
-
5
- ## Send a full document update to a client
6
-
7
- ```ruby
8
- doc = Y::Doc.new
9
- text = doc.get_text("about")
10
- text << "My name is, my name is, my name is … Slim Shady"
11
-
12
- zero = Y::Doc.new
13
- update = doc.diff(zero.state)
14
-
15
- transfer update
16
- ```
data/docs/release.md DELETED
@@ -1,36 +0,0 @@
1
- # Release
2
-
3
- ## Steps
4
-
5
- 1. Make sure CI is green
6
- 2. Update version in `Cargo.toml`
7
- 3. Update version in `lib/y/version.rb`
8
- 4. Create a tag matching the version `git tag -a vx.x.x -m "Release version vx.x.x"`
9
- 5. Push tag to GitHub repo: `git push vx.x.x`
10
- 6. Create a GitHub release (requires GitHub CLI): `gh release create vx.x.x ./build/out/*/*.gz`
11
- 7. Package and upload gem: `gem build && gem push y-rb-x.x.x.gem`
12
-
13
- ## Cross-compile binaries (to be released as assets on GitHub)
14
-
15
- There is a script in `./build` that automates a fair chunk of work, but it is
16
- not bulletproof. I mainly use it to compile for arm64 platforms on my machine,
17
- and then upload manually. Most binaries (especially x86) should come from CI.
18
-
19
- It also includes a workaround for Alpine (popular in Docker images) what usually
20
- requires to be a static lib.
21
-
22
- Run the following script. It produces a bunch of archives in `./build/out/`.
23
- You need to upload the produced assets manually after the GitHub release was
24
- created.
25
-
26
- ```bash
27
- ./build/build.rb
28
- ```
29
-
30
- ## Future work
31
-
32
- With this [PR](https://github.com/rubygems/rubygems/pull/5175) merged into
33
- rubygems, we will most likely be able to rely on the extension to manage builds
34
- for us in the future.
35
-
36
- Pre-build binaries are not verified, and are inherently a security concern.
data/ext/Rakefile DELETED
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "thermite/tasks"
4
-
5
- project_dir = File.dirname(File.dirname(__FILE__))
6
- Thermite::Tasks.new(cargo_project_path: project_dir,
7
- ruby_project_path: project_dir)
8
-
9
- task default: %w[thermite:build]
data/lib/y/rb.rb DELETED
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rutie"
4
- require_relative "array"
5
- require_relative "doc"
6
- require_relative "map"
7
- require_relative "text"
8
- require_relative "transaction"
9
- require_relative "version"
10
- require_relative "xml"
11
-
12
- module Y
13
- # support pre-built and local built libraries
14
- lib_path = if Dir.exist?(File.join(__dir__, "..", "..", "target", "release"))
15
- nil
16
- else
17
- File.join(__dir__, "..", "..")
18
- end
19
-
20
- Rutie.new(
21
- :y_rb,
22
- lib_path: lib_path
23
- ).init(
24
- "Init_yrb",
25
- File.join(__dir__, "..")
26
- )
27
- end
data/src/lib.rs DELETED
@@ -1,248 +0,0 @@
1
- mod util;
2
- mod yarray;
3
- mod ydoc;
4
- mod ymap;
5
- mod ytext;
6
- mod ytransaction;
7
- mod yxml;
8
-
9
- #[macro_use]
10
- extern crate rutie;
11
-
12
- use rutie::{Module, Object};
13
-
14
- module!(Y);
15
-
16
- #[allow(non_snake_case)]
17
- #[no_mangle]
18
- pub extern "C" fn Init_yrb() {
19
- Module::new("Y").define(|module| {
20
- module.define_nested_class("Array", None).define(|klass| {
21
- klass.def_private("yarray_each", yarray::yarray_each);
22
- klass.def_private("yarray_get", yarray::yarray_get);
23
- klass.def_private("yarray_insert", yarray::yarray_insert);
24
- klass.def_private(
25
- "yarray_insert_range",
26
- yarray::yarray_insert_range
27
- );
28
- klass.def_private("yarray_length", yarray::yarray_length);
29
- klass.def_private("yarray_observe", yarray::yarray_observe);
30
- klass.def_private("yarray_push_back", yarray::yarray_push_back);
31
- klass.def_private("yarray_push_front", yarray::yarray_push_front);
32
- klass.def_private("yarray_remove", yarray::yarray_remove);
33
- klass.def_private(
34
- "yarray_remove_range",
35
- yarray::yarray_remove_range
36
- );
37
- klass.def_private("yarray_to_a", yarray::yarray_to_a);
38
- klass.def_private("yarray_unobserve", yarray::yarray_unobserve);
39
- });
40
-
41
- module.define_nested_class("Doc", None).define(|klass| {
42
- klass.def_self("new", ydoc::ydoc_new);
43
- klass.def_private("ydoc_transact", ydoc::ydoc_transact);
44
- klass.def_private("ydoc_encode_diff_v1", ydoc::ydoc_encode_diff_v1);
45
- });
46
-
47
- module.define_nested_class("Map", None).define(|klass| {
48
- klass.def_private("ymap_clear", ymap::ymap_clear);
49
- klass.def_private("ymap_contains", ymap::ymap_contains);
50
- klass.def_private("ymap_each", ymap::ymap_each);
51
- klass.def_private("ymap_get", ymap::ymap_get);
52
- klass.def_private("ymap_insert", ymap::ymap_insert);
53
- klass.def_private("ymap_observe", ymap::ymap_observe);
54
- klass.def_private("ymap_remove", ymap::ymap_remove);
55
- klass.def_private("ymap_size", ymap::ymap_size);
56
- klass.def_private("ymap_to_h", ymap::ymap_to_hash);
57
- klass.def_private("ymap_unobserve", ymap::ymap_unobserve);
58
- });
59
-
60
- module
61
- .define_nested_class("SubscriptionID", None)
62
- .define(|_klass| {});
63
-
64
- module.define_nested_class("Text", None).define(|klass| {
65
- klass.def_private("ytext_insert", ytext::ytext_insert);
66
- klass.def_private("ytext_insert_embed", ytext::ytext_insert_embed);
67
- klass.def_private(
68
- "ytext_insert_embed_with_attrs",
69
- ytext::ytext_insert_embed_with_attributes
70
- );
71
- klass.def_private(
72
- "ytext_insert_with_attrs",
73
- ytext::ytext_insert_with_attributes
74
- );
75
- klass.def_private("ytext_remove_range", ytext::ytext_remove_range);
76
- klass.def_private("ytext_format", ytext::ytext_format);
77
- klass.def_private("ytext_length", ytext::ytext_length);
78
- klass.def_private("ytext_observe", ytext::ytext_observe);
79
- klass.def_private("ytext_push", ytext::ytext_push);
80
- klass.def_private("ytext_to_s", ytext::ytext_to_string);
81
- klass.def_private("ytext_unobserve", ytext::ytext_unobserve);
82
- });
83
-
84
- module
85
- .define_nested_class("Transaction", None)
86
- .define(|klass| {
87
- klass.def_private(
88
- "ytransaction_apply_update",
89
- ytransaction::ytransaction_apply_update
90
- );
91
- klass.def_private(
92
- "ytransaction_commit",
93
- ytransaction::ytransaction_commit
94
- );
95
- klass.def_private(
96
- "ytransaction_get_array",
97
- ytransaction::ytransaction_get_array
98
- );
99
- klass.def_private(
100
- "ytransaction_get_map",
101
- ytransaction::ytransaction_get_map
102
- );
103
- klass.def_private(
104
- "ytransaction_get_text",
105
- ytransaction::ytransaction_get_text
106
- );
107
- klass.def_private(
108
- "ytransaction_get_xml_element",
109
- ytransaction::ytransaction_get_xml_element
110
- );
111
- klass.def_private(
112
- "ytransaction_get_xml_text",
113
- ytransaction::ytransaction_get_xml_text
114
- );
115
- klass.def_private(
116
- "ytransaction_state_vector",
117
- ytransaction::ytransaction_state_vector
118
- );
119
- });
120
-
121
- module
122
- .define_nested_class("XMLElement", None)
123
- .define(|klass| {
124
- klass.def_private(
125
- "yxml_element_attributes",
126
- yxml::yxml_element_attributes
127
- );
128
- klass.def_private(
129
- "yxml_element_first_child",
130
- yxml::yxml_element_first_child
131
- );
132
- klass.def_private("yxml_element_get", yxml::yxml_element_get);
133
- klass.def_private(
134
- "yxml_element_get_attribute",
135
- yxml::yxml_element_get_attribute
136
- );
137
- klass.def_private(
138
- "yxml_element_insert_attribute",
139
- yxml::yxml_element_insert_attribute
140
- );
141
- klass.def_private(
142
- "yxml_element_insert_element",
143
- yxml::yxml_element_insert_element
144
- );
145
- klass.def_private(
146
- "yxml_element_insert_text",
147
- yxml::yxml_element_insert_text
148
- );
149
- klass.def_private(
150
- "yxml_element_next_sibling",
151
- yxml::yxml_element_next_sibling
152
- );
153
- klass.def_private(
154
- "yxml_element_observe",
155
- yxml::yxml_element_observe
156
- );
157
- klass.def_private(
158
- "yxml_element_parent",
159
- yxml::yxml_element_parent
160
- );
161
- klass.def_private(
162
- "yxml_element_prev_sibling",
163
- yxml::yxml_element_prev_sibling
164
- );
165
- klass.def_private(
166
- "yxml_element_push_elem_back",
167
- yxml::yxml_element_push_elem_back
168
- );
169
- klass.def_private(
170
- "yxml_element_push_elem_front",
171
- yxml::yxml_element_push_elem_front
172
- );
173
- klass.def_private(
174
- "yxml_element_push_text_back",
175
- yxml::yxml_element_push_text_back
176
- );
177
- klass.def_private(
178
- "yxml_element_push_text_front",
179
- yxml::yxml_element_push_text_front
180
- );
181
- klass.def_private(
182
- "yxml_element_remove_attribute",
183
- yxml::yxml_element_remove_attribute
184
- );
185
- klass.def_private(
186
- "yxml_element_remove_range",
187
- yxml::yxml_element_remove_range
188
- );
189
- klass.def_private("yxml_element_size", yxml::yxml_element_size);
190
- klass.def_private("yxml_element_tag", yxml::yxml_element_tag);
191
- klass.def_private(
192
- "yxml_element_to_s",
193
- yxml::yxml_element_to_string
194
- );
195
- klass.def_private(
196
- "yxml_element_unobserve",
197
- yxml::yxml_element_unobserve
198
- );
199
- });
200
-
201
- module.define_nested_class("XMLText", None).define(|klass| {
202
- klass.def_private(
203
- "yxml_text_attributes",
204
- yxml::yxml_text_attributes
205
- );
206
- klass.def_private("yxml_text_format", yxml::yxml_text_format);
207
- klass.def_private(
208
- "yxml_text_get_attribute",
209
- yxml::yxml_text_get_attribute
210
- );
211
- klass.def_private("yxml_text_insert", yxml::yxml_text_insert);
212
- klass.def_private(
213
- "yxml_text_insert_attribute",
214
- yxml::yxml_text_insert_attribute
215
- );
216
- klass.def_private(
217
- "yxml_text_insert_embed",
218
- yxml::yxml_text_insert_embed
219
- );
220
- klass.def_private(
221
- "yxml_text_insert_embed_with_attrs",
222
- yxml::yxml_text_insert_embed_with_attributes
223
- );
224
- klass.def_private(
225
- "yxml_text_insert_with_attrs",
226
- yxml::yxml_text_insert_with_attributes
227
- );
228
- klass.def_private("yxml_text_length", yxml::yxml_text_length);
229
- klass.def_private(
230
- "yxml_text_next_sibling",
231
- yxml::yxml_text_next_sibling
232
- );
233
- klass.def_private("yxml_text_observe", yxml::yxml_text_observe);
234
- klass.def_private("yxml_text_parent", yxml::yxml_text_parent);
235
- klass.def_private(
236
- "yxml_text_prev_sibling",
237
- yxml::yxml_text_prev_sibling
238
- );
239
- klass.def_private("yxml_text_push", yxml::yxml_text_push);
240
- klass.def_private(
241
- "yxml_text_remove_range",
242
- yxml::yxml_text_remove_range
243
- );
244
- klass.def_private("yxml_text_to_s", yxml::yxml_text_to_string);
245
- klass.def_private("yxml_text_unobserve", yxml::yxml_text_unobserve);
246
- });
247
- });
248
- }