y-rb 0.1.2 → 0.1.4.alpha.1

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.
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,9 +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 v0.1.1 -m "Release version v0.1.1"`
9
- 5. Push tag to GitLab repo
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,17 +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
- Rutie.new(:y_rb).init(
14
- "Init_yrb",
15
- File.join(__dir__, "..")
16
- )
17
- 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
- }
data/src/util.rs DELETED
@@ -1,146 +0,0 @@
1
- use crate::ymap::MAP_WRAPPER;
2
- use crate::ytext::TEXT_WRAPPER;
3
- use crate::yxml::{XML_ELEMENT_WRAPPER, XML_TEXT_WRAPPER};
4
- use lib0::any::Any;
5
- use rutie::{
6
- AnyException, AnyObject, Array, Boolean, Exception, Fixnum, Float, Hash,
7
- Integer, Module, NilClass, Object, RString, Symbol
8
- };
9
- use std::borrow::Borrow;
10
- use std::collections::HashMap;
11
- use std::convert::TryFrom;
12
- use std::rc::Rc;
13
- use yrs::types::{Attrs, Value};
14
-
15
- pub(crate) fn convert_vecu8_to_array(vec: Vec<u8>) -> Array {
16
- let mut array = Array::new();
17
-
18
- for i in vec {
19
- array.push(Fixnum::new(i64::from(i)));
20
- }
21
-
22
- array
23
- }
24
-
25
- pub(crate) fn convert_array_to_vecu8(arr: Array) -> Vec<u8> {
26
- arr.into_iter()
27
- .map(|val| val.try_convert_to::<Fixnum>().unwrap().to_u32())
28
- .map(|val| u8::try_from(val).unwrap())
29
- .collect()
30
- }
31
-
32
- pub(crate) fn map_any_type_to_ruby(input: &Any) -> AnyObject {
33
- match input {
34
- Any::Null => NilClass::new().to_any_object(),
35
- Any::Undefined => NilClass::new().to_any_object(),
36
- Any::Bool(b) => Boolean::new(*b).to_any_object(),
37
- Any::Number(f) => Float::new(*f).to_any_object(),
38
- Any::BigInt(i) => Integer::new(*i).to_any_object(),
39
- Any::String(s) => RString::new_utf8(s.as_ref()).to_any_object(),
40
- // TODO convert buffer into an array of Fixnum
41
- Any::Buffer(_b) => Array::new().to_any_object(),
42
- Any::Array(a) => {
43
- let values = a.iter().map(|n| map_any_type_to_ruby(n));
44
- Array::from_iter(values).to_any_object()
45
- }
46
- Any::Map(m) => {
47
- let mut h = Hash::new();
48
- m.iter().for_each(|(k, v)| {
49
- let key = Symbol::new(k.as_ref());
50
- let val = map_any_type_to_ruby(v);
51
- h.store(key, val);
52
- });
53
- h.to_any_object()
54
- }
55
- }
56
- }
57
-
58
- pub(crate) fn map_yrs_value_to_ruby(value: Value) -> AnyObject {
59
- match value {
60
- Value::Any(v) => map_any_type_to_ruby(v.borrow()),
61
- Value::YArray(a) => {
62
- let values = a.iter().map(|n| map_yrs_value_to_ruby(n));
63
- Array::from_iter(values).to_any_object()
64
- }
65
- Value::YMap(m) => Module::from_existing("Y")
66
- .get_nested_class("Text")
67
- .wrap_data(m, &*MAP_WRAPPER),
68
- Value::YText(t) => Module::from_existing("Y")
69
- .get_nested_class("Text")
70
- .wrap_data(t, &*TEXT_WRAPPER),
71
- Value::YXmlElement(x) => Module::from_existing("Y")
72
- .get_nested_class("XMLElement")
73
- .wrap_data(x, &*XML_ELEMENT_WRAPPER),
74
- Value::YXmlText(x) => Module::from_existing("Y")
75
- .get_nested_class("XMLText")
76
- .wrap_data(x, &*XML_TEXT_WRAPPER)
77
- }
78
- }
79
-
80
- pub(crate) fn map_ruby_type_to_rust(
81
- input: AnyObject
82
- ) -> Result<Any, AnyException> {
83
- if let Ok(_v) = input.try_convert_to::<NilClass>() {
84
- return Ok(Any::Null);
85
- } else if let Ok(v) = input.try_convert_to::<Boolean>() {
86
- return Ok(Any::Bool(v.to_bool()));
87
- } else if let Ok(v) = input.try_convert_to::<Float>() {
88
- return Ok(Any::Number(v.to_f64()));
89
- } else if let Ok(v) = input.try_convert_to::<Fixnum>() {
90
- return Ok(Any::BigInt(v.to_i64()));
91
- } else if let Ok(v) = input.try_convert_to::<Integer>() {
92
- return Ok(Any::BigInt(v.to_i64()));
93
- } else if let Ok(v) = input.try_convert_to::<RString>() {
94
- return Ok(Any::String(Box::from(v.to_str())));
95
- } else if let Ok(v) = input.try_convert_to::<Array>() {
96
- let arr: Vec<Any> = v
97
- .into_iter()
98
- .map(|value| map_ruby_type_to_rust(value).unwrap())
99
- .collect();
100
- return Ok(Any::Array(arr.into_boxed_slice()));
101
- } else if let Ok(v) = input.try_convert_to::<Hash>() {
102
- let m = map_hash_to_rust(v);
103
- return Ok(Any::Map(Box::from(m)));
104
- }
105
-
106
- Err(AnyException::new(
107
- "TypeError",
108
- Some("cannot map input type")
109
- ))
110
- }
111
-
112
- // This function gets reported as unused.
113
- pub(crate) fn map_hash_to_rust(input: Hash) -> HashMap<String, Any> {
114
- let mut m = HashMap::with_capacity(input.length());
115
- input.each(|key, value| {
116
- if let Ok(v) = map_ruby_type_to_rust(value) {
117
- if let Ok(k) = key.try_convert_to::<RString>() {
118
- m.insert(k.to_string(), v);
119
- } else if let Ok(k) = key.try_convert_to::<Symbol>() {
120
- m.insert(k.to_string(), v);
121
- }
122
- }
123
- });
124
- m
125
- }
126
-
127
- pub(crate) fn map_hash_to_attrs(input: Hash) -> Attrs {
128
- let attributes = map_hash_to_rust(input);
129
- let mut attrs = Attrs::with_capacity(attributes.len());
130
- for (k, v) in attributes {
131
- attrs.insert(Rc::from(k), v);
132
- }
133
- attrs
134
- }
135
-
136
- pub(crate) fn map_attrs_to_hash(attrs: Attrs) -> Hash {
137
- let mut h = Hash::new();
138
-
139
- for (key, val) in attrs {
140
- let key = Symbol::new(key.as_ref());
141
- let value = map_any_type_to_ruby(val.borrow());
142
- h.store(key, value);
143
- }
144
-
145
- h
146
- }