Skip to content

Instantly share code, notes, and snippets.

@manveru
Created June 27, 2013 17:42
Show Gist options
  • Save manveru/5878620 to your computer and use it in GitHub Desktop.
Save manveru/5878620 to your computer and use it in GitHub Desktop.
require 'strscan'
require 'bacon'
Bacon.summary_on_exit
class PGArrayParser
attr_reader :s
def parse(input)
return [] if input.empty?
@s = StringScanner.new(input)
parse_array
end
private
def parse_string
out = ""
s.scan(/"/)
until s.scan(/"/)
if s.scan(/\\(.)/)
out << s[1]
else
out << s.scan(/[^"\\"]+/)
end
end
return out
end
def parse_number
if s.scan(/[+-]?\d+\.\d+/)
Float(s.matched)
elsif s.scan(/[+-]?\d+/)
Integer(s.matched)
end
end
def parse_array
unless s.scan(/\{/)
raise("not an array")
end
array = []
until s.eos?
case s.peek(1)
when '{'
array << parse_array
when '"'
array << parse_string
when /\d/
array << parse_number
when '}'
@s.scan(/./)
return array
end
@s.scan(/,\s*/)
end
end
end
describe 'PostgreSQL Arrays' do
def parse(input)
PGArrayParser.new.parse(input)
end
it 'may be empty' do
parse('').should == []
end
it 'may have a string' do
parse('{"hi"}').should == ["hi"]
end
it 'may have an int' do
parse('{123}').should == [123]
end
it 'may have more than one int' do
parse('{123, 456}').should == [123, 456]
end
it 'may be a float' do
parse('{123.456, 789.0}').should == [123.456, 789.0]
end
it 'may have more than one string' do
parse('{"hello", "world"}').should == ["hello", "world"]
end
it 'may have more than one array of strings in the array' do
parse('{{"hello"}, {"world"}}').should == [["hello"], ["world"]]
end
it 'may have more than one array of ints in the array' do
parse('{{123}, {456}}').should == [[123], [456]]
end
it 'parses a bunch more' do
{
'{"hi","there"}' => ["hi", "there"],
'{"\"","quote"}' => ['"', 'quote'],
'{"\\\\","quote"}' => ['\\', 'quote'],
}.each do |input, output|
parse(input).should == output
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment