y-rb 0.1.2 → 0.1.4.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
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
- }