logging: fix unused variable warning in non-debug builds
[folly.git] / folly / Conv.h
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * Converts anything to anything, with an emphasis on performance and
19  * safety.
20  *
21  * @author Andrei Alexandrescu (andrei.alexandrescu@fb.com)
22  */
23
24 #pragma once
25
26 #include <algorithm>
27 #include <cctype>
28 #include <climits>
29 #include <cstddef>
30 #include <limits>
31 #include <stdexcept>
32 #include <string>
33 #include <tuple>
34 #include <type_traits>
35 #include <typeinfo>
36 #include <utility>
37
38 #include <boost/implicit_cast.hpp>
39 #include <double-conversion/double-conversion.h> // V8 JavaScript implementation
40
41 #include <folly/Demangle.h>
42 #include <folly/Expected.h>
43 #include <folly/FBString.h>
44 #include <folly/Likely.h>
45 #include <folly/Range.h>
46 #include <folly/Traits.h>
47 #include <folly/Unit.h>
48 #include <folly/portability/Math.h>
49
50 namespace folly {
51
52 // Keep this in sync with kErrorStrings in Conv.cpp
53 enum class ConversionCode : unsigned char {
54   SUCCESS,
55   EMPTY_INPUT_STRING,
56   NO_DIGITS,
57   BOOL_OVERFLOW,
58   BOOL_INVALID_VALUE,
59   NON_DIGIT_CHAR,
60   INVALID_LEADING_CHAR,
61   POSITIVE_OVERFLOW,
62   NEGATIVE_OVERFLOW,
63   STRING_TO_FLOAT_ERROR,
64   NON_WHITESPACE_AFTER_END,
65   ARITH_POSITIVE_OVERFLOW,
66   ARITH_NEGATIVE_OVERFLOW,
67   ARITH_LOSS_OF_PRECISION,
68   NUM_ERROR_CODES, // has to be the last entry
69 };
70
71 struct ConversionErrorBase : std::range_error {
72   using std::range_error::range_error;
73 };
74
75 class ConversionError : public ConversionErrorBase {
76  public:
77   ConversionError(const std::string& str, ConversionCode code)
78       : ConversionErrorBase(str), code_(code) {}
79
80   ConversionError(const char* str, ConversionCode code)
81       : ConversionErrorBase(str), code_(code) {}
82
83   ConversionCode errorCode() const {
84     return code_;
85   }
86
87  private:
88   ConversionCode code_;
89 };
90
91 /*******************************************************************************
92  * Custom Error Translation
93  *
94  * Your overloaded parseTo() function can return a custom error code on failure.
95  * ::folly::to() will call makeConversionError to translate that error code into
96  * an object to throw. makeConversionError is found by argument-dependent
97  * lookup. It should have this signature:
98  *
99  * namespace other_namespace {
100  * enum YourErrorCode { BAD_ERROR, WORSE_ERROR };
101  *
102  * struct YourConversionError : ConversionErrorBase {
103  *   YourConversionError(const char* what) : ConversionErrorBase(what) {}
104  * };
105  *
106  * YourConversionError
107  * makeConversionError(YourErrorCode code, ::folly::StringPiece sp) {
108  *   ...
109  *   return YourConversionError(messageString);
110  * }
111  ******************************************************************************/
112 ConversionError makeConversionError(ConversionCode code, StringPiece sp);
113
114 namespace detail {
115 /**
116  * Enforce that the suffix following a number is made up only of whitespace.
117  */
118 inline ConversionCode enforceWhitespaceErr(StringPiece sp) {
119   for (auto c : sp) {
120     if (UNLIKELY(!std::isspace(c))) {
121       return ConversionCode::NON_WHITESPACE_AFTER_END;
122     }
123   }
124   return ConversionCode::SUCCESS;
125 }
126
127 /**
128  * Keep this implementation around for prettyToDouble().
129  */
130 inline void enforceWhitespace(StringPiece sp) {
131   auto err = enforceWhitespaceErr(sp);
132   if (err != ConversionCode::SUCCESS) {
133     throw makeConversionError(err, sp);
134   }
135 }
136 } // namespace detail
137
138 /**
139  * The identity conversion function.
140  * tryTo<T>(T) returns itself for all types T.
141  */
142 template <class Tgt, class Src>
143 typename std::enable_if<
144     std::is_same<Tgt, typename std::decay<Src>::type>::value,
145     Expected<Tgt, ConversionCode>>::type
146 tryTo(Src&& value) {
147   return std::forward<Src>(value);
148 }
149
150 template <class Tgt, class Src>
151 typename std::enable_if<
152     std::is_same<Tgt, typename std::decay<Src>::type>::value,
153     Tgt>::type
154 to(Src&& value) {
155   return std::forward<Src>(value);
156 }
157
158 /*******************************************************************************
159  * Arithmetic to boolean
160  ******************************************************************************/
161
162 /**
163  * Unchecked conversion from arithmetic to boolean. This is different from the
164  * other arithmetic conversions because we use the C convention of treating any
165  * non-zero value as true, instead of range checking.
166  */
167 template <class Tgt, class Src>
168 typename std::enable_if<
169     std::is_arithmetic<Src>::value && !std::is_same<Tgt, Src>::value &&
170         std::is_same<Tgt, bool>::value,
171     Expected<Tgt, ConversionCode>>::type
172 tryTo(const Src& value) {
173   return value != Src();
174 }
175
176 template <class Tgt, class Src>
177 typename std::enable_if<
178     std::is_arithmetic<Src>::value && !std::is_same<Tgt, Src>::value &&
179         std::is_same<Tgt, bool>::value,
180     Tgt>::type
181 to(const Src& value) {
182   return value != Src();
183 }
184
185 /*******************************************************************************
186  * Anything to string
187  ******************************************************************************/
188
189 namespace detail {
190
191 #ifdef _MSC_VER
192 // MSVC can't quite figure out the LastElementImpl::call() stuff
193 // in the base implementation, so we have to use tuples instead,
194 // which result in significantly more templates being compiled,
195 // though the runtime performance is the same.
196
197 template <typename... Ts>
198 auto getLastElement(Ts&&... ts) -> decltype(
199     std::get<sizeof...(Ts)-1>(std::forward_as_tuple(std::forward<Ts>(ts)...))) {
200   return std::get<sizeof...(Ts)-1>(
201       std::forward_as_tuple(std::forward<Ts>(ts)...));
202 }
203
204 inline void getLastElement() {}
205
206 template <size_t size, typename... Ts>
207 struct LastElementType : std::tuple_element<size - 1, std::tuple<Ts...>> {};
208
209 template <>
210 struct LastElementType<0> {
211   using type = void;
212 };
213
214 template <class... Ts>
215 struct LastElement
216     : std::decay<typename LastElementType<sizeof...(Ts), Ts...>::type> {};
217 #else
218 template <typename... Ts>
219 struct LastElementImpl {
220   static void call(Ignored<Ts>...) {}
221 };
222
223 template <typename Head, typename... Ts>
224 struct LastElementImpl<Head, Ts...> {
225   template <typename Last>
226   static Last call(Ignored<Ts>..., Last&& last) {
227     return std::forward<Last>(last);
228   }
229 };
230
231 template <typename... Ts>
232 auto getLastElement(const Ts&... ts)
233     -> decltype(LastElementImpl<Ts...>::call(ts...)) {
234   return LastElementImpl<Ts...>::call(ts...);
235 }
236
237 template <class... Ts>
238 struct LastElement : std::decay<decltype(
239                          LastElementImpl<Ts...>::call(std::declval<Ts>()...))> {
240 };
241 #endif
242
243 } // namespace detail
244
245 /*******************************************************************************
246  * Conversions from integral types to string types.
247  ******************************************************************************/
248
249 #if FOLLY_HAVE_INT128_T
250 namespace detail {
251
252 template <typename IntegerType>
253 constexpr unsigned int
254 digitsEnough() {
255   return (unsigned int)(ceil(sizeof(IntegerType) * CHAR_BIT * M_LN2 / M_LN10));
256 }
257
258 inline size_t
259 unsafeTelescope128(char * buffer, size_t room, unsigned __int128 x) {
260   typedef unsigned __int128 Usrc;
261   size_t p = room - 1;
262
263   while (x >= (Usrc(1) << 64)) { // Using 128-bit division while needed
264     const auto y = x / 10;
265     const auto digit = x % 10;
266
267     buffer[p--] = '0' + digit;
268     x = y;
269   }
270
271   uint64_t xx = x; // Moving to faster 64-bit division thereafter
272
273   while (xx >= 10) {
274     const auto y = xx / 10ULL;
275     const auto digit = xx % 10ULL;
276
277     buffer[p--] = '0' + digit;
278     xx = y;
279   }
280
281   buffer[p] = '0' + xx;
282
283   return p;
284 }
285
286 } // namespace detail
287 #endif
288
289 /**
290  * Returns the number of digits in the base 10 representation of an
291  * uint64_t. Useful for preallocating buffers and such. It's also used
292  * internally, see below. Measurements suggest that defining a
293  * separate overload for 32-bit integers is not worthwhile.
294  */
295
296 inline uint32_t digits10(uint64_t v) {
297 #ifdef __x86_64__
298
299   // For this arch we can get a little help from specialized CPU instructions
300   // which can count leading zeroes; 64 minus that is appx. log (base 2).
301   // Use that to approximate base-10 digits (log_10) and then adjust if needed.
302
303   // 10^i, defined for i 0 through 19.
304   // This is 20 * 8 == 160 bytes, which fits neatly into 5 cache lines
305   // (assuming a cache line size of 64).
306   static const uint64_t powersOf10[20] FOLLY_ALIGNED(64) = {
307       1,
308       10,
309       100,
310       1000,
311       10000,
312       100000,
313       1000000,
314       10000000,
315       100000000,
316       1000000000,
317       10000000000,
318       100000000000,
319       1000000000000,
320       10000000000000,
321       100000000000000,
322       1000000000000000,
323       10000000000000000,
324       100000000000000000,
325       1000000000000000000,
326       10000000000000000000UL,
327   };
328
329   // "count leading zeroes" operation not valid; for 0; special case this.
330   if UNLIKELY (! v) {
331     return 1;
332   }
333
334   // bits is in the ballpark of log_2(v).
335   const uint8_t leadingZeroes = __builtin_clzll(v);
336   const auto bits = 63 - leadingZeroes;
337
338   // approximate log_10(v) == log_10(2) * bits.
339   // Integer magic below: 77/256 is appx. 0.3010 (log_10(2)).
340   // The +1 is to make this the ceiling of the log_10 estimate.
341   const uint32_t minLength = 1 + ((bits * 77) >> 8);
342
343   // return that log_10 lower bound, plus adjust if input >= 10^(that bound)
344   // in case there's a small error and we misjudged length.
345   return minLength + (uint32_t) (UNLIKELY (v >= powersOf10[minLength]));
346
347 #else
348
349   uint32_t result = 1;
350   for (;;) {
351     if (LIKELY(v < 10)) return result;
352     if (LIKELY(v < 100)) return result + 1;
353     if (LIKELY(v < 1000)) return result + 2;
354     if (LIKELY(v < 10000)) return result + 3;
355     // Skip ahead by 4 orders of magnitude
356     v /= 10000U;
357     result += 4;
358   }
359
360 #endif
361 }
362
363 /**
364  * Copies the ASCII base 10 representation of v into buffer and
365  * returns the number of bytes written. Does NOT append a \0. Assumes
366  * the buffer points to digits10(v) bytes of valid memory. Note that
367  * uint64 needs at most 20 bytes, uint32_t needs at most 10 bytes,
368  * uint16_t needs at most 5 bytes, and so on. Measurements suggest
369  * that defining a separate overload for 32-bit integers is not
370  * worthwhile.
371  *
372  * This primitive is unsafe because it makes the size assumption and
373  * because it does not add a terminating \0.
374  */
375
376 inline uint32_t uint64ToBufferUnsafe(uint64_t v, char *const buffer) {
377   auto const result = digits10(v);
378   // WARNING: using size_t or pointer arithmetic for pos slows down
379   // the loop below 20x. This is because several 32-bit ops can be
380   // done in parallel, but only fewer 64-bit ones.
381   uint32_t pos = result - 1;
382   while (v >= 10) {
383     // Keep these together so a peephole optimization "sees" them and
384     // computes them in one shot.
385     auto const q = v / 10;
386     auto const r = static_cast<char>(v % 10);
387     buffer[pos--] = '0' + r;
388     v = q;
389   }
390   // Last digit is trivial to handle
391   buffer[pos] = static_cast<char>(v) + '0';
392   return result;
393 }
394
395 /**
396  * A single char gets appended.
397  */
398 template <class Tgt>
399 void toAppend(char value, Tgt * result) {
400   *result += value;
401 }
402
403 template <class T>
404 constexpr typename std::enable_if<
405   std::is_same<T, char>::value,
406   size_t>::type
407 estimateSpaceNeeded(T) {
408   return 1;
409 }
410
411 template <size_t N>
412 constexpr size_t estimateSpaceNeeded(const char (&)[N]) {
413   return N;
414 }
415
416 /**
417  * Everything implicitly convertible to const char* gets appended.
418  */
419 template <class Tgt, class Src>
420 typename std::enable_if<
421   std::is_convertible<Src, const char*>::value
422   && IsSomeString<Tgt>::value>::type
423 toAppend(Src value, Tgt * result) {
424   // Treat null pointers like an empty string, as in:
425   // operator<<(std::ostream&, const char*).
426   const char* c = value;
427   if (c) {
428     result->append(value);
429   }
430 }
431
432 template <class Src>
433 typename std::enable_if<std::is_convertible<Src, const char*>::value, size_t>::
434     type
435     estimateSpaceNeeded(Src value) {
436   const char *c = value;
437   if (c) {
438     return folly::StringPiece(value).size();
439   };
440   return 0;
441 }
442
443 template <class Src>
444 typename std::enable_if<IsSomeString<Src>::value, size_t>::type
445 estimateSpaceNeeded(Src const& value) {
446   return value.size();
447 }
448
449 template <class Src>
450 typename std::enable_if<
451     std::is_convertible<Src, folly::StringPiece>::value &&
452         !IsSomeString<Src>::value &&
453         !std::is_convertible<Src, const char*>::value,
454     size_t>::type
455 estimateSpaceNeeded(Src value) {
456   return folly::StringPiece(value).size();
457 }
458
459 template <>
460 inline size_t estimateSpaceNeeded(std::nullptr_t /* value */) {
461   return 0;
462 }
463
464 template <class Src>
465 typename std::enable_if<
466   std::is_pointer<Src>::value &&
467   IsSomeString<std::remove_pointer<Src>>::value,
468   size_t>::type
469 estimateSpaceNeeded(Src value) {
470   return value->size();
471 }
472
473 /**
474  * Strings get appended, too.
475  */
476 template <class Tgt, class Src>
477 typename std::enable_if<
478   IsSomeString<Src>::value && IsSomeString<Tgt>::value>::type
479 toAppend(const Src& value, Tgt * result) {
480   result->append(value);
481 }
482
483 /**
484  * and StringPiece objects too
485  */
486 template <class Tgt>
487 typename std::enable_if<
488    IsSomeString<Tgt>::value>::type
489 toAppend(StringPiece value, Tgt * result) {
490   result->append(value.data(), value.size());
491 }
492
493 /**
494  * There's no implicit conversion from fbstring to other string types,
495  * so make a specialization.
496  */
497 template <class Tgt>
498 typename std::enable_if<
499    IsSomeString<Tgt>::value>::type
500 toAppend(const fbstring& value, Tgt * result) {
501   result->append(value.data(), value.size());
502 }
503
504 #if FOLLY_HAVE_INT128_T
505 /**
506  * Special handling for 128 bit integers.
507  */
508
509 template <class Tgt>
510 void
511 toAppend(__int128 value, Tgt * result) {
512   typedef unsigned __int128 Usrc;
513   char buffer[detail::digitsEnough<unsigned __int128>() + 1];
514   size_t p;
515
516   if (value < 0) {
517     p = detail::unsafeTelescope128(buffer, sizeof(buffer), -Usrc(value));
518     buffer[--p] = '-';
519   } else {
520     p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
521   }
522
523   result->append(buffer + p, buffer + sizeof(buffer));
524 }
525
526 template <class Tgt>
527 void
528 toAppend(unsigned __int128 value, Tgt * result) {
529   char buffer[detail::digitsEnough<unsigned __int128>()];
530   size_t p;
531
532   p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
533
534   result->append(buffer + p, buffer + sizeof(buffer));
535 }
536
537 template <class T>
538 constexpr typename std::enable_if<
539   std::is_same<T, __int128>::value,
540   size_t>::type
541 estimateSpaceNeeded(T) {
542   return detail::digitsEnough<__int128>();
543 }
544
545 template <class T>
546 constexpr typename std::enable_if<
547   std::is_same<T, unsigned __int128>::value,
548   size_t>::type
549 estimateSpaceNeeded(T) {
550   return detail::digitsEnough<unsigned __int128>();
551 }
552
553 #endif
554
555 /**
556  * int32_t and int64_t to string (by appending) go through here. The
557  * result is APPENDED to a preexisting string passed as the second
558  * parameter. This should be efficient with fbstring because fbstring
559  * incurs no dynamic allocation below 23 bytes and no number has more
560  * than 22 bytes in its textual representation (20 for digits, one for
561  * sign, one for the terminating 0).
562  */
563 template <class Tgt, class Src>
564 typename std::enable_if<
565   std::is_integral<Src>::value && std::is_signed<Src>::value &&
566   IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
567 toAppend(Src value, Tgt * result) {
568   char buffer[20];
569   if (value < 0) {
570     result->push_back('-');
571     result->append(
572         buffer,
573         uint64ToBufferUnsafe(~static_cast<uint64_t>(value) + 1, buffer));
574   } else {
575     result->append(buffer, uint64ToBufferUnsafe(uint64_t(value), buffer));
576   }
577 }
578
579 template <class Src>
580 typename std::enable_if<
581   std::is_integral<Src>::value && std::is_signed<Src>::value
582   && sizeof(Src) >= 4 && sizeof(Src) < 16,
583   size_t>::type
584 estimateSpaceNeeded(Src value) {
585   if (value < 0) {
586     // When "value" is the smallest negative, negating it would evoke
587     // undefined behavior, so, instead of writing "-value" below, we write
588     // "~static_cast<uint64_t>(value) + 1"
589     return 1 + digits10(~static_cast<uint64_t>(value) + 1);
590   }
591
592   return digits10(static_cast<uint64_t>(value));
593 }
594
595 /**
596  * As above, but for uint32_t and uint64_t.
597  */
598 template <class Tgt, class Src>
599 typename std::enable_if<
600   std::is_integral<Src>::value && !std::is_signed<Src>::value
601   && IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
602 toAppend(Src value, Tgt * result) {
603   char buffer[20];
604   result->append(buffer, uint64ToBufferUnsafe(value, buffer));
605 }
606
607 template <class Src>
608 typename std::enable_if<
609   std::is_integral<Src>::value && !std::is_signed<Src>::value
610   && sizeof(Src) >= 4 && sizeof(Src) < 16,
611   size_t>::type
612 estimateSpaceNeeded(Src value) {
613   return digits10(value);
614 }
615
616 /**
617  * All small signed and unsigned integers to string go through 32-bit
618  * types int32_t and uint32_t, respectively.
619  */
620 template <class Tgt, class Src>
621 typename std::enable_if<
622   std::is_integral<Src>::value
623   && IsSomeString<Tgt>::value && sizeof(Src) < 4>::type
624 toAppend(Src value, Tgt * result) {
625   typedef typename
626     std::conditional<std::is_signed<Src>::value, int64_t, uint64_t>::type
627     Intermediate;
628   toAppend<Tgt>(static_cast<Intermediate>(value), result);
629 }
630
631 template <class Src>
632 typename std::enable_if<
633   std::is_integral<Src>::value
634   && sizeof(Src) < 4
635   && !std::is_same<Src, char>::value,
636   size_t>::type
637 estimateSpaceNeeded(Src value) {
638   typedef typename
639     std::conditional<std::is_signed<Src>::value, int64_t, uint64_t>::type
640     Intermediate;
641   return estimateSpaceNeeded(static_cast<Intermediate>(value));
642 }
643
644 /**
645  * Enumerated values get appended as integers.
646  */
647 template <class Tgt, class Src>
648 typename std::enable_if<
649   std::is_enum<Src>::value && IsSomeString<Tgt>::value>::type
650 toAppend(Src value, Tgt * result) {
651   toAppend(
652       static_cast<typename std::underlying_type<Src>::type>(value), result);
653 }
654
655 template <class Src>
656 typename std::enable_if<
657   std::is_enum<Src>::value, size_t>::type
658 estimateSpaceNeeded(Src value) {
659   return estimateSpaceNeeded(
660       static_cast<typename std::underlying_type<Src>::type>(value));
661 }
662
663 /*******************************************************************************
664  * Conversions from floating-point types to string types.
665  ******************************************************************************/
666
667 namespace detail {
668 constexpr int kConvMaxDecimalInShortestLow = -6;
669 constexpr int kConvMaxDecimalInShortestHigh = 21;
670 } // namespace detail
671
672 /** Wrapper around DoubleToStringConverter **/
673 template <class Tgt, class Src>
674 typename std::enable_if<
675   std::is_floating_point<Src>::value
676   && IsSomeString<Tgt>::value>::type
677 toAppend(
678   Src value,
679   Tgt * result,
680   double_conversion::DoubleToStringConverter::DtoaMode mode,
681   unsigned int numDigits) {
682   using namespace double_conversion;
683   DoubleToStringConverter
684     conv(DoubleToStringConverter::NO_FLAGS,
685          "Infinity", "NaN", 'E',
686          detail::kConvMaxDecimalInShortestLow,
687          detail::kConvMaxDecimalInShortestHigh,
688          6,   // max leading padding zeros
689          1);  // max trailing padding zeros
690   char buffer[256];
691   StringBuilder builder(buffer, sizeof(buffer));
692   switch (mode) {
693     case DoubleToStringConverter::SHORTEST:
694       conv.ToShortest(value, &builder);
695       break;
696     case DoubleToStringConverter::FIXED:
697       conv.ToFixed(value, int(numDigits), &builder);
698       break;
699     default:
700       CHECK(mode == DoubleToStringConverter::PRECISION);
701       conv.ToPrecision(value, int(numDigits), &builder);
702       break;
703   }
704   const size_t length = size_t(builder.position());
705   builder.Finalize();
706   result->append(buffer, length);
707 }
708
709 /**
710  * As above, but for floating point
711  */
712 template <class Tgt, class Src>
713 typename std::enable_if<
714   std::is_floating_point<Src>::value
715   && IsSomeString<Tgt>::value>::type
716 toAppend(Src value, Tgt * result) {
717   toAppend(
718     value, result, double_conversion::DoubleToStringConverter::SHORTEST, 0);
719 }
720
721 /**
722  * Upper bound of the length of the output from
723  * DoubleToStringConverter::ToShortest(double, StringBuilder*),
724  * as used in toAppend(double, string*).
725  */
726 template <class Src>
727 typename std::enable_if<
728   std::is_floating_point<Src>::value, size_t>::type
729 estimateSpaceNeeded(Src value) {
730   // kBase10MaximalLength is 17. We add 1 for decimal point,
731   // e.g. 10.0/9 is 17 digits and 18 characters, including the decimal point.
732   constexpr int kMaxMantissaSpace =
733     double_conversion::DoubleToStringConverter::kBase10MaximalLength + 1;
734   // strlen("E-") + digits10(numeric_limits<double>::max_exponent10)
735   constexpr int kMaxExponentSpace = 2 + 3;
736   static const int kMaxPositiveSpace = std::max({
737       // E.g. 1.1111111111111111E-100.
738       kMaxMantissaSpace + kMaxExponentSpace,
739       // E.g. 0.000001.1111111111111111, if kConvMaxDecimalInShortestLow is -6.
740       kMaxMantissaSpace - detail::kConvMaxDecimalInShortestLow,
741       // If kConvMaxDecimalInShortestHigh is 21, then 1e21 is the smallest
742       // number > 1 which ToShortest outputs in exponential notation,
743       // so 21 is the longest non-exponential number > 1.
744       detail::kConvMaxDecimalInShortestHigh
745     });
746   return size_t(
747       kMaxPositiveSpace +
748       (value < 0 ? 1 : 0)); // +1 for minus sign, if negative
749 }
750
751 /**
752  * This can be specialized, together with adding specialization
753  * for estimateSpaceNeed for your type, so that we allocate
754  * as much as you need instead of the default
755  */
756 template <class Src>
757 struct HasLengthEstimator : std::false_type {};
758
759 template <class Src>
760 constexpr typename std::enable_if<
761   !std::is_fundamental<Src>::value
762 #if FOLLY_HAVE_INT128_T
763   // On OSX 10.10, is_fundamental<__int128> is false :-O
764   && !std::is_same<__int128, Src>::value
765   && !std::is_same<unsigned __int128, Src>::value
766 #endif
767   && !IsSomeString<Src>::value
768   && !std::is_convertible<Src, const char*>::value
769   && !std::is_convertible<Src, StringPiece>::value
770   && !std::is_enum<Src>::value
771   && !HasLengthEstimator<Src>::value,
772   size_t>::type
773 estimateSpaceNeeded(const Src&) {
774   return sizeof(Src) + 1; // dumbest best effort ever?
775 }
776
777 namespace detail {
778
779 template <class Tgt>
780 typename std::enable_if<IsSomeString<Tgt>::value, size_t>::type
781 estimateSpaceToReserve(size_t sofar, Tgt*) {
782   return sofar;
783 }
784
785 template <class T, class... Ts>
786 size_t estimateSpaceToReserve(size_t sofar, const T& v, const Ts&... vs) {
787   return estimateSpaceToReserve(sofar + estimateSpaceNeeded(v), vs...);
788 }
789
790 template <class... Ts>
791 void reserveInTarget(const Ts&...vs) {
792   getLastElement(vs...)->reserve(estimateSpaceToReserve(0, vs...));
793 }
794
795 template <class Delimiter, class... Ts>
796 void reserveInTargetDelim(const Delimiter& d, const Ts&...vs) {
797   static_assert(sizeof...(vs) >= 2, "Needs at least 2 args");
798   size_t fordelim = (sizeof...(vs) - 2) *
799       estimateSpaceToReserve(0, d, static_cast<std::string*>(nullptr));
800   getLastElement(vs...)->reserve(estimateSpaceToReserve(fordelim, vs...));
801 }
802
803 /**
804  * Variadic base case: append one element
805  */
806 template <class T, class Tgt>
807 typename std::enable_if<
808   IsSomeString<typename std::remove_pointer<Tgt>::type>
809   ::value>::type
810 toAppendStrImpl(const T& v, Tgt result) {
811   toAppend(v, result);
812 }
813
814 template <class T, class... Ts>
815 typename std::enable_if<
816     sizeof...(Ts) >= 2 &&
817     IsSomeString<typename std::remove_pointer<
818         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
819 toAppendStrImpl(const T& v, const Ts&... vs) {
820   toAppend(v, getLastElement(vs...));
821   toAppendStrImpl(vs...);
822 }
823
824 template <class Delimiter, class T, class Tgt>
825 typename std::enable_if<
826     IsSomeString<typename std::remove_pointer<Tgt>::type>::value>::type
827 toAppendDelimStrImpl(const Delimiter& /* delim */, const T& v, Tgt result) {
828   toAppend(v, result);
829 }
830
831 template <class Delimiter, class T, class... Ts>
832 typename std::enable_if<
833     sizeof...(Ts) >= 2 &&
834     IsSomeString<typename std::remove_pointer<
835         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
836 toAppendDelimStrImpl(const Delimiter& delim, const T& v, const Ts&... vs) {
837   // we are really careful here, calling toAppend with just one element does
838   // not try to estimate space needed (as we already did that). If we call
839   // toAppend(v, delim, ....) we would do unnecesary size calculation
840   toAppend(v, detail::getLastElement(vs...));
841   toAppend(delim, detail::getLastElement(vs...));
842   toAppendDelimStrImpl(delim, vs...);
843 }
844 } // namespace detail
845
846 /**
847  * Variadic conversion to string. Appends each element in turn.
848  * If we have two or more things to append, we it will not reserve
849  * the space for them and will depend on strings exponential growth.
850  * If you just append once consider using toAppendFit which reserves
851  * the space needed (but does not have exponential as a result).
852  *
853  * Custom implementations of toAppend() can be provided in the same namespace as
854  * the type to customize printing. estimateSpaceNeed() may also be provided to
855  * avoid reallocations in toAppendFit():
856  *
857  * namespace other_namespace {
858  *
859  * template <class String>
860  * void toAppend(const OtherType&, String* out);
861  *
862  * // optional
863  * size_t estimateSpaceNeeded(const OtherType&);
864  *
865  * }
866  */
867 template <class... Ts>
868 typename std::enable_if<
869     sizeof...(Ts) >= 3 &&
870     IsSomeString<typename std::remove_pointer<
871         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
872 toAppend(const Ts&... vs) {
873   ::folly::detail::toAppendStrImpl(vs...);
874 }
875
876 #ifdef _MSC_VER
877 // Special case pid_t on MSVC, because it's a void* rather than an
878 // integral type. We can't do a global special case because this is already
879 // dangerous enough (as most pointers will implicitly convert to a void*)
880 // just doing it for MSVC.
881 template <class Tgt>
882 void toAppend(const pid_t a, Tgt* res) {
883   toAppend(uint64_t(a), res);
884 }
885 #endif
886
887 /**
888  * Special version of the call that preallocates exaclty as much memory
889  * as need for arguments to be stored in target. This means we are
890  * not doing exponential growth when we append. If you are using it
891  * in a loop you are aiming at your foot with a big perf-destroying
892  * bazooka.
893  * On the other hand if you are appending to a string once, this
894  * will probably save a few calls to malloc.
895  */
896 template <class... Ts>
897 typename std::enable_if<IsSomeString<typename std::remove_pointer<
898     typename detail::LastElement<const Ts&...>::type>::type>::value>::type
899 toAppendFit(const Ts&... vs) {
900   ::folly::detail::reserveInTarget(vs...);
901   toAppend(vs...);
902 }
903
904 template <class Ts>
905 void toAppendFit(const Ts&) {}
906
907 /**
908  * Variadic base case: do nothing.
909  */
910 template <class Tgt>
911 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend(
912     Tgt* /* result */) {}
913
914 /**
915  * Variadic base case: do nothing.
916  */
917 template <class Delimiter, class Tgt>
918 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppendDelim(
919     const Delimiter& /* delim */, Tgt* /* result */) {}
920
921 /**
922  * 1 element: same as toAppend.
923  */
924 template <class Delimiter, class T, class Tgt>
925 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppendDelim(
926     const Delimiter& /* delim */, const T& v, Tgt* tgt) {
927   toAppend(v, tgt);
928 }
929
930 /**
931  * Append to string with a delimiter in between elements. Check out
932  * comments for toAppend for details about memory allocation.
933  */
934 template <class Delimiter, class... Ts>
935 typename std::enable_if<
936     sizeof...(Ts) >= 3 &&
937     IsSomeString<typename std::remove_pointer<
938         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
939 toAppendDelim(const Delimiter& delim, const Ts&... vs) {
940   detail::toAppendDelimStrImpl(delim, vs...);
941 }
942
943 /**
944  * Detail in comment for toAppendFit
945  */
946 template <class Delimiter, class... Ts>
947 typename std::enable_if<IsSomeString<typename std::remove_pointer<
948     typename detail::LastElement<const Ts&...>::type>::type>::value>::type
949 toAppendDelimFit(const Delimiter& delim, const Ts&... vs) {
950   detail::reserveInTargetDelim(delim, vs...);
951   toAppendDelim(delim, vs...);
952 }
953
954 template <class De, class Ts>
955 void toAppendDelimFit(const De&, const Ts&) {}
956
957 /**
958  * to<SomeString>(v1, v2, ...) uses toAppend() (see below) as back-end
959  * for all types.
960  */
961 template <class Tgt, class... Ts>
962 typename std::enable_if<
963     IsSomeString<Tgt>::value &&
964         (sizeof...(Ts) != 1 ||
965          !std::is_same<Tgt, typename detail::LastElement<const Ts&...>::type>::
966              value),
967     Tgt>::type
968 to(const Ts&... vs) {
969   Tgt result;
970   toAppendFit(vs..., &result);
971   return result;
972 }
973
974 /**
975  * Special version of to<SomeString> for floating point. When calling
976  * folly::to<SomeString>(double), generic implementation above will
977  * firstly reserve 24 (or 25 when negative value) bytes. This will
978  * introduce a malloc call for most mainstream string implementations.
979  *
980  * But for most cases, a floating point doesn't need 24 (or 25) bytes to
981  * be converted as a string.
982  *
983  * This special version will not do string reserve.
984  */
985 template <class Tgt, class Src>
986 typename std::enable_if<
987     IsSomeString<Tgt>::value && std::is_floating_point<Src>::value,
988     Tgt>::type
989 to(Src value) {
990   Tgt result;
991   toAppend(value, &result);
992   return result;
993 }
994
995 /**
996  * toDelim<SomeString>(SomeString str) returns itself.
997  */
998 template <class Tgt, class Delim, class Src>
999 typename std::enable_if<
1000     IsSomeString<Tgt>::value &&
1001         std::is_same<Tgt, typename std::decay<Src>::type>::value,
1002     Tgt>::type
1003 toDelim(const Delim& /* delim */, Src&& value) {
1004   return std::forward<Src>(value);
1005 }
1006
1007 /**
1008  * toDelim<SomeString>(delim, v1, v2, ...) uses toAppendDelim() as
1009  * back-end for all types.
1010  */
1011 template <class Tgt, class Delim, class... Ts>
1012 typename std::enable_if<
1013     IsSomeString<Tgt>::value &&
1014         (sizeof...(Ts) != 1 ||
1015          !std::is_same<Tgt, typename detail::LastElement<const Ts&...>::type>::
1016              value),
1017     Tgt>::type
1018 toDelim(const Delim& delim, const Ts&... vs) {
1019   Tgt result;
1020   toAppendDelimFit(delim, vs..., &result);
1021   return result;
1022 }
1023
1024 /*******************************************************************************
1025  * Conversions from string types to integral types.
1026  ******************************************************************************/
1027
1028 namespace detail {
1029
1030 Expected<bool, ConversionCode> str_to_bool(StringPiece* src) noexcept;
1031
1032 template <typename T>
1033 Expected<T, ConversionCode> str_to_floating(StringPiece* src) noexcept;
1034
1035 extern template Expected<float, ConversionCode> str_to_floating<float>(
1036     StringPiece* src) noexcept;
1037 extern template Expected<double, ConversionCode> str_to_floating<double>(
1038     StringPiece* src) noexcept;
1039
1040 template <class Tgt>
1041 Expected<Tgt, ConversionCode> digits_to(const char* b, const char* e) noexcept;
1042
1043 extern template Expected<char, ConversionCode> digits_to<char>(
1044     const char*,
1045     const char*) noexcept;
1046 extern template Expected<signed char, ConversionCode> digits_to<signed char>(
1047     const char*,
1048     const char*) noexcept;
1049 extern template Expected<unsigned char, ConversionCode>
1050 digits_to<unsigned char>(const char*, const char*) noexcept;
1051
1052 extern template Expected<short, ConversionCode> digits_to<short>(
1053     const char*,
1054     const char*) noexcept;
1055 extern template Expected<unsigned short, ConversionCode>
1056 digits_to<unsigned short>(const char*, const char*) noexcept;
1057
1058 extern template Expected<int, ConversionCode> digits_to<int>(
1059     const char*,
1060     const char*) noexcept;
1061 extern template Expected<unsigned int, ConversionCode> digits_to<unsigned int>(
1062     const char*,
1063     const char*) noexcept;
1064
1065 extern template Expected<long, ConversionCode> digits_to<long>(
1066     const char*,
1067     const char*) noexcept;
1068 extern template Expected<unsigned long, ConversionCode>
1069 digits_to<unsigned long>(const char*, const char*) noexcept;
1070
1071 extern template Expected<long long, ConversionCode> digits_to<long long>(
1072     const char*,
1073     const char*) noexcept;
1074 extern template Expected<unsigned long long, ConversionCode>
1075 digits_to<unsigned long long>(const char*, const char*) noexcept;
1076
1077 #if FOLLY_HAVE_INT128_T
1078 extern template Expected<__int128, ConversionCode> digits_to<__int128>(
1079     const char*,
1080     const char*) noexcept;
1081 extern template Expected<unsigned __int128, ConversionCode>
1082 digits_to<unsigned __int128>(const char*, const char*) noexcept;
1083 #endif
1084
1085 template <class T>
1086 Expected<T, ConversionCode> str_to_integral(StringPiece* src) noexcept;
1087
1088 extern template Expected<char, ConversionCode> str_to_integral<char>(
1089     StringPiece* src) noexcept;
1090 extern template Expected<signed char, ConversionCode>
1091 str_to_integral<signed char>(StringPiece* src) noexcept;
1092 extern template Expected<unsigned char, ConversionCode>
1093 str_to_integral<unsigned char>(StringPiece* src) noexcept;
1094
1095 extern template Expected<short, ConversionCode> str_to_integral<short>(
1096     StringPiece* src) noexcept;
1097 extern template Expected<unsigned short, ConversionCode>
1098 str_to_integral<unsigned short>(StringPiece* src) noexcept;
1099
1100 extern template Expected<int, ConversionCode> str_to_integral<int>(
1101     StringPiece* src) noexcept;
1102 extern template Expected<unsigned int, ConversionCode>
1103 str_to_integral<unsigned int>(StringPiece* src) noexcept;
1104
1105 extern template Expected<long, ConversionCode> str_to_integral<long>(
1106     StringPiece* src) noexcept;
1107 extern template Expected<unsigned long, ConversionCode>
1108 str_to_integral<unsigned long>(StringPiece* src) noexcept;
1109
1110 extern template Expected<long long, ConversionCode> str_to_integral<long long>(
1111     StringPiece* src) noexcept;
1112 extern template Expected<unsigned long long, ConversionCode>
1113 str_to_integral<unsigned long long>(StringPiece* src) noexcept;
1114
1115 #if FOLLY_HAVE_INT128_T
1116 extern template Expected<__int128, ConversionCode> str_to_integral<__int128>(
1117     StringPiece* src) noexcept;
1118 extern template Expected<unsigned __int128, ConversionCode>
1119 str_to_integral<unsigned __int128>(StringPiece* src) noexcept;
1120 #endif
1121
1122 template <typename T>
1123 typename std::
1124     enable_if<std::is_same<T, bool>::value, Expected<T, ConversionCode>>::type
1125     convertTo(StringPiece* src) noexcept {
1126   return str_to_bool(src);
1127 }
1128
1129 template <typename T>
1130 typename std::enable_if<
1131     std::is_floating_point<T>::value,
1132     Expected<T, ConversionCode>>::type
1133 convertTo(StringPiece* src) noexcept {
1134   return str_to_floating<T>(src);
1135 }
1136
1137 template <typename T>
1138 typename std::enable_if<
1139     std::is_integral<T>::value && !std::is_same<T, bool>::value,
1140     Expected<T, ConversionCode>>::type
1141 convertTo(StringPiece* src) noexcept {
1142   return str_to_integral<T>(src);
1143 }
1144
1145 } // namespace detail
1146
1147 /**
1148  * String represented as a pair of pointers to char to unsigned
1149  * integrals. Assumes NO whitespace before or after.
1150  */
1151 template <typename Tgt>
1152 typename std::enable_if<
1153     std::is_integral<Tgt>::value && !std::is_same<Tgt, bool>::value,
1154     Expected<Tgt, ConversionCode>>::type
1155 tryTo(const char* b, const char* e) {
1156   return detail::digits_to<Tgt>(b, e);
1157 }
1158
1159 template <typename Tgt>
1160 typename std::enable_if<
1161     std::is_integral<Tgt>::value && !std::is_same<Tgt, bool>::value,
1162     Tgt>::type
1163 to(const char* b, const char* e) {
1164   return tryTo<Tgt>(b, e).thenOrThrow(
1165       [](Tgt res) { return res; },
1166       [=](ConversionCode code) {
1167         return makeConversionError(code, StringPiece(b, e));
1168       });
1169 }
1170
1171 /*******************************************************************************
1172  * Conversions from string types to arithmetic types.
1173  ******************************************************************************/
1174
1175 /**
1176  * Parsing strings to numeric types.
1177  */
1178 template <typename Tgt>
1179 FOLLY_NODISCARD inline typename std::enable_if<
1180     std::is_arithmetic<Tgt>::value,
1181     Expected<StringPiece, ConversionCode>>::type
1182 parseTo(StringPiece src, Tgt& out) {
1183   return detail::convertTo<Tgt>(&src).then(
1184       [&](Tgt res) { return void(out = res), src; });
1185 }
1186
1187 /*******************************************************************************
1188  * Integral / Floating Point to integral / Floating Point
1189  ******************************************************************************/
1190
1191 namespace detail {
1192
1193 /**
1194  * Bool to integral/float doesn't need any special checks, and this
1195  * overload means we aren't trying to see if a bool is less than
1196  * an integer.
1197  */
1198 template <class Tgt>
1199 typename std::enable_if<
1200     !std::is_same<Tgt, bool>::value &&
1201         (std::is_integral<Tgt>::value || std::is_floating_point<Tgt>::value),
1202     Expected<Tgt, ConversionCode>>::type
1203 convertTo(const bool& value) noexcept {
1204   return static_cast<Tgt>(value ? 1 : 0);
1205 }
1206
1207 /**
1208  * Checked conversion from integral to integral. The checks are only
1209  * performed when meaningful, e.g. conversion from int to long goes
1210  * unchecked.
1211  */
1212 template <class Tgt, class Src>
1213 typename std::enable_if<
1214     std::is_integral<Src>::value && !std::is_same<Tgt, Src>::value &&
1215         !std::is_same<Tgt, bool>::value &&
1216         std::is_integral<Tgt>::value,
1217     Expected<Tgt, ConversionCode>>::type
1218 convertTo(const Src& value) noexcept {
1219   /* static */ if (
1220       folly::_t<std::make_unsigned<Tgt>>(std::numeric_limits<Tgt>::max()) <
1221       folly::_t<std::make_unsigned<Src>>(std::numeric_limits<Src>::max())) {
1222     if (greater_than<Tgt, std::numeric_limits<Tgt>::max()>(value)) {
1223       return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
1224     }
1225   }
1226   /* static */ if (
1227       std::is_signed<Src>::value &&
1228       (!std::is_signed<Tgt>::value || sizeof(Src) > sizeof(Tgt))) {
1229     if (less_than<Tgt, std::numeric_limits<Tgt>::min()>(value)) {
1230       return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
1231     }
1232   }
1233   return static_cast<Tgt>(value);
1234 }
1235
1236 /**
1237  * Checked conversion from floating to floating. The checks are only
1238  * performed when meaningful, e.g. conversion from float to double goes
1239  * unchecked.
1240  */
1241 template <class Tgt, class Src>
1242 typename std::enable_if<
1243     std::is_floating_point<Tgt>::value && std::is_floating_point<Src>::value &&
1244         !std::is_same<Tgt, Src>::value,
1245     Expected<Tgt, ConversionCode>>::type
1246 convertTo(const Src& value) noexcept {
1247   /* static */ if (
1248       std::numeric_limits<Tgt>::max() < std::numeric_limits<Src>::max()) {
1249     if (value > std::numeric_limits<Tgt>::max()) {
1250       return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
1251     }
1252     if (value < std::numeric_limits<Tgt>::lowest()) {
1253       return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
1254     }
1255   }
1256   return static_cast<Tgt>(value);
1257 }
1258
1259 /**
1260  * Check if a floating point value can safely be converted to an
1261  * integer value without triggering undefined behaviour.
1262  */
1263 template <typename Tgt, typename Src>
1264 inline typename std::enable_if<
1265     std::is_floating_point<Src>::value && std::is_integral<Tgt>::value &&
1266         !std::is_same<Tgt, bool>::value,
1267     bool>::type
1268 checkConversion(const Src& value) {
1269   constexpr Src tgtMaxAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::max());
1270   constexpr Src tgtMinAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::min());
1271   if (value >= tgtMaxAsSrc) {
1272     if (value > tgtMaxAsSrc) {
1273       return false;
1274     }
1275     const Src mmax = folly::nextafter(tgtMaxAsSrc, Src());
1276     if (static_cast<Tgt>(value - mmax) >
1277         std::numeric_limits<Tgt>::max() - static_cast<Tgt>(mmax)) {
1278       return false;
1279     }
1280   } else if (std::is_signed<Tgt>::value && value <= tgtMinAsSrc) {
1281     if (value < tgtMinAsSrc) {
1282       return false;
1283     }
1284     const Src mmin = folly::nextafter(tgtMinAsSrc, Src());
1285     if (static_cast<Tgt>(value - mmin) <
1286         std::numeric_limits<Tgt>::min() - static_cast<Tgt>(mmin)) {
1287       return false;
1288     }
1289   }
1290   return true;
1291 }
1292
1293 // Integers can always safely be converted to floating point values
1294 template <typename Tgt, typename Src>
1295 constexpr typename std::enable_if<
1296     std::is_integral<Src>::value && std::is_floating_point<Tgt>::value,
1297     bool>::type
1298 checkConversion(const Src&) {
1299   return true;
1300 }
1301
1302 // Also, floating point values can always be safely converted to bool
1303 // Per the standard, any floating point value that is not zero will yield true
1304 template <typename Tgt, typename Src>
1305 constexpr typename std::enable_if<
1306     std::is_floating_point<Src>::value && std::is_same<Tgt, bool>::value,
1307     bool>::type
1308 checkConversion(const Src&) {
1309   return true;
1310 }
1311
1312 /**
1313  * Checked conversion from integral to floating point and back. The
1314  * result must be convertible back to the source type without loss of
1315  * precision. This seems Draconian but sometimes is what's needed, and
1316  * complements existing routines nicely. For various rounding
1317  * routines, see <math>.
1318  */
1319 template <typename Tgt, typename Src>
1320 typename std::enable_if<
1321     (std::is_integral<Src>::value && std::is_floating_point<Tgt>::value) ||
1322         (std::is_floating_point<Src>::value && std::is_integral<Tgt>::value),
1323     Expected<Tgt, ConversionCode>>::type
1324 convertTo(const Src& value) noexcept {
1325   if (LIKELY(checkConversion<Tgt>(value))) {
1326     Tgt result = static_cast<Tgt>(value);
1327     if (LIKELY(checkConversion<Src>(result))) {
1328       Src witness = static_cast<Src>(result);
1329       if (LIKELY(value == witness)) {
1330         return result;
1331       }
1332     }
1333   }
1334   return makeUnexpected(ConversionCode::ARITH_LOSS_OF_PRECISION);
1335 }
1336
1337 template <typename Tgt, typename Src>
1338 inline std::string errorValue(const Src& value) {
1339 #ifdef FOLLY_HAS_RTTI
1340   return to<std::string>("(", demangle(typeid(Tgt)), ") ", value);
1341 #else
1342   return to<std::string>(value);
1343 #endif
1344 }
1345
1346 template <typename Tgt, typename Src>
1347 using IsArithToArith = std::integral_constant<
1348     bool,
1349     !std::is_same<Tgt, Src>::value && !std::is_same<Tgt, bool>::value &&
1350         std::is_arithmetic<Src>::value &&
1351         std::is_arithmetic<Tgt>::value>;
1352
1353 } // namespace detail
1354
1355 template <typename Tgt, typename Src>
1356 typename std::enable_if<
1357     detail::IsArithToArith<Tgt, Src>::value,
1358     Expected<Tgt, ConversionCode>>::type
1359 tryTo(const Src& value) noexcept {
1360   return detail::convertTo<Tgt>(value);
1361 }
1362
1363 template <typename Tgt, typename Src>
1364 typename std::enable_if<detail::IsArithToArith<Tgt, Src>::value, Tgt>::type to(
1365     const Src& value) {
1366   return tryTo<Tgt>(value).thenOrThrow(
1367       [](Tgt res) { return res; },
1368       [&](ConversionCode e) {
1369         return makeConversionError(e, detail::errorValue<Tgt>(value));
1370       });
1371 }
1372
1373 /*******************************************************************************
1374  * Custom Conversions
1375  *
1376  * Any type can be used with folly::to by implementing parseTo. The
1377  * implementation should be provided in the namespace of the type to facilitate
1378  * argument-dependent lookup:
1379  *
1380  * namespace other_namespace {
1381  * ::folly::Expected<::folly::StringPiece, SomeErrorCode>
1382  *   parseTo(::folly::StringPiece, OtherType&) noexcept;
1383  * }
1384  ******************************************************************************/
1385 template <class T>
1386 FOLLY_NODISCARD typename std::enable_if<
1387     std::is_enum<T>::value,
1388     Expected<StringPiece, ConversionCode>>::type
1389 parseTo(StringPiece in, T& out) noexcept {
1390   typename std::underlying_type<T>::type tmp{};
1391   auto restOrError = parseTo(in, tmp);
1392   out = static_cast<T>(tmp); // Harmless if parseTo fails
1393   return restOrError;
1394 }
1395
1396 FOLLY_NODISCARD
1397 inline Expected<StringPiece, ConversionCode> parseTo(
1398     StringPiece in,
1399     StringPiece& out) noexcept {
1400   out = in;
1401   return StringPiece{in.end(), in.end()};
1402 }
1403
1404 FOLLY_NODISCARD
1405 inline Expected<StringPiece, ConversionCode> parseTo(
1406     StringPiece in,
1407     std::string& out) {
1408   out.clear();
1409   out.append(in.data(), in.size()); // TODO try/catch?
1410   return StringPiece{in.end(), in.end()};
1411 }
1412
1413 FOLLY_NODISCARD
1414 inline Expected<StringPiece, ConversionCode> parseTo(
1415     StringPiece in,
1416     fbstring& out) {
1417   out.clear();
1418   out.append(in.data(), in.size()); // TODO try/catch?
1419   return StringPiece{in.end(), in.end()};
1420 }
1421
1422 namespace detail {
1423 template <typename Tgt>
1424 using ParseToResult = decltype(parseTo(StringPiece{}, std::declval<Tgt&>()));
1425
1426 struct CheckTrailingSpace {
1427   Expected<Unit, ConversionCode> operator()(StringPiece sp) const {
1428     auto e = enforceWhitespaceErr(sp);
1429     if (UNLIKELY(e != ConversionCode::SUCCESS)) {
1430       return makeUnexpected(e);
1431     }
1432     return unit;
1433   }
1434 };
1435
1436 template <class Error>
1437 struct ReturnUnit {
1438   template <class T>
1439   constexpr Expected<Unit, Error> operator()(T&&) const {
1440     return unit;
1441   }
1442 };
1443
1444 // Older versions of the parseTo customization point threw on error and
1445 // returned void. Handle that.
1446 template <class Tgt>
1447 inline typename std::enable_if<
1448     std::is_void<ParseToResult<Tgt>>::value,
1449     Expected<StringPiece, ConversionCode>>::type
1450 parseToWrap(StringPiece sp, Tgt& out) {
1451   parseTo(sp, out);
1452   return StringPiece(sp.end(), sp.end());
1453 }
1454
1455 template <class Tgt>
1456 inline typename std::enable_if<
1457     !std::is_void<ParseToResult<Tgt>>::value,
1458     ParseToResult<Tgt>>::type
1459 parseToWrap(StringPiece sp, Tgt& out) {
1460   return parseTo(sp, out);
1461 }
1462
1463 template <typename Tgt>
1464 using ParseToError = ExpectedErrorType<decltype(
1465     detail::parseToWrap(StringPiece{}, std::declval<Tgt&>()))>;
1466
1467 } // namespace detail
1468
1469 /**
1470  * String or StringPiece to target conversion. Accepts leading and trailing
1471  * whitespace, but no non-space trailing characters.
1472  */
1473
1474 template <class Tgt>
1475 inline typename std::enable_if<
1476     !std::is_same<StringPiece, Tgt>::value,
1477     Expected<Tgt, detail::ParseToError<Tgt>>>::type
1478 tryTo(StringPiece src) {
1479   Tgt result{};
1480   using Error = detail::ParseToError<Tgt>;
1481   using Check = typename std::conditional<
1482       std::is_arithmetic<Tgt>::value,
1483       detail::CheckTrailingSpace,
1484       detail::ReturnUnit<Error>>::type;
1485   return parseTo(src, result).then(Check(), [&](Unit) {
1486     return std::move(result);
1487   });
1488 }
1489
1490 template <class Tgt, class Src>
1491 inline typename std::enable_if<
1492     IsSomeString<Src>::value && !std::is_same<StringPiece, Tgt>::value,
1493     Tgt>::type
1494 to(Src const& src) {
1495   return to<Tgt>(StringPiece(src.data(), src.size()));
1496 }
1497
1498 template <class Tgt>
1499 inline
1500     typename std::enable_if<!std::is_same<StringPiece, Tgt>::value, Tgt>::type
1501     to(StringPiece src) {
1502   Tgt result{};
1503   using Error = detail::ParseToError<Tgt>;
1504   using Check = typename std::conditional<
1505       std::is_arithmetic<Tgt>::value,
1506       detail::CheckTrailingSpace,
1507       detail::ReturnUnit<Error>>::type;
1508   auto tmp = detail::parseToWrap(src, result);
1509   return tmp
1510       .thenOrThrow(Check(), [&](Error e) { throw makeConversionError(e, src); })
1511       .thenOrThrow(
1512           [&](Unit) { return std::move(result); },
1513           [&](Error e) { throw makeConversionError(e, tmp.value()); });
1514 }
1515
1516 /**
1517  * tryTo/to that take the strings by pointer so the caller gets information
1518  * about how much of the string was consumed by the conversion. These do not
1519  * check for trailing whitepsace.
1520  */
1521 template <class Tgt>
1522 Expected<Tgt, detail::ParseToError<Tgt>> tryTo(StringPiece* src) {
1523   Tgt result;
1524   return parseTo(*src, result).then([&, src](StringPiece sp) -> Tgt {
1525     *src = sp;
1526     return std::move(result);
1527   });
1528 }
1529
1530 template <class Tgt>
1531 Tgt to(StringPiece* src) {
1532   Tgt result{};
1533   using Error = detail::ParseToError<Tgt>;
1534   return parseTo(*src, result)
1535       .thenOrThrow(
1536           [&, src](StringPiece sp) -> Tgt {
1537             *src = sp;
1538             return std::move(result);
1539           },
1540           [=](Error e) { return makeConversionError(e, *src); });
1541 }
1542
1543 /*******************************************************************************
1544  * Enum to anything and back
1545  ******************************************************************************/
1546
1547 template <class Tgt, class Src>
1548 typename std::enable_if<
1549     std::is_enum<Src>::value && !std::is_same<Src, Tgt>::value,
1550     Expected<Tgt, ConversionCode>>::type
1551 tryTo(const Src& value) {
1552   using I = typename std::underlying_type<Src>::type;
1553   return tryTo<Tgt>(static_cast<I>(value));
1554 }
1555
1556 template <class Tgt, class Src>
1557 typename std::enable_if<
1558     std::is_enum<Tgt>::value && !std::is_same<Src, Tgt>::value,
1559     Expected<Tgt, ConversionCode>>::type
1560 tryTo(const Src& value) {
1561   using I = typename std::underlying_type<Tgt>::type;
1562   return tryTo<I>(value).then([](I i) { return static_cast<Tgt>(i); });
1563 }
1564
1565 template <class Tgt, class Src>
1566 typename std::enable_if<
1567     std::is_enum<Src>::value && !std::is_same<Src, Tgt>::value,
1568     Tgt>::type
1569 to(const Src& value) {
1570   return to<Tgt>(static_cast<typename std::underlying_type<Src>::type>(value));
1571 }
1572
1573 template <class Tgt, class Src>
1574 typename std::enable_if<
1575     !IsSomeString<Src>::value && std::is_enum<Tgt>::value &&
1576         !std::is_same<Src, Tgt>::value,
1577     Tgt>::type
1578 to(const Src& value) {
1579   return static_cast<Tgt>(to<typename std::underlying_type<Tgt>::type>(value));
1580 }
1581
1582 } // namespace folly