示例#1
0
        public static void WriteSyncStep2(Stream stream, YDoc doc, byte[] encodedStateVector)
        {
            stream.WriteVarUint(MessageYjsSyncStep2);
            var update = doc.EncodeStateAsUpdateV2(encodedStateVector);

            stream.WriteVarUint8Array(update);
        }
示例#2
0
        internal ContentDoc(YDoc doc)
        {
            if (doc._item != null)
            {
                throw new Exception("This document was already integrated as a sub-document. You should create a second instance instead with the same guid.");
            }

            Doc  = doc;
            Opts = new YDocOptions();

            if (!doc.Gc)
            {
                Opts.Gc = false;
            }

            if (doc.AutoLoad)
            {
                Opts.AutoLoad = true;
            }

            if (doc.Meta != null)
            {
                Opts.Meta = doc.Meta;
            }
        }
示例#3
0
        public void TestRestoreSnapshotWithSubType()
        {
            var doc = new YDoc(new YDocOptions {
                Gc = false
            });

            doc.GetArray("array").Insert(0, new[] { new YMap() });
            var subMap = doc.GetArray("array").Get(0) as YMap;

            subMap.Set("key1", "value1");

            var snap = doc.CreateSnapshot();

            subMap.Set("key2", "value2");
            var docRestored = snap.RestoreDocument(doc);

            var restoredSubMap = docRestored.GetArray("array").Get(0) as YMap;

            subMap = doc.GetArray("array").Get(0) as YMap;

            Assert.AreEqual(1, restoredSubMap.Count);
            Assert.AreEqual("value1", restoredSubMap.Get("key1"));

            Assert.AreEqual(2, subMap.Count);
            Assert.AreEqual("value1", subMap.Get("key1"));
            Assert.AreEqual("value2", subMap.Get("key2"));
        }
示例#4
0
        public static void WriteSyncStep1(Stream stream, YDoc doc)
        {
            stream.WriteVarUint(MessageYjsSyncStep1);
            var sv = doc.EncodeStateVectorV2();

            stream.WriteVarUint8Array(sv);
        }
示例#5
0
        public YDoc RestoreDocument(YDoc originDoc, YDocOptions opts = null)
        {
            if (originDoc.Gc)
            {
                // We should try to restore a GC-ed document, because some of the restored items might have their content deleted.
                throw new Exception("originDoc must not be garbage collected");
            }

            using var encoder = new UpdateEncoderV2();
            originDoc.Transact(tr =>
            {
                int size = StateVector.Count(kvp => kvp.Value /* clock */ > 0);
                encoder.RestWriter.WriteVarUint((uint)size);

                // Splitting the structs before writing them to the encoder.
                foreach (var kvp in StateVector)
                {
                    int client = kvp.Key;
                    int clock  = kvp.Value;

                    if (clock == 0)
                    {
                        continue;
                    }

                    if (clock < originDoc.Store.GetState(client))
                    {
                        tr.Doc.Store.GetItemCleanStart(tr, new ID(client, clock));
                    }

                    var structs         = originDoc.Store.Clients[client];
                    var lastStructIndex = StructStore.FindIndexSS(structs, clock - 1);

                    // Write # encoded structs.
                    encoder.RestWriter.WriteVarUint((uint)(lastStructIndex + 1));
                    encoder.WriteClient(client);

                    // First clock written is 0.
                    encoder.RestWriter.WriteVarUint(0);

                    for (int i = 0; i <= lastStructIndex; i++)
                    {
                        structs[i].Write(encoder, 0);
                    }
                }

                DeleteSet.Write(encoder);
            });

            var newDoc = new YDoc(opts ?? originDoc.CloneOptionsWithNewGuid());

            newDoc.ApplyUpdateV2(encoder.ToArray(), transactionOrigin: "snapshot");
            return(newDoc);
        }
