seanhandley / h3_ruby Goto Github PK
View Code? Open in Web Editor NEWRuby Bindings for H3, a hexagonal geospatial indexing system
Home Page: https://eng.uber.com/h3/
License: MIT License
Ruby Bindings for H3, a hexagonal geospatial indexing system
Home Page: https://eng.uber.com/h3/
License: MIT License
We're currently doing some manual manipulation of the data returned by hex_ranges
i.e. grouping them by distance. This is largely because other bindings (namely python and go) take this approach.
The C lib just returns an array without grouping the contents.
Before we release, we should agree what approach we wish to take.
Ensure specs try to Do Bad Things.
rake-compiler
dep once all functions are in FFI DSL..gemspec
git ls-files
.e.g. hexRing
is called by wrapping snake case function hex_ring
- if we move hexRing
into a private module then it prevents users from accidentally calling it.
ALL DONE ๐
Some functions expect a set i.e. a C array with no duplicates. Without this check, the behaviour can be undefined according to the docs so it's incumbent on us to ensure we removes duplicates ourselves first.
Ensure gem works for multiple Rubies. JRuby, MRI, Rubinius. Current versions and some older versions too.
NOTE: It may be necessary to modify the ffi_lib
call to fall back to the installed lib in case the native extension can't be built (this will be the case on non-MRI Rubies).
https://codeclimate.com/repos/5c18b7f49bc79a02a4000d81/issues
Reduce issues to 0.
https://www.varvet.com/blog/advanced-topics-in-ruby-ffi/#writing-our-own-data-types
This could be helpful in preventing some edge case misbehaviours. For instance, a lot of functions take a resolution
argument as an integer but only accept values 0-15 (or produce undefined behaviour). e.g.
irb(main):035:0> H3.h3_to_children(517700169958293503, 100000000)
Traceback (most recent call last):
5: from /Users/sean/.rbenv/versions/2.5.0/bin/irb:11:in `<main>'
4: from (irb):35
3: from /Users/sean/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/h3-3.2.0/lib/h3/hierarchy.rb:51:in `h3_to_children'
2: from /Users/sean/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/h3-3.2.0/lib/h3/hierarchy.rb:51:in `new'
1: from /Users/sean/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/h3-3.2.0/lib/h3/hierarchy.rb:51:in `initialize'
NoMemoryError (too large allocation size)
In this case, we get told memory can't be allocated - which is ok.
irb(main):036:0> H3.h3_to_children(517700169958293503, 1000000000)
Traceback (most recent call last):
4: from /Users/sean/.rbenv/versions/2.5.0/bin/irb:11:in `<main>'
3: from (irb):36
2: from /Users/sean/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/h3-3.2.0/lib/h3/hierarchy.rb:52:in `h3_to_children'
1: from /Users/sean/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/h3-3.2.0/lib/h3/hierarchy.rb:52:in `h3_to_children'
SystemStackError (stack level too deep)
Here we blow the stack, which is recoverable
irb(main):037:0> H3.h3_to_children(517700169958293503, 10000000000)
Traceback (most recent call last):
4: from /Users/sean/.rbenv/versions/2.5.0/bin/irb:11:in `<main>'
3: from (irb):37
2: from /Users/sean/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/h3-3.2.0/lib/h3/hierarchy.rb:50:in `h3_to_children'
1: from /Users/sean/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/h3-3.2.0/lib/h3/hierarchy.rb:50:in `max_h3_to_children_size'
RangeError (integer 10000000000 too big to convert to `int')
Here FFI raises RangeError
because the value is too large for a C integer.
irb(main):039:0> H3.h3_to_children(613196570357137407, 1000)
Illegal instruction: 4
Now the real problem! We can crash the Ruby process like this ๐ฑ
Setting up some custom types would give us a nice mechanism to validate this kind of data and prevent such nasty behaviour.
Coveralls shows missing test coverage here: https://coveralls.io/builds/20760354/source?filename=lib/h3/geo_json.rb#L162
and here: https://coveralls.io/builds/20760354/source?filename=lib/h3/regions.rb#L158
This flag indicates that the output should be grouped or not
hex_ranges
returns an array or ranges. Each range comes in turn as an array of the concentric hex Rings outwards. The C lib does not have this, so we need to explain what our binding does.
FFI has many benefits that will reduce likelihood of leaks/crashes and make the library simpler to maintain over time.
The method max_hex_ring_size
has a mysterious implementation:
k == 0 ? 1 : 6*k
While this method is private, maintainers would thank us if we explain where does that formula come from in a code comment.
Methods like .h3_pentagon?
should become .pentagon?
etc
A deprecation warning should be shown when using the older version.
Make it possible to use hex strings and integers interchangeably when calling public methods that take them.
Need to consider whether we should always return h3 indexes as integers.
Some of the H3 functions accept a size_t
. FFI has a :size_t
type we can use, so we should use it for parity with the C lib.
There are also :buffer_in
, :buffer_out
, and :buffer_in_out
types available. We should use them where appropriate.
It's possible to install h3 from source as part of the gem installation. We can (and probably should) script this for convenience.
The Python bindings already do this https://github.com/uber/h3-py/blob/master/.install.sh
See here for API reference function groups: https://uber.github.io/h3/#/documentation/api-reference/indexing
The gem's API needn't change, but it would be helpful to split things up so we don't have one large implementation file and one large spec.
Pointers are GC'd automatically in FFI but structs may not be.
See https://www.rubydoc.info/github/ffi/ffi/FFI/ManagedStruct and https://www.varvet.com/blog/advanced-topics-in-ruby-ffi/
Also check the FFI wiki.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.