y-rb 0.6.0-x86_64-linux-gnu
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ext/yrb/Cargo.toml +21 -0
- data/ext/yrb/extconf.rb +6 -0
- data/ext/yrb/src/lib.rs +649 -0
- data/ext/yrb/src/utils.rs +64 -0
- data/ext/yrb/src/yany.rs +46 -0
- data/ext/yrb/src/yarray.rs +191 -0
- data/ext/yrb/src/yattrs.rs +39 -0
- data/ext/yrb/src/yawareness.rs +151 -0
- data/ext/yrb/src/ydiff.rs +19 -0
- data/ext/yrb/src/ydoc.rs +113 -0
- data/ext/yrb/src/ymap.rs +175 -0
- data/ext/yrb/src/ytext.rs +235 -0
- data/ext/yrb/src/ytransaction.rs +127 -0
- data/ext/yrb/src/yvalue.rs +256 -0
- data/ext/yrb/src/yxml_element.rs +280 -0
- data/ext/yrb/src/yxml_fragment.rs +129 -0
- data/ext/yrb/src/yxml_text.rs +177 -0
- data/lib/3.1/yrb.so +0 -0
- data/lib/3.2/yrb.so +0 -0
- data/lib/3.3/yrb.so +0 -0
- data/lib/3.4/yrb.so +0 -0
- data/lib/y/array.rb +371 -0
- data/lib/y/awareness.rb +290 -0
- data/lib/y/diff.rb +38 -0
- data/lib/y/doc.rb +313 -0
- data/lib/y/map.rb +199 -0
- data/lib/y/text.rb +383 -0
- data/lib/y/transaction.rb +189 -0
- data/lib/y/version.rb +5 -0
- data/lib/y/xml.rb +1141 -0
- data/lib/y-rb.rb +24 -0
- data/lib/y.rb +3 -0
- metadata +143 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
use crate::yvalue::YValue;
|
2
|
+
use magnus::r_hash::ForEach::Continue;
|
3
|
+
use magnus::{exception, Error, RArray, RHash, RString, Symbol, Value};
|
4
|
+
use std::sync::Arc;
|
5
|
+
use yrs::types::{Attrs, Value as YrsValue};
|
6
|
+
use yrs::{Any, Array, Map, TransactionMut};
|
7
|
+
|
8
|
+
#[derive(Debug, Clone)]
|
9
|
+
pub(crate) struct TypeConversionError;
|
10
|
+
|
11
|
+
pub(crate) fn indifferent_hash_key(key: Value) -> Option<String> {
|
12
|
+
RString::from_value(key)
|
13
|
+
.map(|v| v.to_string().unwrap())
|
14
|
+
.or_else(|| Symbol::from_value(key).map(|v| v.name().unwrap().to_string()))
|
15
|
+
}
|
16
|
+
|
17
|
+
pub(crate) fn map_rhash_to_attrs(hash: RHash) -> Result<Attrs, Error> {
|
18
|
+
let mut a: Attrs = Default::default();
|
19
|
+
|
20
|
+
let result = hash.foreach(|key: Value, value: Value| {
|
21
|
+
let k = Arc::from(key.to_string());
|
22
|
+
let v = Any::from(YValue::from(value));
|
23
|
+
|
24
|
+
a.insert(k, v);
|
25
|
+
|
26
|
+
Ok(Continue)
|
27
|
+
});
|
28
|
+
|
29
|
+
if result.is_err() {
|
30
|
+
return Err(Error::new(
|
31
|
+
exception::runtime_error(),
|
32
|
+
"could not map hash to attrs",
|
33
|
+
));
|
34
|
+
}
|
35
|
+
|
36
|
+
Ok(a)
|
37
|
+
}
|
38
|
+
|
39
|
+
pub(crate) fn convert_yvalue_to_ruby_value(value: YrsValue, tx: &TransactionMut) -> YValue {
|
40
|
+
match value {
|
41
|
+
YrsValue::Any(val) => YValue::from(val),
|
42
|
+
YrsValue::YText(text) => YValue::from(text),
|
43
|
+
YrsValue::YXmlElement(el) => YValue::from(el),
|
44
|
+
YrsValue::YXmlText(text) => YValue::from(text),
|
45
|
+
YrsValue::YArray(val) => {
|
46
|
+
let arr = RArray::new();
|
47
|
+
for item in val.iter(tx) {
|
48
|
+
let val = convert_yvalue_to_ruby_value(item.clone(), tx);
|
49
|
+
let val = *val.0.borrow();
|
50
|
+
arr.push(val).expect("cannot push item event to array");
|
51
|
+
}
|
52
|
+
YValue::from(arr)
|
53
|
+
}
|
54
|
+
YrsValue::YMap(val) => {
|
55
|
+
let iter = val.iter(tx).map(|(key, val)| {
|
56
|
+
let val = convert_yvalue_to_ruby_value(val.clone(), tx);
|
57
|
+
let val = val.0.into_inner();
|
58
|
+
(key, val)
|
59
|
+
});
|
60
|
+
YValue::from(RHash::from_iter(iter))
|
61
|
+
}
|
62
|
+
v => panic!("cannot map given yrs values to yvalue: {:?}", v),
|
63
|
+
}
|
64
|
+
}
|
data/ext/yrb/src/yany.rs
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
use magnus::r_string::IntoRString;
|
2
|
+
use magnus::value::ReprValue;
|
3
|
+
use magnus::{value, IntoValue, RArray, RHash, RString, Value};
|
4
|
+
use std::borrow::Borrow;
|
5
|
+
use std::ops::{Deref, DerefMut};
|
6
|
+
use yrs::Any;
|
7
|
+
|
8
|
+
pub(crate) struct YAny(pub(crate) Any);
|
9
|
+
|
10
|
+
impl Deref for YAny {
|
11
|
+
type Target = Any;
|
12
|
+
|
13
|
+
fn deref(&self) -> &Self::Target {
|
14
|
+
&self.0
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
impl DerefMut for YAny {
|
19
|
+
fn deref_mut(&mut self) -> &mut Self::Target {
|
20
|
+
&mut self.0
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
impl TryInto<Value> for YAny {
|
25
|
+
type Error = ();
|
26
|
+
|
27
|
+
fn try_into(self) -> Result<Value, Self::Error> {
|
28
|
+
return match self.0 {
|
29
|
+
Any::Array(_v) => {
|
30
|
+
let arr = RArray::new();
|
31
|
+
Ok(arr.as_value())
|
32
|
+
}
|
33
|
+
Any::Map(_v) => {
|
34
|
+
let hash = RHash::new();
|
35
|
+
Ok(hash.as_value())
|
36
|
+
}
|
37
|
+
Any::Null => Ok(value::qnil().as_value()),
|
38
|
+
Any::Undefined => Ok(value::qnil().as_value()),
|
39
|
+
Any::Bool(v) => Ok(v.into_value()),
|
40
|
+
Any::Number(v) => Ok(v.into_value()),
|
41
|
+
Any::BigInt(v) => Ok(v.into_value()),
|
42
|
+
Any::String(v) => Ok(v.into_r_string().as_value()),
|
43
|
+
Any::Buffer(v) => Ok(RString::from_slice(v.borrow()).as_value()),
|
44
|
+
};
|
45
|
+
}
|
46
|
+
}
|
@@ -0,0 +1,191 @@
|
|
1
|
+
use crate::utils::convert_yvalue_to_ruby_value;
|
2
|
+
use crate::ytransaction::YTransaction;
|
3
|
+
use crate::yvalue::YValue;
|
4
|
+
use magnus::block::Proc;
|
5
|
+
use magnus::value::Qnil;
|
6
|
+
use magnus::{Error, IntoValue, RArray, RHash, Symbol, Value};
|
7
|
+
use std::cell::RefCell;
|
8
|
+
use yrs::types::Change;
|
9
|
+
use yrs::{Any, Array, ArrayRef, Observable};
|
10
|
+
|
11
|
+
#[magnus::wrap(class = "Y::Array")]
|
12
|
+
pub(crate) struct YArray(pub(crate) RefCell<ArrayRef>);
|
13
|
+
|
14
|
+
/// SAFETY: This is safe because we only access this data when the GVL is held.
|
15
|
+
unsafe impl Send for YArray {}
|
16
|
+
|
17
|
+
impl YArray {
|
18
|
+
pub(crate) fn yarray_each(&self, transaction: &YTransaction, block: Proc) -> Result<(), Error> {
|
19
|
+
let tx = transaction.transaction();
|
20
|
+
let tx = tx.as_ref().unwrap();
|
21
|
+
|
22
|
+
let arr = self.0.borrow();
|
23
|
+
arr.iter(tx).for_each(|val| {
|
24
|
+
let yvalue = *convert_yvalue_to_ruby_value(val, tx).0.borrow();
|
25
|
+
let args = (yvalue,);
|
26
|
+
let _ = block.call::<(Value,), Qnil>(args);
|
27
|
+
});
|
28
|
+
|
29
|
+
Ok(())
|
30
|
+
}
|
31
|
+
|
32
|
+
pub(crate) fn yarray_get(&self, transaction: &YTransaction, index: u32) -> Value {
|
33
|
+
let tx = transaction.transaction();
|
34
|
+
let tx = tx.as_ref().unwrap();
|
35
|
+
|
36
|
+
let arr = self.0.borrow();
|
37
|
+
let v = arr.get(tx, index).unwrap();
|
38
|
+
*convert_yvalue_to_ruby_value(v, tx).0.borrow()
|
39
|
+
}
|
40
|
+
pub(crate) fn yarray_insert(&self, transaction: &YTransaction, index: u32, value: Value) {
|
41
|
+
let yvalue = YValue::from(value);
|
42
|
+
let avalue = Any::from(yvalue);
|
43
|
+
|
44
|
+
let mut tx = transaction.transaction();
|
45
|
+
let tx = tx.as_mut().unwrap();
|
46
|
+
|
47
|
+
let arr = self.0.borrow_mut();
|
48
|
+
arr.insert(tx, index, avalue);
|
49
|
+
}
|
50
|
+
pub(crate) fn yarray_insert_range(
|
51
|
+
&self,
|
52
|
+
transaction: &YTransaction,
|
53
|
+
index: u32,
|
54
|
+
values: RArray,
|
55
|
+
) {
|
56
|
+
let arr = self.0.borrow_mut();
|
57
|
+
let mut tx = transaction.transaction();
|
58
|
+
let tx = tx.as_mut().unwrap();
|
59
|
+
|
60
|
+
let add_values: Vec<Any> = values
|
61
|
+
.each()
|
62
|
+
.into_iter()
|
63
|
+
.map(|value| YValue::from(value.unwrap()).into())
|
64
|
+
.collect();
|
65
|
+
|
66
|
+
arr.insert_range(tx, index, add_values)
|
67
|
+
}
|
68
|
+
pub(crate) fn yarray_length(&self, transaction: &YTransaction) -> u32 {
|
69
|
+
let arr = self.0.borrow();
|
70
|
+
let tx = transaction.transaction();
|
71
|
+
let tx = tx.as_ref().unwrap();
|
72
|
+
|
73
|
+
arr.len(tx)
|
74
|
+
}
|
75
|
+
pub(crate) fn yarray_observe(&self, block: Proc) -> Result<u32, Error> {
|
76
|
+
let change_added = Symbol::new("added").to_static();
|
77
|
+
let change_retain = Symbol::new("retain").to_static();
|
78
|
+
let change_removed = Symbol::new("removed").to_static();
|
79
|
+
|
80
|
+
// let mut error: Option<Error> = None;
|
81
|
+
|
82
|
+
let subscription_id = self
|
83
|
+
.0
|
84
|
+
.borrow_mut()
|
85
|
+
.observe(move |transaction, array_event| {
|
86
|
+
let delta = array_event.delta(transaction);
|
87
|
+
// let mut changes = RArray::with_capacity(delta.len());
|
88
|
+
let (changes, errors): (Vec<_>, Vec<_>) = delta
|
89
|
+
.iter()
|
90
|
+
.map(|change| {
|
91
|
+
let payload = RHash::new();
|
92
|
+
let result = match change {
|
93
|
+
Change::Added(v) => {
|
94
|
+
let values = v
|
95
|
+
.iter()
|
96
|
+
.map(|v| <YValue as Into<Value>>::into(YValue::from(v.clone())))
|
97
|
+
.collect::<RArray>();
|
98
|
+
payload.aset(change_added, values)
|
99
|
+
}
|
100
|
+
Change::Retain(position) => {
|
101
|
+
payload.aset(change_retain, (*position).into_value())
|
102
|
+
}
|
103
|
+
Change::Removed(position) => {
|
104
|
+
payload.aset(change_removed, (*position).into_value())
|
105
|
+
}
|
106
|
+
};
|
107
|
+
|
108
|
+
match result {
|
109
|
+
Ok(()) => Ok(payload),
|
110
|
+
Err(e) => Err(e),
|
111
|
+
}
|
112
|
+
})
|
113
|
+
.partition(Result::is_ok);
|
114
|
+
|
115
|
+
if errors.is_empty() {
|
116
|
+
let args_changes = RArray::new();
|
117
|
+
for change in changes.iter() {
|
118
|
+
let c = *change.as_ref().unwrap();
|
119
|
+
args_changes
|
120
|
+
.push(c)
|
121
|
+
.expect("cannot push change event to args");
|
122
|
+
}
|
123
|
+
|
124
|
+
let args = (args_changes,);
|
125
|
+
let _ = block.call::<(RArray,), Qnil>(args);
|
126
|
+
// todo: make sure we respect the result and bubble up the
|
127
|
+
// error so that we can return as part of the Result
|
128
|
+
}
|
129
|
+
|
130
|
+
// todo: make sure we respect errors and let the method fail by
|
131
|
+
// by returning a Result containing an Error
|
132
|
+
})
|
133
|
+
.into();
|
134
|
+
|
135
|
+
Ok(subscription_id)
|
136
|
+
}
|
137
|
+
pub(crate) fn yarray_push_back(&self, transaction: &YTransaction, value: Value) {
|
138
|
+
let yvalue = YValue::from(value);
|
139
|
+
let avalue = Any::from(yvalue);
|
140
|
+
let mut tx = transaction.transaction();
|
141
|
+
let tx = tx.as_mut().unwrap();
|
142
|
+
|
143
|
+
self.0.borrow_mut().push_back(tx, avalue);
|
144
|
+
}
|
145
|
+
pub(crate) fn yarray_push_front(&self, transaction: &YTransaction, value: Value) {
|
146
|
+
let yvalue = YValue::from(value);
|
147
|
+
let avalue = Any::from(yvalue);
|
148
|
+
|
149
|
+
let mut tx = transaction.transaction();
|
150
|
+
let tx = tx.as_mut().unwrap();
|
151
|
+
|
152
|
+
let arr = self.0.borrow_mut();
|
153
|
+
arr.push_front(tx, avalue);
|
154
|
+
}
|
155
|
+
pub(crate) fn yarray_remove(&self, transaction: &YTransaction, index: u32) {
|
156
|
+
let mut tx = transaction.transaction();
|
157
|
+
let tx = tx.as_mut().unwrap();
|
158
|
+
|
159
|
+
let arr = self.0.borrow_mut();
|
160
|
+
arr.remove(tx, index)
|
161
|
+
}
|
162
|
+
pub(crate) fn yarray_remove_range(&self, transaction: &YTransaction, index: u32, len: u32) {
|
163
|
+
let mut tx = transaction.transaction();
|
164
|
+
let tx = tx.as_mut().unwrap();
|
165
|
+
|
166
|
+
let arr = self.0.borrow_mut();
|
167
|
+
arr.remove_range(tx, index, len)
|
168
|
+
}
|
169
|
+
pub(crate) fn yarray_to_a(&self, transaction: &YTransaction) -> RArray {
|
170
|
+
let arr = self.0.borrow();
|
171
|
+
let tx = transaction.transaction();
|
172
|
+
let tx = tx.as_ref().unwrap();
|
173
|
+
|
174
|
+
let r_arr = RArray::new();
|
175
|
+
for item in arr.iter(tx) {
|
176
|
+
let r_val = YValue::from(item);
|
177
|
+
let r_val = *r_val.0.borrow();
|
178
|
+
r_arr.push(r_val).expect("cannot push item event to array");
|
179
|
+
}
|
180
|
+
r_arr
|
181
|
+
}
|
182
|
+
pub(crate) fn yarray_unobserve(&self, subscription_id: u32) {
|
183
|
+
self.0.borrow_mut().unobserve(subscription_id);
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
impl From<ArrayRef> for YArray {
|
188
|
+
fn from(v: ArrayRef) -> Self {
|
189
|
+
YArray(RefCell::from(v))
|
190
|
+
}
|
191
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
use crate::yvalue::YValue;
|
2
|
+
use magnus::r_hash::ForEach::Continue;
|
3
|
+
use magnus::{RHash, Value};
|
4
|
+
use std::cell::RefCell;
|
5
|
+
use std::sync::Arc;
|
6
|
+
use yrs::types::Attrs;
|
7
|
+
use yrs::Any;
|
8
|
+
|
9
|
+
#[magnus::wrap(class = "Y::Attrs")]
|
10
|
+
#[derive(Clone)]
|
11
|
+
pub(crate) struct YAttrs(pub(crate) RefCell<Attrs>);
|
12
|
+
|
13
|
+
/// SAFETY: This is safe because we only access this data when the GVL is held.
|
14
|
+
unsafe impl Send for YAttrs {}
|
15
|
+
|
16
|
+
impl From<Attrs> for YAttrs {
|
17
|
+
fn from(value: Attrs) -> Self {
|
18
|
+
YAttrs(RefCell::from(value))
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
impl From<RHash> for YAttrs {
|
23
|
+
fn from(value: RHash) -> Self {
|
24
|
+
let mut attrs = Attrs::new();
|
25
|
+
|
26
|
+
value
|
27
|
+
.foreach(|key: Value, value: Value| {
|
28
|
+
let k = key.to_string();
|
29
|
+
let yvalue = YValue::from(value);
|
30
|
+
let avalue = Any::from(yvalue);
|
31
|
+
attrs.insert(Arc::from(k), avalue);
|
32
|
+
|
33
|
+
Ok(Continue)
|
34
|
+
})
|
35
|
+
.expect("cannot iterate attributes hash");
|
36
|
+
|
37
|
+
YAttrs(RefCell::from(attrs))
|
38
|
+
}
|
39
|
+
}
|
@@ -0,0 +1,151 @@
|
|
1
|
+
use magnus::{block::Proc, exception, Error, Value};
|
2
|
+
use std::borrow::Borrow;
|
3
|
+
use std::cell::RefCell;
|
4
|
+
use std::collections::HashMap;
|
5
|
+
use y_sync::awareness::{Awareness, AwarenessUpdate, Event, UpdateSubscription};
|
6
|
+
use yrs::block::ClientID;
|
7
|
+
use yrs::updates::decoder::Decode;
|
8
|
+
use yrs::updates::encoder::Encode;
|
9
|
+
use yrs::{Doc, OffsetKind, Options};
|
10
|
+
|
11
|
+
#[magnus::wrap(class = "Y::Awareness")]
|
12
|
+
pub(crate) struct YAwareness(pub(crate) RefCell<Awareness>);
|
13
|
+
|
14
|
+
/// SAFETY: This is safe because we only access this data when the GVL is held.
|
15
|
+
unsafe impl Send for YAwareness {}
|
16
|
+
|
17
|
+
impl YAwareness {
|
18
|
+
pub(crate) fn yawareness_new() -> Self {
|
19
|
+
let mut options = Options {
|
20
|
+
offset_kind: OffsetKind::Utf16,
|
21
|
+
..Default::default()
|
22
|
+
};
|
23
|
+
options.offset_kind = OffsetKind::Utf16;
|
24
|
+
|
25
|
+
let doc = Doc::with_options(options);
|
26
|
+
|
27
|
+
let awareness = Awareness::new(doc);
|
28
|
+
|
29
|
+
Self(RefCell::new(awareness))
|
30
|
+
}
|
31
|
+
|
32
|
+
pub(crate) fn yawareness_apply_update(&self, update: Vec<u8>) -> Result<(), Error> {
|
33
|
+
AwarenessUpdate::decode_v1(update.as_slice())
|
34
|
+
.map_err(|_error| Error::new(exception::runtime_error(), "cannot decode update"))
|
35
|
+
.and_then(|value| {
|
36
|
+
self.0.borrow_mut().apply_update(value).map_err(|_error| {
|
37
|
+
Error::new(exception::runtime_error(), "cannot apply awareness update")
|
38
|
+
})
|
39
|
+
})
|
40
|
+
}
|
41
|
+
|
42
|
+
pub(crate) fn yawareness_clean_local_state(&self) {
|
43
|
+
self.0.borrow_mut().clean_local_state();
|
44
|
+
}
|
45
|
+
|
46
|
+
pub(crate) fn yawareness_client_id(&self) -> ClientID {
|
47
|
+
self.0.borrow().client_id()
|
48
|
+
}
|
49
|
+
|
50
|
+
pub(crate) fn yawareness_clients(&self) -> HashMap<ClientID, String> {
|
51
|
+
self.0.borrow().clients().to_owned()
|
52
|
+
}
|
53
|
+
|
54
|
+
pub(crate) fn yawareness_local_state(&self) -> Option<String> {
|
55
|
+
self.0.borrow().local_state().map(|value| value.to_string())
|
56
|
+
}
|
57
|
+
|
58
|
+
pub(crate) fn yawareness_on_update(&self, block: Proc) -> YAwarenessSubscription {
|
59
|
+
let subscription = self.0.borrow_mut().on_update(move |_awareness, event| {
|
60
|
+
let awareness_event = YAwarenessEvent::from(event);
|
61
|
+
let args = (awareness_event,);
|
62
|
+
block
|
63
|
+
.call::<(YAwarenessEvent,), Value>(args)
|
64
|
+
.expect("cannot call block: on_update");
|
65
|
+
});
|
66
|
+
|
67
|
+
// we need to make sure the event handler "survives" and is not being
|
68
|
+
// dropped after leaving this scope, so we pass it back to Ruby.
|
69
|
+
YAwarenessSubscription::from(subscription)
|
70
|
+
}
|
71
|
+
|
72
|
+
pub(crate) fn yawareness_remove_state(&self, client_id: ClientID) {
|
73
|
+
self.0.borrow_mut().remove_state(client_id)
|
74
|
+
}
|
75
|
+
|
76
|
+
pub(crate) fn yawareness_set_local_state(&self, json: String) {
|
77
|
+
self.0.borrow_mut().set_local_state(json)
|
78
|
+
}
|
79
|
+
|
80
|
+
pub(crate) fn yawareness_update(&self) -> Result<Vec<u8>, Error> {
|
81
|
+
self.0
|
82
|
+
.borrow_mut()
|
83
|
+
.update()
|
84
|
+
.map(|update| update.encode_v1())
|
85
|
+
.map_err(|_error| {
|
86
|
+
Error::new(
|
87
|
+
exception::runtime_error(),
|
88
|
+
"cannot create update for current state",
|
89
|
+
)
|
90
|
+
})
|
91
|
+
}
|
92
|
+
|
93
|
+
pub(crate) fn yawareness_update_with_clients(
|
94
|
+
&self,
|
95
|
+
clients: Vec<ClientID>,
|
96
|
+
) -> Result<Vec<u8>, Error> {
|
97
|
+
self.0
|
98
|
+
.borrow_mut()
|
99
|
+
.update_with_clients(clients)
|
100
|
+
.map(|update| update.encode_v1())
|
101
|
+
.map_err(|_error| {
|
102
|
+
Error::new(
|
103
|
+
exception::runtime_error(),
|
104
|
+
"cannot create update for current state and given clients",
|
105
|
+
)
|
106
|
+
})
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
impl From<Awareness> for YAwareness {
|
111
|
+
fn from(value: Awareness) -> Self {
|
112
|
+
Self(RefCell::from(value))
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
#[magnus::wrap(class = "Y::AwarenessEvent")]
|
117
|
+
pub(crate) struct YAwarenessEvent(Event);
|
118
|
+
|
119
|
+
/// SAFETY: This is safe because we only access this data when the GVL is held.
|
120
|
+
unsafe impl Send for YAwarenessEvent {}
|
121
|
+
|
122
|
+
impl YAwarenessEvent {
|
123
|
+
pub(crate) fn added(&self) -> Vec<ClientID> {
|
124
|
+
self.0.borrow().added().to_vec()
|
125
|
+
}
|
126
|
+
pub(crate) fn updated(&self) -> Vec<ClientID> {
|
127
|
+
self.0.borrow().updated().to_vec()
|
128
|
+
}
|
129
|
+
pub(crate) fn removed(&self) -> Vec<ClientID> {
|
130
|
+
self.0.borrow().removed().to_vec()
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
impl From<&Event> for YAwarenessEvent {
|
135
|
+
fn from(value: &Event) -> Self {
|
136
|
+
Self(value.clone())
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
#[magnus::wrap(class = "Y::AwarenessEvent")]
|
141
|
+
pub(crate) struct YAwarenessSubscription(UpdateSubscription);
|
142
|
+
|
143
|
+
unsafe impl Send for YAwarenessSubscription {}
|
144
|
+
|
145
|
+
impl YAwarenessSubscription {}
|
146
|
+
|
147
|
+
impl From<UpdateSubscription> for YAwarenessSubscription {
|
148
|
+
fn from(v: UpdateSubscription) -> Self {
|
149
|
+
YAwarenessSubscription(v)
|
150
|
+
}
|
151
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
use magnus::{IntoValue, RHash, Value};
|
2
|
+
|
3
|
+
unsafe impl Send for YDiff {}
|
4
|
+
|
5
|
+
#[magnus::wrap(class = "Y::Diff")]
|
6
|
+
pub(crate) struct YDiff {
|
7
|
+
pub(crate) ydiff_insert: Value,
|
8
|
+
pub(crate) ydiff_attrs: Option<RHash>,
|
9
|
+
}
|
10
|
+
|
11
|
+
impl YDiff {
|
12
|
+
pub(crate) fn ydiff_insert(&self) -> Value {
|
13
|
+
self.ydiff_insert
|
14
|
+
}
|
15
|
+
|
16
|
+
pub(crate) fn ydiff_attrs(&self) -> Option<Value> {
|
17
|
+
self.ydiff_attrs.as_ref().map(|value| value.into_value())
|
18
|
+
}
|
19
|
+
}
|
data/ext/yrb/src/ydoc.rs
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
use crate::yarray::YArray;
|
2
|
+
use crate::ymap::YMap;
|
3
|
+
use crate::ytext::YText;
|
4
|
+
use crate::yxml_element::YXmlElement;
|
5
|
+
use crate::yxml_fragment::YXmlFragment;
|
6
|
+
use crate::yxml_text::YXmlText;
|
7
|
+
use crate::YTransaction;
|
8
|
+
use magnus::block::Proc;
|
9
|
+
use magnus::{exception::runtime_error, Error, Integer, RArray, Value};
|
10
|
+
use std::borrow::Borrow;
|
11
|
+
use std::cell::RefCell;
|
12
|
+
use yrs::updates::decoder::Decode;
|
13
|
+
use yrs::updates::encoder::{Encoder, EncoderV2};
|
14
|
+
use yrs::{Doc, OffsetKind, Options, ReadTxn, StateVector, SubscriptionId, Transact};
|
15
|
+
|
16
|
+
#[magnus::wrap(class = "Y::Doc")]
|
17
|
+
pub(crate) struct YDoc(pub(crate) RefCell<Doc>);
|
18
|
+
|
19
|
+
unsafe impl Send for YDoc {}
|
20
|
+
|
21
|
+
impl YDoc {
|
22
|
+
pub(crate) fn ydoc_new(client_id: &[Value]) -> Self {
|
23
|
+
let mut options = Options::default();
|
24
|
+
if client_id.len() == 1 {
|
25
|
+
let value = client_id.first().unwrap();
|
26
|
+
options.client_id = Integer::from_value(*value).unwrap().to_u64().unwrap();
|
27
|
+
}
|
28
|
+
options.offset_kind = OffsetKind::Utf16;
|
29
|
+
|
30
|
+
let doc = Doc::with_options(options);
|
31
|
+
Self(RefCell::new(doc))
|
32
|
+
}
|
33
|
+
|
34
|
+
pub(crate) fn ydoc_encode_diff_v1(
|
35
|
+
&self,
|
36
|
+
transaction: &YTransaction,
|
37
|
+
state_vector: Vec<u8>,
|
38
|
+
) -> Result<Vec<u8>, Error> {
|
39
|
+
let mut tx = transaction.transaction();
|
40
|
+
let tx = tx.as_mut().unwrap();
|
41
|
+
|
42
|
+
StateVector::decode_v1(state_vector.borrow())
|
43
|
+
.map(|sv| tx.encode_diff_v1(&sv))
|
44
|
+
.map_err(|_e| Error::new(runtime_error(), "cannot encode diff"))
|
45
|
+
}
|
46
|
+
|
47
|
+
pub(crate) fn ydoc_encode_diff_v2(
|
48
|
+
&self,
|
49
|
+
transaction: &YTransaction,
|
50
|
+
state_vector: Vec<u8>,
|
51
|
+
) -> Result<Vec<u8>, Error> {
|
52
|
+
let mut tx = transaction.transaction();
|
53
|
+
let tx = tx.as_mut().unwrap();
|
54
|
+
let mut encoder = EncoderV2::new();
|
55
|
+
|
56
|
+
StateVector::decode_v2(state_vector.borrow())
|
57
|
+
.map(|sv| tx.encode_diff(&sv, &mut encoder))
|
58
|
+
.map(|_| encoder.to_vec())
|
59
|
+
.map_err(|_e| Error::new(runtime_error(), "cannot encode diff"))
|
60
|
+
}
|
61
|
+
|
62
|
+
pub(crate) fn ydoc_get_or_insert_array(&self, name: String) -> YArray {
|
63
|
+
let array_ref = self.0.borrow().get_or_insert_array(name.as_str());
|
64
|
+
YArray::from(array_ref)
|
65
|
+
}
|
66
|
+
|
67
|
+
pub(crate) fn ydoc_get_or_insert_map(&self, name: String) -> YMap {
|
68
|
+
let map_ref = self.0.borrow().get_or_insert_map(name.as_str());
|
69
|
+
YMap::from(map_ref)
|
70
|
+
}
|
71
|
+
|
72
|
+
pub(crate) fn ydoc_get_or_insert_text(&self, name: String) -> YText {
|
73
|
+
let text_ref = self.0.borrow().get_or_insert_text(name.as_str());
|
74
|
+
YText::from(text_ref)
|
75
|
+
}
|
76
|
+
|
77
|
+
pub(crate) fn ydoc_get_or_insert_xml_element(&self, name: String) -> YXmlElement {
|
78
|
+
let xml_element_ref = self.0.borrow_mut().get_or_insert_xml_element(name.as_str());
|
79
|
+
YXmlElement::from(xml_element_ref) // ::into() maps to YXmlFragment instead of YXmlElement :-(
|
80
|
+
}
|
81
|
+
|
82
|
+
pub(crate) fn ydoc_get_or_insert_xml_fragment(&self, name: String) -> YXmlFragment {
|
83
|
+
let xml_fragment_ref = self.0.borrow().get_or_insert_xml_fragment(name.as_str());
|
84
|
+
YXmlFragment::from(xml_fragment_ref)
|
85
|
+
}
|
86
|
+
|
87
|
+
pub(crate) fn ydoc_get_or_insert_xml_text(&self, name: String) -> YXmlText {
|
88
|
+
let xml_text_ref = self.0.borrow().get_or_insert_xml_text(name.as_str());
|
89
|
+
YXmlText::from(xml_text_ref)
|
90
|
+
}
|
91
|
+
|
92
|
+
pub(crate) fn ydoc_transact(&self) -> YTransaction {
|
93
|
+
let doc = self.0.borrow();
|
94
|
+
let transaction = doc.transact_mut();
|
95
|
+
YTransaction::from(transaction)
|
96
|
+
}
|
97
|
+
|
98
|
+
pub(crate) fn ydoc_observe_update(&self, block: Proc) -> Result<SubscriptionId, Error> {
|
99
|
+
self.0
|
100
|
+
.borrow()
|
101
|
+
.observe_update_v1(move |_tx, update_event| {
|
102
|
+
let update = update_event.update.to_vec();
|
103
|
+
let update = RArray::from_vec(update);
|
104
|
+
|
105
|
+
let args: (RArray,) = (update,);
|
106
|
+
block
|
107
|
+
.call::<(RArray,), Value>(args)
|
108
|
+
.expect("cannot call update block");
|
109
|
+
})
|
110
|
+
.map(|v| v.into())
|
111
|
+
.map_err(|err| Error::new(runtime_error(), err.to_string()))
|
112
|
+
}
|
113
|
+
}
|