private ResultProjectionInfo ProjectTransactionBulkInfo(
            RedisResultInfo.TransactionBulk transactionBulk)
        {
            var projectionInfo = new ResultProjectionInfo(
                transactionBulk,
                ResultProjectionKind.Transaction);

            projectionInfo.Children.AddRange(
                Project(transactionBulk.Array));

            return(projectionInfo);
        }
        public IObservable <StructProjectionInfo> Project(
            ResultProjectionInfo resultProjectionInfo)
        {
            if (resultProjectionInfo == null)
            {
                return(Observable.Return(
                           new StructProjectionInfo(null, StructProjectionKind.None)));
            }

            var key = Encoding.UTF8.GetString(resultProjectionInfo.Value);

            return(_clientAccessor.With(
                       resultProjectionInfo.Result.TargetInfo,
                       client => client.Type(key))
                   .Select(type =>
            {
                switch (type)
                {
                case "string":
                    return new StructProjectionInfo(
                        resultProjectionInfo, StructProjectionKind.String);

                case "list":
                    return new StructProjectionInfo(
                        resultProjectionInfo, StructProjectionKind.List);

                case "set":
                    return new StructProjectionInfo(
                        resultProjectionInfo, StructProjectionKind.Set);

                case "zset":
                    return new StructProjectionInfo(
                        resultProjectionInfo, StructProjectionKind.ZSet);

                case "hash":
                    return new StructProjectionInfo(
                        resultProjectionInfo, StructProjectionKind.Hash);
                }

                return new StructProjectionInfo(
                    resultProjectionInfo, StructProjectionKind.None);
            }));
        }
        private ResultProjectionInfo ProjectMultiBulkInfo(
            RedisResultInfo.MultiBulk multiBulk)
        {
            var projectionInfo = new ResultProjectionInfo(
                multiBulk,
                ResultProjectionKind.Array);

            var commandInfo = multiBulk.CommandInfo;
            var commandName = commandInfo?.Name?.ToLowerInvariant();

            switch (commandName)
            {
            case "keys":
                projectionInfo.Children.AddRange(
                    Project(multiBulk.Array)
                    .Select((p, i) =>
                {
                    switch (p.Kind)
                    {
                    case ResultProjectionKind.Value:
                        p = ProjectBulkInfo(
                            p.Result as RedisResultInfo.Bulk,
                            ResultProjectionKind.Key);
                        p.Index = i;
                        return(p);

                    default:
                        return(p);
                    }
                }));
                break;

            case "scan":
                projectionInfo.Children.AddRange(
                    Project(multiBulk.Array)
                    .Select(p =>
                {
                    switch (p.Kind)
                    {
                    case ResultProjectionKind.Array:
                        for (int i = 0; i < p.Children.Count; i++)
                        {
                            p.Children[i] = ProjectBulkInfo(
                                p.Children[i].Result as RedisResultInfo.Bulk,
                                ResultProjectionKind.Key);
                            p.Children[i].Index = i;
                        }
                        return(p);

                    default:
                        return(p);
                    }
                }));
                break;

            case "sscan":
                projectionInfo.Children.AddRange(
                    Project(multiBulk.Array)
                    .Select(p =>
                {
                    switch (p.Kind)
                    {
                    case ResultProjectionKind.Array:
                        for (int i = 0; i < p.Children.Count; i++)
                        {
                            p.Children[i] = ProjectBulkInfo(
                                p.Children[i].Result as RedisResultInfo.Bulk,
                                ResultProjectionKind.SKey);
                            p.Children[i].Index = i;
                        }
                        return(p);

                    default:
                        return(p);
                    }
                }));
                break;

            case "hscan":
                projectionInfo.Children.AddRange(
                    Project(multiBulk.Array)
                    .Select(p =>
                {
                    switch (p.Kind)
                    {
                    case ResultProjectionKind.Array:
                        for (int i = 0; i < p.Children.Count; i++)
                        {
                            p.Children[i] = ProjectBulkInfo(
                                p.Children[i].Result as RedisResultInfo.Bulk,
                                i % 2 == 0
                                                    ? ResultProjectionKind.HKey
                                                    : ResultProjectionKind.Value);
                            p.Children[i].Index = i;
                        }
                        return(p);

                    default:
                        return(p);
                    }
                }));
                break;

            case "zscan":
                projectionInfo.Children.AddRange(
                    Project(multiBulk.Array)
                    .Select(p =>
                {
                    switch (p.Kind)
                    {
                    case ResultProjectionKind.Array:
                        for (int i = 0; i < p.Children.Count; i++)
                        {
                            p.Children[i] = ProjectBulkInfo(
                                p.Children[i].Result as RedisResultInfo.Bulk,
                                i % 2 == 0
                                                    ? ResultProjectionKind.ZKey
                                                    : ResultProjectionKind.Value);
                            p.Children[i].Index = i;
                        }
                        return(p);

                    default:
                        return(p);
                    }
                }));
                break;

            default:
                projectionInfo.Children.AddRange(
                    Project(multiBulk.Array));
                break;
            }

            for (int i = 0; i < projectionInfo.Children.Count; i++)
            {
                projectionInfo.Children[i].Index = i;
            }

            return(projectionInfo);
        }