示例#6
0
        public void TestYMapEventExceptionsShouldCompleteTransaction()
        {
            var doc = new YDoc();
            var map = doc.GetMap("map");

            bool updateCalled               = false;
            bool throwingObserverCalled     = false;
            bool throwingDeepObserverCalled = false;

            doc.UpdateV2 += (s, e) =>
            {
                updateCalled = true;
            };

            void throwingObserver(object sender, YEventArgs args)
            {
                throwingObserverCalled = true;
                throw new Exception("Failure");
            }

            void throwingDeepObserver(object sender, YDeepEventArgs args)
            {
                throwingDeepObserverCalled = true;
                throw new Exception("Deep failure");
            }

            map.EventHandler     += throwingObserver;
            map.DeepEventHandler += throwingDeepObserver;

            Assert.ThrowsException <Exception>(() =>
            {
                map.Set("y", "2");
            });

            Assert.IsTrue(updateCalled);
            Assert.IsTrue(throwingObserverCalled);
            Assert.IsTrue(throwingDeepObserverCalled);

            // Check if it works again.
            updateCalled               = false;
            throwingObserverCalled     = false;
            throwingDeepObserverCalled = false;

            Assert.ThrowsException <Exception>(() =>
            {
                map.Set("z", "3");
            });

            Assert.IsTrue(updateCalled);
            Assert.IsTrue(throwingObserverCalled);
            Assert.IsTrue(throwingDeepObserverCalled);

            Assert.AreEqual("3", map.Get("z"));
        }
示例#7
0
        internal override void Integrate(YDoc doc, Item item)
        {
            base.Integrate(doc, item);

            foreach (var kvp in _prelimContent)
            {
                Set(kvp.Key, kvp.Value);
            }

            _prelimContent = null;
        }
示例#8
0
文件: YDocTests.cs 项目: alex521/ycs
        public void TestGetTypeEmptyId()
        {
            var doc1 = new YDoc();

            doc1.GetText(string.Empty).Insert(0, "h");
            doc1.GetText().Insert(1, "i");

            var doc2 = new YDoc();

            doc2.ApplyUpdateV2(doc1.EncodeStateAsUpdateV2());

            Assert.AreEqual("hi", doc2.GetText().ToString());
            Assert.AreEqual("hi", doc2.GetText(string.Empty).ToString());
        }
示例#9
0
文件: YDocTests.cs 项目: alex521/ycs
        public void TestClientIdDuplicateChange()
        {
            var doc1 = new YDoc();

            doc1.ClientId = 0;
            var doc2 = new YDoc();

            doc2.ClientId = 0;
            Assert.AreEqual(doc1.ClientId, doc2.ClientId);

            doc1.GetArray("a").Insert(0, new object[] { 1, 2 });
            doc2.ApplyUpdateV2(doc1.EncodeStateAsUpdateV2());
            Assert.AreNotEqual(doc1.ClientId, doc2.ClientId);
        }
示例#10
0
        public void TestBasicUpdate()
        {
            var doc1    = new YDoc();
            var doc2    = new YDoc();
            var content = new List <object> {
                "hi"
            };

            doc1.GetArray("array").Insert(0, content);
            var update = doc1.EncodeStateAsUpdateV2();

            doc2.ApplyUpdateV2(update);

            CollectionAssert.AreEqual(content, (ICollection)doc2.GetArray("array").ToArray());
        }
示例#11
0
        // TODO: [alekseyk] Set default parameters (not for the Func<>), or create options, like YDocOptions.
        public UndoManager(IList <AbstractType> typeScopes, int captureTimeout, Func <Item, bool> deleteFilter, ISet <object> trackedOrigins)
        {
            _scope          = typeScopes;
            _deleteFilter   = deleteFilter ?? (_ => true);
            _trackedOrigins = trackedOrigins ?? new HashSet <object>();
            _trackedOrigins.Add(this);
            _undoStack      = new Stack <StackItem>();
            _redoStack      = new Stack <StackItem>();
            _undoing        = false;
            _redoing        = false;
            _doc            = typeScopes[0].Doc;
            _lastChange     = DateTime.MinValue;
            _captureTimeout = captureTimeout;

            _doc.AfterTransaction += OnAfterTransaction;
        }
