y-rb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/src/ymap.rs ADDED
@@ -0,0 +1,199 @@
1
+ use crate::util::{map_ruby_type_to_rust, map_yrs_value_to_ruby};
2
+ use crate::ytransaction::{YTransaction, TRANSACTION_WRAPPER};
3
+ use lib0::any::Any;
4
+ use rutie::{
5
+ AnyObject, Array, Boolean, Class, Fixnum, Hash, Integer, NilClass, Object,
6
+ Proc, RString, Symbol, VM,
7
+ };
8
+ use std::rc::Rc;
9
+ use yrs::types::EntryChange;
10
+ use yrs::{Map, SubscriptionId};
11
+
12
+ wrappable_struct!(Map, MapWrapper, MAP_WRAPPER);
13
+ class!(YMap);
14
+
15
+ #[rustfmt::skip]
16
+ methods!(
17
+ YMap,
18
+ rtself,
19
+ fn ymap_clear(transaction: YTransaction) -> NilClass {
20
+ let mut tx = transaction.map_err(|e| VM::raise_ex(e)).unwrap();
21
+ let txn = tx.get_data_mut(&*TRANSACTION_WRAPPER);
22
+
23
+ let m: &Map = rtself.get_data(&*MAP_WRAPPER);
24
+ m.clear(txn);
25
+
26
+ NilClass::new()
27
+ },
28
+ fn ymap_contains(key: AnyObject) -> Boolean {
29
+ let k = key.map_err(|e| VM::raise_ex(e)).unwrap();
30
+
31
+ let k2 = if let Ok(t) = k.try_convert_to::<Symbol>() {
32
+ t.to_string()
33
+ } else if let Ok(t) = k.try_convert_to::<RString>() {
34
+ t.to_string()
35
+ } else {
36
+ VM::raise(Class::from_existing("IllegalArgumentError"), "Only strings and symbols are supported as map keys.");
37
+ return Boolean::new(false);
38
+ };
39
+
40
+ let m: &Map = rtself.get_data(&*MAP_WRAPPER);
41
+ let result = m.contains(&k2);
42
+
43
+ Boolean::new(result)
44
+ },
45
+ fn ymap_each(block: Proc) -> NilClass {
46
+ let b = block.map_err(|e| VM::raise_ex(e)).unwrap();
47
+
48
+ let m: &Map = rtself.get_data(&*MAP_WRAPPER);
49
+
50
+ m
51
+ .iter()
52
+ .for_each(|(key, val)| {
53
+ let args = [
54
+ RString::new_utf8(key).to_any_object(),
55
+ map_yrs_value_to_ruby(val)
56
+ ];
57
+ b.call(&args);
58
+ });
59
+
60
+ NilClass::new()
61
+ },
62
+ fn ymap_get(key: AnyObject) -> AnyObject {
63
+ let k = key.map_err(|e| VM::raise_ex(e)).unwrap();
64
+
65
+ let k2 = if let Ok(t) = k.try_convert_to::<Symbol>() {
66
+ t.to_string()
67
+ } else if let Ok(t) = k.try_convert_to::<RString>() {
68
+ t.to_string()
69
+ } else {
70
+ VM::raise(Class::from_existing("IllegalArgumentError"), "Only strings and symbols are supported as map keys.");
71
+ return NilClass::new().to_any_object();
72
+ };
73
+
74
+ let m: &Map = rtself.get_data(&*MAP_WRAPPER);
75
+ let result = m.get(&k2);
76
+
77
+ map_yrs_value_to_ruby(result.unwrap_or(yrs::types::Value::Any(Any::Null)))
78
+ },
79
+ fn ymap_insert(transaction: YTransaction, key: AnyObject, value: AnyObject) -> AnyObject {
80
+ let mut tx = transaction.map_err(|e| VM::raise_ex(e)).unwrap();
81
+ let k = key.map_err(|e| VM::raise_ex(e)).unwrap();
82
+ let v = value.map_err(|e| VM::raise_ex(e)).unwrap();
83
+
84
+ let k2 = if let Ok(t) = k.try_convert_to::<Symbol>() {
85
+ t.to_string()
86
+ } else if let Ok(t) = k.try_convert_to::<RString>() {
87
+ t.to_string()
88
+ } else {
89
+ VM::raise(Class::from_existing("IllegalArgumentError"), "Only strings and symbols are supported as map keys.");
90
+ return NilClass::new().to_any_object();
91
+ };
92
+
93
+ let txn = tx.get_data_mut(&*TRANSACTION_WRAPPER);
94
+
95
+ let m: &Map = rtself.get_data(&*MAP_WRAPPER);
96
+
97
+ let result = m.insert(
98
+ txn,
99
+ Rc::from(k2),
100
+ map_ruby_type_to_rust(v).unwrap()
101
+ );
102
+
103
+ map_yrs_value_to_ruby(result.unwrap_or(yrs::types::Value::Any(Any::Null)))
104
+ },
105
+ fn ymap_observe(callback: Proc) -> Integer {
106
+ let c = callback.map_err(|e| VM::raise_ex(e)).unwrap();
107
+
108
+ let map: &mut Map = rtself.get_data_mut(&*MAP_WRAPPER);
109
+ let subscription_id: SubscriptionId = map
110
+ .observe(move |transaction, map_event| {
111
+ let delta = map_event.keys(transaction);
112
+ let mut changes: Vec<AnyObject> = Vec::new();
113
+
114
+ for (key, change) in delta {
115
+ match change {
116
+ EntryChange::Inserted(v) => {
117
+ let mut h = Hash::new();
118
+ h.store(Symbol::new(&key.to_string()), map_yrs_value_to_ruby(v.clone()));
119
+
120
+ let mut payload = Hash::new();
121
+ payload.store(Symbol::new("inserted"), h);
122
+
123
+ changes.push(payload.to_any_object());
124
+ },
125
+ EntryChange::Updated(old, new) => {
126
+ let mut values = Array::with_capacity(2);
127
+ values.push(map_yrs_value_to_ruby(old.clone()));
128
+ values.push(map_yrs_value_to_ruby(new.clone()));
129
+
130
+ let mut h = Hash::new();
131
+ h.store(Symbol::new(&key.to_string()), values);
132
+
133
+ let mut payload = Hash::new();
134
+ payload.store(Symbol::new("updated"), h);
135
+
136
+ changes.push(payload.to_any_object());
137
+ },
138
+ EntryChange::Removed(v) => {
139
+ let mut h = Hash::new();
140
+ h.store(Symbol::new(&key.to_string()), map_yrs_value_to_ruby(v.clone()));
141
+
142
+ let mut payload = Hash::new();
143
+ payload.store(Symbol::new("removed"), h);
144
+
145
+ changes.push(payload.to_any_object());
146
+ }
147
+ }
148
+ }
149
+
150
+ let args = &[Array::from_iter(changes).to_any_object()];
151
+ c.call(args);
152
+ })
153
+ .into();
154
+
155
+ Integer::from(subscription_id)
156
+ },
157
+ fn ymap_remove(transaction: YTransaction, key: AnyObject) -> AnyObject {
158
+ let mut tx = transaction.map_err(|e| VM::raise_ex(e)).unwrap();
159
+ let k = key.map_err(|e| VM::raise_ex(e)).unwrap();
160
+
161
+ let k2 = if let Ok(t) = k.try_convert_to::<Symbol>() {
162
+ t.to_string()
163
+ } else if let Ok(t) = k.try_convert_to::<RString>() {
164
+ t.to_string()
165
+ } else {
166
+ VM::raise(Class::from_existing("IllegalArgumentError"), "Only strings and symbols are supported as map keys.");
167
+ return NilClass::new().to_any_object();
168
+ };
169
+
170
+ let txn = tx.get_data_mut(&*TRANSACTION_WRAPPER);
171
+
172
+ let m: &Map = rtself.get_data(&*MAP_WRAPPER);
173
+ let result = m.remove(txn, &k2);
174
+
175
+ map_yrs_value_to_ruby(result.unwrap_or(yrs::types::Value::Any(Any::Null)))
176
+ },
177
+ fn ymap_size() -> Fixnum {
178
+ let m: &Map = rtself.get_data(&*MAP_WRAPPER);
179
+ Fixnum::new(i64::from(m.len()))
180
+ },
181
+ fn ymap_to_hash() -> Hash {
182
+ let m: &Map = rtself.get_data(&*MAP_WRAPPER);
183
+ let mut h = Hash::new();
184
+
185
+ for (key, val) in m.iter() {
186
+ h.store(Symbol::new(key), map_yrs_value_to_ruby(val));
187
+ }
188
+
189
+ h
190
+ },
191
+ fn ymap_unobserve(subscription_id: Integer) -> NilClass {
192
+ let s = subscription_id.map_err(|e| VM::raise_ex(e)).unwrap();
193
+
194
+ let map: &mut Map = rtself.get_data_mut(&*MAP_WRAPPER);
195
+ map.unobserve(s.into());
196
+
197
+ NilClass::new()
198
+ }
199
+ );
data/src/ytext.rs ADDED
@@ -0,0 +1,204 @@
1
+ use crate::util::{
2
+ map_attrs_to_hash, map_hash_to_attrs, map_ruby_type_to_rust,
3
+ map_yrs_value_to_ruby,
4
+ };
5
+ use crate::ytransaction::{YTransaction, TRANSACTION_WRAPPER};
6
+ use rutie::{
7
+ AnyObject, Fixnum, Hash, Integer, NilClass, Object, Proc, RString, Symbol,
8
+ VM,
9
+ };
10
+ use yrs::types::Delta;
11
+ use yrs::{SubscriptionId, Text};
12
+
13
+ wrappable_struct!(Text, TextWrapper, TEXT_WRAPPER);
14
+ class!(YText);
15
+
16
+ #[rustfmt::skip]
17
+ methods!(
18
+ YText,
19
+ rtself,
20
+ fn ytext_insert(transaction: YTransaction, index: Fixnum, chunk: RString) -> NilClass {
21
+ let mut txn = transaction.map_err(|e| VM::raise_ex(e)).unwrap();
22
+
23
+ let i = index.map_err(|e| VM::raise_ex(e)).unwrap();
24
+
25
+ let c = chunk.map_err(|e| VM::raise_ex(e)).unwrap().to_string();
26
+
27
+ let tx = txn.get_data_mut(&*TRANSACTION_WRAPPER);
28
+ let text: &Text = rtself.get_data_mut(&*TEXT_WRAPPER);
29
+
30
+ text.insert(tx, i.to_u32(), &c);
31
+
32
+ NilClass::new()
33
+ },
34
+ fn ytext_insert_embed(
35
+ transaction: YTransaction,
36
+ index: Fixnum,
37
+ content: AnyObject) -> NilClass {
38
+ let mut txn = transaction.map_err(|e| VM::raise_ex(e)).unwrap();
39
+ let i = index.map_err(|e| VM::raise_ex(e)).unwrap();
40
+
41
+ let c = content.map_err(|e| VM::raise_ex(e)).unwrap();
42
+ let v = map_ruby_type_to_rust(c).map_err(|e| VM::raise_ex(e)).unwrap();
43
+
44
+ let tx = txn.get_data_mut(&*TRANSACTION_WRAPPER);
45
+ let text: &Text = rtself.get_data_mut(&*TEXT_WRAPPER);
46
+
47
+ text.insert_embed(tx, i.to_u32(), v);
48
+
49
+ NilClass::new()
50
+ }
51
+ fn ytext_insert_embed_with_attributes(
52
+ transaction: YTransaction,
53
+ index: Fixnum,
54
+ embed: AnyObject,
55
+ attrs: Hash) -> NilClass {
56
+ let mut txn = transaction.map_err(|e| VM::raise_ex(e)).unwrap();
57
+ let i = index.map_err(|e| VM::raise_ex(e)).unwrap();
58
+
59
+ let c = embed.map_err(|e| VM::raise_ex(e)).unwrap();
60
+ let v = map_ruby_type_to_rust(c).map_err(|e| VM::raise_ex(e)).unwrap();
61
+
62
+ let a = attrs.map_err(|e| VM::raise_ex(e)).unwrap();
63
+ let mapped_attrs = map_hash_to_attrs(a);
64
+
65
+ let tx = txn.get_data_mut(&*TRANSACTION_WRAPPER);
66
+ let text: &Text = rtself.get_data_mut(&*TEXT_WRAPPER);
67
+
68
+ text.insert_embed_with_attributes(tx, i.to_u32(), v, mapped_attrs);
69
+
70
+ NilClass::new()
71
+ }
72
+ fn ytext_insert_with_attributes(
73
+ transaction: YTransaction,
74
+ index: Fixnum,
75
+ chunk: RString,
76
+ attrs: Hash) -> NilClass {
77
+ let mut txn = transaction.map_err(|e| VM::raise_ex(e)).unwrap();
78
+ let i = index.map_err(|e| VM::raise_ex(e)).unwrap();
79
+
80
+ let c = chunk.map_err(|e| VM::raise_ex(e)).unwrap().to_string();
81
+
82
+ let a = attrs.map_err(|e| VM::raise_ex(e)).unwrap();
83
+ let mapped_attrs = map_hash_to_attrs(a);
84
+
85
+ let tx = txn.get_data_mut(&*TRANSACTION_WRAPPER);
86
+ let text: &Text = rtself.get_data_mut(&*TEXT_WRAPPER);
87
+
88
+ text.insert_with_attributes(tx, i.to_u32(), &c, mapped_attrs);
89
+
90
+ NilClass::new()
91
+ },
92
+ fn ytext_length() -> Fixnum {
93
+ let text = rtself.get_data(&*TEXT_WRAPPER);
94
+
95
+ Fixnum::new(i64::from(text.len()))
96
+ }
97
+ fn ytext_push(transaction: YTransaction, value: RString) -> NilClass {
98
+ let value_str = value.map_err(|e| VM::raise_ex(e)).unwrap().to_string();
99
+
100
+ let mut txn = transaction.map_err(|e| VM::raise_ex(e)).unwrap();
101
+
102
+ let t = txn.get_data_mut(&*TRANSACTION_WRAPPER);
103
+ let text = rtself.get_data_mut(&*TEXT_WRAPPER);
104
+
105
+ text.push(t, &value_str);
106
+
107
+ NilClass::new()
108
+ },
109
+ fn ytext_remove_range(transaction: YTransaction, index: Fixnum, length: Fixnum) -> NilClass {
110
+ let mut txn = transaction.map_err(|e| VM::raise_ex(e)).unwrap();
111
+ let i = index.map_err(|e| VM::raise_ex(e)).unwrap();
112
+ let l = length.map_err(|e| VM::raise_ex(e)).unwrap();
113
+
114
+ let tx = txn.get_data_mut(&*TRANSACTION_WRAPPER);
115
+ let text: &Text = rtself.get_data_mut(&*TEXT_WRAPPER);
116
+
117
+ text.remove_range(tx, i.to_u32(), l.to_u32());
118
+
119
+ NilClass::new()
120
+ },
121
+ fn ytext_format(transaction: YTransaction, index: Fixnum, length: Fixnum, attrs: Hash) -> NilClass {
122
+ let mut txn = transaction.map_err(|e| VM::raise_ex(e)).unwrap();
123
+ let i = index.map_err(|e| VM::raise_ex(e)).unwrap();
124
+ let l = length.map_err(|e| VM::raise_ex(e)).unwrap();
125
+
126
+ let a = attrs.map_err(|e| VM::raise_ex(e)).unwrap();
127
+ let mapped_attrs = map_hash_to_attrs(a);
128
+
129
+ let tx = txn.get_data_mut(&*TRANSACTION_WRAPPER);
130
+ let text: &Text = rtself.get_data_mut(&*TEXT_WRAPPER);
131
+
132
+ text.format(tx, i.to_u32(), l.to_u32(), mapped_attrs);
133
+
134
+ NilClass::new()
135
+ },
136
+ fn ytext_observe(callback: Proc) -> Integer {
137
+ let c = callback.map_err(|e| VM::raise_ex(e)).unwrap();
138
+
139
+ let text: &mut Text = rtself.get_data_mut(&*TEXT_WRAPPER);
140
+ let subscription_id: SubscriptionId = text
141
+ .observe(move |transaction, text_event| {
142
+ let delta = text_event.delta(transaction);
143
+ for event in delta {
144
+ match event {
145
+ Delta::Inserted(v, attrs) => {
146
+ let mut payload = Hash::new();
147
+ payload.store(Symbol::new("insert"), map_yrs_value_to_ruby(v.clone()));
148
+
149
+ match attrs {
150
+ Some(a) => {
151
+ let copy = a.clone();
152
+ let result = map_attrs_to_hash(*copy).to_any_object();
153
+ payload.store(Symbol::new("attributes"), result);
154
+ },
155
+ None => ()
156
+ }
157
+
158
+ let args = &[payload.to_any_object()];
159
+ c.call(args);
160
+ },
161
+ Delta::Retain(position, attrs) => {
162
+ let mut payload = Hash::new();
163
+ payload.store(Symbol::new("retain"), Integer::from(*position));
164
+
165
+ match attrs {
166
+ Some(a) => {
167
+ let copy = a.clone();
168
+ let result = map_attrs_to_hash(*copy).to_any_object();
169
+ payload.store(Symbol::new("attributes"), result);
170
+ },
171
+ None => ()
172
+ }
173
+
174
+ let args = &[payload.to_any_object()];
175
+ c.call(args);
176
+ },
177
+ Delta::Deleted(position) => {
178
+ let mut payload = Hash::new();
179
+ payload.store(Symbol::new("delete"), Integer::from(*position));
180
+
181
+ let args = &[payload.to_any_object()];
182
+ c.call(args);
183
+ }
184
+ }
185
+ }
186
+ })
187
+ .into();
188
+
189
+ Integer::from(subscription_id)
190
+ },
191
+ fn ytext_to_string() -> RString {
192
+ let text = rtself.get_data(&*TEXT_WRAPPER);
193
+
194
+ RString::new_utf8(&text.to_string())
195
+ },
196
+ fn ytext_unobserve(subscription_id: Integer) -> NilClass {
197
+ let s = subscription_id.map_err(|e| VM::raise_ex(e)).unwrap();
198
+
199
+ let text: &mut Text = rtself.get_data_mut(&*TEXT_WRAPPER);
200
+ text.unobserve(s.into());
201
+
202
+ NilClass::new()
203
+ }
204
+ );
@@ -0,0 +1,101 @@
1
+ use crate::util::{convert_array_to_vecu8, convert_vecu8_to_array};
2
+ use crate::yarray::ARRAY_WRAPPER;
3
+ use crate::ymap::MAP_WRAPPER;
4
+ use crate::ytext::TEXT_WRAPPER;
5
+ use crate::yxml::{XML_ELEMENT_WRAPPER, XML_TEXT_WRAPPER};
6
+ use rutie::{
7
+ AnyObject, Array, Module, NilClass, Object, RString, VerifiedObject, VM,
8
+ };
9
+ use yrs::updates::decoder::Decode;
10
+ use yrs::updates::encoder::Encode;
11
+ use yrs::{Transaction, Update};
12
+
13
+ wrappable_struct!(Transaction, TransactionWrapper, TRANSACTION_WRAPPER);
14
+ class!(YTransaction);
15
+
16
+ impl VerifiedObject for YTransaction {
17
+ fn is_correct_type<T: Object>(object: &T) -> bool {
18
+ object.class()
19
+ == Module::from_existing("Y").get_nested_class("Transaction")
20
+ }
21
+
22
+ fn error_message() -> &'static str {
23
+ "Error converting to YTransaction"
24
+ }
25
+ }
26
+
27
+ methods!(
28
+ YTransaction,
29
+ rtself,
30
+ fn ytransaction_apply_update(update: Array) -> NilClass {
31
+ let u = convert_array_to_vecu8(update.unwrap());
32
+
33
+ let transaction = rtself.get_data_mut(&*TRANSACTION_WRAPPER);
34
+ transaction.apply_update(Update::decode_v1(u.as_slice()));
35
+
36
+ NilClass::new()
37
+ },
38
+ fn ytransaction_commit() -> NilClass {
39
+ let transaction = rtself.get_data_mut(&*TRANSACTION_WRAPPER);
40
+ transaction.commit();
41
+
42
+ NilClass::new()
43
+ },
44
+ fn ytransaction_get_array(name: RString) -> AnyObject {
45
+ let name_str = name.map_err(|e| VM::raise_ex(e)).unwrap().to_string();
46
+
47
+ let transaction = rtself.get_data_mut(&*TRANSACTION_WRAPPER);
48
+ let arr = transaction.get_array(&name_str);
49
+
50
+ Module::from_existing("Y")
51
+ .get_nested_class("Array")
52
+ .wrap_data(arr, &*ARRAY_WRAPPER)
53
+ },
54
+ fn ytransaction_get_map(name: RString) -> AnyObject {
55
+ let name_str = name.map_err(|e| VM::raise_ex(e)).unwrap().to_string();
56
+
57
+ let transaction = rtself.get_data_mut(&*TRANSACTION_WRAPPER);
58
+ let map = transaction.get_map(&name_str);
59
+
60
+ Module::from_existing("Y")
61
+ .get_nested_class("Map")
62
+ .wrap_data(map, &*MAP_WRAPPER)
63
+ },
64
+ fn ytransaction_get_text(name: RString) -> AnyObject {
65
+ let name_str = name.map_err(|e| VM::raise_ex(e)).unwrap().to_string();
66
+
67
+ let transaction = rtself.get_data_mut(&*TRANSACTION_WRAPPER);
68
+ let text = transaction.get_text(&name_str);
69
+
70
+ Module::from_existing("Y")
71
+ .get_nested_class("Text")
72
+ .wrap_data(text, &*TEXT_WRAPPER)
73
+ },
74
+ fn ytransaction_get_xml_element(name: RString) -> AnyObject {
75
+ let name_str = name.map_err(|e| VM::raise_ex(e)).unwrap().to_string();
76
+
77
+ let transaction = rtself.get_data_mut(&*TRANSACTION_WRAPPER);
78
+ let xml_element = transaction.get_xml_element(&name_str);
79
+
80
+ Module::from_existing("Y")
81
+ .get_nested_class("XMLElement")
82
+ .wrap_data(xml_element, &*XML_ELEMENT_WRAPPER)
83
+ },
84
+ fn ytransaction_get_xml_text(name: RString) -> AnyObject {
85
+ let name_str = name.map_err(|e| VM::raise_ex(e)).unwrap().to_string();
86
+
87
+ let transaction = rtself.get_data_mut(&*TRANSACTION_WRAPPER);
88
+ let xml_text = transaction.get_xml_text(&name_str);
89
+
90
+ Module::from_existing("Y")
91
+ .get_nested_class("XMLText")
92
+ .wrap_data(xml_text, &*XML_TEXT_WRAPPER)
93
+ },
94
+ fn ytransaction_state_vector() -> Array {
95
+ let transaction = rtself.get_data_mut(&*TRANSACTION_WRAPPER);
96
+ let sv = transaction.state_vector();
97
+ let payload = sv.encode_v1();
98
+
99
+ convert_vecu8_to_array(payload)
100
+ }
101
+ );