static StylePropertyPart CreatePart(StyleSheet styleSheet, StyleValueHandle handle, int offset)
        {
            var part = StylePropertyPart.Create();

            part.offset = offset;
            part.handles.Add(
                new StyleValueHandleContext
            {
                styleSheet = styleSheet,
                handle     = handle
            });
            return(part);
        }
        void RemoveValue(Index indices)
        {
            var part          = stylePropertyParts[indices.partIndex];
            var initialOffset = part.offset;
            var nextOffset    = indices.partIndex + 1 >= stylePropertyParts.Count
                ? -1
                : stylePropertyParts[indices.partIndex + 1].offset;

            // Range of handles to remove in the StyleProperty.values array
            var range = nextOffset < 0
                ? styleProperty.values.Length - initialOffset
                : nextOffset - initialOffset;

            if (part.isVariable)
            {
                if (part.isVariableUnresolved && indices.valueIndex == -1)
                {
                    // If there's only a single value, simply remove the property.
                    if (stylePropertyParts.Count == 1)
                    {
                        RemoveProperty();
                        return;
                    }

                    var valueList = styleProperty.values.ToList();

                    if (indices.partIndex > 0)
                    {
                        initialOffset -= 1;
                    }

                    if (indices.partIndex == stylePropertyParts.Count - 1)
                    {
                        range += 1;
                    }

                    valueList.RemoveRange(initialOffset, range);
                    var firstPropertyValue = stylePropertyParts[indices.partIndex];
                    for (var i = indices.partIndex + 1; i < stylePropertyParts.Count; ++i)
                    {
                        var propertyValue = stylePropertyParts[i];
                        propertyValue.offset -= 2;
                    }
                    firstPropertyValue.Dispose();
                    stylePropertyParts.RemoveAt(indices.partIndex);
                    styleProperty.values = valueList.ToArray();
                    return;
                }

                var newParts = new List <StylePropertyPart>();

                // To set an explicit value on top of a variable, we must first remove the variable. In the case where
                // the variable points to a list of values, we must remove all values of the list and set them as
                // explicit values of the same type.
                var list = styleProperty.values.ToList();
                list.RemoveRange(initialOffset, range);

                var currentOffset = initialOffset;
                for (var i = 0; i < part.handles.Count; ++i, ++currentOffset)
                {
                    var propertyValue = StylePropertyPart.Create();
                    propertyValue.offset = currentOffset;

                    var handle = TransferTypedValue(part.handles[i]);

                    list.Insert(currentOffset, handle);

                    if (i < part.handles.Count - 1 || indices.partIndex < stylePropertyParts.Count - 1)
                    {
                        list.Insert(++currentOffset, new StyleValueHandle(-1, StyleValueType.CommaSeparator));
                    }

                    propertyValue.handles.Add(new StyleValueHandleContext {
                        styleSheet = styleSheet, handle = handle
                    });

                    newParts.Add(propertyValue);
                }

                styleProperty.values = list.ToArray();
                stylePropertyParts.RemoveAt(indices.partIndex);
                // Manually dispose removed part
                part.Dispose();

                stylePropertyParts.InsertRange(indices.partIndex, newParts);
                var adjustIndex = indices.partIndex + newParts.Count;

                var offset = currentOffset - nextOffset;
                for (var i = adjustIndex; i < stylePropertyParts.Count; ++i)
                {
                    var nextPart = stylePropertyParts[i];
                    nextPart.offset      += offset;
                    stylePropertyParts[i] = nextPart;
                }

                // Now that the variable has been transferred as explicit values, we can remove the actual value.
                if (indices.valueIndex >= 0)
                {
                    RemoveAtIndex(indices.index);
                }
            }
            else
            {
                // If there's only a single value, simply remove the property.
                if (stylePropertyParts.Count == 1)
                {
                    RemoveProperty();
                    return;
                }

                var list = styleProperty.values.ToList();

                if (indices.partIndex > 0)
                {
                    initialOffset -= 1;
                }

                if (indices.partIndex == stylePropertyParts.Count - 1)
                {
                    range += 1;
                }

                list.RemoveRange(initialOffset, range);
                var partToRemove = stylePropertyParts[indices.partIndex];
                partToRemove.Dispose();
                stylePropertyParts.RemoveAt(indices.partIndex);
                AdjustOffsets(indices.partIndex, -2);
                styleProperty.values = list.ToArray();
            }
        }
        void OverrideVariableWithValue <T>(Index indices, T value, StyleValueType valueType)
        {
            if (!stylePropertyParts[indices.partIndex].isVariable)
            {
                return;
            }

            var part          = stylePropertyParts[indices.partIndex];
            var initialOffset = part.offset;
            var nextOffset    = indices.partIndex + 1 >= stylePropertyParts.Count
                ? -1
                : stylePropertyParts[indices.partIndex + 1].offset;

            // Range of handles to remove in the StyleProperty.values array
            var range = nextOffset < 0
                ? styleProperty.values.Length - initialOffset
                : nextOffset - initialOffset;

            var newParts = new List <StylePropertyPart>();

            // To set an explicit value on top of a variable, we must first remove the variable. In the case where
            // the variable points to a list of values, we must remove all values of the list and set them as
            // explicit values of the same type.
            var list = styleProperty.values.ToList();

            list.RemoveRange(initialOffset, range);

            var currentOffset = initialOffset;

            for (var i = 0; i < part.handles.Count; ++i, ++currentOffset)
            {
                var propertyValue = StylePropertyPart.Create();
                propertyValue.offset = currentOffset;

                if (i == indices.valueIndex && typeof(Variable).IsAssignableFrom(typeof(T)) && value is Variable variable)
                {
                    var handles = AddVariableToStyleSheet(variable.name);

                    var property = new StyleProperty
                    {
                        name   = styleProperty.name,
                        values = handles
                    };

                    var ib      = 0;
                    var newPart = ResolveValueOrVariable(styleSheet, element, styleRule, property, ref ib,
                                                         editorExtensionMode);

                    list.InsertRange(currentOffset, handles);
                    currentOffset += 2;
                    if (i < part.handles.Count - 1 || indices.partIndex < stylePropertyParts.Count - 1)
                    {
                        list.Insert(++currentOffset, new StyleValueHandle(-1, StyleValueType.CommaSeparator));
                    }

                    newParts.Add(newPart);
                }
                else
                {
                    var handle = i == indices.valueIndex
                        ? AddTypedValue(value, valueType)
                        : TransferTypedValue(part.handles[i]);
                    list.Insert(currentOffset, handle);

                    if (i < part.handles.Count - 1 || indices.partIndex < stylePropertyParts.Count - 1)
                    {
                        list.Insert(++currentOffset, new StyleValueHandle(-1, StyleValueType.CommaSeparator));
                    }

                    propertyValue.handles.Add(new StyleValueHandleContext {
                        styleSheet = styleSheet, handle = handle
                    });

                    newParts.Add(propertyValue);
                }
            }

            if (part.isVariableUnresolved && indices.valueIndex == -1)
            {
                if (typeof(Variable).IsAssignableFrom(typeof(T)) && value is Variable variable)
                {
                    var handles = AddVariableToStyleSheet(variable.name);
                    var newPart = StylePropertyPart.Create();
                    newPart.offset = currentOffset;
                    newPart.handles.Add(new StyleValueHandleContext
                    {
                        styleSheet = styleSheet,
                        handle     = handles[2],
                    });
                    list.InsertRange(currentOffset, handles);
                    newParts.Add(newPart);
                }
                else
                {
                    var handle = AddTypedValue(value, valueType);

                    var newPart = StylePropertyPart.Create();
                    newPart.offset = currentOffset;
                    newPart.handles.Add(new StyleValueHandleContext
                    {
                        styleSheet = styleSheet,
                        handle     = handle,
                    });
                    list.Insert(currentOffset, handle);
                    newParts.Add(newPart);
                }
            }

            styleProperty.values = list.ToArray();
            stylePropertyParts.RemoveAt(indices.partIndex);
            // Manually dispose removed part
            part.Dispose();

            stylePropertyParts.InsertRange(indices.partIndex, newParts);
            var partsCount = indices.partIndex + newParts.Count;

            var offset = currentOffset - nextOffset;

            for (var i = partsCount; i < stylePropertyParts.Count; ++i)
            {
                var nextPart = stylePropertyParts[i];
                nextPart.offset      += offset;
                stylePropertyParts[i] = nextPart;
            }
        }
        internal static StylePropertyPart ResolveValueOrVariable(
            StyleSheet styleSheet,
            VisualElement element,
            StyleRule styleRule,
            StyleProperty property,
            ref int currentIndex,
            bool isEditorExtensionMode)
        {
            var handle = property.values[currentIndex];

            switch (handle.valueType)
            {
            case StyleValueType.Invalid:
            case StyleValueType.Keyword:
            case StyleValueType.Float:
            case StyleValueType.Dimension:
            case StyleValueType.Color:
            case StyleValueType.ResourcePath:
            case StyleValueType.AssetReference:
            case StyleValueType.Enum:
            case StyleValueType.String:
            case StyleValueType.ScalableImage:
            case StyleValueType.MissingAssetReference:
            {
                // skip comma
                ++currentIndex;

                var part = StylePropertyPart.Create();
                part.handles.Add(new StyleValueHandleContext
                    {
                        styleSheet = styleSheet,
                        handle     = handle
                    });
                return(part);
            }

            case StyleValueType.Function:
            {
                var argCountHandle = property.values[++currentIndex];
                var argCount       = (int)styleSheet.ReadFloat(argCountHandle);
                var varHandle      = property.values[++currentIndex];
                var variable       = styleSheet.ReadVariable(varHandle);
                using (var manipulator = ResolveVariable(element, styleSheet, styleRule, variable, isEditorExtensionMode))
                {
                    if (argCount == 1)
                    {
                        // Skip comma
                        ++currentIndex;
                        var part = StylePropertyPart.Create();
                        if (null == manipulator || manipulator.stylePropertyParts.Count == 0)
                        {
                            part.isVariable   = true;
                            part.variableName = variable;
                            return(part);
                        }

                        part.handles.AddRange(manipulator.stylePropertyParts.SelectMany(o => o.handles));
                        part.isVariable   = true;
                        part.variableName = variable;
                        return(part);
                    }
                }

                // Skip comma and point to next function argument.
                currentIndex += 2;

                var fallbackPart = ResolveValueOrVariable(styleSheet, element, styleRule, property, ref currentIndex, isEditorExtensionMode);
                fallbackPart.isVariable   = true;
                fallbackPart.variableName = variable;

                return(fallbackPart);
            }

            // These should never be hit as they are being handled by the cases above
            case StyleValueType.Variable:
            case StyleValueType.CommaSeparator:
                throw new InvalidOperationException();

            default:
                throw new ArgumentOutOfRangeException();
            }
        }