Question

I want to implement an IInputStream which delegates to another IInputStream and processes the read data before returning it to the user, like this:

using System;

using Windows.Storage.Streams;

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;

namespace Core.Crypto {
    public class RC4InputStream : IInputStream {

        public RC4InputStream(IInputStream stream, byte[] readKey) {
            _stream = stream;

            _cipher = new RC4Engine();
            _cipher.Init(false, new KeyParameter(readKey));
        }

        public Windows.Foundation.IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer buffer, uint count, InputStreamOptions options)
        {
            var op = _stream.ReadAsync(buffer, count, options);
            // Somehow magically hook up something so that I can call _cipher.ProcessBytes(...)
            return op;
        }

        private readonly IInputStream _stream;
        private readonly IStreamCipher _cipher;
    }
}

I have two different problems which I have not been able to answer by searching the vastness of the internets:

  • What is the best way to chain another operation to run after delegated ReadAsync() (I could use 'await' and maybe create a new IAsyncOperation using AsyncInfo but I do not know how to connect the progress reporter et al)
  • How do I access the data behind the 'IBuffer'?
Was it helpful?

Solution

You'll need to return your own IAsyncOperationWithProgress. You can use AsyncInfo.Run to do that:

public IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer buffer, uint count, InputStreamOptions options)
{
    return AsyncInfo.Run<IBuffer, uint>(async (token, progress) =>
        {
            progress.Report(0);
            await _stream.ReadAsync(buffer, count, options);
            progress.Report(50);
            // call _cipher.ProcessBytes(...)
            progress.Report(100);
            return buffer;
        });
}

Of course you could make your own progress reporting more granular depending on what you are doing.

To access data in IBuffer you can use either ToArray or AsStream extension method.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top