示例#12
0
 internal Transaction(YDoc doc, object origin, bool local)
 {
     Doc                = doc;
     DeleteSet          = new DeleteSet();
     BeforeState        = Doc.Store.GetStateVector();
     AfterState         = new Dictionary <int, int>();
     Changed            = new Dictionary <AbstractType, ISet <string> >();
     ChangedParentTypes = new Dictionary <AbstractType, IList <YEvent> >();
     _mergeStructs      = new List <AbstractStruct>();
     Origin             = origin;
     Meta               = new Dictionary <string, object>();
     Local              = local;
     SubdocsAdded       = new HashSet <YDoc>();
     SubdocsRemoved     = new HashSet <YDoc>();
     SubdocsLoaded      = new HashSet <YDoc>();
 }
示例#13
0
        public void TestRestoreDeletedItem1()
        {
            var doc = new YDoc(new YDocOptions {
                Gc = false
            });

            doc.GetArray("array").Insert(0, new[] { "item1", "item2" });

            var snap = doc.CreateSnapshot();

            doc.GetArray("array").Delete(0);
            var docRestored = snap.RestoreDocument(doc);

            CollectionAssert.AreEqual(new[] { "item1", "item2" }, (ICollection)docRestored.GetArray("array").ToArray());
            CollectionAssert.AreEqual(new[] { "item2" }, (ICollection)doc.GetArray("array").ToArray());
        }
示例#14
0
        public void TestBasicRestoreSnapshot()
        {
            var doc = new YDoc(new YDocOptions {
                Gc = false
            });

            doc.GetArray("array").Insert(0, new[] { "hello" });

            var snap = doc.CreateSnapshot();

            doc.GetArray("array").Insert(1, new[] { "world" });

            var docRestored = snap.RestoreDocument(doc);

            CollectionAssert.AreEqual(new[] { "hello" }, (ICollection)docRestored.GetArray("array").ToArray());
            CollectionAssert.AreEqual(new[] { "hello", "world" }, (ICollection)doc.GetArray("array").ToArray());
        }
示例#15
0
        public void TestRestoreLeftItem()
        {
            var doc = new YDoc(new YDocOptions {
                Gc = false
            });

            doc.GetArray("array").Insert(0, new[] { "item1" });
            doc.GetMap("map").Set("test", 1);
            doc.GetArray("array").Insert(0, new[] { "item0" });

            var snap = doc.CreateSnapshot();

            doc.GetArray("array").Delete(1);
            var docRestored = snap.RestoreDocument(doc);

            CollectionAssert.AreEqual(new[] { "item0", "item1" }, (ICollection)docRestored.GetArray("array").ToArray());
            CollectionAssert.AreEqual(new[] { "item0" }, (ICollection)doc.GetArray("array").ToArray());
        }
示例#16
0
        public void TestDoubleUndo()
        {
            var doc  = new YDoc();
            var text = doc.GetText();

            text.Insert(0, "1221");

            var undoManager = new UndoManager(text);

            text.Insert(2, "3");
            text.Insert(3, "3");

            undoManager.Undo();
            undoManager.Undo();

            text.Insert(2, "3");
            Assert.AreEqual("12321", text.ToString());
        }
示例#17
0
        public void TestEmptyRestoreSnapshot()
        {
            var doc = new YDoc(new YDocOptions {
                Gc = false
            });
            var snap = doc.CreateSnapshot();

            snap.StateVector[9999] = 0;
            doc.GetArray().Insert(0, new[] { "world" });

            var docRestored = snap.RestoreDocument(doc);

            Assert.AreEqual(0, docRestored.GetArray().ToArray().Count);
            CollectionAssert.AreEqual(new[] { "world" }, (ICollection)doc.GetArray().ToArray());

            // Now this snapshot reflects the latest state. It should still work.
            var snap2        = doc.CreateSnapshot();
            var docRestored2 = snap2.RestoreDocument(doc);

            CollectionAssert.AreEqual(new[] { "world" }, (ICollection)docRestored2.GetArray().ToArray());
        }
示例#18
0
        public void TestIteratingArrayContainingTypes()
        {
            var       y        = new YDoc();
            var       arr      = y.GetArray("arr");
            const int numItems = 10;

            for (int i = 0; i < numItems; i++)
            {
                var map = new YMap();
                map.Set("value", i);
                arr.Add(new[] { map });
            }

            int cnt = 0;

            foreach (var item in arr)
            {
                Assert.AreEqual(cnt++, (item as YMap).Get("value"));
            }

            y.Destroy();
        }
