string-keys-to-int: converting string keys into integers.

This commit is contained in:
Karchnu 2020-11-30 04:55:15 +01:00
parent c094ed7dfb
commit 331d918190
3 changed files with 101 additions and 0 deletions

View File

@ -25,3 +25,13 @@ json-to-cbor < file.json > file.cbor
hs < file.cbor
```
# string-keys-to-int usage
JSON format has a limitation on the type of hash keys: it has to be a string.
CBOR doesn't come with such limitation.
`string-keys-to-int` automatically converts string keys into integers, whenever all the keys in a hash can be converted.
```sh
string-keys-to-int < file.cbor
```

View File

@ -14,6 +14,8 @@ targets:
main: src/json-to-cbor.cr
hs:
main: src/hs.cr
string-keys-to-int:
main: src/string-keys-to-int.cr
bm-json-vs-cbor:
main: tests/json-vs-cbor.cr

89
src/string-keys-to-int.cr Normal file
View File

@ -0,0 +1,89 @@
require "cbor"
require "option_parser"
class Context
class_property debug = false
end
OptionParser.parse do |parser|
parser.banner = "usage: string-keys-to-int < file.cbor"
parser.on "-d", "--debug",
"Debug: print keys to convert, input and output data." do
Context.debug = true
end
parser.on "-h", "--help", "Displays this help and exits." do
puts parser
exit 0
end
end
def are_hash_keys_all_int?(data)
case d = data
when Hash
keys = d.keys
if keys.all? {|v| v.is_a?(String) }
keys.all? {|v| v.as(String).to_i64 rescue false }
else
false
end
else
false
end
end
def change(data)
# 1. change keys
if are_hash_keys_all_int? data
if Context.debug
puts "keys to convert: #{data.as(Hash).keys}"
end
# Do something
case d = data
when Hash
keys = d.keys
keys.each do |k|
d[k.as(String).to_i32] = d[k]
d.delete k
end
end
end
# 2. dig
case d = data
when Hash
keys = d.keys
keys.each do |k|
change d[k]
end
end
rescue e
STDERR.puts "something went wrong: #{e}"
end
buffer = Bytes.new 1_000_000 # 1 MB
until STDIN.read(buffer) == 0
decoder = CBOR::Decoder.new(buffer)
while data = decoder.read_value
break if data == 0
if Context.debug
puts "input data:"
pp data
end
change data
if Context.debug
puts "output data:"
pp data
else
STDOUT.write data.to_cbor
STDOUT.flush
end
end
buffer = Bytes.new 1_000_000 # 1 MB
end