using System.Collections.Generic; using System.IO; using Vellum; namespace Ariadne.Vellum { /// /// Saves and loads the waits that are subscribed to a waitable, for the converters of the types that have them. /// public static class SavedSubscriptions { private const string WaitKey = "wait"; private const string IndexKey = "index"; private const string StampKey = "stamp"; /// /// Returns the live subscriptions of as a list, each naming its wait, its position in /// the wait and the number of the wait it was made for. /// public static SaveNode Write(Waitable value, SaveSession session) { SaveNode returnMe = SaveNode.NewList(value.SubscriptionCount); for (int i = 0; i < value.SubscriptionCount; ++i) { if (!value.IsLiveAt(i)) { continue; } Subscription subscription = value.SubscriptionAt(i); SaveNode entry = SaveNode.NewTable(); entry.Entries[WaitKey] = session.ToNode(subscription.Target); entry.Entries[IndexKey] = session.ToNode(subscription.Index); entry.Entries[StampKey] = session.ToNode(value.WaitAt(i)); returnMe.Items.Add(entry); } return returnMe; } /// /// Gives the subscriptions that lists. /// /// A subscription is for a position its wait doesn't have. public static void Fill(Waitable blank, SaveNode node, SaveSession session) { // The wait may not have its data yet, since things that refer to one another are filled in any order. foreach (SaveNode entry in node.RequireItems()) { TriggerWait wait = session.FromNode(entry.RequireEntry(WaitKey)); int index = session.FromNode(entry.RequireEntry(IndexKey)); int stamp = session.FromNode(entry.RequireEntry(StampKey)); if (index < 0 || index >= wait.Subscriptions.Length) { throw new InvalidDataException("A saved subscription is for position " + index + " of a wait that holds " + wait.Subscriptions.Length + "."); } blank.Restore(wait.Subscriptions[index], stamp); } } /// /// Checks that every subscription was given is for a wait that lists it there. /// /// A subscription is for a wait that doesn't list it. public static void Check(Waitable blank) { for (int i = 0; i < blank.SubscriptionCount; ++i) { Subscription subscription = blank.SubscriptionAt(i); if (!subscription.Target.Holds(blank, subscription.Index)) { throw new InvalidDataException("A saved subscription is for position " + subscription.Index + " of a wait that doesn't list it there."); } } } /// /// Adds the waits that lists to , and returns false if it /// isn't a list of subscriptions. /// public static bool ListChildren(SaveNode node, ChildList children) { IReadOnlyList entries; if (!node.TryGetItems(out entries)) { return false; } foreach (SaveNode entry in entries) { SaveNode wait; if (!entry.TryGetEntry(WaitKey, out wait)) { return false; } children.Add(wait, typeof(TriggerWait)); } return true; } } }