public ValueTask <T> DeserializeAsync(CborReader reader, CancellationToken cancellationToken = default) { var result = new WrappedResult(); var task = Deserializer(reader, ref result, cancellationToken); if (task.IsCompletedSuccessfully && result.State == MaxSteps) // if everything is synchronous, we should not hit any async path at all { return(new ValueTask <T>(result.Result)); } return(AwaitDeserializeAsync(task.AsTask(), reader, result, cancellationToken)); }
private async ValueTask <T> AwaitDeserializeAsync(Task task, CborReader reader, WrappedResult result, CancellationToken cancellationToken) { await task.ConfigureAwait(false); result.TempTask = task; while (result.State < MaxSteps) { // This is not really nice, as depending on the valuetasksource this allocates the task // The idea is, that only if the valuetask really needs awaiting the delegate will return and // then the valuetask wraps a task anyway. // This is not completely true, as custom valuetasksources might behave differently var vTask = Deserializer(reader, ref result, cancellationToken); if (vTask.IsCompletedSuccessfully && result.State == MaxSteps) { return(result.Result); } task = vTask.AsTask(); result.TempTask = task; } return(result.Result); }