public static IGremlinQuerySerializer UseCosmosDbWorkarounds(this IGremlinQuerySerializer serializer)
        {
            return(serializer
                   .OverrideFragmentSerializer <CosmosDbKey>((key, overridden, recurse) => recurse(key.PartitionKey != null ? new[] { key.PartitionKey, key.Id } : (object)key.Id))
                   .OverrideFragmentSerializer <SkipStep>((step, overridden, recurse) => recurse(new RangeStep(step.Count, -1)))
                   .OverrideFragmentSerializer <LimitStep>((step, overridden, recurse) =>
            {
                // Workaround for https://feedback.azure.com/forums/263030-azure-cosmos-db/suggestions/33998623-cosmosdb-s-implementation-of-the-tinkerpop-dsl-has
                if (step.Count > int.MaxValue)
                {
                    throw new ArgumentOutOfRangeException(nameof(step), "CosmosDb doesn't currently support values for 'Limit' outside the range of a 32-bit-integer.");
                }

                return overridden(step);
            })
                   .OverrideFragmentSerializer <TailStep>((step, overridden, recurse) =>
            {
                // Workaround for https://feedback.azure.com/forums/263030-azure-cosmos-db/suggestions/33998623-cosmosdb-s-implementation-of-the-tinkerpop-dsl-has
                if (step.Count > int.MaxValue)
                {
                    throw new ArgumentOutOfRangeException(nameof(step), "CosmosDb doesn't currently support values for 'Tail' outside the range of a 32-bit-integer.");
                }

                return overridden(step);
            })
                   .OverrideFragmentSerializer <RangeStep>((step, overridden, recurse) =>
            {
                // Workaround for https://feedback.azure.com/forums/263030-azure-cosmos-db/suggestions/33998623-cosmosdb-s-implementation-of-the-tinkerpop-dsl-has
                if (step.Lower > int.MaxValue || step.Upper > int.MaxValue)
                {
                    throw new ArgumentOutOfRangeException(nameof(step), "CosmosDb doesn't currently support values for 'Range' outside the range of a 32-bit-integer.");
                }

                return overridden(step);
            })
                   .OverrideFragmentSerializer <long>((l, overridden, recurse) =>
            {
                // Workaround for https://feedback.azure.com/forums/263030-azure-cosmos-db/suggestions/33998623-cosmosdb-s-implementation-of-the-tinkerpop-dsl-has
                return recurse((int)l);
            }));
        }
        public static IGremlinQuerySerializer UseDefaultGremlinStepSerializationHandlers(this IGremlinQuerySerializer serializer)
        {
            return(serializer
                   .OverrideFragmentSerializer <AddEStep>((step, overridden, recurse) => CreateInstruction("addE", recurse, step.Label))
                   .OverrideFragmentSerializer <AddEStep.ToLabelStep>((step, overridden, recurse) => CreateInstruction("to", recurse, step.StepLabel))
                   .OverrideFragmentSerializer <AddEStep.ToTraversalStep>((step, overridden, recurse) => CreateInstruction("to", recurse, step.Traversal))
                   .OverrideFragmentSerializer <AddVStep>((step, overridden, recurse) => CreateInstruction("addV", recurse, step.Label))
                   .OverrideFragmentSerializer <AndStep>((step, overridden, recurse) => CreateInstruction("and", recurse, step.Traversals.SelectMany(FlattenLogicalTraversals <AndStep>).ToArray()))
                   .OverrideFragmentSerializer <AggregateStep>((step, overridden, recurse) => CreateInstruction("aggregate", recurse, step.StepLabel))
                   .OverrideFragmentSerializer <AsStep>((step, overridden, recurse) => CreateInstruction("as", recurse, step.StepLabels))
                   .OverrideFragmentSerializer <BarrierStep>((step, overridden, recurse) => CreateInstruction("barrier", recurse))
                   .OverrideFragmentSerializer <BothStep>((step, overridden, recurse) => CreateInstruction("both", recurse, step.Labels))
                   .OverrideFragmentSerializer <BothEStep>((step, overridden, recurse) => CreateInstruction("bothE", recurse, step.Labels))
                   .OverrideFragmentSerializer <BothVStep>((step, overridden, recurse) => CreateInstruction("bothV", recurse))
                   .OverrideFragmentSerializer <BuildStep>((step, overridden, recurse) => CreateInstruction("build", recurse))
                   .OverrideFragmentSerializer <ChooseOptionTraversalStep>((step, overridden, recurse) => CreateInstruction("choose", recurse, step.Traversal))
                   .OverrideFragmentSerializer <ChoosePredicateStep>((step, overridden, recurse) =>
            {
                return step.ElseTraversal.Match(
                    elseTraversal => CreateInstruction(
                        "choose",
                        recurse,
                        step.Predicate,
                        step.ThenTraversal,
                        elseTraversal),
                    () => CreateInstruction(
                        "choose",
                        recurse,
                        step.Predicate,
                        step.ThenTraversal));
            })
                   .OverrideFragmentSerializer <ChooseTraversalStep>((step, overridden, recurse) =>
            {
                return step.ElseTraversal.Match(
                    elseTraversal => CreateInstruction(
                        "choose",
                        recurse,
                        step.IfTraversal,
                        step.ThenTraversal,
                        elseTraversal),
                    () => CreateInstruction(
                        "choose",
                        recurse,
                        step.IfTraversal,
                        step.ThenTraversal));
            })
                   .OverrideFragmentSerializer <CoalesceStep>((step, overridden, recurse) => CreateInstruction("coalesce", recurse, step.Traversals.ToArray()))
                   .OverrideFragmentSerializer <CoinStep>((step, overridden, recurse) => CreateInstruction("coin", recurse, step.Probability))
                   .OverrideFragmentSerializer <ConstantStep>((step, overridden, recurse) => CreateInstruction("constant", recurse, step.Value))
                   .OverrideFragmentSerializer <CountStep>((step, overridden, recurse) => step.Scope.Equals(Scope.Local) ? CreateInstruction("count", recurse, step.Scope) : CreateInstruction("count", recurse))
                   .OverrideFragmentSerializer <CreateStep>((step, overridden, recurse) => CreateInstruction("create", recurse))
                   .OverrideFragmentSerializer <DedupStep>((step, overridden, recurse) => CreateInstruction("dedup", recurse))
                   .OverrideFragmentSerializer <DropStep>((step, overridden, recurse) => CreateInstruction("drop", recurse))
                   .OverrideFragmentSerializer <EdgesStep>((step, overridden, recurse) => CreateInstruction("edges", recurse, step.Traversal))
                   .OverrideFragmentSerializer <EmitStep>((step, overridden, recurse) => CreateInstruction("emit", recurse))
                   .OverrideFragmentSerializer <EnumWrapper>((enumValue, overridden, recurse) => enumValue)
                   .OverrideFragmentSerializer <EStep>((step, overridden, recurse) => CreateInstruction("E", recurse, step.Ids))
                   .OverrideFragmentSerializer <ExplainStep>((step, overridden, recurse) => CreateInstruction("explain", recurse))
                   .OverrideFragmentSerializer <FoldStep>((step, overridden, recurse) => CreateInstruction("fold", recurse))
                   .OverrideFragmentSerializer <FilterStep>((step, overridden, recurse) => CreateInstruction("filter", recurse, step.Lambda))
                   .OverrideFragmentSerializer <FlatMapStep>((step, overridden, recurse) => CreateInstruction("flatMap", recurse, step.Traversal))
                   .OverrideFragmentSerializer <FromLabelStep>((step, overridden, recurse) => CreateInstruction("from", recurse, step.StepLabel))
                   .OverrideFragmentSerializer <FromTraversalStep>((step, overridden, recurse) => CreateInstruction("from", recurse, step.Traversal))
                   .OverrideFragmentSerializer <GroupStep>((step, overridden, recurse) => CreateInstruction("group", recurse))
                   .OverrideFragmentSerializer <GroupStep.ByTraversalStep>((step, overridden, recurse) => CreateInstruction("by", recurse, step.Traversal))
                   .OverrideFragmentSerializer <HasStep>((step, overridden, recurse) =>
            {
                if (step.Value is P p1 && p1.EqualsConstant(false))
                {
                    return recurse(NoneStep.Instance);
                }

                var stepName = "has";
                var argument = (object?)step.Value;

                if (argument is P p2)
                {
                    if (p2.EqualsConstant(true))
                    {
                        argument = null;
                    }
                    else
                    {
                        if (p2.Value == null)
                        {
                            if (p2.OperatorName == "eq")
                            {
                                stepName = "hasNot";
                            }
                            else if (p2.OperatorName == "neq")
                            {
                                argument = null;
                            }
                        }

                        if (p2.OperatorName == "eq")
                        {
                            argument = p2.Value;
                        }
                    }
                }

                return argument != null
                        ? CreateInstruction(stepName, recurse, step.Key, argument)
                        : CreateInstruction(stepName, recurse, step.Key);
            })
                   .OverrideFragmentSerializer <HasLabelStep>((step, overridden, recurse) => CreateInstruction("hasLabel", recurse, step.Labels))
                   .OverrideFragmentSerializer <HasNotStep>((step, overridden, recurse) => CreateInstruction("hasNot", recurse, step.Key))
                   .OverrideFragmentSerializer <HasValueStep>((step, overridden, recurse) => CreateInstruction(
                                                                  "hasValue",
                                                                  recurse,
                                                                  step.Argument is P p && p.OperatorName == "eq"
                        ? p.Value
                        : step.Argument))
                   .OverrideFragmentSerializer <IdentityStep>((step, overridden, recurse) => CreateInstruction("identity", recurse))
                   .OverrideFragmentSerializer <IdStep>((step, overridden, recurse) => CreateInstruction("id", recurse))
                   .OverrideFragmentSerializer <IGremlinQueryBase>((query, overridden, recurse) =>
            {
                var steps = query.AsAdmin().Steps.HandleAnonymousQueries();

                if (query.AsAdmin().Environment.Options.GetValue(WorkaroundTinkerpop2112))
                {
                    steps = steps.WorkaroundTINKERPOP_2112();
                }

                var byteCode = new Bytecode();

                foreach (var step in steps)
                {
                    if (recurse(step) is Instruction instruction)
                    {
                        byteCode.StepInstructions.Add(instruction);
                    }
                }

                if (query is GremlinQueryBase gremlinQueryBase && gremlinQueryBase.SurfaceVisible)
                {
                    switch (gremlinQueryBase.Semantics)
                    {
                    case QuerySemantics.Vertex:
                        {
                            byteCode.StepInstructions.AddRange(VertexProjectionInstructions);
                            break;
                        }

                    case QuerySemantics.Edge:
                        {
                            byteCode.StepInstructions.AddRange(EdgeProjectionInstructions);
                            break;
                        }
                    }
                }

                return byteCode;
            })
                   .OverrideFragmentSerializer <ILambda>((lambda, overridden, recurse) => lambda)
                   .OverrideFragmentSerializer <InjectStep>((step, overridden, recurse) => CreateInstruction("inject", recurse, step.Elements))
                   .OverrideFragmentSerializer <InEStep>((step, overridden, recurse) => CreateInstruction("inE", recurse, step.Labels))
                   .OverrideFragmentSerializer <InStep>((step, overridden, recurse) => CreateInstruction("in", recurse, step.Labels))
                   .OverrideFragmentSerializer <InVStep>((step, overridden, recurse) => CreateInstruction("inV", recurse))
                   .OverrideFragmentSerializer <IsStep>((step, overridden, recurse) => CreateInstruction(
                                                            "is",
                                                            recurse,
                                                            step.Argument is P p && p.OperatorName == "eq"
                        ? p.Value
                        : step.Argument))
                   .OverrideFragmentSerializer <KeyStep>((step, overridden, recurse) => CreateInstruction("key", recurse))
                   .OverrideFragmentSerializer <LabelStep>((step, overridden, recurse) => CreateInstruction("label", recurse))
                   .OverrideFragmentSerializer <LimitStep>((step, overridden, recurse) => step.Scope.Equals(Scope.Local)
                    ? CreateInstruction("limit", recurse, step.Scope, step.Count)
                    : CreateInstruction("limit", recurse, step.Count))
                   .OverrideFragmentSerializer <LocalStep>((step, overridden, recurse) => CreateInstruction("local", recurse, step.Traversal))
                   .OverrideFragmentSerializer <MatchStep>((step, overridden, recurse) => CreateInstruction("match", recurse, step.Traversals.ToArray()))
                   .OverrideFragmentSerializer <MapStep>((step, overridden, recurse) => CreateInstruction("map", recurse, step.Traversal))
                   .OverrideFragmentSerializer <NoneStep>((step, overridden, recurse) => recurse(GremlinQueryEnvironment.NoneWorkaround))
                   .OverrideFragmentSerializer <NotStep>((step, overridden, recurse) =>
            {
                var traversalSteps = step.Traversal.AsAdmin().Steps;

                return !(traversalSteps.Count > 0 && traversalSteps[traversalSteps.Count - 1] is HasStep hasStep && hasStep.Value is P p && p.EqualsConstant(false))
                        ? CreateInstruction("not", recurse, step.Traversal)
                        : null;
            })
                   .OverrideFragmentSerializer <OptionalStep>((step, overridden, recurse) => CreateInstruction("optional", recurse, step.Traversal))
                   .OverrideFragmentSerializer <OptionTraversalStep>((step, overridden, recurse) => CreateInstruction("option", recurse, step.Guard ?? Pick.None, step.OptionTraversal))
                   .OverrideFragmentSerializer <OrderStep>((step, overridden, recurse) => CreateInstruction("order", recurse))
                   .OverrideFragmentSerializer <OrderStep.ByLambdaStep>((step, overridden, recurse) => CreateInstruction("by", recurse, step.Lambda))
                   .OverrideFragmentSerializer <OrderStep.ByMemberStep>((step, overridden, recurse) => CreateInstruction("by", recurse, step.Key, step.Order))
                   .OverrideFragmentSerializer <OrderStep.ByTraversalStep>((step, overridden, recurse) => CreateInstruction("by", recurse, step.Traversal, step.Order))
                   .OverrideFragmentSerializer <OrStep>((step, overridden, recurse) => CreateInstruction("or", recurse, step.Traversals.SelectMany(FlattenLogicalTraversals <OrStep>).ToArray()))
                   .OverrideFragmentSerializer <OutStep>((step, overridden, recurse) => CreateInstruction("out", recurse, step.Labels))
                   .OverrideFragmentSerializer <OutEStep>((step, overridden, recurse) => CreateInstruction("outE", recurse, step.Labels))
                   .OverrideFragmentSerializer <OutVStep>((step, overridden, recurse) => CreateInstruction("outV", recurse))
                   .OverrideFragmentSerializer <OtherVStep>((step, overridden, recurse) => CreateInstruction("otherV", recurse))
                   .OverrideFragmentSerializer <P>((p, overridden, recurse) => new P(
                                                       p.OperatorName,
                                                       !(p.Value is string) && p.Value is IEnumerable enumerable
                        ? enumerable.Cast <object>().Select(recurse).ToArray()
                        : recurse(p.Value),
                                                       (P)recurse(p.Other)))
                   .OverrideFragmentSerializer <ProfileStep>((step, overridden, recurse) => CreateInstruction("profile", recurse))
                   .OverrideFragmentSerializer <PropertiesStep>((step, overridden, recurse) => CreateInstruction("properties", recurse, step.Keys))
                   .OverrideFragmentSerializer <PropertyStep>((step, overridden, recurse) =>
            {
                if (T.Id.Equals(step.Key))
                {
                    if (!Cardinality.Single.Equals(step.Cardinality ?? Cardinality.Single))
                    {
                        throw new NotSupportedException("Cannot have an id property on non-single cardinality.");
                    }

                    return CreateInstruction("property", recurse, step.MetaProperties.Prepend(step.Value).Prepend(step.Key).ToArray());
                }

                return (step.Cardinality != null)
                         ? CreateInstruction("property", recurse, step.MetaProperties.Prepend(step.Value).Prepend(step.Key).Prepend(step.Cardinality).ToArray())
                         : CreateInstruction("property", recurse, step.MetaProperties.Prepend(step.Value).Prepend(step.Key).ToArray());
            })
                   .OverrideFragmentSerializer <ProjectStep.ByTraversalStep>((step, overridden, recurse) => CreateInstruction("by", recurse, step.Traversal))
                   .OverrideFragmentSerializer <ProjectStep>((step, overridden, recurse) => CreateInstruction("project", recurse, step.Projections))
                   .OverrideFragmentSerializer <RangeStep>((step, overridden, recurse) => CreateInstruction("range", recurse, step.Lower, step.Upper))
                   .OverrideFragmentSerializer <RepeatStep>((step, overridden, recurse) => CreateInstruction("repeat", recurse, step.Traversal))
                   .OverrideFragmentSerializer <SelectStep>((step, overridden, recurse) => CreateInstruction("select", recurse, step.StepLabels))
                   .OverrideFragmentSerializer <SideEffectStep>((step, overridden, recurse) => CreateInstruction("sideEffect", recurse, step.Traversal))
                   .OverrideFragmentSerializer <SkipStep>((step, overridden, recurse) => CreateInstruction("skip", recurse, step.Count))
                   .OverrideFragmentSerializer <SumStep>((step, overridden, recurse) => CreateInstruction("sum", recurse, step.Scope))
                   .OverrideFragmentSerializer <TextP>((textP, overridden, recurse) => textP)
                   .OverrideFragmentSerializer <TailStep>((step, overridden, recurse) => step.Scope.Equals(Scope.Local) ? CreateInstruction("tail", recurse, step.Scope, step.Count) : CreateInstruction("tail", recurse, step.Count))
                   .OverrideFragmentSerializer <TimesStep>((step, overridden, recurse) => CreateInstruction("times", recurse, step.Count))
                   .OverrideFragmentSerializer <Type>((type, overridden, recurse) => type)
                   .OverrideFragmentSerializer <UnfoldStep>((step, overridden, recurse) => CreateInstruction("unfold", recurse))
                   .OverrideFragmentSerializer <UnionStep>((step, overridden, recurse) => CreateInstruction("union", recurse, step.Traversals.ToArray()))
                   .OverrideFragmentSerializer <UntilStep>((step, overridden, recurse) => CreateInstruction("until", recurse, step.Traversal))
                   .OverrideFragmentSerializer <ValueStep>((step, overridden, recurse) => CreateInstruction("value", recurse))
                   .OverrideFragmentSerializer <ValueMapStep>((step, overridden, recurse) => CreateInstruction("valueMap", recurse, step.Keys))
                   .OverrideFragmentSerializer <ValuesStep>((step, overridden, recurse) => CreateInstruction("values", recurse, step.Keys))
                   .OverrideFragmentSerializer <VerticesStep>((step, overridden, recurse) => CreateInstruction("vertices", recurse, step.Traversal))
                   .OverrideFragmentSerializer <VStep>((step, overridden, recurse) => CreateInstruction("V", recurse, step.Ids))
                   .OverrideFragmentSerializer <WhereTraversalStep>((step, overridden, recurse) => CreateInstruction("where", recurse, step.Traversal))
                   .OverrideFragmentSerializer <WithStrategiesStep>((step, overridden, recurse) => CreateInstruction("withStrategies", recurse, step.Traversal))
                   .OverrideFragmentSerializer <WithoutStrategiesStep>((step, overridden, recurse) => CreateInstruction("withoutStrategies", recurse, step.StrategyTypes))
                   .OverrideFragmentSerializer <WherePredicateStep>((step, overridden, recurse) => CreateInstruction("where", recurse, step.Predicate)));
        }
 public IGremlinQuerySerializer OverrideFragmentSerializer <TAtom>(QueryFragmentSerializer <TAtom> queryFragmentSerializer)
 {
     return(new SelectGremlinQuerySerializer(_baseSerializer.OverrideFragmentSerializer(queryFragmentSerializer), _projection));
 }