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