private static int GetContentRangeLength(string input, int startIndex, out ContentRangeHeaderValue parsedValue)
        {
            Contract.Requires(startIndex >= 0);

            parsedValue = null;

            if (string.IsNullOrEmpty(input) || (startIndex >= input.Length))
            {
                return(0);
            }

            // Parse the unit string: <unit> in '<unit> <from>-<to>/<length>'
            var unitLength = HttpRuleParser.GetTokenLength(input, startIndex);

            if (unitLength == 0)
            {
                return(0);
            }

            var unit            = input.Substring(startIndex, unitLength);
            var current         = startIndex + unitLength;
            var separatorLength = HttpRuleParser.GetWhitespaceLength(input, current);

            if (separatorLength == 0)
            {
                return(0);
            }

            current = current + separatorLength;

            if (current == input.Length)
            {
                return(0);
            }

            // Read range values <from> and <to> in '<unit> <from>-<to>/<length>'
            var fromStartIndex = current;
            var fromLength     = 0;
            var toStartIndex   = 0;
            var toLength       = 0;

            if (!TryGetRangeLength(input, ref current, out fromLength, out toStartIndex, out toLength))
            {
                return(0);
            }

            // After the range is read we expect the length separator '/'
            if ((current == input.Length) || (input[current] != '/'))
            {
                return(0);
            }

            current++; // Skip '/' separator
            current = current + HttpRuleParser.GetWhitespaceLength(input, current);

            if (current == input.Length)
            {
                return(0);
            }

            // We may not have a length (e.g. 'bytes 1-2/*'). But if we do, parse the length now.
            var lengthStartIndex = current;
            var lengthLength     = 0;

            if (!TryGetLengthLength(input, ref current, out lengthLength))
            {
                return(0);
            }

            if (!TryCreateContentRange(input, unit, fromStartIndex, fromLength, toStartIndex, toLength,
                                       lengthStartIndex, lengthLength, out parsedValue))
            {
                return(0);
            }

            return(current - startIndex);
        }
        private static bool TryCreateContentRange(
            string input,
            string unit,
            int fromStartIndex,
            int fromLength,
            int toStartIndex,
            int toLength,
            int lengthStartIndex,
            int lengthLength,
            out ContentRangeHeaderValue parsedValue)
        {
            parsedValue = null;

            long from = 0;

            if ((fromLength > 0) && !HeaderUtilities.TryParseInt64(input.Substring(fromStartIndex, fromLength), out from))
            {
                return(false);
            }

            long to = 0;

            if ((toLength > 0) && !HeaderUtilities.TryParseInt64(input.Substring(toStartIndex, toLength), out to))
            {
                return(false);
            }

            // 'from' must not be greater than 'to'
            if ((fromLength > 0) && (toLength > 0) && (from > to))
            {
                return(false);
            }

            long length = 0;

            if ((lengthLength > 0) && !HeaderUtilities.TryParseInt64(input.Substring(lengthStartIndex, lengthLength),
                                                                     out length))
            {
                return(false);
            }

            // 'from' and 'to' must be less than 'length'
            if ((toLength > 0) && (lengthLength > 0) && (to >= length))
            {
                return(false);
            }

            var result = new ContentRangeHeaderValue();

            result._unit = unit;

            if (fromLength > 0)
            {
                result._from = from;
                result._to   = to;
            }

            if (lengthLength > 0)
            {
                result._length = length;
            }

            parsedValue = result;
            return(true);
        }
        public static bool TryParse(string input, out ContentRangeHeaderValue parsedValue)
        {
            var index = 0;

            return(Parser.TryParseValue(input, ref index, out parsedValue));
        }