Skip to content
This repository has been archived by the owner on Jul 5, 2023. It is now read-only.

Added support for Infinity and -Infinity #166

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/css/prettyprint.less
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
position: relative;
white-space: pre;

.null, .bool, .atom,
.null, .bool, .atom, .inf,
.z, .b, .a {
color: #0086b3;
}
Expand Down
12 changes: 10 additions & 2 deletions client/js/json.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,12 @@ GenghisJSON =
# Property value has to be an array, object, literal, or a whitelisted call
when 'Property'
if node.value
if node.value.type is 'Identifier' and node.value.name is 'NaN'
node.update("\"#{node.key.name}\": {\"$genghisType\": \"NaN\"}")
# -Infinity is seen as a UnaryExp, so handle it with a special case
if node.value.type is 'UnaryExpression' and node.value.argument.type is 'Identifier' and node.value.argument.name is 'Infinity'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are other unary expressions (e.g. ~) so we should be checking the operator as well, and maybe whether it's a prefix operator. Otherwise things like this:

~Infinity

would get encoded as -Infinity. This is getting long and heinous now, so I'd extract the conditions into a helper function :)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@richthegeek poke :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure in what case someone would do that exactly? Should be a simple change either way, but I'm at home now so I'll sort it tomorrow.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is when someone unintentionally does that. It should be a parse error, not an implicit thunk into -Infinity.

node.update("\"#{node.key.name}\": {\"$genghisType\": \"-Infinity\"}")
# +Infinity and NaN are known identifiers, where the genghisType is the same as the identifier
else if node.value.type is 'Identifier' and node.value.name in ['NaN', 'Infinity']
node.update("\"#{node.key.name}\": {\"$genghisType\": \"#{node.value.name}\"}")
else
unless ALLOWED_PROPERTY_VALUES[node.value.type]
addError("Unexpected value: #{node.value.source()}", node.value)
Expand Down Expand Up @@ -336,6 +340,10 @@ GenghisJSON =
"<span class='call bindata'>BinData(#{$subtype}, #{$binary})</span>"
when 'NaN'
"<span class='v a'>NaN</span>"
when 'Infinity'
"<span class='v a inf'>Infinity</span>"
when '-Infinity'
"<span class='v a inf'>-Infinity</span>"
when 'Timestamp'
$t = printScalar(value.$value.$t)
$i = printScalar(value.$value.$i)
Expand Down
36 changes: 18 additions & 18 deletions genghis.php

Large diffs are not rendered by default.

40 changes: 21 additions & 19 deletions genghis.rb

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions server/php/Genghis/Json.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ private static function doEncode($object)
}
} elseif (is_float($object) && is_nan($object)) {
return array('$genghisType' => 'NaN');
} elseif (is_float($object) && is_infinite($object)) {
return array('$genghisType' => $object > 0 ? 'Infinity' : '-Infinity');
}

return $object;
Expand Down Expand Up @@ -158,6 +160,12 @@ private static function doDecode($object)
case 'NaN':
return NAN;

case 'Infinity':
return INF;

case '-Infinity':
return -INF;

case 'Timestamp':
$sec = self::getProp($value, 't');
$inc = self::getProp($value, 'i');
Expand Down
4 changes: 3 additions & 1 deletion server/rb/genghis/json.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def enc(o, *a)
when BSON::Timestamp then thunk('Timestamp', '$t' => o.seconds, '$i' => o.increment)
when BSON::MinKey then {'$genghisType' => 'MinKey'}
when BSON::MaxKey then {'$genghisType' => 'MaxKey'}
when Float then o.nan? ? {'$genghisType' => 'NaN'} : o
when Float then o.nan? ? {'$genghisType' => 'NaN'} : o.finite? ? o : {'$genghisType' => o.to_s}
else o
end
end
Expand Down Expand Up @@ -100,6 +100,8 @@ def dec(o)
when 'MinKey' then BSON::MinKey.new
when 'MaxKey' then BSON::MaxKey.new
when 'NaN' then Float::NAN
when 'Infinity' then Float::INFINITY
when '-Infinity' then 0 - Float::INFINITY
when 'NumberLong' then o['$value'].to_i
else fail Genghis::MalformedDocument
end
Expand Down
28 changes: 28 additions & 0 deletions spec/requests/api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,34 @@
end
end

context 'with Infinity values' do
let(:doc) { {:foo => {'$genghisType' => 'Infinity'}} }

it 'handles Infinity values like a champ' do
expect(res.status).to eq 200
expect(res).to be_a_json_response
expect(res.body).to match_json_expression \
:_id => OBJECT_ID,
:foo => {
'$genghisType' => 'Infinity'
}
end
end

context 'with -Infinity values' do
let(:doc) { {:foo => {'$genghisType' => '-Infinity'}} }

it 'handles -Infinity values like a champ' do
expect(res.status).to eq 200
expect(res).to be_a_json_response
expect(res.body).to match_json_expression \
:_id => OBJECT_ID,
:foo => {
'$genghisType' => '-Infinity'
}
end
end

context 'with MinKey and MaxKey values' do
let(:doc) { {:foo => {'$genghisType' => 'MinKey'}, :bar => {'$genghisType' => 'MaxKey'}} }

Expand Down