示例#19
0
        public static int ReadSyncMessage(Stream reader, Stream writer, YDoc doc, object transactionOrigin)
        {
            var messageType = (int)reader.ReadVarUint();

            switch (messageType)
            {
            case MessageYjsSyncStep1:
                ReadSyncStep1(reader, writer, doc);
                break;

            case MessageYjsSyncStep2:
                ReadSyncStep2(reader, doc, transactionOrigin);
                break;

            case MessageYjsUpdate:
                ReadUpdate(reader, doc, transactionOrigin);
                break;

            default:
                throw new Exception($"Unknown message type: {messageType}");
            }

            return(messageType);
        }
示例#20
0
文件: YDocTests.cs 项目: alex521/ycs
        public void TestSubdoc()
        {
            var doc = new YDoc();

            doc.Load();

            {
                List <List <string> > events = null;
                doc.SubdocsChanged += (s, e) =>
                {
                    events = new List <List <string> >();
                    events.Add(new List <string>(e.Added.Select(d => d.Guid)));
                    events.Add(new List <string>(e.Removed.Select(d => d.Guid)));
                    events.Add(new List <string>(e.Loaded.Select(d => d.Guid)));
                };

                var subdocs = doc.GetMap("mysubdocs");
                var docA    = new YDoc(new YDocOptions {
                    Guid = "a"
                });
                docA.Load();
                subdocs.Set("a", docA);
                CollectionAssert.AreEqual(new[] { "a" }, events[0]);
                CollectionAssert.AreEqual(new object[] { }, events[1]);
                CollectionAssert.AreEqual(new[] { "a" }, events[2]);
                events = null;

                (subdocs.Get("a") as YDoc).Load();
                Assert.IsNull(events);
                events = null;

                (subdocs.Get("a") as YDoc).Destroy();
                CollectionAssert.AreEqual(new[] { "a" }, events[0]);
                CollectionAssert.AreEqual(new[] { "a" }, events[1]);
                CollectionAssert.AreEqual(new object[] { }, events[2]);
                events = null;

                (subdocs.Get("a") as YDoc).Load();
                CollectionAssert.AreEqual(new object[] { }, events[0]);
                CollectionAssert.AreEqual(new object[] { }, events[1]);
                CollectionAssert.AreEqual(new[] { "a" }, events[2]);
                events = null;

                subdocs.Set("b", new YDoc(new YDocOptions {
                    Guid = "a"
                }));
                CollectionAssert.AreEqual(new[] { "a" }, events[0]);
                CollectionAssert.AreEqual(new object[] { }, events[1]);
                CollectionAssert.AreEqual(new object[] { }, events[2]);
                events = null;

                (subdocs.Get("b") as YDoc).Load();
                CollectionAssert.AreEqual(new object[] { }, events[0]);
                CollectionAssert.AreEqual(new object[] { }, events[1]);
                CollectionAssert.AreEqual(new[] { "a" }, events[2]);
                events = null;

                var docC = new YDoc(new YDocOptions {
                    Guid = "c"
                });
                docC.Load();
                subdocs.Set("c", docC);
                CollectionAssert.AreEqual(new[] { "c" }, events[0]);
                CollectionAssert.AreEqual(new object[] { }, events[1]);
                CollectionAssert.AreEqual(new[] { "c" }, events[2]);
                events = null;

                var guids = doc.GetSubdocGuids().ToList();
                guids.Sort();
                CollectionAssert.AreEqual(new[] { "a", "c" }, guids);
            }

            var doc2 = new YDoc();

            {
                Assert.AreEqual(0, doc2.GetSubdocGuids().Count());

                List <List <string> > events = null;
                doc2.SubdocsChanged += (s, e) =>
                {
                    events = new List <List <string> >();
                    events.Add(new List <string>(e.Added.Select(d => d.Guid)));
                    events.Add(new List <string>(e.Removed.Select(d => d.Guid)));
                    events.Add(new List <string>(e.Loaded.Select(d => d.Guid)));
                };

                doc2.ApplyUpdateV2(doc.EncodeStateAsUpdateV2());
                CollectionAssert.AreEqual(new[] { "a", "a", "c" }, events[0]);
                CollectionAssert.AreEqual(new object[] { }, events[1]);
                CollectionAssert.AreEqual(new object[] { }, events[2]);
                events = null;

                (doc2.GetMap("mysubdocs").Get("a") as YDoc).Load();
                CollectionAssert.AreEqual(new object[] { }, events[0]);
                CollectionAssert.AreEqual(new object[] { }, events[1]);
                CollectionAssert.AreEqual(new[] { "a" }, events[2]);
                events = null;

                var guids = doc2.GetSubdocGuids().ToList();
                guids.Sort();
                CollectionAssert.AreEqual(new[] { "a", "c" }, guids);

                doc2.GetMap("mysubdocs").Delete("a");
                CollectionAssert.AreEqual(new object[] { }, events[0]);
                CollectionAssert.AreEqual(new[] { "a" }, events[1]);
                CollectionAssert.AreEqual(new object[] { }, events[2]);
                events = null;

                guids = doc2.GetSubdocGuids().ToList();
                guids.Sort();
                CollectionAssert.AreEqual(new[] { "a", "c" }, guids);
            }
        }
