public ReadResults Read(Converter <string> function, Func <string, CommandError> invalidNumberErrorProvider, T minimum, T maximum, bool loopable, out Range <T> result) { result = default; if (!StringReader.CanRead()) { return(ReadResults.Failure(CommandError.ExpectedValueOrRange().WithContext(StringReader))); } int start = StringReader.GetCursor(); T? right; ReadResults readResults = ReadNumber(function, invalidNumberErrorProvider, out T? left); if (!readResults.Successful) { return(readResults); } if (StringReader.CanRead(2) && StringReader.Peek() == '.' && StringReader.Peek(1) == '.') { StringReader.Skip(2); readResults = ReadNumber(function, invalidNumberErrorProvider, out right); if (!readResults.Successful) { return(readResults); } } else { right = left; } if (left == null && right == null) { return(ReadResults.Failure(CommandError.ExpectedValueOrRange().WithContext(StringReader))); } if (left == null) { left = minimum; } if (right == null) { right = maximum; } if (!loopable && ((T)left).CompareTo((T)right) > 0) { StringReader.SetCursor(start); return(ReadResults.Failure(CommandError.RangeMinBiggerThanMax().WithContext(StringReader))); } result = new Range <T>((T)left, (T)right); return(ReadResults.Success()); }