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;
}
}
}