Last active
August 29, 2015 14:27
-
-
Save jesseschalken/f5f772a283260af65119 to your computer and use it in GitHub Desktop.
Simple fast bidirectional mapping between scalars and strings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class ScalarSerializer { | |
/** | |
* @param string $s | |
* @return string|int|float|bool|null | |
*/ | |
static function unserialize($s) { | |
$t = (string)substr($s, 0, 1); | |
$v = (string)substr($s, 1); | |
switch ($t) { | |
case 'b': | |
return (bool) $v; | |
case 'i': | |
return (int) $v; | |
case 'f': | |
return (float) $v; | |
case ':': | |
return $v; | |
case '~': | |
return null; | |
default: | |
throw new \Exception('Unhandled type tag: ' . $t); | |
} | |
} | |
/** | |
* @param string|int|float|bool|null $x | |
* @return string | |
*/ | |
static function serialize($x) { | |
if (is_string($x)) { | |
return ':' . $x; | |
} else if (is_int($x)) { | |
return 'i' . $x; | |
} else if (is_null($x)) { | |
return '~'; | |
} else if (is_bool($x)) { | |
return 'b' . ($x ? '1' : '0'); | |
} else if (is_float($x)) { | |
if (is_finite($x)) { | |
list($l, $r) = explode('.', number_format(abs($x), 400, '.', ''), 2); | |
$l = $l ?: '0'; | |
$r = $r ?: '0'; | |
$n = $x < 0 ? '-' : ''; | |
return "f$n$l.$r"; | |
} else { | |
throw new \Exception('INF, -INF and NAN are not supported'); | |
} | |
} else { | |
throw new \Exception('Unhandled type: ' . gettype($x)); | |
} | |
} | |
/** | |
* @return void | |
*/ | |
static function test() { | |
static $values = array( | |
'hello', | |
'', | |
"\x00", | |
null, | |
true, | |
false, | |
-1.0/3.0, | |
0, | |
2, | |
-9, | |
PHP_INT_MAX, | |
); | |
foreach ($values as $v1) { | |
$s = ScalarSerializer::serialize($v1); | |
$v2 = ScalarSerializer::unserialize($s); | |
if ($v1 !== $v2) { | |
$v1 = var_export($v1, true); | |
$v2 = var_export($v2, true); | |
throw new \Exception("Failed to serialize $v1 (serialized: $s, unserialized: $v2)"); | |
} | |
} | |
} | |
} | |
ScalarSerializer::test(); | |
print "done\n"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment