using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Capnp.Rpc.Interception
{
///
/// Context of an intercepted call. Provides access to parameters and results,
/// and the possibility to redirect the call to some other capability.
///
public class CallContext
{
class PromisedAnswer : IPromisedAnswer
{
CallContext _callContext;
TaskCompletionSource _futureResult = new TaskCompletionSource();
public PromisedAnswer(CallContext callContext)
{
_callContext = callContext;
}
public Task WhenReturned => _futureResult.Task;
async Task AccessWhenReturned(MemberAccessPath access)
{
await WhenReturned;
return new Proxy(Access(access));
}
public ConsumedCapability Access(MemberAccessPath access)
{
if (_futureResult.Task.IsCompleted)
{
try
{
return access.Eval(WhenReturned.Result);
}
catch (AggregateException exception)
{
throw exception.InnerException;
}
}
else
{
return new LazyCapability(AccessWhenReturned(access));
}
}
public void Dispose()
{
}
public void Return()
{
if (_callContext.IsCanceled)
{
_futureResult.SetCanceled();
}
else if (_callContext.Exception != null)
{
_futureResult.SetException(new RpcException(_callContext.Exception));
}
else
{
_futureResult.SetResult(_callContext.OutArgs);
}
}
}
public ulong InterfaceId { get; }
public ushort MethodId { get; }
public bool IsTailCall { get; }
public InterceptionState State { get; private set; }
public SerializerState InArgs { get; set; }
public DeserializerState OutArgs { get; set; }
public string Exception { get; set; }
public bool IsCanceled { get; set; }
public object Bob
{
get => _bob;
set
{
if (value != _bob)
{
BobProxy?.Dispose();
BobProxy = null;
_bob = value;
switch (value)
{
case Proxy proxy:
BobProxy = proxy;
break;
case Skeleton skeleton:
BobProxy = CapabilityReflection.CreateProxy