示例#21
0
 internal virtual void Integrate(YDoc doc, Item item)
 {
     Doc   = doc;
     _item = item;
 }
示例#22
0
        public static AbsolutePosition TryCreateFromAbsolutePosition(RelativePosition rpos, YDoc doc)
        {
            var          store   = doc.Store;
            var          rightId = rpos.Item;
            var          typeId  = rpos.TypeId;
            var          tName   = rpos.TName;
            int          index   = 0;
            AbstractType type;

            if (rightId != null)
            {
                if (store.GetState(rightId.Value.Client) <= rightId.Value.Clock)
                {
                    return(null);
                }

                var res   = store.FollowRedone(rightId.Value);
                var right = res.item as Item;
                if (right == null)
                {
                    return(null);
                }

                type = right.Parent as AbstractType;
                Debug.Assert(type != null);

                if (type._item == null || !type._item.Deleted)
                {
                    index = right.Deleted || !right.Countable ? 0 : res.diff;
                    var n = right.Left as Item;
                    while (n != null)
                    {
                        if (!n.Deleted && n.Countable)
                        {
                            index += n.Length;
                        }

                        n = n.Left as Item;
                    }
                }
            }
            else
            {
                if (tName != null)
                {
                    type = doc.Get <AbstractType>(tName);
                }
                else if (typeId != null)
                {
                    if (store.GetState(typeId.Value.Client) <= typeId.Value.Clock)
                    {
                        // Type does not exist yet.
                        return(null);
                    }

                    var item = store.FollowRedone(typeId.Value).item as Item;
                    if (item != null && item.Content is ContentType)
                    {
                        type = (item.Content as ContentType).Type;
                    }
                    else
                    {
                        // Struct is garbage collected.
                        return(null);
                    }
                }
                else
                {
                    throw new Exception();
                }

                index = type.Length;
            }

            return(new AbsolutePosition(type, index));
        }
示例#23
0
 internal override void Integrate(YDoc doc, Item item)
 {
     base.Integrate(doc, item);
     Insert(0, _prelimContent);
     _prelimContent = null;
 }
