Suppress more warnings for MSVC
[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 }
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 }
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 /**
412  * Everything implicitly convertible to const char* gets appended.
413  */
414 template <class Tgt, class Src>
415 typename std::enable_if<
416   std::is_convertible<Src, const char*>::value
417   && IsSomeString<Tgt>::value>::type
418 toAppend(Src value, Tgt * result) {
419   // Treat null pointers like an empty string, as in:
420   // operator<<(std::ostream&, const char*).
421   const char* c = value;
422   if (c) {
423     result->append(value);
424   }
425 }
426
427 template <class Src>
428 typename std::enable_if<std::is_convertible<Src, const char*>::value, size_t>::
429     type
430     estimateSpaceNeeded(Src value) {
431   const char *c = value;
432   if (c) {
433     return folly::StringPiece(value).size();
434   };
435   return 0;
436 }
437
438 template<class Src>
439 typename std::enable_if<
440   (std::is_convertible<Src, folly::StringPiece>::value ||
441   IsSomeString<Src>::value) &&
442   !std::is_convertible<Src, const char*>::value,
443   size_t>::type
444 estimateSpaceNeeded(Src value) {
445   return folly::StringPiece(value).size();
446 }
447
448 template <>
449 inline size_t estimateSpaceNeeded(std::nullptr_t /* value */) {
450   return 0;
451 }
452
453 template<class Src>
454 typename std::enable_if<
455   std::is_pointer<Src>::value &&
456   IsSomeString<std::remove_pointer<Src>>::value,
457   size_t>::type
458 estimateSpaceNeeded(Src value) {
459   return value->size();
460 }
461
462 /**
463  * Strings get appended, too.
464  */
465 template <class Tgt, class Src>
466 typename std::enable_if<
467   IsSomeString<Src>::value && IsSomeString<Tgt>::value>::type
468 toAppend(const Src& value, Tgt * result) {
469   result->append(value);
470 }
471
472 /**
473  * and StringPiece objects too
474  */
475 template <class Tgt>
476 typename std::enable_if<
477    IsSomeString<Tgt>::value>::type
478 toAppend(StringPiece value, Tgt * result) {
479   result->append(value.data(), value.size());
480 }
481
482 /**
483  * There's no implicit conversion from fbstring to other string types,
484  * so make a specialization.
485  */
486 template <class Tgt>
487 typename std::enable_if<
488    IsSomeString<Tgt>::value>::type
489 toAppend(const fbstring& value, Tgt * result) {
490   result->append(value.data(), value.size());
491 }
492
493 #if FOLLY_HAVE_INT128_T
494 /**
495  * Special handling for 128 bit integers.
496  */
497
498 template <class Tgt>
499 void
500 toAppend(__int128 value, Tgt * result) {
501   typedef unsigned __int128 Usrc;
502   char buffer[detail::digitsEnough<unsigned __int128>() + 1];
503   size_t p;
504
505   if (value < 0) {
506     p = detail::unsafeTelescope128(buffer, sizeof(buffer), -Usrc(value));
507     buffer[--p] = '-';
508   } else {
509     p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
510   }
511
512   result->append(buffer + p, buffer + sizeof(buffer));
513 }
514
515 template <class Tgt>
516 void
517 toAppend(unsigned __int128 value, Tgt * result) {
518   char buffer[detail::digitsEnough<unsigned __int128>()];
519   size_t p;
520
521   p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
522
523   result->append(buffer + p, buffer + sizeof(buffer));
524 }
525
526 template<class T>
527 constexpr typename std::enable_if<
528   std::is_same<T, __int128>::value,
529   size_t>::type
530 estimateSpaceNeeded(T) {
531   return detail::digitsEnough<__int128>();
532 }
533
534 template<class T>
535 constexpr typename std::enable_if<
536   std::is_same<T, unsigned __int128>::value,
537   size_t>::type
538 estimateSpaceNeeded(T) {
539   return detail::digitsEnough<unsigned __int128>();
540 }
541
542 #endif
543
544 /**
545  * int32_t and int64_t to string (by appending) go through here. The
546  * result is APPENDED to a preexisting string passed as the second
547  * parameter. This should be efficient with fbstring because fbstring
548  * incurs no dynamic allocation below 23 bytes and no number has more
549  * than 22 bytes in its textual representation (20 for digits, one for
550  * sign, one for the terminating 0).
551  */
552 template <class Tgt, class Src>
553 typename std::enable_if<
554   std::is_integral<Src>::value && std::is_signed<Src>::value &&
555   IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
556 toAppend(Src value, Tgt * result) {
557   char buffer[20];
558   if (value < 0) {
559     result->push_back('-');
560     using u = std::make_signed<size_t>::type;
561     result->append(
562         buffer,
563         uint64ToBufferUnsafe(
564             static_cast<size_t>(-static_cast<u>(value)), buffer));
565   } else {
566     result->append(buffer, uint64ToBufferUnsafe(uint64_t(value), buffer));
567   }
568 }
569
570 template <class Src>
571 typename std::enable_if<
572   std::is_integral<Src>::value && std::is_signed<Src>::value
573   && sizeof(Src) >= 4 && sizeof(Src) < 16,
574   size_t>::type
575 estimateSpaceNeeded(Src value) {
576   if (value < 0) {
577     // When "value" is the smallest negative, negating it would evoke
578     // undefined behavior, so, instead of writing "-value" below, we write
579     // "~static_cast<uint64_t>(value) + 1"
580     return 1 + digits10(~static_cast<uint64_t>(value) + 1);
581   }
582
583   return digits10(static_cast<uint64_t>(value));
584 }
585
586 /**
587  * As above, but for uint32_t and uint64_t.
588  */
589 template <class Tgt, class Src>
590 typename std::enable_if<
591   std::is_integral<Src>::value && !std::is_signed<Src>::value
592   && IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
593 toAppend(Src value, Tgt * result) {
594   char buffer[20];
595   result->append(buffer, uint64ToBufferUnsafe(value, buffer));
596 }
597
598 template <class Src>
599 typename std::enable_if<
600   std::is_integral<Src>::value && !std::is_signed<Src>::value
601   && sizeof(Src) >= 4 && sizeof(Src) < 16,
602   size_t>::type
603 estimateSpaceNeeded(Src value) {
604   return digits10(value);
605 }
606
607 /**
608  * All small signed and unsigned integers to string go through 32-bit
609  * types int32_t and uint32_t, respectively.
610  */
611 template <class Tgt, class Src>
612 typename std::enable_if<
613   std::is_integral<Src>::value
614   && IsSomeString<Tgt>::value && sizeof(Src) < 4>::type
615 toAppend(Src value, Tgt * result) {
616   typedef typename
617     std::conditional<std::is_signed<Src>::value, int64_t, uint64_t>::type
618     Intermediate;
619   toAppend<Tgt>(static_cast<Intermediate>(value), result);
620 }
621
622 template <class Src>
623 typename std::enable_if<
624   std::is_integral<Src>::value
625   && sizeof(Src) < 4
626   && !std::is_same<Src, char>::value,
627   size_t>::type
628 estimateSpaceNeeded(Src value) {
629   typedef typename
630     std::conditional<std::is_signed<Src>::value, int64_t, uint64_t>::type
631     Intermediate;
632   return estimateSpaceNeeded(static_cast<Intermediate>(value));
633 }
634
635 /**
636  * Enumerated values get appended as integers.
637  */
638 template <class Tgt, class Src>
639 typename std::enable_if<
640   std::is_enum<Src>::value && IsSomeString<Tgt>::value>::type
641 toAppend(Src value, Tgt * result) {
642   toAppend(
643       static_cast<typename std::underlying_type<Src>::type>(value), result);
644 }
645
646 template <class Src>
647 typename std::enable_if<
648   std::is_enum<Src>::value, size_t>::type
649 estimateSpaceNeeded(Src value) {
650   return estimateSpaceNeeded(
651       static_cast<typename std::underlying_type<Src>::type>(value));
652 }
653
654 /*******************************************************************************
655  * Conversions from floating-point types to string types.
656  ******************************************************************************/
657
658 namespace detail {
659 constexpr int kConvMaxDecimalInShortestLow = -6;
660 constexpr int kConvMaxDecimalInShortestHigh = 21;
661 } // folly::detail
662
663 /** Wrapper around DoubleToStringConverter **/
664 template <class Tgt, class Src>
665 typename std::enable_if<
666   std::is_floating_point<Src>::value
667   && IsSomeString<Tgt>::value>::type
668 toAppend(
669   Src value,
670   Tgt * result,
671   double_conversion::DoubleToStringConverter::DtoaMode mode,
672   unsigned int numDigits) {
673   using namespace double_conversion;
674   DoubleToStringConverter
675     conv(DoubleToStringConverter::NO_FLAGS,
676          "Infinity", "NaN", 'E',
677          detail::kConvMaxDecimalInShortestLow,
678          detail::kConvMaxDecimalInShortestHigh,
679          6,   // max leading padding zeros
680          1);  // max trailing padding zeros
681   char buffer[256];
682   StringBuilder builder(buffer, sizeof(buffer));
683   switch (mode) {
684     case DoubleToStringConverter::SHORTEST:
685       conv.ToShortest(value, &builder);
686       break;
687     case DoubleToStringConverter::FIXED:
688       conv.ToFixed(value, int(numDigits), &builder);
689       break;
690     default:
691       CHECK(mode == DoubleToStringConverter::PRECISION);
692       conv.ToPrecision(value, int(numDigits), &builder);
693       break;
694   }
695   const size_t length = size_t(builder.position());
696   builder.Finalize();
697   result->append(buffer, length);
698 }
699
700 /**
701  * As above, but for floating point
702  */
703 template <class Tgt, class Src>
704 typename std::enable_if<
705   std::is_floating_point<Src>::value
706   && IsSomeString<Tgt>::value>::type
707 toAppend(Src value, Tgt * result) {
708   toAppend(
709     value, result, double_conversion::DoubleToStringConverter::SHORTEST, 0);
710 }
711
712 /**
713  * Upper bound of the length of the output from
714  * DoubleToStringConverter::ToShortest(double, StringBuilder*),
715  * as used in toAppend(double, string*).
716  */
717 template <class Src>
718 typename std::enable_if<
719   std::is_floating_point<Src>::value, size_t>::type
720 estimateSpaceNeeded(Src value) {
721   // kBase10MaximalLength is 17. We add 1 for decimal point,
722   // e.g. 10.0/9 is 17 digits and 18 characters, including the decimal point.
723   constexpr int kMaxMantissaSpace =
724     double_conversion::DoubleToStringConverter::kBase10MaximalLength + 1;
725   // strlen("E-") + digits10(numeric_limits<double>::max_exponent10)
726   constexpr int kMaxExponentSpace = 2 + 3;
727   static const int kMaxPositiveSpace = std::max({
728       // E.g. 1.1111111111111111E-100.
729       kMaxMantissaSpace + kMaxExponentSpace,
730       // E.g. 0.000001.1111111111111111, if kConvMaxDecimalInShortestLow is -6.
731       kMaxMantissaSpace - detail::kConvMaxDecimalInShortestLow,
732       // If kConvMaxDecimalInShortestHigh is 21, then 1e21 is the smallest
733       // number > 1 which ToShortest outputs in exponential notation,
734       // so 21 is the longest non-exponential number > 1.
735       detail::kConvMaxDecimalInShortestHigh
736     });
737   return size_t(
738       kMaxPositiveSpace +
739       (value < 0 ? 1 : 0)); // +1 for minus sign, if negative
740 }
741
742 /**
743  * This can be specialized, together with adding specialization
744  * for estimateSpaceNeed for your type, so that we allocate
745  * as much as you need instead of the default
746  */
747 template<class Src>
748 struct HasLengthEstimator : std::false_type {};
749
750 template <class Src>
751 constexpr typename std::enable_if<
752   !std::is_fundamental<Src>::value
753 #if FOLLY_HAVE_INT128_T
754   // On OSX 10.10, is_fundamental<__int128> is false :-O
755   && !std::is_same<__int128, Src>::value
756   && !std::is_same<unsigned __int128, Src>::value
757 #endif
758   && !IsSomeString<Src>::value
759   && !std::is_convertible<Src, const char*>::value
760   && !std::is_convertible<Src, StringPiece>::value
761   && !std::is_enum<Src>::value
762   && !HasLengthEstimator<Src>::value,
763   size_t>::type
764 estimateSpaceNeeded(const Src&) {
765   return sizeof(Src) + 1; // dumbest best effort ever?
766 }
767
768 namespace detail {
769
770 template <class Tgt>
771 typename std::enable_if<IsSomeString<Tgt>::value, size_t>::type
772 estimateSpaceToReserve(size_t sofar, Tgt*) {
773   return sofar;
774 }
775
776 template <class T, class... Ts>
777 size_t estimateSpaceToReserve(size_t sofar, const T& v, const Ts&... vs) {
778   return estimateSpaceToReserve(sofar + estimateSpaceNeeded(v), vs...);
779 }
780
781 template<class...Ts>
782 void reserveInTarget(const Ts&...vs) {
783   getLastElement(vs...)->reserve(estimateSpaceToReserve(0, vs...));
784 }
785
786 template<class Delimiter, class...Ts>
787 void reserveInTargetDelim(const Delimiter& d, const Ts&...vs) {
788   static_assert(sizeof...(vs) >= 2, "Needs at least 2 args");
789   size_t fordelim = (sizeof...(vs) - 2) *
790       estimateSpaceToReserve(0, d, static_cast<std::string*>(nullptr));
791   getLastElement(vs...)->reserve(estimateSpaceToReserve(fordelim, vs...));
792 }
793
794 /**
795  * Variadic base case: append one element
796  */
797 template <class T, class Tgt>
798 typename std::enable_if<
799   IsSomeString<typename std::remove_pointer<Tgt>::type>
800   ::value>::type
801 toAppendStrImpl(const T& v, Tgt result) {
802   toAppend(v, result);
803 }
804
805 template <class T, class... Ts>
806 typename std::enable_if<
807     sizeof...(Ts) >= 2 &&
808     IsSomeString<typename std::remove_pointer<
809         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
810 toAppendStrImpl(const T& v, const Ts&... vs) {
811   toAppend(v, getLastElement(vs...));
812   toAppendStrImpl(vs...);
813 }
814
815 template <class Delimiter, class T, class Tgt>
816 typename std::enable_if<
817     IsSomeString<typename std::remove_pointer<Tgt>::type>::value>::type
818 toAppendDelimStrImpl(const Delimiter& /* delim */, const T& v, Tgt result) {
819   toAppend(v, result);
820 }
821
822 template <class Delimiter, class T, class... Ts>
823 typename std::enable_if<
824     sizeof...(Ts) >= 2 &&
825     IsSomeString<typename std::remove_pointer<
826         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
827 toAppendDelimStrImpl(const Delimiter& delim, const T& v, const Ts&... vs) {
828   // we are really careful here, calling toAppend with just one element does
829   // not try to estimate space needed (as we already did that). If we call
830   // toAppend(v, delim, ....) we would do unnecesary size calculation
831   toAppend(v, detail::getLastElement(vs...));
832   toAppend(delim, detail::getLastElement(vs...));
833   toAppendDelimStrImpl(delim, vs...);
834 }
835 } // folly::detail
836
837
838 /**
839  * Variadic conversion to string. Appends each element in turn.
840  * If we have two or more things to append, we it will not reserve
841  * the space for them and will depend on strings exponential growth.
842  * If you just append once consider using toAppendFit which reserves
843  * the space needed (but does not have exponential as a result).
844  *
845  * Custom implementations of toAppend() can be provided in the same namespace as
846  * the type to customize printing. estimateSpaceNeed() may also be provided to
847  * avoid reallocations in toAppendFit():
848  *
849  * namespace other_namespace {
850  *
851  * template <class String>
852  * void toAppend(const OtherType&, String* out);
853  *
854  * // optional
855  * size_t estimateSpaceNeeded(const OtherType&);
856  *
857  * }
858  */
859 template <class... Ts>
860 typename std::enable_if<
861     sizeof...(Ts) >= 3 &&
862     IsSomeString<typename std::remove_pointer<
863         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
864 toAppend(const Ts&... vs) {
865   ::folly::detail::toAppendStrImpl(vs...);
866 }
867
868 #ifdef _MSC_VER
869 // Special case pid_t on MSVC, because it's a void* rather than an
870 // integral type. We can't do a global special case because this is already
871 // dangerous enough (as most pointers will implicitly convert to a void*)
872 // just doing it for MSVC.
873 template <class Tgt>
874 void toAppend(const pid_t a, Tgt* res) {
875   toAppend(uint64_t(a), res);
876 }
877 #endif
878
879 /**
880  * Special version of the call that preallocates exaclty as much memory
881  * as need for arguments to be stored in target. This means we are
882  * not doing exponential growth when we append. If you are using it
883  * in a loop you are aiming at your foot with a big perf-destroying
884  * bazooka.
885  * On the other hand if you are appending to a string once, this
886  * will probably save a few calls to malloc.
887  */
888 template <class... Ts>
889 typename std::enable_if<IsSomeString<typename std::remove_pointer<
890     typename detail::LastElement<const Ts&...>::type>::type>::value>::type
891 toAppendFit(const Ts&... vs) {
892   ::folly::detail::reserveInTarget(vs...);
893   toAppend(vs...);
894 }
895
896 template <class Ts>
897 void toAppendFit(const Ts&) {}
898
899 /**
900  * Variadic base case: do nothing.
901  */
902 template <class Tgt>
903 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend(
904     Tgt* /* result */) {}
905
906 /**
907  * Variadic base case: do nothing.
908  */
909 template <class Delimiter, class Tgt>
910 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppendDelim(
911     const Delimiter& /* delim */, Tgt* /* result */) {}
912
913 /**
914  * 1 element: same as toAppend.
915  */
916 template <class Delimiter, class T, class Tgt>
917 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppendDelim(
918     const Delimiter& /* delim */, const T& v, Tgt* tgt) {
919   toAppend(v, tgt);
920 }
921
922 /**
923  * Append to string with a delimiter in between elements. Check out
924  * comments for toAppend for details about memory allocation.
925  */
926 template <class Delimiter, class... Ts>
927 typename std::enable_if<
928     sizeof...(Ts) >= 3 &&
929     IsSomeString<typename std::remove_pointer<
930         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
931 toAppendDelim(const Delimiter& delim, const Ts&... vs) {
932   detail::toAppendDelimStrImpl(delim, vs...);
933 }
934
935 /**
936  * Detail in comment for toAppendFit
937  */
938 template <class Delimiter, class... Ts>
939 typename std::enable_if<IsSomeString<typename std::remove_pointer<
940     typename detail::LastElement<const Ts&...>::type>::type>::value>::type
941 toAppendDelimFit(const Delimiter& delim, const Ts&... vs) {
942   detail::reserveInTargetDelim(delim, vs...);
943   toAppendDelim(delim, vs...);
944 }
945
946 template <class De, class Ts>
947 void toAppendDelimFit(const De&, const Ts&) {}
948
949 /**
950  * to<SomeString>(v1, v2, ...) uses toAppend() (see below) as back-end
951  * for all types.
952  */
953 template <class Tgt, class... Ts>
954 typename std::enable_if<
955     IsSomeString<Tgt>::value &&
956         (sizeof...(Ts) != 1 ||
957          !std::is_same<Tgt, typename detail::LastElement<const Ts&...>::type>::
958              value),
959     Tgt>::type
960 to(const Ts&... vs) {
961   Tgt result;
962   toAppendFit(vs..., &result);
963   return result;
964 }
965
966 /**
967  * Special version of to<SomeString> for floating point. When calling
968  * folly::to<SomeString>(double), generic implementation above will
969  * firstly reserve 24 (or 25 when negative value) bytes. This will
970  * introduce a malloc call for most mainstream string implementations.
971  *
972  * But for most cases, a floating point doesn't need 24 (or 25) bytes to
973  * be converted as a string.
974  *
975  * This special version will not do string reserve.
976  */
977 template <class Tgt, class Src>
978 typename std::enable_if<
979     IsSomeString<Tgt>::value && std::is_floating_point<Src>::value,
980     Tgt>::type
981 to(Src value) {
982   Tgt result;
983   toAppend(value, &result);
984   return result;
985 }
986
987 /**
988  * toDelim<SomeString>(SomeString str) returns itself.
989  */
990 template <class Tgt, class Delim, class Src>
991 typename std::enable_if<IsSomeString<Tgt>::value &&
992                             std::is_same<Tgt, Src>::value,
993                         Tgt>::type
994 toDelim(const Delim& /* delim */, const Src& value) {
995   return value;
996 }
997
998 /**
999  * toDelim<SomeString>(delim, v1, v2, ...) uses toAppendDelim() as
1000  * back-end for all types.
1001  */
1002 template <class Tgt, class Delim, class... Ts>
1003 typename std::enable_if<
1004     IsSomeString<Tgt>::value &&
1005         (sizeof...(Ts) != 1 ||
1006          !std::is_same<Tgt, typename detail::LastElement<const Ts&...>::type>::
1007              value),
1008     Tgt>::type
1009 toDelim(const Delim& delim, const Ts&... vs) {
1010   Tgt result;
1011   toAppendDelimFit(delim, vs..., &result);
1012   return result;
1013 }
1014
1015 /*******************************************************************************
1016  * Conversions from string types to integral types.
1017  ******************************************************************************/
1018
1019 namespace detail {
1020
1021 Expected<bool, ConversionCode> str_to_bool(StringPiece* src) noexcept;
1022
1023 template <typename T>
1024 Expected<T, ConversionCode> str_to_floating(StringPiece* src) noexcept;
1025
1026 extern template Expected<float, ConversionCode> str_to_floating<float>(
1027     StringPiece* src) noexcept;
1028 extern template Expected<double, ConversionCode> str_to_floating<double>(
1029     StringPiece* src) noexcept;
1030
1031 template <class Tgt>
1032 Expected<Tgt, ConversionCode> digits_to(const char* b, const char* e) noexcept;
1033
1034 extern template Expected<char, ConversionCode> digits_to<char>(
1035     const char*,
1036     const char*) noexcept;
1037 extern template Expected<signed char, ConversionCode> digits_to<signed char>(
1038     const char*,
1039     const char*) noexcept;
1040 extern template Expected<unsigned char, ConversionCode>
1041 digits_to<unsigned char>(const char*, const char*) noexcept;
1042
1043 extern template Expected<short, ConversionCode> digits_to<short>(
1044     const char*,
1045     const char*) noexcept;
1046 extern template Expected<unsigned short, ConversionCode>
1047 digits_to<unsigned short>(const char*, const char*) noexcept;
1048
1049 extern template Expected<int, ConversionCode> digits_to<int>(
1050     const char*,
1051     const char*) noexcept;
1052 extern template Expected<unsigned int, ConversionCode> digits_to<unsigned int>(
1053     const char*,
1054     const char*) noexcept;
1055
1056 extern template Expected<long, ConversionCode> digits_to<long>(
1057     const char*,
1058     const char*) noexcept;
1059 extern template Expected<unsigned long, ConversionCode>
1060 digits_to<unsigned long>(const char*, const char*) noexcept;
1061
1062 extern template Expected<long long, ConversionCode> digits_to<long long>(
1063     const char*,
1064     const char*) noexcept;
1065 extern template Expected<unsigned long long, ConversionCode>
1066 digits_to<unsigned long long>(const char*, const char*) noexcept;
1067
1068 #if FOLLY_HAVE_INT128_T
1069 extern template Expected<__int128, ConversionCode> digits_to<__int128>(
1070     const char*,
1071     const char*) noexcept;
1072 extern template Expected<unsigned __int128, ConversionCode>
1073 digits_to<unsigned __int128>(const char*, const char*) noexcept;
1074 #endif
1075
1076 template <class T>
1077 Expected<T, ConversionCode> str_to_integral(StringPiece* src) noexcept;
1078
1079 extern template Expected<char, ConversionCode> str_to_integral<char>(
1080     StringPiece* src) noexcept;
1081 extern template Expected<signed char, ConversionCode>
1082 str_to_integral<signed char>(StringPiece* src) noexcept;
1083 extern template Expected<unsigned char, ConversionCode>
1084 str_to_integral<unsigned char>(StringPiece* src) noexcept;
1085
1086 extern template Expected<short, ConversionCode> str_to_integral<short>(
1087     StringPiece* src) noexcept;
1088 extern template Expected<unsigned short, ConversionCode>
1089 str_to_integral<unsigned short>(StringPiece* src) noexcept;
1090
1091 extern template Expected<int, ConversionCode> str_to_integral<int>(
1092     StringPiece* src) noexcept;
1093 extern template Expected<unsigned int, ConversionCode>
1094 str_to_integral<unsigned int>(StringPiece* src) noexcept;
1095
1096 extern template Expected<long, ConversionCode> str_to_integral<long>(
1097     StringPiece* src) noexcept;
1098 extern template Expected<unsigned long, ConversionCode>
1099 str_to_integral<unsigned long>(StringPiece* src) noexcept;
1100
1101 extern template Expected<long long, ConversionCode> str_to_integral<long long>(
1102     StringPiece* src) noexcept;
1103 extern template Expected<unsigned long long, ConversionCode>
1104 str_to_integral<unsigned long long>(StringPiece* src) noexcept;
1105
1106 #if FOLLY_HAVE_INT128_T
1107 extern template Expected<__int128, ConversionCode> str_to_integral<__int128>(
1108     StringPiece* src) noexcept;
1109 extern template Expected<unsigned __int128, ConversionCode>
1110 str_to_integral<unsigned __int128>(StringPiece* src) noexcept;
1111 #endif
1112
1113 template <typename T>
1114 typename std::
1115     enable_if<std::is_same<T, bool>::value, Expected<T, ConversionCode>>::type
1116     convertTo(StringPiece* src) noexcept {
1117   return str_to_bool(src);
1118 }
1119
1120 template <typename T>
1121 typename std::enable_if<
1122     std::is_floating_point<T>::value,
1123     Expected<T, ConversionCode>>::type
1124 convertTo(StringPiece* src) noexcept {
1125   return str_to_floating<T>(src);
1126 }
1127
1128 template <typename T>
1129 typename std::enable_if<
1130     std::is_integral<T>::value && !std::is_same<T, bool>::value,
1131     Expected<T, ConversionCode>>::type
1132 convertTo(StringPiece* src) noexcept {
1133   return str_to_integral<T>(src);
1134 }
1135
1136 } // namespace detail
1137
1138 /**
1139  * String represented as a pair of pointers to char to unsigned
1140  * integrals. Assumes NO whitespace before or after.
1141  */
1142 template <typename Tgt>
1143 typename std::enable_if<
1144     std::is_integral<Tgt>::value && !std::is_same<Tgt, bool>::value,
1145     Expected<Tgt, ConversionCode>>::type
1146 tryTo(const char* b, const char* e) {
1147   return detail::digits_to<Tgt>(b, e);
1148 }
1149
1150 template <typename Tgt>
1151 typename std::enable_if<
1152     std::is_integral<Tgt>::value && !std::is_same<Tgt, bool>::value,
1153     Tgt>::type
1154 to(const char* b, const char* e) {
1155   return tryTo<Tgt>(b, e).thenOrThrow(
1156       [](Tgt res) { return res; },
1157       [=](ConversionCode code) {
1158         return makeConversionError(code, StringPiece(b, e));
1159       });
1160 }
1161
1162 /*******************************************************************************
1163  * Conversions from string types to arithmetic types.
1164  ******************************************************************************/
1165
1166 /**
1167  * Parsing strings to numeric types.
1168  */
1169 template <typename Tgt>
1170 FOLLY_WARN_UNUSED_RESULT inline typename std::enable_if<
1171     std::is_arithmetic<Tgt>::value,
1172     Expected<StringPiece, ConversionCode>>::type
1173 parseTo(StringPiece src, Tgt& out) {
1174   return detail::convertTo<Tgt>(&src).then(
1175       [&](Tgt res) { return void(out = res), src; });
1176 }
1177
1178 /*******************************************************************************
1179  * Integral / Floating Point to integral / Floating Point
1180  ******************************************************************************/
1181
1182 namespace detail {
1183
1184 /**
1185  * Bool to integral/float doesn't need any special checks, and this
1186  * overload means we aren't trying to see if a bool is less than
1187  * an integer.
1188  */
1189 template <class Tgt>
1190 typename std::enable_if<
1191     !std::is_same<Tgt, bool>::value &&
1192         (std::is_integral<Tgt>::value || std::is_floating_point<Tgt>::value),
1193     Expected<Tgt, ConversionCode>>::type
1194 convertTo(const bool& value) noexcept {
1195   return static_cast<Tgt>(value ? 1 : 0);
1196 }
1197
1198 /**
1199  * Checked conversion from integral to integral. The checks are only
1200  * performed when meaningful, e.g. conversion from int to long goes
1201  * unchecked.
1202  */
1203 template <class Tgt, class Src>
1204 typename std::enable_if<
1205     std::is_integral<Src>::value && !std::is_same<Tgt, Src>::value &&
1206         !std::is_same<Tgt, bool>::value &&
1207         std::is_integral<Tgt>::value,
1208     Expected<Tgt, ConversionCode>>::type
1209 convertTo(const Src& value) noexcept {
1210   /* static */ if (
1211       folly::_t<std::make_unsigned<Tgt>>(std::numeric_limits<Tgt>::max()) <
1212       folly::_t<std::make_unsigned<Src>>(std::numeric_limits<Src>::max())) {
1213     if (greater_than<Tgt, std::numeric_limits<Tgt>::max()>(value)) {
1214       return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
1215     }
1216   }
1217   /* static */ if (
1218       std::is_signed<Src>::value &&
1219       (!std::is_signed<Tgt>::value || sizeof(Src) > sizeof(Tgt))) {
1220     if (less_than<Tgt, std::numeric_limits<Tgt>::min()>(value)) {
1221       return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
1222     }
1223   }
1224   return static_cast<Tgt>(value);
1225 }
1226
1227 /**
1228  * Checked conversion from floating to floating. The checks are only
1229  * performed when meaningful, e.g. conversion from float to double goes
1230  * unchecked.
1231  */
1232 template <class Tgt, class Src>
1233 typename std::enable_if<
1234     std::is_floating_point<Tgt>::value && std::is_floating_point<Src>::value &&
1235         !std::is_same<Tgt, Src>::value,
1236     Expected<Tgt, ConversionCode>>::type
1237 convertTo(const Src& value) noexcept {
1238   /* static */ if (
1239       std::numeric_limits<Tgt>::max() < std::numeric_limits<Src>::max()) {
1240     if (value > std::numeric_limits<Tgt>::max()) {
1241       return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
1242     }
1243     if (value < std::numeric_limits<Tgt>::lowest()) {
1244       return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
1245     }
1246   }
1247   return static_cast<Tgt>(value);
1248 }
1249
1250 /**
1251  * Check if a floating point value can safely be converted to an
1252  * integer value without triggering undefined behaviour.
1253  */
1254 template <typename Tgt, typename Src>
1255 inline typename std::enable_if<
1256     std::is_floating_point<Src>::value && std::is_integral<Tgt>::value &&
1257         !std::is_same<Tgt, bool>::value,
1258     bool>::type
1259 checkConversion(const Src& value) {
1260   constexpr Src tgtMaxAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::max());
1261   constexpr Src tgtMinAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::min());
1262   if (value >= tgtMaxAsSrc) {
1263     if (value > tgtMaxAsSrc) {
1264       return false;
1265     }
1266     const Src mmax = folly::nextafter(tgtMaxAsSrc, Src());
1267     if (static_cast<Tgt>(value - mmax) >
1268         std::numeric_limits<Tgt>::max() - static_cast<Tgt>(mmax)) {
1269       return false;
1270     }
1271   } else if (std::is_signed<Tgt>::value && value <= tgtMinAsSrc) {
1272     if (value < tgtMinAsSrc) {
1273       return false;
1274     }
1275     const Src mmin = folly::nextafter(tgtMinAsSrc, Src());
1276     if (static_cast<Tgt>(value - mmin) <
1277         std::numeric_limits<Tgt>::min() - static_cast<Tgt>(mmin)) {
1278       return false;
1279     }
1280   }
1281   return true;
1282 }
1283
1284 // Integers can always safely be converted to floating point values
1285 template <typename Tgt, typename Src>
1286 constexpr typename std::enable_if<
1287     std::is_integral<Src>::value && std::is_floating_point<Tgt>::value,
1288     bool>::type
1289 checkConversion(const Src&) {
1290   return true;
1291 }
1292
1293 // Also, floating point values can always be safely converted to bool
1294 // Per the standard, any floating point value that is not zero will yield true
1295 template <typename Tgt, typename Src>
1296 constexpr typename std::enable_if<
1297     std::is_floating_point<Src>::value && std::is_same<Tgt, bool>::value,
1298     bool>::type
1299 checkConversion(const Src&) {
1300   return true;
1301 }
1302
1303 /**
1304  * Checked conversion from integral to floating point and back. The
1305  * result must be convertible back to the source type without loss of
1306  * precision. This seems Draconian but sometimes is what's needed, and
1307  * complements existing routines nicely. For various rounding
1308  * routines, see <math>.
1309  */
1310 template <typename Tgt, typename Src>
1311 typename std::enable_if<
1312     (std::is_integral<Src>::value && std::is_floating_point<Tgt>::value) ||
1313         (std::is_floating_point<Src>::value && std::is_integral<Tgt>::value),
1314     Expected<Tgt, ConversionCode>>::type
1315 convertTo(const Src& value) noexcept {
1316   if (LIKELY(checkConversion<Tgt>(value))) {
1317     Tgt result = static_cast<Tgt>(value);
1318     if (LIKELY(checkConversion<Src>(result))) {
1319       Src witness = static_cast<Src>(result);
1320       if (LIKELY(value == witness)) {
1321         return result;
1322       }
1323     }
1324   }
1325   return makeUnexpected(ConversionCode::ARITH_LOSS_OF_PRECISION);
1326 }
1327
1328 template <typename Tgt, typename Src>
1329 inline std::string errorValue(const Src& value) {
1330 #ifdef FOLLY_HAS_RTTI
1331   return to<std::string>("(", demangle(typeid(Tgt)), ") ", value);
1332 #else
1333   return to<std::string>(value);
1334 #endif
1335 }
1336
1337 template <typename Tgt, typename Src>
1338 using IsArithToArith = std::integral_constant<
1339     bool,
1340     !std::is_same<Tgt, Src>::value && !std::is_same<Tgt, bool>::value &&
1341         std::is_arithmetic<Src>::value &&
1342         std::is_arithmetic<Tgt>::value>;
1343
1344 } // namespace detail
1345
1346 template <typename Tgt, typename Src>
1347 typename std::enable_if<
1348     detail::IsArithToArith<Tgt, Src>::value,
1349     Expected<Tgt, ConversionCode>>::type
1350 tryTo(const Src& value) noexcept {
1351   return detail::convertTo<Tgt>(value);
1352 }
1353
1354 template <typename Tgt, typename Src>
1355 typename std::enable_if<detail::IsArithToArith<Tgt, Src>::value, Tgt>::type to(
1356     const Src& value) {
1357   return tryTo<Tgt>(value).thenOrThrow(
1358       [](Tgt res) { return res; },
1359       [&](ConversionCode e) {
1360         return makeConversionError(e, detail::errorValue<Tgt>(value));
1361       });
1362 }
1363
1364 /*******************************************************************************
1365  * Custom Conversions
1366  *
1367  * Any type can be used with folly::to by implementing parseTo. The
1368  * implementation should be provided in the namespace of the type to facilitate
1369  * argument-dependent lookup:
1370  *
1371  * namespace other_namespace {
1372  * ::folly::Expected<::folly::StringPiece, SomeErrorCode>
1373  *   parseTo(::folly::StringPiece, OtherType&) noexcept;
1374  * }
1375  ******************************************************************************/
1376 template <class T>
1377 FOLLY_WARN_UNUSED_RESULT typename std::enable_if<
1378     std::is_enum<T>::value,
1379     Expected<StringPiece, ConversionCode>>::type
1380 parseTo(StringPiece in, T& out) noexcept {
1381   typename std::underlying_type<T>::type tmp{};
1382   auto restOrError = parseTo(in, tmp);
1383   out = static_cast<T>(tmp); // Harmless if parseTo fails
1384   return restOrError;
1385 }
1386
1387 FOLLY_WARN_UNUSED_RESULT
1388 inline Expected<StringPiece, ConversionCode> parseTo(
1389     StringPiece in,
1390     StringPiece& out) noexcept {
1391   out = in;
1392   return StringPiece{in.end(), in.end()};
1393 }
1394
1395 FOLLY_WARN_UNUSED_RESULT
1396 inline Expected<StringPiece, ConversionCode> parseTo(
1397     StringPiece in,
1398     std::string& out) {
1399   out.clear();
1400   out.append(in.data(), in.size()); // TODO try/catch?
1401   return StringPiece{in.end(), in.end()};
1402 }
1403
1404 FOLLY_WARN_UNUSED_RESULT
1405 inline Expected<StringPiece, ConversionCode> parseTo(
1406     StringPiece in,
1407     fbstring& out) {
1408   out.clear();
1409   out.append(in.data(), in.size()); // TODO try/catch?
1410   return StringPiece{in.end(), in.end()};
1411 }
1412
1413 namespace detail {
1414 template <typename Tgt>
1415 using ParseToResult = decltype(parseTo(StringPiece{}, std::declval<Tgt&>()));
1416
1417 struct CheckTrailingSpace {
1418   Expected<Unit, ConversionCode> operator()(StringPiece sp) const {
1419     auto e = enforceWhitespaceErr(sp);
1420     if (UNLIKELY(e != ConversionCode::SUCCESS))
1421       return makeUnexpected(e);
1422     return unit;
1423   }
1424 };
1425
1426 template <class Error>
1427 struct ReturnUnit {
1428   template <class T>
1429   constexpr Expected<Unit, Error> operator()(T&&) const {
1430     return unit;
1431   }
1432 };
1433
1434 // Older versions of the parseTo customization point threw on error and
1435 // returned void. Handle that.
1436 template <class Tgt>
1437 inline typename std::enable_if<
1438     std::is_void<ParseToResult<Tgt>>::value,
1439     Expected<StringPiece, ConversionCode>>::type
1440 parseToWrap(StringPiece sp, Tgt& out) {
1441   parseTo(sp, out);
1442   return StringPiece(sp.end(), sp.end());
1443 }
1444
1445 template <class Tgt>
1446 inline typename std::enable_if<
1447     !std::is_void<ParseToResult<Tgt>>::value,
1448     ParseToResult<Tgt>>::type
1449 parseToWrap(StringPiece sp, Tgt& out) {
1450   return parseTo(sp, out);
1451 }
1452
1453 template <typename Tgt>
1454 using ParseToError = ExpectedErrorType<decltype(
1455     detail::parseToWrap(StringPiece{}, std::declval<Tgt&>()))>;
1456
1457 } // namespace detail
1458
1459 /**
1460  * String or StringPiece to target conversion. Accepts leading and trailing
1461  * whitespace, but no non-space trailing characters.
1462  */
1463
1464 template <class Tgt>
1465 inline typename std::enable_if<
1466     !std::is_same<StringPiece, Tgt>::value,
1467     Expected<Tgt, detail::ParseToError<Tgt>>>::type
1468 tryTo(StringPiece src) {
1469   Tgt result{};
1470   using Error = detail::ParseToError<Tgt>;
1471   using Check = typename std::conditional<
1472       std::is_arithmetic<Tgt>::value,
1473       detail::CheckTrailingSpace,
1474       detail::ReturnUnit<Error>>::type;
1475   return parseTo(src, result).then(Check(), [&](Unit) {
1476     return std::move(result);
1477   });
1478 }
1479
1480 template <class Tgt>
1481 inline
1482     typename std::enable_if<!std::is_same<StringPiece, Tgt>::value, Tgt>::type
1483     to(StringPiece src) {
1484   Tgt result{};
1485   using Error = detail::ParseToError<Tgt>;
1486   using Check = typename std::conditional<
1487       std::is_arithmetic<Tgt>::value,
1488       detail::CheckTrailingSpace,
1489       detail::ReturnUnit<Error>>::type;
1490   auto tmp = detail::parseToWrap(src, result);
1491   return tmp
1492       .thenOrThrow(Check(), [&](Error e) { throw makeConversionError(e, src); })
1493       .thenOrThrow(
1494           [&](Unit) { return std::move(result); },
1495           [&](Error e) { throw makeConversionError(e, tmp.value()); });
1496 }
1497
1498 /**
1499  * tryTo/to that take the strings by pointer so the caller gets information
1500  * about how much of the string was consumed by the conversion. These do not
1501  * check for trailing whitepsace.
1502  */
1503 template <class Tgt>
1504 Expected<Tgt, detail::ParseToError<Tgt>> tryTo(StringPiece* src) {
1505   Tgt result;
1506   return parseTo(*src, result).then([&, src](StringPiece sp) -> Tgt {
1507     *src = sp;
1508     return std::move(result);
1509   });
1510 }
1511
1512 template <class Tgt>
1513 Tgt to(StringPiece* src) {
1514   Tgt result{};
1515   using Error = detail::ParseToError<Tgt>;
1516   return parseTo(*src, result)
1517       .thenOrThrow(
1518           [&, src](StringPiece sp) -> Tgt {
1519             *src = sp;
1520             return std::move(result);
1521           },
1522           [=](Error e) { return makeConversionError(e, *src); });
1523 }
1524
1525 /*******************************************************************************
1526  * Enum to anything and back
1527  ******************************************************************************/
1528
1529 template <class Tgt, class Src>
1530 typename std::enable_if<
1531     std::is_enum<Src>::value && !std::is_same<Src, Tgt>::value,
1532     Expected<Tgt, ConversionCode>>::type
1533 tryTo(const Src& value) {
1534   using I = typename std::underlying_type<Src>::type;
1535   return tryTo<Tgt>(static_cast<I>(value));
1536 }
1537
1538 template <class Tgt, class Src>
1539 typename std::enable_if<
1540     std::is_enum<Tgt>::value && !std::is_same<Src, Tgt>::value,
1541     Tgt>::type
1542 tryTo(const Src& value) {
1543   using I = typename std::underlying_type<Tgt>::type;
1544   return tryTo<I>(value).then([](I i) { return static_cast<Tgt>(i); });
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     Tgt>::type
1551 to(const Src& value) {
1552   return to<Tgt>(static_cast<typename std::underlying_type<Src>::type>(value));
1553 }
1554
1555 template <class Tgt, class Src>
1556 typename std::enable_if<
1557   std::is_enum<Tgt>::value && !std::is_same<Src, Tgt>::value, Tgt>::type
1558 to(const Src & value) {
1559   return static_cast<Tgt>(to<typename std::underlying_type<Tgt>::type>(value));
1560 }
1561
1562 } // namespace folly