GHComp deflates and inflates sets of geohashes.
- Deflate removes redundant prefix information.
- Inflate reconstructs full geohashes from deflated tokens.
- Order and duplicates are not preserved.
GHComp now exposes a layered API:
- Core token API:
DeflateEach/InflateEach(callback emitter). - Stream adapters:
Deflate(io.Reader, io.Writer)/Inflate(io.Reader, io.Writer). - String slice adapters:
DeflateStrings/InflateStrings(+ append variants). - Byte slice adapters:
DeflateBytes/InflateBytes(+ append variants).
The stream, tree, string, and byte APIs all route through the same core inflate/deflate logic.
Use the core API when you want custom input/output handling without newline-delimited stream parsing.
package main
import (
"fmt"
"log"
"github.com/andrewfrench/ghcomp"
)
func main() {
in := [][]byte{
[]byte("bdvkhunfnc90"),
[]byte("bdvkj7vyvtz5"),
[]byte("bdvkjkjbpr1t"),
}
deflated := make([][]byte, 0)
err := ghcomp.DeflateEach(func(v []byte) error {
deflated = append(deflated, append([]byte(nil), v...))
return nil
}, in...)
if err != nil {
log.Fatalf("deflate failed: %v", err)
}
err = ghcomp.InflateEach(func(v []byte) error {
fmt.Println(string(v))
return nil
}, deflated...)
if err != nil {
log.Fatalf("inflate failed: %v", err)
}
}Use this in application code when you already have geohashes in memory.
inflated := []string{
"bdvkhunfnc90",
"bdvkj7vyvtz5",
"bdvkjkjbpr1t",
}
deflated, err := ghcomp.DeflateStrings(inflated)
if err != nil {
// handle
}
roundTrip, err := ghcomp.InflateStrings(deflated)
if err != nil {
// handle
}
_ = roundTripAppend variants:
DeflateStringsAppend(dst, in)InflateStringsAppend(dst, in)
Use this to avoid string conversions.
inflated := [][]byte{
[]byte("bdvkhunfnc90"),
[]byte("bdvkj7vyvtz5"),
[]byte("bdvkjkjbpr1t"),
}
deflated, err := ghcomp.DeflateBytes(inflated)
if err != nil {
// handle
}
roundTrip, err := ghcomp.InflateBytes(deflated)
if err != nil {
// handle
}
_ = roundTripAppend variants:
DeflateBytesAppend(dst, in)InflateBytesAppend(dst, in)
Use stream APIs for newline-delimited input/output:
in, _ := os.Open("data.txt")
out, _ := os.Create("deflated.txt")
err := ghcomp.Deflate(in, out)
if err != nil {
log.Fatalf("failed to deflate data: %v", err)
}And inflate:
in, _ := os.Open("deflated.txt")
out, _ := os.Create("inflated.txt")
err := ghcomp.Inflate(in, out)
if err != nil {
log.Fatalf("failed to inflate data: %v", err)
}You can still interact with the tree directly:
precision := 12
tree := ghcomp.New(precision)
_ = tree.Entree([]byte("bdvkhunfnc90"))
_ = tree.Entree([]byte("bdvkj7vyvtz5"))
out, _ := os.Create("inflated.txt")
_ = tree.WriteInflated(out)Or load deflated data and write inflated output:
in, _ := os.Open("deflated.txt")
out, _ := os.Create("inflated.txt")
tree := ghcomp.New(12)
if err := tree.EntreeDeflated(in); err != nil {
log.Fatalf("failed to load deflated data: %v", err)
}
if err := tree.WriteInflated(out); err != nil {
log.Fatalf("failed to write inflated data: %v", err)
}Deflate:
go run cmd/deflate/main.go data.txt deflated.txtInflate:
go run cmd/inflate/main.go deflated.txt inflated.txtSentinel errors:
ErrPrecision: input length does not match tree precision.ErrInflateEmptyInput: inflate was called with no input tokens.ErrInvalidMask: a deflated token is longer than the current inflate window.