示例#24
0
        internal static void CleanupTransactions(IList <Transaction> transactionCleanups, int i)
        {
            if (i < transactionCleanups.Count)
            {
                var transaction  = transactionCleanups[i];
                var doc          = transaction.Doc;
                var store        = doc.Store;
                var ds           = transaction.DeleteSet;
                var mergeStructs = transaction._mergeStructs;
                var actions      = new List <Action>();

                try
                {
                    ds.SortAndMergeDeleteSet();
                    transaction.AfterState = store.GetStateVector();
                    doc._transaction       = null;

                    actions.Add(() =>
                    {
                        doc.InvokeOnBeforeObserverCalls(transaction);
                    });

                    actions.Add(() =>
                    {
                        foreach (var kvp in transaction.Changed)
                        {
                            var itemType = kvp.Key;
                            var subs     = kvp.Value;

                            if (itemType._item == null || !itemType._item.Deleted)
                            {
                                itemType.CallObserver(transaction, subs);
                            }
                        }
                    });

                    actions.Add(() =>
                    {
                        // Deep observe events.
                        foreach (var kvp in transaction.ChangedParentTypes)
                        {
                            var type   = kvp.Key;
                            var events = kvp.Value;

                            // We need to think about the possibility that the user transforms the YDoc in the event.
                            if (type._item == null || !type._item.Deleted)
                            {
                                foreach (var evt in events)
                                {
                                    if (evt.Target._item == null || !evt.Target._item.Deleted)
                                    {
                                        evt.CurrentTarget = type;
                                    }
                                }

                                // Sort events by path length so that top-level events are fired first.
                                var sortedEvents = events.ToList();
                                sortedEvents.Sort((a, b) => a.Path.Count - b.Path.Count);
                                Debug.Assert(sortedEvents.Count > 0);

                                actions.Add(() =>
                                {
                                    type.CallDeepEventHandlerListeners(sortedEvents, transaction);
                                });
                            }
                        }
                    });

                    actions.Add(() =>
                    {
                        doc.InvokeOnAfterTransaction(transaction);
                    });

                    CallAll(actions);
                }
                finally
                {
                    // Replace deleted items with ItemDeleted / GC.
                    // This is where content is actually removed from the Yjs Doc.
                    if (doc.Gc)
                    {
                        ds.TryGcDeleteSet(store, doc.GcFilter);
                    }

                    ds.TryMergeDeleteSet(store);

                    // On all affected store.clients props, try to merge.
                    foreach (var kvp in transaction.AfterState)
                    {
                        var client = kvp.Key;
                        var clock  = kvp.Value;

                        if (!transaction.BeforeState.TryGetValue(client, out int beforeClock))
                        {
                            beforeClock = 0;
                        }

                        if (beforeClock != clock)
                        {
                            var structs        = store.Clients[client];
                            var firstChangePos = Math.Max(StructStore.FindIndexSS(structs, beforeClock), 1);
                            for (int j = structs.Count - 1; j >= firstChangePos; j--)
                            {
                                DeleteSet.TryToMergeWithLeft(structs, j);
                            }
                        }
                    }

                    // Try to merge mergeStructs.
                    // TODO: It makes more sense to transform mergeStructs to a DS, sort it, and merge from right to left
                    //       but at the moment DS does not handle duplicates.
                    for (int j = 0; j < mergeStructs.Count; j++)
                    {
                        var client            = mergeStructs[j].Id.Client;
                        var clock             = mergeStructs[j].Id.Clock;
                        var structs           = store.Clients[client];
                        var replacedStructPos = StructStore.FindIndexSS(structs, clock);

                        if (replacedStructPos + 1 < structs.Count)
                        {
                            DeleteSet.TryToMergeWithLeft(structs, replacedStructPos + 1);
                        }

                        if (replacedStructPos > 0)
                        {
                            DeleteSet.TryToMergeWithLeft(structs, replacedStructPos);
                        }
                    }

                    if (!transaction.Local)
                    {
                        if (!transaction.AfterState.TryGetValue(doc.ClientId, out int afterClock))
                        {
                            afterClock = -1;
                        }

                        if (!transaction.BeforeState.TryGetValue(doc.ClientId, out int beforeClock))
                        {
                            beforeClock = -1;
                        }

                        if (afterClock != beforeClock)
                        {
                            doc.ClientId = YDoc.GenerateNewClientId();
                            // Debug.WriteLine($"{nameof(Transaction)}: Changed the client-id because another client seems to be using it.");
                        }
                    }

                    // @todo: Merge all the transactions into one and provide send the data as a single update message.
                    doc.InvokeOnAfterTransactionCleanup(transaction);

                    doc.InvokeUpdateV2(transaction);

                    foreach (var subDoc in transaction.SubdocsAdded)
                    {
                        doc.Subdocs.Add(subDoc);
                    }

                    foreach (var subDoc in transaction.SubdocsRemoved)
                    {
                        doc.Subdocs.Remove(subDoc);
                    }

                    doc.InvokeSubdocsChanged(transaction.SubdocsLoaded, transaction.SubdocsAdded, transaction.SubdocsRemoved);

                    foreach (var subDoc in transaction.SubdocsRemoved)
                    {
                        subDoc.Destroy();
                    }

                    if (transactionCleanups.Count <= i + 1)
                    {
                        doc._transactionCleanups.Clear();
                        doc.InvokeAfterAllTransactions(transactionCleanups);
                    }
                    else
                    {
                        CleanupTransactions(transactionCleanups, i + 1);
                    }
                }
            }
        }
示例#25
0
 public static void ReadUpdate(Stream stream, YDoc doc, object transactionOrigin)
 {
     ReadSyncStep2(stream, doc, transactionOrigin);
 }
示例#26
0
        public static void ReadSyncStep2(Stream stream, YDoc doc, object transactionOrigin)
        {
            var update = stream.ReadVarUint8Array();

            doc.ApplyUpdateV2(update, transactionOrigin);
        }
示例#27
0
        public static IDictionary <int, List <AbstractStruct> > ReadClientStructRefs(IUpdateDecoder decoder, YDoc doc)
        {
            var clientRefs = new Dictionary <int, List <AbstractStruct> >();

            var numOfStateUpdates = decoder.Reader.ReadVarUint();

            for (int i = 0; i < numOfStateUpdates; i++)
            {
                var numberOfStructs = (int)decoder.Reader.ReadVarUint();
                Debug.Assert(numberOfStructs >= 0);

                var refs   = new List <AbstractStruct>(numberOfStructs);
                var client = decoder.ReadClient();
                var clock  = (int)decoder.Reader.ReadVarUint();

                clientRefs[client] = refs;

                for (int j = 0; j < numberOfStructs; j++)
                {
                    var info = decoder.ReadInfo();
                    if ((Bits.Bits5 & info) != 0)
                    {
                        // The item that was originally to the left of this item.
                        var leftOrigin = (info & Bit.Bit8) == Bit.Bit8 ? (ID?)decoder.ReadLeftId() : null;
                        // The item that was originally to the right of this item.
                        var rightOrigin        = (info & Bit.Bit7) == Bit.Bit7 ? (ID?)decoder.ReadRightId() : null;
                        var cantCopyParentInfo = (info & (Bit.Bit7 | Bit.Bit8)) == 0;
                        var hasParentYKey      = cantCopyParentInfo ? decoder.ReadParentInfo() : false;

                        // If parent == null and neither left nor right are defined, then we know that 'parent' is child of 'y'
                        // and we read the next string as parentYKey.
                        // It indicates how we store/retrieve parent from 'y.share'.
                        var parentYKey = cantCopyParentInfo && hasParentYKey?decoder.ReadString() : null;

                        var str = new Item(
                            new ID(client, clock),
                            null,                                                                                                                                   // left
                            leftOrigin,
                            null,                                                                                                                                   // right
                            rightOrigin,                                                                                                                            // rightOrigin
                            cantCopyParentInfo && !hasParentYKey ? decoder.ReadLeftId() : (parentYKey != null ? (object)doc.Get <AbstractType>(parentYKey) : null), // parent
                            cantCopyParentInfo && (info & Bit.Bit6) == Bit.Bit6 ? decoder.ReadString() : null,                                                      // parentSub
                            ReadItemContent(decoder, info)                                                                                                          // content
                            );

                        refs.Add(str);
                        clock += str.Length;
                    }
                    else
                    {
                        var length = decoder.ReadLength();
                        refs.Add(new GC(new ID(client, clock), length));
                        clock += length;
                    }
                }
            }

            return(clientRefs);
        }
示例#28
0
        public static void ReadSyncStep1(Stream reader, Stream writer, YDoc doc)
        {
            var encodedStateVector = reader.ReadVarUint8Array();

            WriteSyncStep2(writer, doc, encodedStateVector);
        }