From 78f2a87c5e7d5663a927343fe7528fbd628d6072 Mon Sep 17 00:00:00 2001 From: sfomuseumbot Date: Wed, 1 Mar 2023 13:15:05 -0800 Subject: [PATCH] update vendor deps; recompile data --- cmd/compile-galleries-data/main.go | 3 +- cmd/compile-gates-data/main.go | 3 +- cmd/compile-terminals-data/main.go | 3 +- cmd/current-complex/main.go | 3 +- cmd/lookup/main.go | 3 +- cmd/supersede-gallery/main.go | 6 +- data/galleries.json | 2 +- data/gates.json | 2 +- data/terminals.json | 2 +- galleries/compile.go | 5 +- galleries/galleries.go | 1 + galleries/geometry.go | 1 + galleries/lookup.go | 11 +- galleries/lookup_test.go | 5 +- gates/compile.go | 5 +- gates/gates.go | 1 + gates/lookup.go | 11 +- gates/lookup_test.go | 3 +- go.mod | 9 +- go.sum | 40 +- lookup.go | 3 +- terminals/compile.go | 7 +- terminals/lookup.go | 11 +- terminals/lookup_test.go | 3 +- terminals/terminals.go | 1 + vendor/github.com/paulmach/orb/CHANGELOG.md | 21 + vendor/github.com/paulmach/orb/README.md | 8 +- .../paulmach/orb/encoding/wkt/unmarshal.go | 6 + .../github.com/paulmach/orb/geojson/README.md | 9 +- .../paulmach/orb/geojson/feature.go | 69 +- .../orb/geojson/feature_collection.go | 65 +- .../paulmach/orb/geojson/geometry.go | 282 ++- .../go-whosonfirst-export/v2/export.go | 75 +- .../v2/properties/alt.go | 22 + .../v2/properties/properties.go | 20 +- .../whosonfirst/go-whosonfirst-uri/doc.go | 2 +- .../whosonfirst/go-whosonfirst-uri/uri.go | 26 + vendor/go.mongodb.org/mongo-driver/LICENSE | 201 ++ .../go.mongodb.org/mongo-driver/bson/bson.go | 50 + .../bson/bsoncodec/array_codec.go | 50 + .../mongo-driver/bson/bsoncodec/bsoncodec.go | 238 +++ .../bson/bsoncodec/byte_slice_codec.go | 111 ++ .../bson/bsoncodec/cond_addr_codec.go | 63 + .../bson/bsoncodec/default_value_decoders.go | 1729 +++++++++++++++++ .../bson/bsoncodec/default_value_encoders.go | 766 ++++++++ .../mongo-driver/bson/bsoncodec/doc.go | 90 + .../bson/bsoncodec/empty_interface_codec.go | 147 ++ .../mongo-driver/bson/bsoncodec/map_codec.go | 309 +++ .../mongo-driver/bson/bsoncodec/mode.go | 65 + .../bson/bsoncodec/pointer_codec.go | 109 ++ .../mongo-driver/bson/bsoncodec/proxy.go | 14 + .../mongo-driver/bson/bsoncodec/registry.go | 469 +++++ .../bson/bsoncodec/slice_codec.go | 199 ++ .../bson/bsoncodec/string_codec.go | 119 ++ .../bson/bsoncodec/struct_codec.go | 664 +++++++ .../bson/bsoncodec/struct_tag_parser.go | 139 ++ .../mongo-driver/bson/bsoncodec/time_codec.go | 127 ++ .../mongo-driver/bson/bsoncodec/types.go | 57 + .../mongo-driver/bson/bsoncodec/uint_codec.go | 173 ++ .../bsonoptions/byte_slice_codec_options.go | 38 + .../mongo-driver/bson/bsonoptions/doc.go | 8 + .../empty_interface_codec_options.go | 38 + .../bson/bsonoptions/map_codec_options.go | 67 + .../bson/bsonoptions/slice_codec_options.go | 38 + .../bson/bsonoptions/string_codec_options.go | 41 + .../bson/bsonoptions/struct_codec_options.go | 87 + .../bson/bsonoptions/time_codec_options.go | 38 + .../bson/bsonoptions/uint_codec_options.go | 38 + .../mongo-driver/bson/bsonrw/copier.go | 445 +++++ .../mongo-driver/bson/bsonrw/doc.go | 9 + .../bson/bsonrw/extjson_parser.go | 806 ++++++++ .../bson/bsonrw/extjson_reader.go | 644 ++++++ .../bson/bsonrw/extjson_tables.go | 223 +++ .../bson/bsonrw/extjson_wrappers.go | 492 +++++ .../bson/bsonrw/extjson_writer.go | 732 +++++++ .../mongo-driver/bson/bsonrw/json_scanner.go | 528 +++++ .../mongo-driver/bson/bsonrw/mode.go | 108 + .../mongo-driver/bson/bsonrw/reader.go | 63 + .../mongo-driver/bson/bsonrw/value_reader.go | 874 +++++++++ .../mongo-driver/bson/bsonrw/value_writer.go | 606 ++++++ .../mongo-driver/bson/bsonrw/writer.go | 78 + .../mongo-driver/bson/bsontype/bsontype.go | 97 + .../mongo-driver/bson/decoder.go | 141 ++ .../go.mongodb.org/mongo-driver/bson/doc.go | 141 ++ .../mongo-driver/bson/encoder.go | 99 + .../mongo-driver/bson/marshal.go | 248 +++ .../mongo-driver/bson/primitive/decimal.go | 423 ++++ .../mongo-driver/bson/primitive/objectid.go | 206 ++ .../mongo-driver/bson/primitive/primitive.go | 217 +++ .../mongo-driver/bson/primitive_codecs.go | 92 + .../go.mongodb.org/mongo-driver/bson/raw.go | 85 + .../mongo-driver/bson/raw_element.go | 51 + .../mongo-driver/bson/raw_value.go | 309 +++ .../mongo-driver/bson/registry.go | 24 + .../go.mongodb.org/mongo-driver/bson/types.go | 36 + .../mongo-driver/bson/unmarshal.go | 101 + .../mongo-driver/x/bsonx/bsoncore/array.go | 164 ++ .../x/bsonx/bsoncore/bson_arraybuilder.go | 201 ++ .../x/bsonx/bsoncore/bson_documentbuilder.go | 189 ++ .../mongo-driver/x/bsonx/bsoncore/bsoncore.go | 862 ++++++++ .../mongo-driver/x/bsonx/bsoncore/document.go | 386 ++++ .../x/bsonx/bsoncore/document_sequence.go | 189 ++ .../mongo-driver/x/bsonx/bsoncore/element.go | 152 ++ .../mongo-driver/x/bsonx/bsoncore/tables.go | 223 +++ .../mongo-driver/x/bsonx/bsoncore/value.go | 980 ++++++++++ vendor/modules.txt | 17 +- 106 files changed, 18150 insertions(+), 122 deletions(-) create mode 100644 vendor/github.com/whosonfirst/go-whosonfirst-export/v2/properties/alt.go create mode 100644 vendor/go.mongodb.org/mongo-driver/LICENSE create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bson.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/cond_addr_codec.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/mode.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/proxy.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/byte_slice_codec_options.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/doc.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/empty_interface_codec_options.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/map_codec_options.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/slice_codec_options.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/string_codec_options.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/struct_codec_options.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/time_codec_options.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/uint_codec_options.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonrw/doc.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_tables.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_wrappers.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonrw/mode.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonrw/reader.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsonrw/writer.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/bsontype/bsontype.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/decoder.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/doc.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/encoder.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/marshal.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/primitive/primitive.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/primitive_codecs.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/raw.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/raw_element.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/raw_value.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/registry.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/types.go create mode 100644 vendor/go.mongodb.org/mongo-driver/bson/unmarshal.go create mode 100644 vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/array.go create mode 100644 vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bson_arraybuilder.go create mode 100644 vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bson_documentbuilder.go create mode 100644 vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go create mode 100644 vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/document.go create mode 100644 vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/document_sequence.go create mode 100644 vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/element.go create mode 100644 vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/tables.go create mode 100644 vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go diff --git a/cmd/compile-galleries-data/main.go b/cmd/compile-galleries-data/main.go index 53ab047..6ba9585 100644 --- a/cmd/compile-galleries-data/main.go +++ b/cmd/compile-galleries-data/main.go @@ -5,10 +5,11 @@ import ( "encoding/json" "flag" "fmt" - "github.com/sfomuseum/go-sfomuseum-architecture/galleries" "io" "log" "os" + + "github.com/sfomuseum/go-sfomuseum-architecture/galleries" ) func main() { diff --git a/cmd/compile-gates-data/main.go b/cmd/compile-gates-data/main.go index 1c045a1..738d222 100644 --- a/cmd/compile-gates-data/main.go +++ b/cmd/compile-gates-data/main.go @@ -5,10 +5,11 @@ import ( "encoding/json" "flag" "fmt" - "github.com/sfomuseum/go-sfomuseum-architecture/gates" "io" "log" "os" + + "github.com/sfomuseum/go-sfomuseum-architecture/gates" ) func main() { diff --git a/cmd/compile-terminals-data/main.go b/cmd/compile-terminals-data/main.go index 37c6888..2216de8 100644 --- a/cmd/compile-terminals-data/main.go +++ b/cmd/compile-terminals-data/main.go @@ -5,10 +5,11 @@ import ( "encoding/json" "flag" "fmt" - "github.com/sfomuseum/go-sfomuseum-architecture/terminals" "io" "log" "os" + + "github.com/sfomuseum/go-sfomuseum-architecture/terminals" ) func main() { diff --git a/cmd/current-complex/main.go b/cmd/current-complex/main.go index 5b12fdf..d076488 100644 --- a/cmd/current-complex/main.go +++ b/cmd/current-complex/main.go @@ -4,10 +4,11 @@ import ( "context" "encoding/json" "flag" - "github.com/sfomuseum/go-sfomuseum-architecture/campus" "io" "log" "os" + + "github.com/sfomuseum/go-sfomuseum-architecture/campus" ) func main() { diff --git a/cmd/lookup/main.go b/cmd/lookup/main.go index dfda99d..5763ab0 100644 --- a/cmd/lookup/main.go +++ b/cmd/lookup/main.go @@ -10,8 +10,9 @@ import ( "context" "flag" "fmt" - "github.com/sfomuseum/go-sfomuseum-architecture" "log" + + "github.com/sfomuseum/go-sfomuseum-architecture" ) func main() { diff --git a/cmd/supersede-gallery/main.go b/cmd/supersede-gallery/main.go index 2774a43..e2eee3a 100644 --- a/cmd/supersede-gallery/main.go +++ b/cmd/supersede-gallery/main.go @@ -1,11 +1,14 @@ // supersede-gallery is a command line tool to clone and supersede an existing gallery record assigning // updated parent and hierarchy information at the same time. For example: -// $> ./bin/supersede-gallery -architecture-reader-uri repo:///usr/local/build/collection/sfomuseum-data-architecture/ -gallery-id 1763595133 -parent-id 1763588365 +// +// $> ./bin/supersede-gallery -architecture-reader-uri repo:///usr/local/build/collection/sfomuseum-data-architecture/ -gallery-id 1763595133 -parent-id 1763588365 package main import ( "context" "flag" + "log" + sfom_writer "github.com/sfomuseum/go-sfomuseum-writer/v3" "github.com/tidwall/gjson" "github.com/whosonfirst/go-reader" @@ -13,7 +16,6 @@ import ( "github.com/whosonfirst/go-whosonfirst-id" wof_reader "github.com/whosonfirst/go-whosonfirst-reader" "github.com/whosonfirst/go-writer/v3" - "log" ) func main() { diff --git a/data/galleries.json b/data/galleries.json index d48ea88..c86b7a9 100644 --- a/data/galleries.json +++ b/data/galleries.json @@ -1 +1 @@ -[{"wof:id":1729813677,"sfomuseum:id":63,"map_id":"C04","wof:name":"C-04 Entrance Lobby C Meet and Greet","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1729813679,"sfomuseum:id":68,"map_id":"F12","wof:name":"F-12 Student Art","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813683,"sfomuseum:id":60,"map_id":"F11","wof:name":"F-11 Photographs","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813687,"sfomuseum:id":71,"map_id":"1E","wof:name":"1E Mid-Pier Gallery","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1729813691,"sfomuseum:id":72,"map_id":"HM02","wof:name":"HM02 Harvey Milk Temporary Wall Gallery","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1729813693,"sfomuseum:id":74,"map_id":"B08","wof:name":"B-08 Central Photo Wall","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813695,"sfomuseum:id":77,"map_id":"1D","wof:name":"1D Alley Gallery","edtf:inception":"2021~","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813697,"sfomuseum:id":79,"map_id":"1A","wof:name":"1A Student Art South","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813733,"sfomuseum:id":55,"map_id":"K08","wof:name":"AML Aviation Museum Perimeter 08","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813699,"sfomuseum:id":80,"map_id":"2D","wof:name":"2D Sky Terrace Platform","edtf:inception":"2020~","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1175727175,"sfomuseum:id":65,"map_id":"3B","wof:name":"3B Kid’s Spot Boarding Area E","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1729813735,"sfomuseum:id":42,"map_id":"K06","wof:name":"AML Aviation Museum Gallery 06a-e","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":1},{"wof:id":1729813737,"sfomuseum:id":62,"map_id":"K04","wof:name":"AML Aviation Museum Gallery 04","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":1},{"wof:id":1729813739,"sfomuseum:id":28,"map_id":"K02","wof:name":"AML Aviation Museum Gallery 02","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":1},{"wof:id":1729813747,"sfomuseum:id":29,"map_id":"K03","wof:name":"AML Aviation Museum Gallery 03","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":0},{"wof:id":1729792767,"sfomuseum:id":67,"map_id":"2B","wof:name":"2B Kids’ Spot","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792771,"sfomuseum:id":2,"map_id":"3C","wof:name":"3C North Connector","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792769,"sfomuseum:id":58,"map_id":"2A","wof:name":"2A Boomerang Gallery","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792775,"sfomuseum:id":25,"map_id":"3F","wof:name":"3F Gate 87a","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792777,"sfomuseum:id":3,"map_id":"3E","wof:name":"3E Gate 76","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792783,"sfomuseum:id":17,"map_id":"","wof:name":"A-02 International South Cases","edtf:inception":"2020-~05","edtf:cessation":"2020-01-13","mz:is_current":0},{"wof:id":1729792785,"sfomuseum:id":18,"map_id":"4C","wof:name":"4C International South Wall","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792787,"sfomuseum:id":19,"map_id":"4B","wof:name":"4B International North Wall","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792795,"sfomuseum:id":20,"map_id":"","wof:name":"G-02 International North Cases","edtf:inception":"2020-~05","edtf:cessation":"2020-02-02","mz:is_current":0},{"wof:id":1729792789,"sfomuseum:id":59,"map_id":"","wof:name":"A-07 International Central Vitrine","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1745882455,"sfomuseum:id":67,"map_id":"2B","wof:name":"2B Kids’ Spot","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882457,"sfomuseum:id":58,"map_id":"D12","wof:name":"D-12 Wall Case","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882459,"sfomuseum:id":80,"map_id":"2D","wof:name":"2D Sky Terrace Platform","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882465,"sfomuseum:id":72,"map_id":"HM02","wof:name":"HM02 Harvey Milk Temporary Wall Gallery","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882471,"sfomuseum:id":79,"map_id":"1A","wof:name":"1A Student Art South","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882483,"sfomuseum:id":3,"map_id":"3E","wof:name":"3E Gate 76","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882467,"sfomuseum:id":74,"map_id":"HM01","wof:name":"HM01 Central Photo Wall","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882473,"sfomuseum:id":71,"map_id":"1E","wof:name":"1E Mid-Pier Gallery","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882489,"sfomuseum:id":65,"map_id":"E06","wof:name":"E-06 Kid’s Spot Boarding Area E","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882501,"sfomuseum:id":18,"map_id":"A01","wof:name":"A-01 International South Wall","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882475,"sfomuseum:id":40,"map_id":"1J","wof:name":"1J Terminal One Lower Gallery","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745885813,"sfomuseum:id":91,"map_id":"1F","wof:name":"1F Kids’ Spot/Tree Town","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882503,"sfomuseum:id":19,"map_id":"G01","wof:name":"G-01 International North Wall","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745887099,"sfomuseum:id":92,"map_id":"1C","wof:name":"1C Kids’ Spot","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882507,"sfomuseum:id":70,"map_id":"4E","wof:name":"4E Video Arts Gallery","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882477,"sfomuseum:id":63,"map_id":"1K","wof:name":"1K Entrance Lobby C Meet and Greet","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1729837317,"sfomuseum:id":72,"map_id":"B15","wof:name":"B-15 Harvey Milk Temporary Wall Gallery","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1745882493,"sfomuseum:id":51,"map_id":"3L","wof:name":"3L Terminal 3 Connector Arrival Level","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1729837319,"sfomuseum:id":40,"map_id":"1J","wof:name":"1J Terminal One Lower Gallery","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1745882497,"sfomuseum:id":60,"map_id":"3J","wof:name":"3J Photographs","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882479,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1729837321,"sfomuseum:id":63,"map_id":"C04","wof:name":"C-04 Entrance Lobby C Meet and Greet","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1763594987,"sfomuseum:id":84,"map_id":"HM03","wof:name":"HM03 Sterile Connector","edtf:inception":"","edtf:cessation":"","mz:is_current":1},{"wof:id":1763595139,"sfomuseum:id":64,"map_id":"3A","wof:name":"E-05 E Plaza Meet and Greet","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763601213,"sfomuseum:id":41,"map_id":"K04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1763595185,"sfomuseum:id":41,"map_id":"AML 04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1763594989,"sfomuseum:id":90,"map_id":"2F","wof:name":"2F Pre-Security Connector/Zuber","edtf:inception":"","edtf:cessation":"","mz:is_current":1},{"wof:id":1763595187,"sfomuseum:id":41,"map_id":"AML 04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1360392583,"sfomuseum:id":25,"map_id":"3F","wof:name":"3F Gate 87a","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360392585,"sfomuseum:id":25,"map_id":"3F","wof:name":"3F Gate 87a","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360392589,"sfomuseum:id":25,"map_id":"F04","wof:name":"F-04 Gate 87a","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360392587,"sfomuseum:id":25,"map_id":"F04","wof:name":"F-04 Gate 87a","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360392591,"sfomuseum:id":25,"map_id":"F04","wof:name":"F-04 Gate 87a","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360392593,"sfomuseum:id":25,"map_id":"F04","wof:name":"F-04 Gate 87a","edtf:inception":"1987~","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1360521555,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360521557,"sfomuseum:id":10,"map_id":"","wof:name":"D-05 Central South Connector","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360521559,"sfomuseum:id":10,"map_id":"D05","wof:name":"D-05 Central South Connector","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360521553,"sfomuseum:id":6,"map_id":"","wof:name":"D-01 Central North Connector","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1763588487,"sfomuseum:id":58,"map_id":"D12","wof:name":"D-12 Wall Case","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588503,"sfomuseum:id":79,"map_id":"1A","wof:name":"1A Student Art South","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588515,"sfomuseum:id":63,"map_id":"1K","wof:name":"1K Entrance Lobby C Meet and Greet","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588521,"sfomuseum:id":25,"map_id":"F04","wof:name":"F-04 Gate 87a","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588505,"sfomuseum:id":71,"map_id":"1E","wof:name":"1E Mid-Pier Gallery","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588517,"sfomuseum:id":91,"map_id":"1F","wof:name":"1F Kids’ Spot/Tree Town","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588523,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588507,"sfomuseum:id":92,"map_id":"1C","wof:name":"1C Kids’ Spot","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588495,"sfomuseum:id":81,"map_id":"2D","wof:name":"2D Sky Terrace Wall","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588519,"sfomuseum:id":2,"map_id":"3C","wof:name":"3C North Connector","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588509,"sfomuseum:id":93,"map_id":"HM04","wof:name":"HM04 Harvey Milk Temporary Wall 2","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588497,"sfomuseum:id":72,"map_id":"HM02","wof:name":"HM02 Harvey Milk Temporary Wall Gallery","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588525,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588535,"sfomuseum:id":68,"map_id":"3K","wof:name":"3K Aviation Photographs","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588541,"sfomuseum:id":59,"map_id":"A07","wof:name":"A-07 International Central Case","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588499,"sfomuseum:id":74,"map_id":"HM01","wof:name":"HM01 Central Photo Wall","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588527,"sfomuseum:id":65,"map_id":"E06","wof:name":"E-06 Kid’s Spot Boarding Area E","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588537,"sfomuseum:id":51,"map_id":"3L","wof:name":"3L Terminal 3 Connector Arrival Level","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588543,"sfomuseum:id":18,"map_id":"A01","wof:name":"A-01 International South Wall","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588553,"sfomuseum:id":86,"map_id":"4A","wof:name":"4A International North Cases","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588545,"sfomuseum:id":19,"map_id":"G01","wof:name":"G-01 International North Wall","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588549,"sfomuseum:id":70,"map_id":"4E","wof:name":"4E Video Arts Gallery","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1360516117,"sfomuseum:id":65,"map_id":"E06","wof:name":"E-06 Kid’s Spot Boarding Area E","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516119,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541555,"sfomuseum:id":26,"map_id":"","wof:name":"D-08 International Garage Passageway","edtf:inception":"1997-11-01","edtf:cessation":"1998-03-01","mz:is_current":0},{"wof:id":1360541553,"sfomuseum:id":4,"map_id":"","wof:name":"E-01 Children’s Art Gallery #2","edtf:inception":"1990-12-16","edtf:cessation":"1998-12-17","mz:is_current":0},{"wof:id":1360541557,"sfomuseum:id":27,"map_id":"AML 01","wof:name":"AML 01 Aviation Museum Gallery 01","edtf:inception":"2000-11-20","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541561,"sfomuseum:id":29,"map_id":"","wof:name":"K-03 Aviation Museum Gallery 03","edtf:inception":"2000-11-20","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541559,"sfomuseum:id":28,"map_id":"AML 02","wof:name":"AML 02 Aviation Museum Gallery 02","edtf:inception":"2000-11-20","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516121,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541563,"sfomuseum:id":30,"map_id":"","wof:name":"K-4A Aviation Museum Gallery 04a","edtf:inception":"2000-12-01","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516123,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541567,"sfomuseum:id":31,"map_id":"AML 05","wof:name":"AML 05 Aviation Museum Gallery 05a-d","edtf:inception":"2000-11-20","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516125,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541569,"sfomuseum:id":38,"map_id":"AML 07","wof:name":"AML 07 Aviation Museum Ceiling 07","edtf:inception":"2000-11-22","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516127,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516129,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"1983~","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1360516133,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"1981-01-01","edtf:cessation":"1983~","mz:is_current":0},{"wof:id":1360516135,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"1981~","edtf:cessation":"1981~","mz:is_current":0},{"wof:id":1360516137,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516139,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516141,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516143,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541571,"sfomuseum:id":41,"map_id":"AML 04B","wof:name":"AML 04B Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2000-12-03","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516145,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360541573,"sfomuseum:id":42,"map_id":"AML 06","wof:name":"AML 06 Aviation Museum Gallery 06a-e","edtf:inception":"2000-11-20","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541575,"sfomuseum:id":55,"map_id":"AML 08","wof:name":"AML 08 Aviation Museum Perimeter 08","edtf:inception":"2004-02-17","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516147,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"1985~","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1360541577,"sfomuseum:id":62,"map_id":"AML 04","wof:name":"AML 04 Aviation Museum Gallery 04","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541615,"sfomuseum:id":30,"map_id":"","wof:name":"K-4A Aviation Museum Gallery 04a","edtf:inception":"2006~","edtf:cessation":"2010-09-20","mz:is_current":0},{"wof:id":1360541625,"sfomuseum:id":38,"map_id":"AML 07","wof:name":"AML 07 Aviation Museum Ceiling 07","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516151,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541627,"sfomuseum:id":38,"map_id":"K07","wof:name":"AML Aviation Museum Ceiling 07","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516153,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516155,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541629,"sfomuseum:id":38,"map_id":"K07","wof:name":"AML Aviation Museum Ceiling 07","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516157,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516159,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"1991~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516161,"sfomuseum:id":60,"map_id":"F11","wof:name":"F-11 Photographs","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516163,"sfomuseum:id":60,"map_id":"F11","wof:name":"F-11 Photographs","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516165,"sfomuseum:id":60,"map_id":"F11","wof:name":"F-11 Photographs","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516169,"sfomuseum:id":60,"map_id":"F11","wof:name":"F-11 Photographs","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541631,"sfomuseum:id":38,"map_id":"AML 07","wof:name":"AML 07 Aviation Museum Ceiling 07","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360541633,"sfomuseum:id":31,"map_id":"AML 05","wof:name":"AML 05 Aviation Museum Gallery 05a-d","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516171,"sfomuseum:id":60,"map_id":"F11","wof:name":"F-11 Photographs","edtf:inception":"1991-06-01","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516173,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516175,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541635,"sfomuseum:id":31,"map_id":"AML 05","wof:name":"AML 05 Aviation Museum Gallery 05a-d","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516177,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516179,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2002-04-07","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541643,"sfomuseum:id":29,"map_id":"","wof:name":"K-03 Aviation Museum Gallery 03","edtf:inception":"2006~","edtf:cessation":"2010-01-29","mz:is_current":0},{"wof:id":1360541639,"sfomuseum:id":31,"map_id":"K05","wof:name":"AML Aviation Museum Gallery 05a-d","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541647,"sfomuseum:id":29,"map_id":"K03","wof:name":"AML Aviation Museum Gallery 03","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541649,"sfomuseum:id":29,"map_id":"K03","wof:name":"AML Aviation Museum Gallery 03","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360516181,"sfomuseum:id":18,"map_id":"A01","wof:name":"A-01 International South Wall","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541651,"sfomuseum:id":28,"map_id":"K02","wof:name":"AML Aviation Museum Gallery 02","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541653,"sfomuseum:id":28,"map_id":"K02","wof:name":"AML Aviation Museum Gallery 02","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516183,"sfomuseum:id":18,"map_id":"A01","wof:name":"A-01 International South Wall","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541657,"sfomuseum:id":28,"map_id":"K02","wof:name":"AML Aviation Museum Gallery 02","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516187,"sfomuseum:id":18,"map_id":"A01","wof:name":"A-01 International South Wall","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541659,"sfomuseum:id":28,"map_id":"K02","wof:name":"AML Aviation Museum Gallery 02","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360516189,"sfomuseum:id":18,"map_id":"A01","wof:name":"A-01 International South Wall","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516191,"sfomuseum:id":19,"map_id":"G01","wof:name":"G-01 International North Wall","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516193,"sfomuseum:id":19,"map_id":"G01","wof:name":"G-01 International North Wall","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516195,"sfomuseum:id":19,"map_id":"G01","wof:name":"G-01 International North Wall","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516197,"sfomuseum:id":19,"map_id":"G01","wof:name":"G-01 International North Wall","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516199,"sfomuseum:id":59,"map_id":"A07","wof:name":"A-07 International Central Case","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541661,"sfomuseum:id":27,"map_id":"AML 01","wof:name":"AML 01 Aviation Museum Gallery 01","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516201,"sfomuseum:id":59,"map_id":"A07","wof:name":"A-07 International Central Case","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541645,"sfomuseum:id":29,"map_id":"K03","wof:name":"AML Aviation Museum Gallery 03","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541663,"sfomuseum:id":27,"map_id":"K01","wof:name":"AML Aviation Museum Gallery 01","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516205,"sfomuseum:id":59,"map_id":"A07","wof:name":"A-07 International Central Case","edtf:inception":"2010~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541665,"sfomuseum:id":27,"map_id":"K01","wof:name":"AML Aviation Museum Gallery 01","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541667,"sfomuseum:id":27,"map_id":"K01","wof:name":"AML Aviation Museum Gallery 01","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360516207,"sfomuseum:id":63,"map_id":"C04","wof:name":"C-04 Entrance Lobby C Meet and Greet","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516209,"sfomuseum:id":63,"map_id":"C04","wof:name":"C-04 Entrance Lobby C Meet and Greet","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541669,"sfomuseum:id":42,"map_id":"AML 06","wof:name":"AML 06 Aviation Museum Gallery 06a-e","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541671,"sfomuseum:id":42,"map_id":"AML 06","wof:name":"AML 06 Aviation Museum Gallery 06a-e","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541675,"sfomuseum:id":42,"map_id":"K06","wof:name":"AML Aviation Museum Gallery 06a-e","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541677,"sfomuseum:id":42,"map_id":"K06","wof:name":"AML Aviation Museum Gallery 06a-e","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360541679,"sfomuseum:id":62,"map_id":"AML 04","wof:name":"AML 04 Aviation Museum Gallery 04","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516211,"sfomuseum:id":63,"map_id":"1K","wof:name":"1K Entrance Lobby C Meet and Greet","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541681,"sfomuseum:id":62,"map_id":"K04","wof:name":"AML Aviation Museum Gallery 04","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541683,"sfomuseum:id":62,"map_id":"AML 04","wof:name":"AML 04 Aviation Museum Gallery 04","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541685,"sfomuseum:id":62,"map_id":"K04","wof:name":"AML Aviation Museum Gallery 04","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360516223,"sfomuseum:id":16,"map_id":"","wof:name":"B-03 Gate 36","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516213,"sfomuseum:id":63,"map_id":"C04","wof:name":"C-04 Entrance Lobby C Meet and Greet","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516215,"sfomuseum:id":63,"map_id":"C04","wof:name":"C-04 Entrance Lobby C Meet and Greet","edtf:inception":"1996~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360541687,"sfomuseum:id":55,"map_id":"K08","wof:name":"AML Aviation Museum Perimeter 08","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516225,"sfomuseum:id":16,"map_id":"B03","wof:name":"B-03 Gate 36","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516217,"sfomuseum:id":16,"map_id":"","wof:name":"B-03 Gate 36","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541689,"sfomuseum:id":55,"map_id":"K08","wof:name":"AML Aviation Museum Perimeter 08","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516227,"sfomuseum:id":16,"map_id":"B03","wof:name":"B-03 Gate 36","edtf:inception":"1990~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516219,"sfomuseum:id":16,"map_id":"B03","wof:name":"B-03 Gate 36","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516229,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516241,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"1988~","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1360516231,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516243,"sfomuseum:id":66,"map_id":"D13","wof:name":"D-13 Kids’ Spot","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516233,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541641,"sfomuseum:id":31,"map_id":"K05","wof:name":"AML Aviation Museum Gallery 05a-d","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360516251,"sfomuseum:id":67,"map_id":"2B","wof:name":"2B Kids’ Spot","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516235,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516245,"sfomuseum:id":66,"map_id":"D13","wof:name":"D-13 Kids’ Spot","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516247,"sfomuseum:id":69,"map_id":"","wof:name":"B-06 Kids’ Spot","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516253,"sfomuseum:id":67,"map_id":"D14","wof:name":"D-14 Kids’ Spot","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516255,"sfomuseum:id":58,"map_id":"D12","wof:name":"D-12 Wall Case","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516237,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516259,"sfomuseum:id":58,"map_id":"D12","wof:name":"D-12 Wall Case","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516249,"sfomuseum:id":64,"map_id":"3A","wof:name":"3A E Plaza Meet and Greet","edtf:inception":"2015~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541695,"sfomuseum:id":55,"map_id":"K08","wof:name":"AML Aviation Museum Perimeter 08","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360541693,"sfomuseum:id":55,"map_id":"K08","wof:name":"AML Aviation Museum Perimeter 08","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516261,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541699,"sfomuseum:id":41,"map_id":"AML 04B","wof:name":"AML 04B Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541697,"sfomuseum:id":41,"map_id":"K04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516263,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516265,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516269,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"1983~","edtf:cessation":"1983~","mz:is_current":0},{"wof:id":1360516267,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"1983~","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1360516277,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516271,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516273,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516279,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541701,"sfomuseum:id":41,"map_id":"K04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541703,"sfomuseum:id":41,"map_id":"K04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516281,"sfomuseum:id":20,"map_id":"G02","wof:name":"G-02 International North Cases","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516283,"sfomuseum:id":20,"map_id":"","wof:name":"G-02 International North Cases","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516285,"sfomuseum:id":20,"map_id":"G02","wof:name":"G-02 International North Cases","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516435,"sfomuseum:id":39,"map_id":"","wof:name":"A-05 Terminal One Lower Gallery","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516287,"sfomuseum:id":20,"map_id":"G02","wof:name":"G-02 International North Cases","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516441,"sfomuseum:id":39,"map_id":"","wof:name":"A-05 Terminal One Lower Gallery","edtf:inception":"2014~","edtf:cessation":"2016-08-19","mz:is_current":0},{"wof:id":1360516439,"sfomuseum:id":39,"map_id":"","wof:name":"A-05 Terminal One Lower Gallery","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516443,"sfomuseum:id":13,"map_id":"","wof:name":"C-03 Entrance Lobby C","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516445,"sfomuseum:id":13,"map_id":"","wof:name":"C-03 Entrance Lobby C","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516447,"sfomuseum:id":13,"map_id":"C03","wof:name":"C-03 Entrance Lobby C","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516449,"sfomuseum:id":13,"map_id":"C03","wof:name":"C-03 Entrance Lobby C","edtf:inception":"2014~","edtf:cessation":"2016-03-31","mz:is_current":0},{"wof:id":1360516451,"sfomuseum:id":5,"map_id":"","wof:name":"E-02 Gate 62 Cultural Wall","edtf:inception":"1988~","edtf:cessation":"1997-03-21","mz:is_current":0},{"wof:id":1360516453,"sfomuseum:id":24,"map_id":"","wof:name":"B-04 Entrance Lobby B","edtf:inception":"2000~","edtf:cessation":"2001-11-26","mz:is_current":0},{"wof:id":1360516457,"sfomuseum:id":23,"map_id":"","wof:name":"D-06 Kids’ Spot","edtf:inception":"2011~","edtf:cessation":"2011-12-01","mz:is_current":0},{"wof:id":1360516459,"sfomuseum:id":14,"map_id":"","wof:name":"B-01 Gate 20","edtf:inception":"2000~","edtf:cessation":"2001-06-15","mz:is_current":0},{"wof:id":1360516461,"sfomuseum:id":11,"map_id":"","wof:name":"C-01 Aquarium","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516465,"sfomuseum:id":11,"map_id":"C01","wof:name":"C-01 Aquarium","edtf:inception":"2011~","edtf:cessation":"2013-10-31","mz:is_current":0},{"wof:id":1360516463,"sfomuseum:id":11,"map_id":"C01","wof:name":"C-01 Aquarium","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516467,"sfomuseum:id":10,"map_id":"","wof:name":"D-05 Central South Connector","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516471,"sfomuseum:id":9,"map_id":"","wof:name":"D-04 Central Gallery","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516469,"sfomuseum:id":10,"map_id":"D05","wof:name":"D-05 Central South Connector","edtf:inception":"2011~","edtf:cessation":"2012-04-30","mz:is_current":0},{"wof:id":1360516475,"sfomuseum:id":9,"map_id":"D04","wof:name":"D-04 Central Gallery","edtf:inception":"2011~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516479,"sfomuseum:id":34,"map_id":"A03","wof:name":"A-03 Entrance Lobby A","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516477,"sfomuseum:id":34,"map_id":"","wof:name":"A-03 Entrance Lobby A","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516481,"sfomuseum:id":34,"map_id":"","wof:name":"A-03 Entrance Lobby A","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516483,"sfomuseum:id":34,"map_id":"A03","wof:name":"A-03 Entrance Lobby A","edtf:inception":"2014~","edtf:cessation":"2015-09-22","mz:is_current":0},{"wof:id":1360516485,"sfomuseum:id":1,"map_id":"","wof:name":"F-01 Gate 68 Children’s Art Gallery","edtf:inception":"2000~","edtf:cessation":"2002-01-15","mz:is_current":0},{"wof:id":1360516487,"sfomuseum:id":48,"map_id":"","wof:name":"F-08 Gate 81","edtf:inception":"1988~","edtf:cessation":"1990-10-01","mz:is_current":0},{"wof:id":1360516489,"sfomuseum:id":46,"map_id":"","wof:name":"F-07 Gate 74","edtf:inception":"1988~","edtf:cessation":"1990-12-15","mz:is_current":0},{"wof:id":1360516501,"sfomuseum:id":8,"map_id":"","wof:name":"D-03 Central Concourse","edtf:inception":"2011~","edtf:cessation":"2013~","mz:is_current":0},{"wof:id":1360516493,"sfomuseum:id":45,"map_id":"","wof:name":"F-06 Gate 72","edtf:inception":"1988~","edtf:cessation":"1990-08-06","mz:is_current":0},{"wof:id":1360516495,"sfomuseum:id":50,"map_id":"","wof:name":"D-11 Central Wall (Duty Free)","edtf:inception":"1988~","edtf:cessation":"1998-02-01","mz:is_current":0},{"wof:id":1360516497,"sfomuseum:id":49,"map_id":"","wof:name":"D-10 Central Cases (Currency Exchange)","edtf:inception":"1988~","edtf:cessation":"1991-12-19","mz:is_current":0},{"wof:id":1360516499,"sfomuseum:id":8,"map_id":"","wof:name":"D-03 Central Concourse","edtf:inception":"1988~","edtf:cessation":"1996-12-30","mz:is_current":0},{"wof:id":1159157037,"sfomuseum:id":20,"map_id":"","wof:name":"G-02 International North Cases","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157039,"sfomuseum:id":17,"map_id":"","wof:name":"A-02 International South Cases","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157041,"sfomuseum:id":59,"map_id":"","wof:name":"A-07 International Central Vitrine","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157045,"sfomuseum:id":19,"map_id":"4B","wof:name":"4B International North Wall","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157047,"sfomuseum:id":18,"map_id":"4C","wof:name":"4C International South Wall","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157049,"sfomuseum:id":51,"map_id":"3L","wof:name":"3L Terminal 3 Connector Arrival Level","edtf:inception":"2017~","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1159157051,"sfomuseum:id":60,"map_id":"3J","wof:name":"3J Photographs","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157053,"sfomuseum:id":2,"map_id":"3C","wof:name":"3C North Connector","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157055,"sfomuseum:id":37,"map_id":"3D","wof:name":"3D Terminal 3 Hub","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157057,"sfomuseum:id":3,"map_id":"3E","wof:name":"3E Gate 76","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157059,"sfomuseum:id":25,"map_id":"3F","wof:name":"3F Gate 87a","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157063,"sfomuseum:id":64,"map_id":"3A","wof:name":"3A E Plaza Meet and Greet","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157065,"sfomuseum:id":6,"map_id":"","wof:name":"D-01 Central North Connector","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157067,"sfomuseum:id":58,"map_id":"2A","wof:name":"2A Boomerang Gallery","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157069,"sfomuseum:id":67,"map_id":"2B","wof:name":"2B Kids’ Spot","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157071,"sfomuseum:id":66,"map_id":"2C","wof:name":"2C Kids’ Spot","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157073,"sfomuseum:id":63,"map_id":"1K","wof:name":"1K Entrance Lobby C Meet and Greet","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157075,"sfomuseum:id":40,"map_id":"1J","wof:name":"1J Terminal One Lower Gallery","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157077,"sfomuseum:id":16,"map_id":"","wof:name":"B-03 Gate 36","edtf:inception":"2017~","edtf:cessation":"2019-07-22","mz:is_current":0},{"wof:id":1159157081,"sfomuseum:id":69,"map_id":"","wof:name":"B-06 Kids’ Spot","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157873,"sfomuseum:id":13,"map_id":"","wof:name":"C-03 Entrance Lobby C","edtf:inception":"1988-08-01","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157875,"sfomuseum:id":24,"map_id":"B04","wof:name":"B-04 Entrance Lobby B","edtf:inception":"1997-01-29","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157877,"sfomuseum:id":15,"map_id":"","wof:name":"B-02 Gate 26","edtf:inception":"1988-07-01","edtf:cessation":"1998-10-31","mz:is_current":0},{"wof:id":1159157879,"sfomuseum:id":5,"map_id":"","wof:name":"E-02 Gate 62 Cultural Wall","edtf:inception":"1985-05-29","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157865,"sfomuseum:id":9,"map_id":"","wof:name":"D-04 Central Gallery","edtf:inception":"1983-12-15","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157867,"sfomuseum:id":10,"map_id":"","wof:name":"D-05 Central South Connector","edtf:inception":"1983-07-13","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157869,"sfomuseum:id":12,"map_id":"","wof:name":"C-02 Gate 40 Gallery","edtf:inception":"1996-01-01","edtf:cessation":"1999-01-25","mz:is_current":0},{"wof:id":1477855613,"sfomuseum:id":66,"map_id":"D13","wof:name":"D-13 Kids’ Spot","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1159157881,"sfomuseum:id":1,"map_id":"","wof:name":"F-01 Gate 68 Children’s Art Gallery","edtf:inception":"1988-07-01","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157883,"sfomuseum:id":34,"map_id":"","wof:name":"A-03 Entrance Lobby A","edtf:inception":"1990-09-01","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157891,"sfomuseum:id":11,"map_id":"","wof:name":"C-01 Aquarium","edtf:inception":"1995-11-13","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157885,"sfomuseum:id":7,"map_id":"","wof:name":"D-02 Central Fountain Gallery","edtf:inception":"1991-06-01","edtf:cessation":"1997-04-10","mz:is_current":0},{"wof:id":1159157893,"sfomuseum:id":23,"map_id":"","wof:name":"D-06 Kids’ Spot","edtf:inception":"1997-08-01","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157887,"sfomuseum:id":21,"map_id":"","wof:name":"D-07 International Customs Area","edtf:inception":"1992-05-01","edtf:cessation":"1998-06-02","mz:is_current":0},{"wof:id":1159157895,"sfomuseum:id":14,"map_id":"","wof:name":"B-01 Gate 20","edtf:inception":"1995-12-01","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157897,"sfomuseum:id":32,"map_id":"","wof:name":"E-03 Entrance Lobby E","edtf:inception":"1998-10-16","edtf:cessation":"1999-01-29","mz:is_current":0},{"wof:id":1477855625,"sfomuseum:id":67,"map_id":"D14","wof:name":"D-14 Kids’ Spot","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1159157905,"sfomuseum:id":43,"map_id":"","wof:name":"D-09 Central South","edtf:inception":"2001-12-10","edtf:cessation":"2002-09-25","mz:is_current":0},{"wof:id":1477855627,"sfomuseum:id":58,"map_id":"D12","wof:name":"D-12 Wall Case","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1159157909,"sfomuseum:id":39,"map_id":"","wof:name":"A-05 Terminal One Lower Gallery","edtf:inception":"2000-07-15","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1159157911,"sfomuseum:id":8,"map_id":"","wof:name":"D-03 Central Concourse","edtf:inception":"1987-07-01","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157915,"sfomuseum:id":49,"map_id":"","wof:name":"D-10 Central Cases (Currency Exchange)","edtf:inception":"1987-09-01","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157917,"sfomuseum:id":50,"map_id":"","wof:name":"D-11 Central Wall (Duty Free)","edtf:inception":"1987-09-01","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157919,"sfomuseum:id":45,"map_id":"","wof:name":"F-06 Gate 72","edtf:inception":"1987-05-01","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157921,"sfomuseum:id":46,"map_id":"","wof:name":"F-07 Gate 74","edtf:inception":"1987-05-01","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157923,"sfomuseum:id":47,"map_id":"","wof:name":"A-06 Gate 08","edtf:inception":"1987-04-01","edtf:cessation":"1987-12-31","mz:is_current":0},{"wof:id":1159157931,"sfomuseum:id":53,"map_id":"","wof:name":"B-05 Boarding Lobby","edtf:inception":"2003-09-24","edtf:cessation":"2016-10-28","mz:is_current":0},{"wof:id":1159157927,"sfomuseum:id":48,"map_id":"","wof:name":"F-08 Gate 81","edtf:inception":"1987-09-01","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157937,"sfomuseum:id":68,"map_id":"3K","wof:name":"3K Aviation Photographs","edtf:inception":"2017-04-06","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157929,"sfomuseum:id":44,"map_id":"","wof:name":"E-04 Gate 61 Cultural Wall","edtf:inception":"1988-01-01","edtf:cessation":"1998-06-30","mz:is_current":0},{"wof:id":1477855661,"sfomuseum:id":63,"map_id":"C04","wof:name":"C-04 Entrance Lobby C Meet and Greet","edtf:inception":"2015-01-20","edtf:cessation":"","mz:is_current":0},{"wof:id":1477855663,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855653,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"2019-07-23","edtf:cessation":"2019-10-28","mz:is_current":0},{"wof:id":1159157939,"sfomuseum:id":70,"map_id":"G03","wof:name":"G-03 Video Arts Gallery","edtf:inception":"2017-09-07","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1477855731,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855725,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855727,"sfomuseum:id":25,"map_id":"F04","wof:name":"F-04 Gate 87a","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855729,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855787,"sfomuseum:id":65,"map_id":"E06","wof:name":"E-06 Kid’s Spot Boarding Area E","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855823,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2002-04-07","edtf:cessation":"","mz:is_current":0},{"wof:id":1477855821,"sfomuseum:id":60,"map_id":"F11","wof:name":"F-11 Photographs","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855825,"sfomuseum:id":64,"map_id":"E05","wof:name":"E-05 E Plaza Meet and Greet","edtf:inception":"2019-07-23","edtf:cessation":"2019-10-17","mz:is_current":0},{"wof:id":1477855831,"sfomuseum:id":68,"map_id":"F12","wof:name":"F-12 Aviation Photographs","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855929,"sfomuseum:id":18,"map_id":"A01","wof:name":"A-01 International South Wall","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855951,"sfomuseum:id":29,"map_id":"","wof:name":"K-03 Aviation Museum Gallery 03","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855955,"sfomuseum:id":31,"map_id":"K05","wof:name":"AML Aviation Museum Gallery 05a-d","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855957,"sfomuseum:id":70,"map_id":"G03","wof:name":"G-03 Video Arts Gallery","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855959,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855941,"sfomuseum:id":55,"map_id":"K08","wof:name":"AML Aviation Museum Perimeter 08","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855947,"sfomuseum:id":28,"map_id":"AML 02","wof:name":"AML 02 Aviation Museum Gallery 02","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855943,"sfomuseum:id":42,"map_id":"K06","wof:name":"AML Aviation Museum Gallery 06a-e","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855949,"sfomuseum:id":27,"map_id":"K01","wof:name":"AML Aviation Museum Gallery 01","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855961,"sfomuseum:id":20,"map_id":"G02","wof:name":"G-02 International North Cases","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855931,"sfomuseum:id":19,"map_id":"G01","wof:name":"G-01 International North Wall","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855933,"sfomuseum:id":59,"map_id":"A07","wof:name":"A-07 International Central Case","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855939,"sfomuseum:id":38,"map_id":"AML 07","wof:name":"AML 07 Aviation Museum Ceiling 07","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855945,"sfomuseum:id":62,"map_id":"K04","wof:name":"AML Aviation Museum Gallery 04","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1746403233,"sfomuseum:id":86,"map_id":"4A","wof:name":"4A International North Cases","edtf:inception":"","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1729813681,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813685,"sfomuseum:id":41,"map_id":"K04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813701,"sfomuseum:id":81,"map_id":"2D","wof:name":"2D Sky Terrace Wall","edtf:inception":"2020~","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813731,"sfomuseum:id":38,"map_id":"K07","wof:name":"AML Aviation Museum Ceiling 07","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":0},{"wof:id":1729813741,"sfomuseum:id":27,"map_id":"K01","wof:name":"AML Aviation Museum Gallery 01","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":1},{"wof:id":1729813745,"sfomuseum:id":31,"map_id":"K05","wof:name":"AML Aviation Museum Gallery 05a-d","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":1},{"wof:id":1729792765,"sfomuseum:id":66,"map_id":"2C","wof:name":"2C Kids’ Spot","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792779,"sfomuseum:id":37,"map_id":"3D","wof:name":"3D Terminal 3 Hub","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792793,"sfomuseum:id":70,"map_id":"4E","wof:name":"4E Video Arts Gallery","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792781,"sfomuseum:id":65,"map_id":"E06","wof:name":"E-06 Kid’s Spot Boarding Area E","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1745882461,"sfomuseum:id":81,"map_id":"2D","wof:name":"2D Sky Terrace Wall","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882463,"sfomuseum:id":77,"map_id":"1D","wof:name":"1D Alley Gallery","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882453,"sfomuseum:id":66,"map_id":"D13","wof:name":"D-13 Kids’ Spot","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882491,"sfomuseum:id":51,"map_id":"3L","wof:name":"3L Terminal 3 Connector Arrival Level","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882481,"sfomuseum:id":25,"map_id":"F04","wof:name":"F-04 Gate 87a","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882485,"sfomuseum:id":37,"map_id":"3D","wof:name":"3D Terminal 3 Hub","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745887097,"sfomuseum:id":85,"map_id":"4D","wof:name":"4D International South Cases","edtf:inception":"2021-05-29","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745887101,"sfomuseum:id":93,"map_id":"HM04","wof:name":"HM04 Harvey Milk Temporary Wall 2","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882509,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745887111,"sfomuseum:id":55,"map_id":"AML 08","wof:name":"AML 08 Aviation Museum Perimeter 08","edtf:inception":"2021-05-25","edtf:cessation":"..","mz:is_current":0},{"wof:id":1745882495,"sfomuseum:id":68,"map_id":"3K","wof:name":"3K Aviation Photographs","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1729837315,"sfomuseum:id":71,"map_id":"1E","wof:name":"1E Mid-Pier Gallery","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1763594985,"sfomuseum:id":83,"map_id":"2E","wof:name":"2E Kadish Gallery","edtf:inception":"","edtf:cessation":"","mz:is_current":1},{"wof:id":1745882499,"sfomuseum:id":59,"map_id":"A07","wof:name":"A-07 International Central Case","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1763595133,"sfomuseum:id":64,"map_id":"3A","wof:name":"E-05 E Plaza Meet and Greet","edtf:inception":"2021-10","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1763601211,"sfomuseum:id":41,"map_id":"K04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1763588491,"sfomuseum:id":80,"map_id":"2D","wof:name":"2D Sky Terrace Platform","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588485,"sfomuseum:id":66,"map_id":"D13","wof:name":"D-13 Kids’ Spot","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588501,"sfomuseum:id":77,"map_id":"1D","wof:name":"1D Alley Gallery","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588489,"sfomuseum:id":67,"map_id":"2B","wof:name":"2B Kids’ Spot","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588513,"sfomuseum:id":40,"map_id":"1J","wof:name":"1J Terminal One Lower Gallery","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588531,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588533,"sfomuseum:id":60,"map_id":"3J","wof:name":"3J Photographs","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588539,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588551,"sfomuseum:id":85,"map_id":"4D","wof:name":"4D International South Cases","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1}] +[{"wof:id":1477855933,"sfomuseum:id":59,"map_id":"A07","wof:name":"A-07 International Central Case","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855943,"sfomuseum:id":42,"map_id":"K06","wof:name":"AML Aviation Museum Gallery 06a-e","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855951,"sfomuseum:id":29,"map_id":"","wof:name":"K-03 Aviation Museum Gallery 03","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855945,"sfomuseum:id":62,"map_id":"K04","wof:name":"AML Aviation Museum Gallery 04","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855955,"sfomuseum:id":31,"map_id":"K05","wof:name":"AML Aviation Museum Gallery 05a-d","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855947,"sfomuseum:id":28,"map_id":"AML 02","wof:name":"AML 02 Aviation Museum Gallery 02","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855957,"sfomuseum:id":70,"map_id":"G03","wof:name":"G-03 Video Arts Gallery","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855929,"sfomuseum:id":18,"map_id":"A01","wof:name":"A-01 International South Wall","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855949,"sfomuseum:id":27,"map_id":"K01","wof:name":"AML Aviation Museum Gallery 01","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855959,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1360541625,"sfomuseum:id":38,"map_id":"AML 07","wof:name":"AML 07 Aviation Museum Ceiling 07","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541633,"sfomuseum:id":31,"map_id":"AML 05","wof:name":"AML 05 Aviation Museum Gallery 05a-d","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541643,"sfomuseum:id":29,"map_id":"","wof:name":"K-03 Aviation Museum Gallery 03","edtf:inception":"2006~","edtf:cessation":"2010-01-29","mz:is_current":0},{"wof:id":1360541627,"sfomuseum:id":38,"map_id":"K07","wof:name":"AML Aviation Museum Ceiling 07","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541639,"sfomuseum:id":31,"map_id":"K05","wof:name":"AML Aviation Museum Gallery 05a-d","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541645,"sfomuseum:id":29,"map_id":"K03","wof:name":"AML Aviation Museum Gallery 03","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541629,"sfomuseum:id":38,"map_id":"K07","wof:name":"AML Aviation Museum Ceiling 07","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541647,"sfomuseum:id":29,"map_id":"K03","wof:name":"AML Aviation Museum Gallery 03","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541649,"sfomuseum:id":29,"map_id":"K03","wof:name":"AML Aviation Museum Gallery 03","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1729792765,"sfomuseum:id":66,"map_id":"D13","wof:name":"2C Kids’ Spot","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792775,"sfomuseum:id":25,"map_id":"F04","wof:name":"3F Gate 87a","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792769,"sfomuseum:id":58,"map_id":"D12","wof:name":"2A Boomerang Gallery","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792779,"sfomuseum:id":37,"map_id":"3D","wof:name":"3D Terminal 3 Hub","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792781,"sfomuseum:id":65,"map_id":"E06","wof:name":"E-06 Kid’s Spot Boarding Area E","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792795,"sfomuseum:id":20,"map_id":"","wof:name":"G-02 International North Cases","edtf:inception":"2020-~05","edtf:cessation":"2020-02-02","mz:is_current":0},{"wof:id":1729792785,"sfomuseum:id":18,"map_id":"A01","wof:name":"4C International South Wall","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1360541651,"sfomuseum:id":28,"map_id":"K02","wof:name":"AML Aviation Museum Gallery 02","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1729792787,"sfomuseum:id":19,"map_id":"G01","wof:name":"4B International North Wall","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1360541665,"sfomuseum:id":27,"map_id":"K01","wof:name":"AML Aviation Museum Gallery 01","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541653,"sfomuseum:id":28,"map_id":"K02","wof:name":"AML Aviation Museum Gallery 02","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541671,"sfomuseum:id":42,"map_id":"AML 06","wof:name":"AML 06 Aviation Museum Gallery 06a-e","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1729792789,"sfomuseum:id":59,"map_id":"","wof:name":"A-07 International Central Vitrine","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1360541667,"sfomuseum:id":27,"map_id":"K01","wof:name":"AML Aviation Museum Gallery 01","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360541657,"sfomuseum:id":28,"map_id":"K02","wof:name":"AML Aviation Museum Gallery 02","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541675,"sfomuseum:id":42,"map_id":"K06","wof:name":"AML Aviation Museum Gallery 06a-e","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541683,"sfomuseum:id":62,"map_id":"AML 04","wof:name":"AML 04 Aviation Museum Gallery 04","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541693,"sfomuseum:id":55,"map_id":"K08","wof:name":"AML Aviation Museum Perimeter 08","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541659,"sfomuseum:id":28,"map_id":"K02","wof:name":"AML Aviation Museum Gallery 02","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360541677,"sfomuseum:id":42,"map_id":"K06","wof:name":"AML Aviation Museum Gallery 06a-e","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360541695,"sfomuseum:id":55,"map_id":"K08","wof:name":"AML Aviation Museum Perimeter 08","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360541685,"sfomuseum:id":62,"map_id":"K04","wof:name":"AML Aviation Museum Gallery 04","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360541701,"sfomuseum:id":41,"map_id":"K04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541699,"sfomuseum:id":41,"map_id":"AML 04B","wof:name":"AML 04B Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541703,"sfomuseum:id":41,"map_id":"K04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360541687,"sfomuseum:id":55,"map_id":"K08","wof:name":"AML Aviation Museum Perimeter 08","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541689,"sfomuseum:id":55,"map_id":"K08","wof:name":"AML Aviation Museum Perimeter 08","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1746403233,"sfomuseum:id":86,"map_id":"4A","wof:name":"4A International North Cases","edtf:inception":"","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882453,"sfomuseum:id":66,"map_id":"D13","wof:name":"D-13 Kids’ Spot","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882463,"sfomuseum:id":77,"map_id":"1D","wof:name":"1D Alley Gallery","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882455,"sfomuseum:id":67,"map_id":"2B","wof:name":"2B Kids’ Spot","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882465,"sfomuseum:id":72,"map_id":"HM02","wof:name":"HM02 Harvey Milk Temporary Wall Gallery","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882467,"sfomuseum:id":74,"map_id":"HM01","wof:name":"HM01 Central Photo Wall","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882457,"sfomuseum:id":58,"map_id":"D12","wof:name":"D-12 Wall Case","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882471,"sfomuseum:id":79,"map_id":"1A","wof:name":"1A Student Art South","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882483,"sfomuseum:id":3,"map_id":"3E","wof:name":"3E Gate 76","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882459,"sfomuseum:id":80,"map_id":"2D","wof:name":"2D Sky Terrace Platform","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882473,"sfomuseum:id":71,"map_id":"1E","wof:name":"1E Mid-Pier Gallery","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882485,"sfomuseum:id":37,"map_id":"3D","wof:name":"3D Terminal 3 Hub","edtf:inception":"2021-05-25","edtf:cessation":"2021-04-18","mz:is_current":0},{"wof:id":1745882475,"sfomuseum:id":40,"map_id":"1J","wof:name":"1J Terminal One Lower Gallery","edtf:inception":"2021-05-25","edtf:cessation":"2021-06-21","mz:is_current":0},{"wof:id":1745882491,"sfomuseum:id":51,"map_id":"3L","wof:name":"3L Terminal 3 Connector Arrival Level","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882489,"sfomuseum:id":65,"map_id":"E06","wof:name":"3B Kid’s Spot Boarding Area E","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882477,"sfomuseum:id":63,"map_id":"1K","wof:name":"1K Entrance Lobby C Meet and Greet","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882501,"sfomuseum:id":18,"map_id":"A01","wof:name":"A-01 International South Wall","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882479,"sfomuseum:id":2,"map_id":"F02","wof:name":"3C North Connector","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882503,"sfomuseum:id":19,"map_id":"G01","wof:name":"G-01 International North Wall","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882495,"sfomuseum:id":68,"map_id":"F12","wof:name":"3K Aviation Photographs","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882507,"sfomuseum:id":70,"map_id":"G05","wof:name":"4E Video Arts Gallery","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882497,"sfomuseum:id":60,"map_id":"3J","wof:name":"3J Photographs","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882509,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882499,"sfomuseum:id":59,"map_id":"A07","wof:name":"A-07 International Central Case","edtf:inception":"2021-05-25","edtf:cessation":"2021-03-15","mz:is_current":0},{"wof:id":1763594989,"sfomuseum:id":90,"map_id":"2F","wof:name":"2F Pre-Security Connector/Zuber","edtf:inception":"","edtf:cessation":"","mz:is_current":1},{"wof:id":1763595133,"sfomuseum:id":64,"map_id":"3A","wof:name":"E-05 E Plaza Meet and Greet","edtf:inception":"2021-10","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1763595187,"sfomuseum:id":41,"map_id":"AML 04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763595139,"sfomuseum:id":64,"map_id":"3A","wof:name":"3A E Plaza Meet and Greet","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763601211,"sfomuseum:id":41,"map_id":"K04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1763601213,"sfomuseum:id":41,"map_id":"K04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1763588495,"sfomuseum:id":81,"map_id":"2D","wof:name":"2D Sky Terrace Wall","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588485,"sfomuseum:id":66,"map_id":"2C","wof:name":"D-13 Kids’ Spot","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588503,"sfomuseum:id":79,"map_id":"1A","wof:name":"1A Student Art South","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588487,"sfomuseum:id":58,"map_id":"2A","wof:name":"D-12 Wall Case","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588505,"sfomuseum:id":71,"map_id":"1E","wof:name":"1E Mid-Pier Gallery","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588489,"sfomuseum:id":67,"map_id":"2B","wof:name":"2B Kids’ Spot","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588509,"sfomuseum:id":93,"map_id":"HM04","wof:name":"HM04 Harvey Milk Temporary Wall 2","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588513,"sfomuseum:id":40,"map_id":"1J","wof:name":"1J Terminal One Lower Gallery","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":0},{"wof:id":1763588525,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":0},{"wof:id":1763588515,"sfomuseum:id":63,"map_id":"C04","wof:name":"1K Entrance Lobby C Meet and Greet","edtf:inception":"2021-11-09","edtf:cessation":"2022-09-07","mz:is_current":0},{"wof:id":1763588531,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":0},{"wof:id":1763588499,"sfomuseum:id":74,"map_id":"HM01","wof:name":"HM01 Central Photo Wall","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588527,"sfomuseum:id":65,"map_id":"3B","wof:name":"E-06 Kid’s Spot Boarding Area E","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588517,"sfomuseum:id":91,"map_id":"1F","wof:name":"1F Kids’ Spot/Tree Town","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588533,"sfomuseum:id":60,"map_id":"3J","wof:name":"3J Photographs","edtf:inception":"2021-11-09","edtf:cessation":"2022-01-17","mz:is_current":0},{"wof:id":1763588553,"sfomuseum:id":86,"map_id":"4A","wof:name":"4A International North Cases","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588543,"sfomuseum:id":18,"map_id":"4C","wof:name":"A-01 International South Wall","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588519,"sfomuseum:id":2,"map_id":"3C","wof:name":"3C North Connector","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588535,"sfomuseum:id":68,"map_id":"3K","wof:name":"3K Aviation Photographs","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588545,"sfomuseum:id":19,"map_id":"4B","wof:name":"G-01 International North Wall","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588537,"sfomuseum:id":51,"map_id":"3L","wof:name":"3L Terminal 3 Connector Arrival Level","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588549,"sfomuseum:id":70,"map_id":"4E","wof:name":"4E Video Arts Gallery","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588539,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":0},{"wof:id":1360392583,"sfomuseum:id":25,"map_id":"3F","wof:name":"3F Gate 87a","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360392591,"sfomuseum:id":25,"map_id":"F04","wof:name":"F-04 Gate 87a","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360392593,"sfomuseum:id":25,"map_id":"F04","wof:name":"F-04 Gate 87a","edtf:inception":"1987~","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1360392585,"sfomuseum:id":25,"map_id":"3F","wof:name":"3F Gate 87a","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360392587,"sfomuseum:id":25,"map_id":"F04","wof:name":"F-04 Gate 87a","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516117,"sfomuseum:id":65,"map_id":"E06","wof:name":"E-06 Kid’s Spot Boarding Area E","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516119,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360392589,"sfomuseum:id":25,"map_id":"F04","wof:name":"F-04 Gate 87a","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360521553,"sfomuseum:id":6,"map_id":"","wof:name":"D-01 Central North Connector","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360521555,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360521557,"sfomuseum:id":10,"map_id":"","wof:name":"D-05 Central South Connector","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360521559,"sfomuseum:id":10,"map_id":"D05","wof:name":"D-05 Central South Connector","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516121,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516123,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516125,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516127,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516129,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"1983~","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1360516133,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"1981-01-01","edtf:cessation":"1983~","mz:is_current":0},{"wof:id":1360516135,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"1981~","edtf:cessation":"1981~","mz:is_current":0},{"wof:id":1360516137,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516139,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516143,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516145,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516147,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"1985~","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1360516161,"sfomuseum:id":60,"map_id":"F11","wof:name":"F-11 Photographs","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516141,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516163,"sfomuseum:id":60,"map_id":"F11","wof:name":"F-11 Photographs","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516165,"sfomuseum:id":60,"map_id":"F11","wof:name":"F-11 Photographs","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516169,"sfomuseum:id":60,"map_id":"F11","wof:name":"F-11 Photographs","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516171,"sfomuseum:id":60,"map_id":"F11","wof:name":"F-11 Photographs","edtf:inception":"1991-06-01","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516173,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516175,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516177,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516179,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2002-04-07","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1159157037,"sfomuseum:id":20,"map_id":"","wof:name":"G-02 International North Cases","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157039,"sfomuseum:id":17,"map_id":"","wof:name":"A-02 International South Cases","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360516181,"sfomuseum:id":18,"map_id":"A01","wof:name":"A-01 International South Wall","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516183,"sfomuseum:id":18,"map_id":"A01","wof:name":"A-01 International South Wall","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516189,"sfomuseum:id":18,"map_id":"A01","wof:name":"A-01 International South Wall","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516151,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516153,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516155,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516157,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516159,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"1991~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157041,"sfomuseum:id":59,"map_id":"","wof:name":"A-07 International Central Vitrine","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157045,"sfomuseum:id":19,"map_id":"4B","wof:name":"4B International North Wall","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157047,"sfomuseum:id":18,"map_id":"4C","wof:name":"4C International South Wall","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157049,"sfomuseum:id":51,"map_id":"3L","wof:name":"3L Terminal 3 Connector Arrival Level","edtf:inception":"2017~","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1360516191,"sfomuseum:id":19,"map_id":"G01","wof:name":"G-01 International North Wall","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516193,"sfomuseum:id":19,"map_id":"G01","wof:name":"G-01 International North Wall","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516195,"sfomuseum:id":19,"map_id":"G01","wof:name":"G-01 International North Wall","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516187,"sfomuseum:id":18,"map_id":"A01","wof:name":"A-01 International South Wall","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516197,"sfomuseum:id":19,"map_id":"G01","wof:name":"G-01 International North Wall","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516199,"sfomuseum:id":59,"map_id":"A07","wof:name":"A-07 International Central Case","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1159157051,"sfomuseum:id":60,"map_id":"3J","wof:name":"3J Photographs","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157053,"sfomuseum:id":2,"map_id":"3C","wof:name":"3C North Connector","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157055,"sfomuseum:id":37,"map_id":"3D","wof:name":"3D Terminal 3 Hub","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157057,"sfomuseum:id":3,"map_id":"3E","wof:name":"3E Gate 76","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157059,"sfomuseum:id":25,"map_id":"3F","wof:name":"3F Gate 87a","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360516201,"sfomuseum:id":59,"map_id":"A07","wof:name":"A-07 International Central Case","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1159157063,"sfomuseum:id":64,"map_id":"3A","wof:name":"3A E Plaza Meet and Greet","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360516205,"sfomuseum:id":59,"map_id":"A07","wof:name":"A-07 International Central Case","edtf:inception":"2010~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1159157065,"sfomuseum:id":6,"map_id":"","wof:name":"D-01 Central North Connector","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360516207,"sfomuseum:id":63,"map_id":"C04","wof:name":"C-04 Entrance Lobby C Meet and Greet","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1159157067,"sfomuseum:id":58,"map_id":"2A","wof:name":"2A Boomerang Gallery","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360516209,"sfomuseum:id":63,"map_id":"C04","wof:name":"C-04 Entrance Lobby C Meet and Greet","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516213,"sfomuseum:id":63,"map_id":"C04","wof:name":"C-04 Entrance Lobby C Meet and Greet","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1159157069,"sfomuseum:id":67,"map_id":"2B","wof:name":"2B Kids’ Spot","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360516211,"sfomuseum:id":63,"map_id":"1K","wof:name":"1K Entrance Lobby C Meet and Greet","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516215,"sfomuseum:id":63,"map_id":"C04","wof:name":"C-04 Entrance Lobby C Meet and Greet","edtf:inception":"1996~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516217,"sfomuseum:id":16,"map_id":"","wof:name":"B-03 Gate 36","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516219,"sfomuseum:id":16,"map_id":"B03","wof:name":"B-03 Gate 36","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1159157071,"sfomuseum:id":66,"map_id":"2C","wof:name":"2C Kids’ Spot","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157073,"sfomuseum:id":63,"map_id":"1K","wof:name":"1K Entrance Lobby C Meet and Greet","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157075,"sfomuseum:id":40,"map_id":"1J","wof:name":"1J Terminal One Lower Gallery","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157077,"sfomuseum:id":16,"map_id":"","wof:name":"B-03 Gate 36","edtf:inception":"2017~","edtf:cessation":"2019-07-22","mz:is_current":0},{"wof:id":1360516223,"sfomuseum:id":16,"map_id":"","wof:name":"B-03 Gate 36","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516225,"sfomuseum:id":16,"map_id":"B03","wof:name":"B-03 Gate 36","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516227,"sfomuseum:id":16,"map_id":"B03","wof:name":"B-03 Gate 36","edtf:inception":"1990~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516229,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516231,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1159157081,"sfomuseum:id":69,"map_id":"","wof:name":"B-06 Kids’ Spot","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360516233,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516237,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516243,"sfomuseum:id":66,"map_id":"D13","wof:name":"D-13 Kids’ Spot","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516235,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516241,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"1988~","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1360516245,"sfomuseum:id":66,"map_id":"D13","wof:name":"D-13 Kids’ Spot","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516247,"sfomuseum:id":69,"map_id":"","wof:name":"B-06 Kids’ Spot","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516249,"sfomuseum:id":64,"map_id":"3A","wof:name":"3A E Plaza Meet and Greet","edtf:inception":"2015~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516251,"sfomuseum:id":67,"map_id":"2B","wof:name":"2B Kids’ Spot","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516253,"sfomuseum:id":67,"map_id":"D14","wof:name":"D-14 Kids’ Spot","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516255,"sfomuseum:id":58,"map_id":"D12","wof:name":"D-12 Wall Case","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516259,"sfomuseum:id":58,"map_id":"D12","wof:name":"D-12 Wall Case","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516261,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516263,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516265,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516267,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"1983~","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1360516269,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"1983~","edtf:cessation":"1983~","mz:is_current":0},{"wof:id":1360516271,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516273,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516277,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516279,"sfomuseum:id":17,"map_id":"A02","wof:name":"A-02 International South Cases","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516281,"sfomuseum:id":20,"map_id":"G02","wof:name":"G-02 International North Cases","edtf:inception":"2014~","edtf:cessation":"2017~","mz:is_current":0},{"wof:id":1360516285,"sfomuseum:id":20,"map_id":"G02","wof:name":"G-02 International North Cases","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516287,"sfomuseum:id":20,"map_id":"G02","wof:name":"G-02 International North Cases","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516435,"sfomuseum:id":39,"map_id":"","wof:name":"A-05 Terminal One Lower Gallery","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516439,"sfomuseum:id":39,"map_id":"","wof:name":"A-05 Terminal One Lower Gallery","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516441,"sfomuseum:id":39,"map_id":"","wof:name":"A-05 Terminal One Lower Gallery","edtf:inception":"2014~","edtf:cessation":"2016-08-19","mz:is_current":0},{"wof:id":1360516443,"sfomuseum:id":13,"map_id":"","wof:name":"C-03 Entrance Lobby C","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516445,"sfomuseum:id":13,"map_id":"","wof:name":"C-03 Entrance Lobby C","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516447,"sfomuseum:id":13,"map_id":"C03","wof:name":"C-03 Entrance Lobby C","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516449,"sfomuseum:id":13,"map_id":"C03","wof:name":"C-03 Entrance Lobby C","edtf:inception":"2014~","edtf:cessation":"2016-03-31","mz:is_current":0},{"wof:id":1360516451,"sfomuseum:id":5,"map_id":"","wof:name":"E-02 Gate 62 Cultural Wall","edtf:inception":"1988~","edtf:cessation":"1997-03-21","mz:is_current":0},{"wof:id":1360516283,"sfomuseum:id":20,"map_id":"","wof:name":"G-02 International North Cases","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516453,"sfomuseum:id":24,"map_id":"","wof:name":"B-04 Entrance Lobby B","edtf:inception":"2000~","edtf:cessation":"2001-11-26","mz:is_current":0},{"wof:id":1360516457,"sfomuseum:id":23,"map_id":"","wof:name":"D-06 Kids’ Spot","edtf:inception":"2011~","edtf:cessation":"2011-12-01","mz:is_current":0},{"wof:id":1360516459,"sfomuseum:id":14,"map_id":"","wof:name":"B-01 Gate 20","edtf:inception":"2000~","edtf:cessation":"2001-06-15","mz:is_current":0},{"wof:id":1360516461,"sfomuseum:id":11,"map_id":"","wof:name":"C-01 Aquarium","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516463,"sfomuseum:id":11,"map_id":"C01","wof:name":"C-01 Aquarium","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516465,"sfomuseum:id":11,"map_id":"C01","wof:name":"C-01 Aquarium","edtf:inception":"2011~","edtf:cessation":"2013-10-31","mz:is_current":0},{"wof:id":1360516467,"sfomuseum:id":10,"map_id":"","wof:name":"D-05 Central South Connector","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516469,"sfomuseum:id":10,"map_id":"D05","wof:name":"D-05 Central South Connector","edtf:inception":"2011~","edtf:cessation":"2012-04-30","mz:is_current":0},{"wof:id":1360516471,"sfomuseum:id":9,"map_id":"","wof:name":"D-04 Central Gallery","edtf:inception":"1988~","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1360516475,"sfomuseum:id":9,"map_id":"D04","wof:name":"D-04 Central Gallery","edtf:inception":"2011~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516477,"sfomuseum:id":34,"map_id":"","wof:name":"A-03 Entrance Lobby A","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360516479,"sfomuseum:id":34,"map_id":"A03","wof:name":"A-03 Entrance Lobby A","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360516481,"sfomuseum:id":34,"map_id":"","wof:name":"A-03 Entrance Lobby A","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360516483,"sfomuseum:id":34,"map_id":"A03","wof:name":"A-03 Entrance Lobby A","edtf:inception":"2014~","edtf:cessation":"2015-09-22","mz:is_current":0},{"wof:id":1360516493,"sfomuseum:id":45,"map_id":"","wof:name":"F-06 Gate 72","edtf:inception":"1988~","edtf:cessation":"1990-08-06","mz:is_current":0},{"wof:id":1360516495,"sfomuseum:id":50,"map_id":"","wof:name":"D-11 Central Wall (Duty Free)","edtf:inception":"1988~","edtf:cessation":"1998-02-01","mz:is_current":0},{"wof:id":1360516497,"sfomuseum:id":49,"map_id":"","wof:name":"D-10 Central Cases (Currency Exchange)","edtf:inception":"1988~","edtf:cessation":"1991-12-19","mz:is_current":0},{"wof:id":1360516499,"sfomuseum:id":8,"map_id":"","wof:name":"D-03 Central Concourse","edtf:inception":"1988~","edtf:cessation":"1996-12-30","mz:is_current":0},{"wof:id":1360516485,"sfomuseum:id":1,"map_id":"","wof:name":"F-01 Gate 68 Children’s Art Gallery","edtf:inception":"2000~","edtf:cessation":"2002-01-15","mz:is_current":0},{"wof:id":1360516487,"sfomuseum:id":48,"map_id":"","wof:name":"F-08 Gate 81","edtf:inception":"1988~","edtf:cessation":"1990-10-01","mz:is_current":0},{"wof:id":1360516489,"sfomuseum:id":46,"map_id":"","wof:name":"F-07 Gate 74","edtf:inception":"1988~","edtf:cessation":"1990-12-15","mz:is_current":0},{"wof:id":1360516501,"sfomuseum:id":8,"map_id":"","wof:name":"D-03 Central Concourse","edtf:inception":"2011~","edtf:cessation":"2013~","mz:is_current":0},{"wof:id":1360541553,"sfomuseum:id":4,"map_id":"","wof:name":"E-01 Children’s Art Gallery #2","edtf:inception":"1990-12-16","edtf:cessation":"1998-12-17","mz:is_current":0},{"wof:id":1360541555,"sfomuseum:id":26,"map_id":"","wof:name":"D-08 International Garage Passageway","edtf:inception":"1997-11-01","edtf:cessation":"1998-03-01","mz:is_current":0},{"wof:id":1360541557,"sfomuseum:id":27,"map_id":"K01","wof:name":"AML 01 AML Front Gallery","edtf:inception":"2000-11-20","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541559,"sfomuseum:id":28,"map_id":"AML 02","wof:name":"AML 02 Aviation Museum Gallery 02","edtf:inception":"2000-11-20","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541561,"sfomuseum:id":29,"map_id":"","wof:name":"K-03 Aviation Museum Gallery 03","edtf:inception":"2000-11-20","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541567,"sfomuseum:id":31,"map_id":"AML 05","wof:name":"AML 05 Aviation Museum Gallery 05a-d","edtf:inception":"2000-11-20","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541569,"sfomuseum:id":38,"map_id":"AML 07","wof:name":"AML 07 AML Ceiling","edtf:inception":"2000-11-22","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541563,"sfomuseum:id":30,"map_id":"","wof:name":"K-4A Aviation Museum Gallery 04a","edtf:inception":"2000-12-01","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541571,"sfomuseum:id":41,"map_id":"AML 04B","wof:name":"AML 04B Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2000-12-03","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541573,"sfomuseum:id":42,"map_id":"AML 06","wof:name":"AML 06 Aviation Museum Gallery 06a-e","edtf:inception":"2000-11-20","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541575,"sfomuseum:id":55,"map_id":"AML 08","wof:name":"AML 08 Aviation Museum Perimeter 08","edtf:inception":"2004-02-17","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1360541615,"sfomuseum:id":30,"map_id":"","wof:name":"K-4A Aviation Museum Gallery 04a","edtf:inception":"2006~","edtf:cessation":"2010-09-20","mz:is_current":0},{"wof:id":1360541577,"sfomuseum:id":62,"map_id":"AML 04","wof:name":"AML 04 Aviation Museum Gallery 04","edtf:inception":"2000~","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1159157865,"sfomuseum:id":9,"map_id":"","wof:name":"D-04 Central Gallery","edtf:inception":"1983-12-15","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157867,"sfomuseum:id":10,"map_id":"","wof:name":"D-05 Central South Connector","edtf:inception":"1983-07-13","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157869,"sfomuseum:id":12,"map_id":"","wof:name":"C-02 Gate 40 Gallery","edtf:inception":"1996-01-01","edtf:cessation":"1999-01-25","mz:is_current":0},{"wof:id":1159157873,"sfomuseum:id":13,"map_id":"","wof:name":"C-03 Entrance Lobby C","edtf:inception":"1988-08-01","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157875,"sfomuseum:id":24,"map_id":"","wof:name":"B-04 Entrance Lobby B","edtf:inception":"1997-01-29","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157879,"sfomuseum:id":5,"map_id":"","wof:name":"E-02 Gate 62 Cultural Wall","edtf:inception":"1985-05-29","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157877,"sfomuseum:id":15,"map_id":"","wof:name":"B-02 Gate 26","edtf:inception":"1988-07-01","edtf:cessation":"1998-10-31","mz:is_current":0},{"wof:id":1159157881,"sfomuseum:id":1,"map_id":"","wof:name":"F-01 Gate 68 Children’s Art Gallery","edtf:inception":"1988-07-01","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157883,"sfomuseum:id":34,"map_id":"","wof:name":"A-03 Entrance Lobby A","edtf:inception":"1990-09-01","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157887,"sfomuseum:id":21,"map_id":"","wof:name":"D-07 International Customs Area","edtf:inception":"1992-05-01","edtf:cessation":"1998-06-02","mz:is_current":0},{"wof:id":1159157885,"sfomuseum:id":7,"map_id":"","wof:name":"D-02 Central Fountain Gallery","edtf:inception":"1991-06-01","edtf:cessation":"1997-04-10","mz:is_current":0},{"wof:id":1159157891,"sfomuseum:id":11,"map_id":"","wof:name":"C-01 Aquarium","edtf:inception":"1995-11-13","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157893,"sfomuseum:id":23,"map_id":"","wof:name":"D-06 Kids’ Spot","edtf:inception":"1997-08-01","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157895,"sfomuseum:id":14,"map_id":"","wof:name":"B-01 Gate 20","edtf:inception":"1995-12-01","edtf:cessation":"2000~","mz:is_current":0},{"wof:id":1159157897,"sfomuseum:id":32,"map_id":"","wof:name":"E-03 Entrance Lobby E","edtf:inception":"1998-10-16","edtf:cessation":"1999-01-29","mz:is_current":0},{"wof:id":1159157905,"sfomuseum:id":43,"map_id":"","wof:name":"D-09 Central South","edtf:inception":"2001-12-10","edtf:cessation":"2002-09-25","mz:is_current":0},{"wof:id":1159157909,"sfomuseum:id":39,"map_id":"","wof:name":"A-05 Terminal One Lower Gallery","edtf:inception":"2000-07-15","edtf:cessation":"2006~","mz:is_current":0},{"wof:id":1159157915,"sfomuseum:id":49,"map_id":"","wof:name":"D-10 Central Cases (Currency Exchange)","edtf:inception":"1987-09-01","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157917,"sfomuseum:id":50,"map_id":"","wof:name":"D-11 Central Wall (Duty Free)","edtf:inception":"1987-09-01","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157911,"sfomuseum:id":8,"map_id":"","wof:name":"D-03 Central Concourse","edtf:inception":"1987-07-01","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157919,"sfomuseum:id":45,"map_id":"","wof:name":"F-06 Gate 72","edtf:inception":"1987-05-01","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157923,"sfomuseum:id":47,"map_id":"","wof:name":"A-06 Gate 08","edtf:inception":"1987-04-01","edtf:cessation":"1987-12-31","mz:is_current":0},{"wof:id":1159157921,"sfomuseum:id":46,"map_id":"","wof:name":"F-07 Gate 74","edtf:inception":"1987-05-01","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157927,"sfomuseum:id":48,"map_id":"","wof:name":"F-08 Gate 81","edtf:inception":"1987-09-01","edtf:cessation":"1988~","mz:is_current":0},{"wof:id":1159157931,"sfomuseum:id":53,"map_id":"","wof:name":"B-05 Boarding Lobby","edtf:inception":"2003-09-24","edtf:cessation":"2016-10-28","mz:is_current":0},{"wof:id":1159157929,"sfomuseum:id":44,"map_id":"","wof:name":"E-04 Gate 61 Cultural Wall","edtf:inception":"1988-01-01","edtf:cessation":"1998-06-30","mz:is_current":0},{"wof:id":1159157937,"sfomuseum:id":68,"map_id":"3K","wof:name":"3K Aviation Photographs","edtf:inception":"2017-04-06","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1159157939,"sfomuseum:id":70,"map_id":"G03","wof:name":"G-03 Video Arts Gallery","edtf:inception":"2017-09-07","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1729813681,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813677,"sfomuseum:id":63,"map_id":"1K","wof:name":"1K Entrance Lobby C Meet and Greet","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1729813683,"sfomuseum:id":60,"map_id":"3J","wof:name":"3J Photographs","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813679,"sfomuseum:id":68,"map_id":"3K","wof:name":"3K Aviation Photographs","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813685,"sfomuseum:id":41,"map_id":"K04B","wof:name":"AML 04B AML Special Collections Room","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813687,"sfomuseum:id":71,"map_id":"B12","wof:name":"1E Mid-Pier Gallery","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1729813691,"sfomuseum:id":72,"map_id":"HM02","wof:name":"HM02 Harvey Milk Temporary Wall Gallery","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1729813693,"sfomuseum:id":74,"map_id":"B08","wof:name":"HM01 Central Photo Wall","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813695,"sfomuseum:id":77,"map_id":"B11","wof:name":"1D Alley Gallery","edtf:inception":"2021~","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813697,"sfomuseum:id":79,"map_id":"B14","wof:name":"1A Student Art South","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813701,"sfomuseum:id":81,"map_id":"2D","wof:name":"2D Sky Terrace Wall","edtf:inception":"2020~","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813699,"sfomuseum:id":80,"map_id":"D15","wof:name":"2D Sky Terrace Platform","edtf:inception":"2020~","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813731,"sfomuseum:id":38,"map_id":"K07","wof:name":"AML Aviation Museum Ceiling 07","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":0},{"wof:id":1729813733,"sfomuseum:id":55,"map_id":"K08","wof:name":"AML 08 AML Perimeter","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729813737,"sfomuseum:id":62,"map_id":"AML 04","wof:name":"AML 04 AML South Interior","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":1},{"wof:id":1729813735,"sfomuseum:id":42,"map_id":"AML 06","wof:name":"AML 06 AML Photography","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":1},{"wof:id":1729813739,"sfomuseum:id":28,"map_id":"AML 02","wof:name":"AML 02 AML Back Gallery","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":1},{"wof:id":1729813741,"sfomuseum:id":27,"map_id":"AML","wof:name":"AML Aviation Museum Gallery 01","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":1},{"wof:id":1729813745,"sfomuseum:id":31,"map_id":"AML 05","wof:name":"AML 05 AML Book Show","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":1},{"wof:id":1729813747,"sfomuseum:id":29,"map_id":"K03","wof:name":"AML 03 AML North Interior","edtf:inception":"2020-~05","edtf:cessation":"..","mz:is_current":0},{"wof:id":1729837315,"sfomuseum:id":71,"map_id":"1E","wof:name":"1E Mid-Pier Gallery","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729837317,"sfomuseum:id":72,"map_id":"HM02","wof:name":"HM02 Harvey Milk Temporary Wall Gallery","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729837321,"sfomuseum:id":63,"map_id":"C04","wof:name":"C-04 Entrance Lobby C Meet and Greet","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729837319,"sfomuseum:id":40,"map_id":"1J","wof:name":"1J Terminal One Lower Gallery","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1477855625,"sfomuseum:id":67,"map_id":"D14","wof:name":"D-14 Kids’ Spot","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855627,"sfomuseum:id":58,"map_id":"D12","wof:name":"D-12 Wall Case","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855653,"sfomuseum:id":6,"map_id":"D01","wof:name":"D-01 Central North Connector","edtf:inception":"2019-07-23","edtf:cessation":"2019-10-28","mz:is_current":0},{"wof:id":1477855613,"sfomuseum:id":66,"map_id":"D13","wof:name":"D-13 Kids’ Spot","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855661,"sfomuseum:id":63,"map_id":"C04","wof:name":"C-04 Entrance Lobby C Meet and Greet","edtf:inception":"2015-01-20","edtf:cessation":"","mz:is_current":0},{"wof:id":1477855663,"sfomuseum:id":40,"map_id":"C05","wof:name":"C-05 Terminal One Lower Gallery","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855725,"sfomuseum:id":2,"map_id":"F02","wof:name":"F-02 North Connector","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855731,"sfomuseum:id":37,"map_id":"F05","wof:name":"F-05 Terminal 3 Hub","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855727,"sfomuseum:id":25,"map_id":"F04","wof:name":"F-04 Gate 87a","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855729,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855787,"sfomuseum:id":65,"map_id":"E06","wof:name":"E-06 Kid’s Spot Boarding Area E","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855821,"sfomuseum:id":60,"map_id":"F11","wof:name":"F-11 Photographs","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855823,"sfomuseum:id":51,"map_id":"F09","wof:name":"F-09 Terminal 3 Connector Arrival Level","edtf:inception":"2002-04-07","edtf:cessation":"","mz:is_current":0},{"wof:id":1477855825,"sfomuseum:id":64,"map_id":"E05","wof:name":"E-05 E Plaza Meet and Greet","edtf:inception":"2019-07-23","edtf:cessation":"2019-10-17","mz:is_current":0},{"wof:id":1477855831,"sfomuseum:id":68,"map_id":"F12","wof:name":"F-12 Aviation Photographs","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855931,"sfomuseum:id":19,"map_id":"G01","wof:name":"G-01 International North Wall","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855939,"sfomuseum:id":38,"map_id":"AML 07","wof:name":"AML 07 Aviation Museum Ceiling 07","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855941,"sfomuseum:id":55,"map_id":"K08","wof:name":"AML Aviation Museum Perimeter 08","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1477855961,"sfomuseum:id":20,"map_id":"G02","wof:name":"G-02 International North Cases","edtf:inception":"2019-07-23","edtf:cessation":"2020-~05","mz:is_current":0},{"wof:id":1360541631,"sfomuseum:id":38,"map_id":"AML 07","wof:name":"AML 07 Aviation Museum Ceiling 07","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360541641,"sfomuseum:id":31,"map_id":"K05","wof:name":"AML Aviation Museum Gallery 05a-d","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0},{"wof:id":1360541635,"sfomuseum:id":31,"map_id":"AML 05","wof:name":"AML 05 Aviation Museum Gallery 05a-d","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1729792767,"sfomuseum:id":67,"map_id":"D14","wof:name":"2B Kids’ Spot","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792771,"sfomuseum:id":2,"map_id":"3C","wof:name":"3C North Connector","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792793,"sfomuseum:id":70,"map_id":"4E","wof:name":"4E Video Arts Gallery","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792777,"sfomuseum:id":3,"map_id":"3E","wof:name":"3E Gate 76","edtf:inception":"2020-~05","edtf:cessation":"2021-05-25","mz:is_current":0},{"wof:id":1729792783,"sfomuseum:id":17,"map_id":"","wof:name":"A-02 International South Cases","edtf:inception":"2020-~05","edtf:cessation":"2020-01-13","mz:is_current":0},{"wof:id":1360541661,"sfomuseum:id":27,"map_id":"AML 01","wof:name":"AML 01 Aviation Museum Gallery 01","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541663,"sfomuseum:id":27,"map_id":"K01","wof:name":"AML Aviation Museum Gallery 01","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541669,"sfomuseum:id":42,"map_id":"AML 06","wof:name":"AML 06 Aviation Museum Gallery 06a-e","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541681,"sfomuseum:id":62,"map_id":"K04","wof:name":"AML Aviation Museum Gallery 04","edtf:inception":"2011~","edtf:cessation":"2014~","mz:is_current":0},{"wof:id":1360541679,"sfomuseum:id":62,"map_id":"AML 04","wof:name":"AML 04 Aviation Museum Gallery 04","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1360541697,"sfomuseum:id":41,"map_id":"K04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2006~","edtf:cessation":"2011~","mz:is_current":0},{"wof:id":1745882461,"sfomuseum:id":81,"map_id":"2D","wof:name":"2D Sky Terrace Wall","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882481,"sfomuseum:id":25,"map_id":"F04","wof:name":"F-04 Gate 87a","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745882493,"sfomuseum:id":51,"map_id":"F09","wof:name":"3L Terminal 3 Connector Arrival Level","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745885813,"sfomuseum:id":91,"map_id":"B17","wof:name":"1F Kids’ Spot/Tree Town","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745887097,"sfomuseum:id":85,"map_id":"A08","wof:name":"4D International South Cases","edtf:inception":"2021-05-29","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745887099,"sfomuseum:id":92,"map_id":"B18","wof:name":"1C Kids’ Spot","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1745887101,"sfomuseum:id":93,"map_id":"B15","wof:name":"HM04 Harvey Milk Temporary Wall 2","edtf:inception":"2021-05-25","edtf:cessation":"2021-04-09","mz:is_current":0},{"wof:id":1745887111,"sfomuseum:id":55,"map_id":"AML 08","wof:name":"AML 08 Aviation Museum Perimeter 08","edtf:inception":"2021-05-25","edtf:cessation":"..","mz:is_current":0},{"wof:id":1763594985,"sfomuseum:id":83,"map_id":"2E","wof:name":"2E Kadish Gallery","edtf:inception":"","edtf:cessation":"","mz:is_current":1},{"wof:id":1763594987,"sfomuseum:id":84,"map_id":"HM03","wof:name":"HM03 Sterile Connector","edtf:inception":"","edtf:cessation":"","mz:is_current":1},{"wof:id":1763595185,"sfomuseum:id":41,"map_id":"K04B","wof:name":"AML Aviation Museum Gallery 04b Special Collections Room","edtf:inception":"2021-05-25","edtf:cessation":"2021-11-09","mz:is_current":0},{"wof:id":1763588491,"sfomuseum:id":80,"map_id":"2D","wof:name":"2D Sky Terrace Platform","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588501,"sfomuseum:id":77,"map_id":"1D","wof:name":"1D Alley Gallery","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588497,"sfomuseum:id":72,"map_id":"HM02","wof:name":"HM02 Harvey Milk Temporary Wall Gallery","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":0},{"wof:id":1763588507,"sfomuseum:id":92,"map_id":"1C","wof:name":"1C Kids’ Spot","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588523,"sfomuseum:id":3,"map_id":"F03","wof:name":"F-03 Gate 76","edtf:inception":"2021-11-09","edtf:cessation":"2022-05-08","mz:is_current":0},{"wof:id":1763588521,"sfomuseum:id":25,"map_id":"3F","wof:name":"F-04 Gate 87a","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1763588541,"sfomuseum:id":59,"map_id":"A07","wof:name":"A-07 International Central Case","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":0},{"wof:id":1763588551,"sfomuseum:id":85,"map_id":"4D","wof:name":"4D International South Cases","edtf:inception":"2021-11-09","edtf:cessation":"..","mz:is_current":1},{"wof:id":1796989589,"sfomuseum:id":82,"map_id":"AML 09","wof:name":"AML 09 AML New Corner Gallery","edtf:inception":"","edtf:cessation":"","mz:is_current":1},{"wof:id":1175727175,"sfomuseum:id":65,"map_id":"3B","wof:name":"3B Kid’s Spot Boarding Area E","edtf:inception":"2017~","edtf:cessation":"2019-07-23","mz:is_current":0}] diff --git a/data/gates.json b/data/gates.json index 3d280a5..c0559ed 100644 --- a/data/gates.json +++ b/data/gates.json @@ -1 +1 @@ -[{"wof:id":1477855891,"wof:name":"G101A","mz:is_current":0},{"wof:id":1477855889,"wof:name":"G95","mz:is_current":0},{"wof:id":1729792673,"wof:name":"G12","mz:is_current":0},{"wof:id":1477855895,"wof:name":"G101","mz:is_current":0},{"wof:id":1729792675,"wof:name":"G13","mz:is_current":0},{"wof:id":1477855897,"wof:name":"G96","mz:is_current":0},{"wof:id":1729792677,"wof:name":"G14","mz:is_current":0},{"wof:id":1477855901,"wof:name":"G97","mz:is_current":0},{"wof:id":1477855903,"wof:name":"G98","mz:is_current":0},{"wof:id":1477855905,"wof:name":"G100","mz:is_current":0},{"wof:id":1477855907,"wof:name":"G99B","mz:is_current":0},{"wof:id":1477855913,"wof:name":"G93","mz:is_current":0},{"wof:id":1477855921,"wof:name":"G99A","mz:is_current":0},{"wof:id":1477855919,"wof:name":"G99","mz:is_current":0},{"wof:id":1477855923,"wof:name":"G102","mz:is_current":0},{"wof:id":1729792733,"wof:name":"B26","mz:is_current":0},{"wof:id":1729792735,"wof:name":"B1","mz:is_current":0},{"wof:id":1729792723,"wof:name":"B10","mz:is_current":0},{"wof:id":1729792725,"wof:name":"B25","mz:is_current":0},{"wof:id":1729792741,"wof:name":"B21","mz:is_current":0},{"wof:id":1729792727,"wof:name":"B11","mz:is_current":0},{"wof:id":1729792743,"wof:name":"B19","mz:is_current":0},{"wof:id":1729792751,"wof:name":"B23","mz:is_current":0},{"wof:id":1729792745,"wof:name":"B20","mz:is_current":0},{"wof:id":1729792753,"wof:name":"B16","mz:is_current":0},{"wof:id":1729792747,"wof:name":"B5","mz:is_current":0},{"wof:id":1729792763,"wof:name":"B27","mz:is_current":0},{"wof:id":1729792757,"wof:name":"B2","mz:is_current":0},{"wof:id":1729792749,"wof:name":"B4","mz:is_current":0},{"wof:id":1477881723,"wof:name":"B8","mz:is_current":0},{"wof:id":1477881735,"wof:name":"B17","mz:is_current":0},{"wof:id":1477881725,"wof:name":"B9","mz:is_current":0},{"wof:id":1477881737,"wof:name":"B18","mz:is_current":0},{"wof:id":1477921767,"wof:name":"D59B","mz:is_current":0},{"wof:id":1477930281,"wof:name":"A1","mz:is_current":0},{"wof:id":1477930283,"wof:name":"A2","mz:is_current":0},{"wof:id":1477930297,"wof:name":"A7","mz:is_current":0},{"wof:id":1477930301,"wof:name":"A9","mz:is_current":0},{"wof:id":1477930313,"wof:name":"A14","mz:is_current":0},{"wof:id":1477930299,"wof:name":"A8","mz:is_current":0},{"wof:id":1477930303,"wof:name":"A10","mz:is_current":0},{"wof:id":1477930287,"wof:name":"A3","mz:is_current":0},{"wof:id":1477930315,"wof:name":"A15","mz:is_current":0},{"wof:id":1477930323,"wof:name":"C5","mz:is_current":0},{"wof:id":1477930305,"wof:name":"A11","mz:is_current":0},{"wof:id":1477930289,"wof:name":"A4","mz:is_current":0},{"wof:id":1477930317,"wof:name":"C2","mz:is_current":0},{"wof:id":1477930325,"wof:name":"C6","mz:is_current":0},{"wof:id":1477930307,"wof:name":"A12","mz:is_current":0},{"wof:id":1477930333,"wof:name":"C9","mz:is_current":0},{"wof:id":1477930319,"wof:name":"C3","mz:is_current":0},{"wof:id":1477930327,"wof:name":"C7","mz:is_current":0},{"wof:id":1477930309,"wof:name":"A13","mz:is_current":0},{"wof:id":1477930335,"wof:name":"C10","mz:is_current":0},{"wof:id":1477930363,"wof:name":"D12","mz:is_current":0},{"wof:id":1477930345,"wof:name":"D4","mz:is_current":0},{"wof:id":1477930351,"wof:name":"D6","mz:is_current":0},{"wof:id":1477930337,"wof:name":"C11","mz:is_current":0},{"wof:id":1477930367,"wof:name":"D14","mz:is_current":0},{"wof:id":1477930349,"wof:name":"D5","mz:is_current":0},{"wof:id":1477930339,"wof:name":"D1","mz:is_current":0},{"wof:id":1477930353,"wof:name":"D7","mz:is_current":0},{"wof:id":1477930369,"wof:name":"D15","mz:is_current":0},{"wof:id":1477930373,"wof:name":"D17","mz:is_current":0},{"wof:id":1477930357,"wof:name":"D9","mz:is_current":0},{"wof:id":1477930381,"wof:name":"E3","mz:is_current":0},{"wof:id":1477930377,"wof:name":"E1","mz:is_current":0},{"wof:id":1477930359,"wof:name":"D10","mz:is_current":0},{"wof:id":1477930391,"wof:name":"E7","mz:is_current":0},{"wof:id":1477930385,"wof:name":"E4","mz:is_current":0},{"wof:id":1477930387,"wof:name":"E5","mz:is_current":0},{"wof:id":1477930403,"wof:name":"E12","mz:is_current":0},{"wof:id":1477930395,"wof:name":"E9","mz:is_current":0},{"wof:id":1477930397,"wof:name":"E10","mz:is_current":0},{"wof:id":1477930389,"wof:name":"E6","mz:is_current":0},{"wof:id":1477930407,"wof:name":"F1","mz:is_current":0},{"wof:id":1477930411,"wof:name":"F3","mz:is_current":0},{"wof:id":1477930409,"wof:name":"F2","mz:is_current":0},{"wof:id":1477930413,"wof:name":"F3A","mz:is_current":0},{"wof:id":1477930421,"wof:name":"F5","mz:is_current":0},{"wof:id":1477930433,"wof:name":"F11","mz:is_current":0},{"wof:id":1477930415,"wof:name":"F4","mz:is_current":0},{"wof:id":1477930423,"wof:name":"F6","mz:is_current":0},{"wof:id":1477930417,"wof:name":"F5","mz:is_current":0},{"wof:id":1477930425,"wof:name":"F7","mz:is_current":0},{"wof:id":1477930435,"wof:name":"F12","mz:is_current":0},{"wof:id":1477930427,"wof:name":"F8","mz:is_current":0},{"wof:id":1477930439,"wof:name":"F13","mz:is_current":0},{"wof:id":1745882095,"wof:name":"D3","mz:is_current":0},{"wof:id":1477930429,"wof:name":"F9","mz:is_current":0},{"wof:id":1745882089,"wof:name":"D1","mz:is_current":0},{"wof:id":1477930443,"wof:name":"F15","mz:is_current":0},{"wof:id":1745882097,"wof:name":"D4","mz:is_current":0},{"wof:id":1745882103,"wof:name":"D7","mz:is_current":0},{"wof:id":1477930447,"wof:name":"F17","mz:is_current":0},{"wof:id":1745882099,"wof:name":"D5","mz:is_current":0},{"wof:id":1745882105,"wof:name":"D9","mz:is_current":0},{"wof:id":1477930451,"wof:name":"F19","mz:is_current":0},{"wof:id":1745882107,"wof:name":"D8","mz:is_current":0},{"wof:id":1477930449,"wof:name":"F18","mz:is_current":0},{"wof:id":1745882113,"wof:name":"D10","mz:is_current":0},{"wof:id":1477930453,"wof:name":"F20","mz:is_current":0},{"wof:id":1745882117,"wof:name":"D14","mz:is_current":0},{"wof:id":1477930463,"wof:name":"G2","mz:is_current":0},{"wof:id":1745882121,"wof:name":"D16","mz:is_current":0},{"wof:id":1745882123,"wof:name":"D17","mz:is_current":0},{"wof:id":1745882119,"wof:name":"D15","mz:is_current":0},{"wof:id":1477930465,"wof:name":"G3","mz:is_current":0},{"wof:id":1477930457,"wof:name":"F21","mz:is_current":0},{"wof:id":1745882125,"wof:name":"D18","mz:is_current":0},{"wof:id":1477930471,"wof:name":"G6","mz:is_current":0},{"wof:id":1477930469,"wof:name":"G5","mz:is_current":0},{"wof:id":1477930459,"wof:name":"F22","mz:is_current":0},{"wof:id":1477930475,"wof:name":"G7","mz:is_current":0},{"wof:id":1477930477,"wof:name":"G8","mz:is_current":0},{"wof:id":1477930483,"wof:name":"G11","mz:is_current":0},{"wof:id":1477930485,"wof:name":"G12","mz:is_current":0},{"wof:id":1745882141,"wof:name":"B6","mz:is_current":0},{"wof:id":1477930487,"wof:name":"G13","mz:is_current":0},{"wof:id":1477930489,"wof:name":"G14","mz:is_current":0},{"wof:id":1745882143,"wof:name":"B7","mz:is_current":0},{"wof:id":1745882161,"wof:name":"B10","mz:is_current":0},{"wof:id":1745882149,"wof:name":"B9","mz:is_current":0},{"wof:id":1745882173,"wof:name":"B22","mz:is_current":0},{"wof:id":1745882165,"wof:name":"B25","mz:is_current":0},{"wof:id":1745882151,"wof:name":"B12","mz:is_current":0},{"wof:id":1745882185,"wof:name":"B23","mz:is_current":0},{"wof:id":1745882167,"wof:name":"B11","mz:is_current":0},{"wof:id":1745882153,"wof:name":"B13","mz:is_current":0},{"wof:id":1745882187,"wof:name":"B16","mz:is_current":0},{"wof:id":1745882169,"wof:name":"B24","mz:is_current":0},{"wof:id":1745882155,"wof:name":"B14","mz:is_current":0},{"wof:id":1745882175,"wof:name":"B21","mz:is_current":0},{"wof:id":1745882189,"wof:name":"B3","mz:is_current":0},{"wof:id":1745882193,"wof:name":"B27","mz:is_current":0},{"wof:id":1745882157,"wof:name":"B17","mz:is_current":0},{"wof:id":1745882177,"wof:name":"B19","mz:is_current":0},{"wof:id":1745882159,"wof:name":"B18","mz:is_current":0},{"wof:id":1745882179,"wof:name":"B20","mz:is_current":0},{"wof:id":1745882197,"wof:name":"C2","mz:is_current":0},{"wof:id":1746415339,"wof:name":"A13R","mz:is_current":1},{"wof:id":1745882213,"wof:name":"C9","mz:is_current":0},{"wof:id":1745882201,"wof:name":"C4","mz:is_current":0},{"wof:id":1746415347,"wof:name":"F15M","mz:is_current":1},{"wof:id":1745882203,"wof:name":"C3","mz:is_current":0},{"wof:id":1745882215,"wof:name":"C10","mz:is_current":0},{"wof:id":1746415349,"wof:name":"C4U","mz:is_current":1},{"wof:id":1745882205,"wof:name":"C5","mz:is_current":0},{"wof:id":1745882219,"wof:name":"C11","mz:is_current":0},{"wof:id":1745882209,"wof:name":"C7","mz:is_current":0},{"wof:id":1746415351,"wof:name":"C10T","mz:is_current":1},{"wof:id":1745882241,"wof:name":"E1","mz:is_current":0},{"wof:id":1745882231,"wof:name":"B2","mz:is_current":0},{"wof:id":1746415355,"wof:name":"E13T","mz:is_current":1},{"wof:id":1745882229,"wof:name":"B1","mz:is_current":1},{"wof:id":1745882243,"wof:name":"E2","mz:is_current":0},{"wof:id":1745882245,"wof:name":"E3","mz:is_current":0},{"wof:id":1746415357,"wof:name":"G13R","mz:is_current":1},{"wof:id":1746415363,"wof:name":"E10V","mz:is_current":1},{"wof:id":1746415371,"wof:name":"A7T","mz:is_current":1},{"wof:id":1745882249,"wof:name":"F2","mz:is_current":0},{"wof:id":1746415365,"wof:name":"A1T","mz:is_current":1},{"wof:id":1746415373,"wof:name":"B27V","mz:is_current":1},{"wof:id":1745882255,"wof:name":"F4","mz:is_current":0},{"wof:id":1746415367,"wof:name":"G11R","mz:is_current":1},{"wof:id":1746415375,"wof:name":"F15L","mz:is_current":1},{"wof:id":1745882239,"wof:name":"F5","mz:is_current":0},{"wof:id":1745882257,"wof:name":"F3A","mz:is_current":0},{"wof:id":1746415369,"wof:name":"B23V","mz:is_current":1},{"wof:id":1746415379,"wof:name":"F15N","mz:is_current":1},{"wof:id":1745882263,"wof:name":"F8","mz:is_current":0},{"wof:id":1746415381,"wof:name":"A13S","mz:is_current":1},{"wof:id":1745882259,"wof:name":"F5","mz:is_current":0},{"wof:id":1745882269,"wof:name":"F10","mz:is_current":0},{"wof:id":1745882273,"wof:name":"F11","mz:is_current":0},{"wof:id":1746415383,"wof:name":"G104","mz:is_current":1},{"wof:id":1746415397,"wof:name":"G12T","mz:is_current":1},{"wof:id":1745882281,"wof:name":"F15","mz:is_current":0},{"wof:id":1745882275,"wof:name":"F13","mz:is_current":0},{"wof:id":1746415385,"wof:name":"G13S","mz:is_current":1},{"wof:id":1746415399,"wof:name":"A6R","mz:is_current":1},{"wof:id":1745882283,"wof:name":"F16","mz:is_current":0},{"wof:id":1745882277,"wof:name":"F12","mz:is_current":0},{"wof:id":1746415387,"wof:name":"G103","mz:is_current":1},{"wof:id":1746415401,"wof:name":"E3T","mz:is_current":1},{"wof:id":1745882287,"wof:name":"F18","mz:is_current":0},{"wof:id":1745882279,"wof:name":"F14","mz:is_current":0},{"wof:id":1746415403,"wof:name":"B20S","mz:is_current":1},{"wof:id":1746415389,"wof:name":"A6S","mz:is_current":1},{"wof:id":1745882293,"wof:name":"F20","mz:is_current":0},{"wof:id":1746415407,"wof:name":"G105","mz:is_current":1},{"wof:id":1745882301,"wof:name":"E4","mz:is_current":0},{"wof:id":1746415409,"wof:name":"E11V","mz:is_current":1},{"wof:id":1746415411,"wof:name":"C4R","mz:is_current":1},{"wof:id":1745882297,"wof:name":"F22","mz:is_current":0},{"wof:id":1745882303,"wof:name":"E5","mz:is_current":0},{"wof:id":1746415421,"wof:name":"E3K","mz:is_current":1},{"wof:id":1746415417,"wof:name":"E13K","mz:is_current":1},{"wof:id":1745882305,"wof:name":"E6","mz:is_current":0},{"wof:id":1745882311,"wof:name":"E8","mz:is_current":0},{"wof:id":1746415419,"wof:name":"E10U","mz:is_current":1},{"wof:id":1746415423,"wof:name":"A4T","mz:is_current":1},{"wof:id":1745882309,"wof:name":"E7","mz:is_current":0},{"wof:id":1745882341,"wof:name":"A4","mz:is_current":0},{"wof:id":1745882313,"wof:name":"E9","mz:is_current":0},{"wof:id":1745882345,"wof:name":"A5","mz:is_current":0},{"wof:id":1745882315,"wof:name":"E10","mz:is_current":0},{"wof:id":1745882317,"wof:name":"E11","mz:is_current":0},{"wof:id":1745882349,"wof:name":"A6","mz:is_current":0},{"wof:id":1745882351,"wof:name":"A10","mz:is_current":0},{"wof:id":1745882319,"wof:name":"E12","mz:is_current":0},{"wof:id":1745882353,"wof:name":"A9","mz:is_current":0},{"wof:id":1745882365,"wof:name":"A1","mz:is_current":0},{"wof:id":1745882371,"wof:name":"A3","mz:is_current":0},{"wof:id":1745882367,"wof:name":"A1","mz:is_current":0},{"wof:id":1745882355,"wof:name":"A8","mz:is_current":0},{"wof:id":1745882373,"wof:name":"A4","mz:is_current":0},{"wof:id":1745882339,"wof:name":"A2","mz:is_current":0},{"wof:id":1745882357,"wof:name":"A12","mz:is_current":0},{"wof:id":1745882369,"wof:name":"A2","mz:is_current":0},{"wof:id":1745882375,"wof:name":"A5","mz:is_current":0},{"wof:id":1745882383,"wof:name":"A7","mz:is_current":0},{"wof:id":1763588135,"wof:name":"D4","mz:is_current":1},{"wof:id":1745882377,"wof:name":"A6","mz:is_current":0},{"wof:id":1763588137,"wof:name":"D5","mz:is_current":1},{"wof:id":1745882385,"wof:name":"A9","mz:is_current":0},{"wof:id":1745882389,"wof:name":"A12","mz:is_current":0},{"wof:id":1745882391,"wof:name":"A11","mz:is_current":0},{"wof:id":1745882405,"wof:name":"G1","mz:is_current":0},{"wof:id":1745882407,"wof:name":"G2","mz:is_current":0},{"wof:id":1763588141,"wof:name":"D7","mz:is_current":1},{"wof:id":1745882395,"wof:name":"A14","mz:is_current":0},{"wof:id":1745882409,"wof:name":"G3","mz:is_current":0},{"wof:id":1745882413,"wof:name":"G5","mz:is_current":0},{"wof:id":1745882399,"wof:name":"A15","mz:is_current":0},{"wof:id":1763588143,"wof:name":"D9","mz:is_current":1},{"wof:id":1745882417,"wof:name":"G6","mz:is_current":0},{"wof:id":1763588147,"wof:name":"D11","mz:is_current":1},{"wof:id":1745882419,"wof:name":"G7","mz:is_current":0},{"wof:id":1745882421,"wof:name":"G10","mz:is_current":0},{"wof:id":1745882423,"wof:name":"G8","mz:is_current":0},{"wof:id":1763588163,"wof:name":"D18","mz:is_current":1},{"wof:id":1745882425,"wof:name":"G11","mz:is_current":0},{"wof:id":1745882427,"wof:name":"G9","mz:is_current":0},{"wof:id":1745882429,"wof:name":"G12","mz:is_current":0},{"wof:id":1763588153,"wof:name":"D12","mz:is_current":1},{"wof:id":1745882435,"wof:name":"G14","mz:is_current":0},{"wof:id":1763588155,"wof:name":"D14","mz:is_current":1},{"wof:id":1763588157,"wof:name":"D16","mz:is_current":1},{"wof:id":1763588159,"wof:name":"D15","mz:is_current":1},{"wof:id":1763588129,"wof:name":"D1","mz:is_current":1},{"wof:id":1763588181,"wof:name":"B7","mz:is_current":1},{"wof:id":1763588191,"wof:name":"B13","mz:is_current":1},{"wof:id":1763588183,"wof:name":"B8","mz:is_current":1},{"wof:id":1763588193,"wof:name":"B14","mz:is_current":1},{"wof:id":1763588185,"wof:name":"B12","mz:is_current":1},{"wof:id":1763588195,"wof:name":"B17","mz:is_current":1},{"wof:id":1763588197,"wof:name":"B18","mz:is_current":1},{"wof:id":1763588201,"wof:name":"B25","mz:is_current":1},{"wof:id":1763588199,"wof:name":"B10","mz:is_current":1},{"wof:id":1763588203,"wof:name":"B11","mz:is_current":1},{"wof:id":1763588211,"wof:name":"B15","mz:is_current":1},{"wof:id":1763588207,"wof:name":"B24","mz:is_current":1},{"wof:id":1763588213,"wof:name":"B22","mz:is_current":1},{"wof:id":1763588221,"wof:name":"B23","mz:is_current":1},{"wof:id":1763588215,"wof:name":"B4","mz:is_current":1},{"wof:id":1763588209,"wof:name":"B26","mz:is_current":1},{"wof:id":1763588225,"wof:name":"B19","mz:is_current":1},{"wof:id":1763588217,"wof:name":"B27","mz:is_current":1},{"wof:id":1763588231,"wof:name":"B3","mz:is_current":1},{"wof:id":1763588219,"wof:name":"B21","mz:is_current":1},{"wof:id":1763588227,"wof:name":"B16","mz:is_current":1},{"wof:id":1763588235,"wof:name":"C2","mz:is_current":1},{"wof:id":1763588243,"wof:name":"C5","mz:is_current":1},{"wof:id":1763588229,"wof:name":"B20","mz:is_current":1},{"wof:id":1763588237,"wof:name":"C4","mz:is_current":1},{"wof:id":1763588245,"wof:name":"C6","mz:is_current":1},{"wof:id":1763588239,"wof:name":"C3","mz:is_current":1},{"wof:id":1763588253,"wof:name":"C10","mz:is_current":1},{"wof:id":1763588247,"wof:name":"C8","mz:is_current":1},{"wof:id":1763588249,"wof:name":"C7","mz:is_current":1},{"wof:id":1763588275,"wof:name":"E1","mz:is_current":1},{"wof:id":1763588279,"wof:name":"E2","mz:is_current":1},{"wof:id":1763588283,"wof:name":"F1","mz:is_current":1},{"wof:id":1763588267,"wof:name":"B2","mz:is_current":1},{"wof:id":1763588301,"wof:name":"F7","mz:is_current":1},{"wof:id":1763588285,"wof:name":"F3","mz:is_current":1},{"wof:id":1763588297,"wof:name":"F6","mz:is_current":1},{"wof:id":1763588303,"wof:name":"F9","mz:is_current":1},{"wof:id":1763588287,"wof:name":"F2","mz:is_current":1},{"wof:id":1763588305,"wof:name":"F10","mz:is_current":1},{"wof:id":1763588323,"wof:name":"F18","mz:is_current":1},{"wof:id":1763588311,"wof:name":"F12","mz:is_current":1},{"wof:id":1763588289,"wof:name":"F4","mz:is_current":1},{"wof:id":1763588307,"wof:name":"F11","mz:is_current":1},{"wof:id":1763588325,"wof:name":"F19","mz:is_current":1},{"wof:id":1763588315,"wof:name":"F14","mz:is_current":1},{"wof:id":1763588327,"wof:name":"F20","mz:is_current":1},{"wof:id":1763588341,"wof:name":"E6","mz:is_current":1},{"wof:id":1763588317,"wof:name":"F15","mz:is_current":1},{"wof:id":1763588329,"wof:name":"F21","mz:is_current":1},{"wof:id":1763588343,"wof:name":"E7","mz:is_current":1},{"wof:id":1763588319,"wof:name":"F16","mz:is_current":1},{"wof:id":1763588337,"wof:name":"E4","mz:is_current":1},{"wof:id":1763588347,"wof:name":"E10","mz:is_current":1},{"wof:id":1763588339,"wof:name":"E5","mz:is_current":1},{"wof:id":1763588351,"wof:name":"E9","mz:is_current":1},{"wof:id":1763588355,"wof:name":"E12","mz:is_current":1},{"wof:id":1763588373,"wof:name":"A11","mz:is_current":0},{"wof:id":1763588357,"wof:name":"E13","mz:is_current":1},{"wof:id":1763588381,"wof:name":"A6","mz:is_current":0},{"wof:id":1763588393,"wof:name":"A3","mz:is_current":1},{"wof:id":1763588375,"wof:name":"A10","mz:is_current":0},{"wof:id":1763588395,"wof:name":"A5","mz:is_current":0},{"wof:id":1763588383,"wof:name":"A7","mz:is_current":0},{"wof:id":1763588397,"wof:name":"A12","mz:is_current":0},{"wof:id":1763588387,"wof:name":"A2","mz:is_current":0},{"wof:id":1763588389,"wof:name":"A1","mz:is_current":0},{"wof:id":1763588377,"wof:name":"A4","mz:is_current":0},{"wof:id":1763588399,"wof:name":"A3","mz:is_current":0},{"wof:id":1763588405,"wof:name":"A2","mz:is_current":1},{"wof:id":1763588379,"wof:name":"A9","mz:is_current":0},{"wof:id":1763588409,"wof:name":"A5","mz:is_current":1},{"wof:id":1763588411,"wof:name":"A6","mz:is_current":1},{"wof:id":1763588437,"wof:name":"G1","mz:is_current":1},{"wof:id":1763588423,"wof:name":"A13","mz:is_current":1},{"wof:id":1763588413,"wof:name":"A8","mz:is_current":1},{"wof:id":1763588443,"wof:name":"G3","mz:is_current":1},{"wof:id":1763588415,"wof:name":"A7","mz:is_current":1},{"wof:id":1763588427,"wof:name":"A15","mz:is_current":1},{"wof:id":1763588445,"wof:name":"G4","mz:is_current":1},{"wof:id":1763588453,"wof:name":"G10","mz:is_current":1},{"wof:id":1763588417,"wof:name":"A9","mz:is_current":1},{"wof:id":1763588429,"wof:name":"A11","mz:is_current":1},{"wof:id":1763588455,"wof:name":"G8","mz:is_current":1},{"wof:id":1763588447,"wof:name":"G5","mz:is_current":1},{"wof:id":1763588461,"wof:name":"G9","mz:is_current":1},{"wof:id":1763588463,"wof:name":"G12","mz:is_current":1},{"wof:id":1763588483,"wof:name":"B5","mz:is_current":1},{"wof:id":1763588449,"wof:name":"G6","mz:is_current":1},{"wof:id":1763588465,"wof:name":"G13","mz:is_current":1},{"wof:id":1763588467,"wof:name":"G14","mz:is_current":1},{"wof:id":1360832519,"wof:name":"C45","mz:is_current":0},{"wof:id":1360832521,"wof:name":"F84","mz:is_current":0},{"wof:id":1360832523,"wof:name":"F77","mz:is_current":0},{"wof:id":1159157603,"wof:name":"A10A","mz:is_current":0},{"wof:id":1159157605,"wof:name":"A11B","mz:is_current":0},{"wof:id":1159157607,"wof:name":"A12","mz:is_current":0},{"wof:id":1159157609,"wof:name":"A2","mz:is_current":0},{"wof:id":1159157611,"wof:name":"A3A","mz:is_current":0},{"wof:id":1159157615,"wof:name":"G101A","mz:is_current":0},{"wof:id":1159157617,"wof:name":"A1A","mz:is_current":0},{"wof:id":1159157613,"wof:name":"A1","mz:is_current":0},{"wof:id":1159157621,"wof:name":"G95","mz:is_current":0},{"wof:id":1159157623,"wof:name":"G91","mz:is_current":0},{"wof:id":1159157625,"wof:name":"B22","mz:is_current":0},{"wof:id":1159157629,"wof:name":"A11A","mz:is_current":0},{"wof:id":1159157627,"wof:name":"A11","mz:is_current":0},{"wof:id":1159157631,"wof:name":"A8","mz:is_current":0},{"wof:id":1159157633,"wof:name":"A9","mz:is_current":0},{"wof:id":1159157639,"wof:name":"A7","mz:is_current":0},{"wof:id":1159157635,"wof:name":"A6","mz:is_current":0},{"wof:id":1159157641,"wof:name":"A4","mz:is_current":0},{"wof:id":1159157643,"wof:name":"A5B","mz:is_current":0},{"wof:id":1159157645,"wof:name":"F79","mz:is_current":0},{"wof:id":1159157647,"wof:name":"E63","mz:is_current":0},{"wof:id":1159157649,"wof:name":"D53","mz:is_current":0},{"wof:id":1159157651,"wof:name":"D58B","mz:is_current":0},{"wof:id":1159157653,"wof:name":"E65","mz:is_current":0},{"wof:id":1159157657,"wof:name":"G96","mz:is_current":0},{"wof:id":1159157659,"wof:name":"F73","mz:is_current":0},{"wof:id":1159157661,"wof:name":"C44","mz:is_current":0},{"wof:id":1159157663,"wof:name":"C46","mz:is_current":0},{"wof:id":1159157665,"wof:name":"F89","mz:is_current":0},{"wof:id":1159157669,"wof:name":"F73A","mz:is_current":0},{"wof:id":1159157667,"wof:name":"A1B","mz:is_current":0},{"wof:id":1159157671,"wof:name":"F86","mz:is_current":0},{"wof:id":1159157675,"wof:name":"F87","mz:is_current":0},{"wof:id":1159157677,"wof:name":"G102","mz:is_current":0},{"wof:id":1159157679,"wof:name":"G99A","mz:is_current":0},{"wof:id":1159157681,"wof:name":"G99B","mz:is_current":0},{"wof:id":1159157683,"wof:name":"G97","mz:is_current":0},{"wof:id":1159157685,"wof:name":"G100","mz:is_current":0},{"wof:id":1159157687,"wof:name":"G98","mz:is_current":0},{"wof:id":1159157689,"wof:name":"F84B","mz:is_current":0},{"wof:id":1159157693,"wof:name":"F84D","mz:is_current":0},{"wof:id":1159157695,"wof:name":"F84C","mz:is_current":0},{"wof:id":1159157697,"wof:name":"F74","mz:is_current":0},{"wof:id":1159157699,"wof:name":"E68","mz:is_current":0},{"wof:id":1159157701,"wof:name":"D50A","mz:is_current":0},{"wof:id":1159157703,"wof:name":"D51A","mz:is_current":0},{"wof:id":1159157705,"wof:name":"D51B","mz:is_current":0},{"wof:id":1159157707,"wof:name":"C45B","mz:is_current":0},{"wof:id":1159157711,"wof:name":"C42","mz:is_current":0},{"wof:id":1159157713,"wof:name":"B25","mz:is_current":0},{"wof:id":1159157715,"wof:name":"B24","mz:is_current":0},{"wof:id":1159157717,"wof:name":"A3","mz:is_current":0},{"wof:id":1159157719,"wof:name":"G101B","mz:is_current":0},{"wof:id":1159157721,"wof:name":"F70","mz:is_current":0},{"wof:id":1159157723,"wof:name":"F71A","mz:is_current":0},{"wof:id":1159157725,"wof:name":"F71B","mz:is_current":0},{"wof:id":1159157729,"wof:name":"F76","mz:is_current":0},{"wof:id":1159157743,"wof:name":"C48","mz:is_current":0},{"wof:id":1159157747,"wof:name":"C41","mz:is_current":0},{"wof:id":1159157731,"wof:name":"F70A","mz:is_current":0},{"wof:id":1159157749,"wof:name":"F85","mz:is_current":0},{"wof:id":1159157735,"wof:name":"E65A","mz:is_current":0},{"wof:id":1159157733,"wof:name":"E67","mz:is_current":0},{"wof:id":1159157737,"wof:name":"E64A","mz:is_current":0},{"wof:id":1159157739,"wof:name":"F77C","mz:is_current":0},{"wof:id":1159157741,"wof:name":"F90","mz:is_current":0},{"wof:id":1159157753,"wof:name":"C47","mz:is_current":0},{"wof:id":1159157751,"wof:name":"F88","mz:is_current":0},{"wof:id":1159157755,"wof:name":"C45A","mz:is_current":0},{"wof:id":1159157759,"wof:name":"E69","mz:is_current":0},{"wof:id":1159157757,"wof:name":"F81","mz:is_current":0},{"wof:id":1159157761,"wof:name":"F82","mz:is_current":0},{"wof:id":1159157765,"wof:name":"E60","mz:is_current":0},{"wof:id":1159157769,"wof:name":"F77B","mz:is_current":0},{"wof:id":1159157767,"wof:name":"E61","mz:is_current":0},{"wof:id":1159157771,"wof:name":"E62","mz:is_current":0},{"wof:id":1159157773,"wof:name":"D59","mz:is_current":0},{"wof:id":1159157775,"wof:name":"G93","mz:is_current":0},{"wof:id":1159157777,"wof:name":"G94","mz:is_current":0},{"wof:id":1159157779,"wof:name":"G92","mz:is_current":0},{"wof:id":1159157783,"wof:name":"F75","mz:is_current":0},{"wof:id":1159157785,"wof:name":"E64","mz:is_current":0},{"wof:id":1159157787,"wof:name":"E67A","mz:is_current":0},{"wof:id":1159157789,"wof:name":"E66","mz:is_current":0},{"wof:id":1159157791,"wof:name":"D58A","mz:is_current":0},{"wof:id":1159157793,"wof:name":"D55","mz:is_current":0},{"wof:id":1159157797,"wof:name":"D56A","mz:is_current":0},{"wof:id":1159157795,"wof:name":"D56B","mz:is_current":0},{"wof:id":1159157801,"wof:name":"D57","mz:is_current":0},{"wof:id":1159157803,"wof:name":"C43","mz:is_current":0},{"wof:id":1159157807,"wof:name":"A3B","mz:is_current":0},{"wof:id":1159157805,"wof:name":"A5","mz:is_current":0},{"wof:id":1159157809,"wof:name":"B26","mz:is_current":0},{"wof:id":1159157811,"wof:name":"B27","mz:is_current":0},{"wof:id":1159157813,"wof:name":"B23","mz:is_current":0},{"wof:id":1159157815,"wof:name":"G99","mz:is_current":0},{"wof:id":1159157821,"wof:name":"F80","mz:is_current":0},{"wof:id":1159157819,"wof:name":"C48A","mz:is_current":0},{"wof:id":1159157823,"wof:name":"A10","mz:is_current":0},{"wof:id":1159157827,"wof:name":"G101","mz:is_current":0},{"wof:id":1159157825,"wof:name":"F72","mz:is_current":0},{"wof:id":1159157829,"wof:name":"D52","mz:is_current":0},{"wof:id":1159157831,"wof:name":"D54B","mz:is_current":0},{"wof:id":1159157837,"wof:name":"F84A","mz:is_current":0},{"wof:id":1159157833,"wof:name":"D54A","mz:is_current":0},{"wof:id":1159157843,"wof:name":"A3X","mz:is_current":0},{"wof:id":1159157841,"wof:name":"G99X","mz:is_current":0},{"wof:id":1159157839,"wof:name":"D50B","mz:is_current":0},{"wof:id":1376996231,"wof:name":"B28","mz:is_current":0},{"wof:id":1159157845,"wof:name":"C42A","mz:is_current":0},{"wof:id":1159157847,"wof:name":"F77A","mz:is_current":0},{"wof:id":1159157849,"wof:name":"F87A","mz:is_current":0},{"wof:id":1159157851,"wof:name":"E62A","mz:is_current":0},{"wof:id":1159157855,"wof:name":"F78","mz:is_current":0},{"wof:id":1159157857,"wof:name":"C40","mz:is_current":0},{"wof:id":1159157859,"wof:name":"B28","mz:is_current":0},{"wof:id":1159157861,"wof:name":"F83","mz:is_current":0},{"wof:id":1729792393,"wof:name":"D1","mz:is_current":0},{"wof:id":1729792397,"wof:name":"D2","mz:is_current":0},{"wof:id":1729792401,"wof:name":"D4","mz:is_current":0},{"wof:id":1729792403,"wof:name":"D5","mz:is_current":0},{"wof:id":1729792399,"wof:name":"D3","mz:is_current":0},{"wof:id":1729792405,"wof:name":"D6","mz:is_current":0},{"wof:id":1729792409,"wof:name":"D8","mz:is_current":0},{"wof:id":1729792407,"wof:name":"D7","mz:is_current":0},{"wof:id":1729792411,"wof:name":"D9","mz:is_current":0},{"wof:id":1477855615,"wof:name":"D52","mz:is_current":0},{"wof:id":1729792415,"wof:name":"D11","mz:is_current":0},{"wof:id":1729792417,"wof:name":"D10","mz:is_current":0},{"wof:id":1477855617,"wof:name":"D51A","mz:is_current":0},{"wof:id":1729792419,"wof:name":"D12","mz:is_current":0},{"wof:id":1477855619,"wof:name":"D51B","mz:is_current":0},{"wof:id":1729792421,"wof:name":"D14","mz:is_current":0},{"wof:id":1477855631,"wof:name":"D57","mz:is_current":0},{"wof:id":1729792423,"wof:name":"D15","mz:is_current":0},{"wof:id":1477855621,"wof:name":"D50A","mz:is_current":0},{"wof:id":1477855633,"wof:name":"D59","mz:is_current":0},{"wof:id":1477855635,"wof:name":"D53","mz:is_current":0},{"wof:id":1477855623,"wof:name":"D58B","mz:is_current":0},{"wof:id":1729792425,"wof:name":"D16","mz:is_current":0},{"wof:id":1477855637,"wof:name":"D54A","mz:is_current":0},{"wof:id":1729792427,"wof:name":"D17","mz:is_current":0},{"wof:id":1729792429,"wof:name":"D18","mz:is_current":0},{"wof:id":1477855643,"wof:name":"D55","mz:is_current":0},{"wof:id":1477855639,"wof:name":"D50B","mz:is_current":0},{"wof:id":1477855645,"wof:name":"D56A","mz:is_current":0},{"wof:id":1477855641,"wof:name":"D54B","mz:is_current":0},{"wof:id":1477855649,"wof:name":"D56B","mz:is_current":0},{"wof:id":1477855651,"wof:name":"D58A","mz:is_current":0},{"wof:id":1729792439,"wof:name":"B6","mz:is_current":0},{"wof:id":1729792451,"wof:name":"B13","mz:is_current":0},{"wof:id":1729792453,"wof:name":"B14","mz:is_current":0},{"wof:id":1729792457,"wof:name":"B18","mz:is_current":0},{"wof:id":1729792455,"wof:name":"B17","mz:is_current":0},{"wof:id":1729792441,"wof:name":"B7","mz:is_current":0},{"wof:id":1729792443,"wof:name":"B8","mz:is_current":0},{"wof:id":1729792445,"wof:name":"B9","mz:is_current":0},{"wof:id":1729792447,"wof:name":"B12","mz:is_current":0},{"wof:id":1729792461,"wof:name":"C2","mz:is_current":0},{"wof:id":1729792465,"wof:name":"C3","mz:is_current":0},{"wof:id":1729792463,"wof:name":"C4","mz:is_current":0},{"wof:id":1477855673,"wof:name":"C47","mz:is_current":0},{"wof:id":1477855671,"wof:name":"C45","mz:is_current":0},{"wof:id":1729792469,"wof:name":"C5","mz:is_current":0},{"wof:id":1477855675,"wof:name":"C45A","mz:is_current":0},{"wof:id":1477855677,"wof:name":"C48","mz:is_current":0},{"wof:id":1729792471,"wof:name":"C6","mz:is_current":0},{"wof:id":1729792473,"wof:name":"C7","mz:is_current":0},{"wof:id":1729792475,"wof:name":"C8","mz:is_current":0},{"wof:id":1477855681,"wof:name":"C42","mz:is_current":0},{"wof:id":1477855685,"wof:name":"C45B","mz:is_current":0},{"wof:id":1477855679,"wof:name":"C41","mz:is_current":0},{"wof:id":1729792477,"wof:name":"C9","mz:is_current":0},{"wof:id":1729792479,"wof:name":"C10","mz:is_current":0},{"wof:id":1477855689,"wof:name":"C44","mz:is_current":0},{"wof:id":1477855687,"wof:name":"C46","mz:is_current":0},{"wof:id":1729792481,"wof:name":"C11","mz:is_current":0},{"wof:id":1477855691,"wof:name":"C43","mz:is_current":0},{"wof:id":1477855693,"wof:name":"C42A","mz:is_current":0},{"wof:id":1477855705,"wof:name":"F77","mz:is_current":0},{"wof:id":1477855695,"wof:name":"C48A","mz:is_current":0},{"wof:id":1477855707,"wof:name":"F84","mz:is_current":0},{"wof:id":1477855697,"wof:name":"C40","mz:is_current":0},{"wof:id":1477855709,"wof:name":"F84D","mz:is_current":0},{"wof:id":1477855711,"wof:name":"F74","mz:is_current":0},{"wof:id":1477855713,"wof:name":"F84C","mz:is_current":0},{"wof:id":1729792501,"wof:name":"F2","mz:is_current":0},{"wof:id":1477855715,"wof:name":"F71A","mz:is_current":0},{"wof:id":1729792491,"wof:name":"F5","mz:is_current":0},{"wof:id":1729792505,"wof:name":"F3","mz:is_current":0},{"wof:id":1477855717,"wof:name":"F76","mz:is_current":0},{"wof:id":1729792507,"wof:name":"F4","mz:is_current":0},{"wof:id":1729792495,"wof:name":"E2","mz:is_current":0},{"wof:id":1729792493,"wof:name":"E1","mz:is_current":0},{"wof:id":1729792509,"wof:name":"F3A","mz:is_current":0},{"wof:id":1729792499,"wof:name":"F1","mz:is_current":0},{"wof:id":1729792497,"wof:name":"E3","mz:is_current":0},{"wof:id":1477855723,"wof:name":"F70","mz:is_current":0},{"wof:id":1477855721,"wof:name":"F71B","mz:is_current":0},{"wof:id":1729792511,"wof:name":"F5","mz:is_current":0},{"wof:id":1729792523,"wof:name":"F10","mz:is_current":0},{"wof:id":1729792513,"wof:name":"F6","mz:is_current":0},{"wof:id":1729792525,"wof:name":"F11","mz:is_current":0},{"wof:id":1729792527,"wof:name":"F13","mz:is_current":0},{"wof:id":1729792515,"wof:name":"F7","mz:is_current":0},{"wof:id":1729792529,"wof:name":"F12","mz:is_current":0},{"wof:id":1729792517,"wof:name":"F8","mz:is_current":0},{"wof:id":1729792519,"wof:name":"F9","mz:is_current":0},{"wof:id":1477855733,"wof:name":"F81","mz:is_current":0},{"wof:id":1477855735,"wof:name":"F88","mz:is_current":0},{"wof:id":1477855739,"wof:name":"F85","mz:is_current":0},{"wof:id":1729792531,"wof:name":"F14","mz:is_current":0},{"wof:id":1729792541,"wof:name":"F18","mz:is_current":0},{"wof:id":1729792533,"wof:name":"F15","mz:is_current":0},{"wof:id":1729792543,"wof:name":"F19","mz:is_current":0},{"wof:id":1729792535,"wof:name":"F16","mz:is_current":0},{"wof:id":1729792545,"wof:name":"F20","mz:is_current":0},{"wof:id":1729792547,"wof:name":"F21","mz:is_current":0},{"wof:id":1729792537,"wof:name":"F17","mz:is_current":0},{"wof:id":1729792549,"wof:name":"F22","mz:is_current":0},{"wof:id":1477855743,"wof:name":"F77B","mz:is_current":0},{"wof:id":1477855741,"wof:name":"F90","mz:is_current":0},{"wof:id":1477855745,"wof:name":"F82","mz:is_current":0},{"wof:id":1477855749,"wof:name":"F80","mz:is_current":0},{"wof:id":1477855747,"wof:name":"F72","mz:is_current":0},{"wof:id":1477855751,"wof:name":"F73A","mz:is_current":0},{"wof:id":1477855753,"wof:name":"F89","mz:is_current":0},{"wof:id":1477855759,"wof:name":"F84B","mz:is_current":0},{"wof:id":1477855757,"wof:name":"F73","mz:is_current":0},{"wof:id":1729792553,"wof:name":"E4","mz:is_current":0},{"wof:id":1729792559,"wof:name":"E6","mz:is_current":0},{"wof:id":1729792555,"wof:name":"E5","mz:is_current":0},{"wof:id":1729792561,"wof:name":"E7","mz:is_current":0},{"wof:id":1729792563,"wof:name":"E8","mz:is_current":0},{"wof:id":1477855761,"wof:name":"F83","mz:is_current":0},{"wof:id":1729792565,"wof:name":"E9","mz:is_current":0},{"wof:id":1729792567,"wof:name":"E10","mz:is_current":0},{"wof:id":1477855763,"wof:name":"F75","mz:is_current":0},{"wof:id":1729792569,"wof:name":"E11","mz:is_current":0},{"wof:id":1477855765,"wof:name":"F79","mz:is_current":0},{"wof:id":1477855767,"wof:name":"F87A","mz:is_current":0},{"wof:id":1477855769,"wof:name":"F77A","mz:is_current":0},{"wof:id":1729792571,"wof:name":"E12","mz:is_current":0},{"wof:id":1477855771,"wof:name":"F78","mz:is_current":0},{"wof:id":1477855775,"wof:name":"F87","mz:is_current":0},{"wof:id":1729792573,"wof:name":"E13","mz:is_current":0},{"wof:id":1477855777,"wof:name":"F86","mz:is_current":0},{"wof:id":1477855779,"wof:name":"F77C","mz:is_current":0},{"wof:id":1477855781,"wof:name":"F70A","mz:is_current":0},{"wof:id":1477855783,"wof:name":"F84A","mz:is_current":0},{"wof:id":1729792583,"wof:name":"A2","mz:is_current":0},{"wof:id":1729792585,"wof:name":"A4","mz:is_current":0},{"wof:id":1729792589,"wof:name":"A7","mz:is_current":0},{"wof:id":1729792587,"wof:name":"A5","mz:is_current":0},{"wof:id":1477855789,"wof:name":"E68","mz:is_current":0},{"wof:id":1729792591,"wof:name":"A6","mz:is_current":0},{"wof:id":1477855795,"wof:name":"E61","mz:is_current":0},{"wof:id":1477855793,"wof:name":"E69","mz:is_current":0},{"wof:id":1729792595,"wof:name":"A10","mz:is_current":0},{"wof:id":1729792599,"wof:name":"A8","mz:is_current":0},{"wof:id":1477855797,"wof:name":"E60","mz:is_current":0},{"wof:id":1477855799,"wof:name":"E65","mz:is_current":0},{"wof:id":1729792597,"wof:name":"A9","mz:is_current":0},{"wof:id":1477855801,"wof:name":"E66","mz:is_current":0},{"wof:id":1477855803,"wof:name":"E67A","mz:is_current":0},{"wof:id":1477855811,"wof:name":"E63","mz:is_current":0},{"wof:id":1477855805,"wof:name":"E64","mz:is_current":0},{"wof:id":1477855813,"wof:name":"E62A","mz:is_current":0},{"wof:id":1477855807,"wof:name":"E62","mz:is_current":0},{"wof:id":1477855815,"wof:name":"E67","mz:is_current":0},{"wof:id":1477855819,"wof:name":"E65A","mz:is_current":0},{"wof:id":1477855817,"wof:name":"E64A","mz:is_current":0},{"wof:id":1729792601,"wof:name":"A12","mz:is_current":0},{"wof:id":1729792603,"wof:name":"A11","mz:is_current":0},{"wof:id":1729792605,"wof:name":"A3","mz:is_current":0},{"wof:id":1729792613,"wof:name":"A2","mz:is_current":0},{"wof:id":1729792607,"wof:name":"A1","mz:is_current":0},{"wof:id":1729792615,"wof:name":"A3","mz:is_current":0},{"wof:id":1729792609,"wof:name":"A1","mz:is_current":0},{"wof:id":1729792617,"wof:name":"A4","mz:is_current":0},{"wof:id":1729792619,"wof:name":"A5","mz:is_current":0},{"wof:id":1729792621,"wof:name":"A6","mz:is_current":0},{"wof:id":1477855841,"wof:name":"A1","mz:is_current":0},{"wof:id":1477855843,"wof:name":"A1A","mz:is_current":0},{"wof:id":1729792623,"wof:name":"A8","mz:is_current":0},{"wof:id":1729792625,"wof:name":"A7","mz:is_current":0},{"wof:id":1477855847,"wof:name":"A3A","mz:is_current":0},{"wof:id":1477855837,"wof:name":"A11A","mz:is_current":0},{"wof:id":1729792627,"wof:name":"A9","mz:is_current":0},{"wof:id":1729792641,"wof:name":"A15","mz:is_current":0},{"wof:id":1477855839,"wof:name":"A11","mz:is_current":0},{"wof:id":1477855849,"wof:name":"A3","mz:is_current":0},{"wof:id":1729792631,"wof:name":"A10","mz:is_current":0},{"wof:id":1477855851,"wof:name":"A10","mz:is_current":0},{"wof:id":1477855855,"wof:name":"A3B","mz:is_current":0},{"wof:id":1477855853,"wof:name":"A1B","mz:is_current":0},{"wof:id":1729792633,"wof:name":"A11","mz:is_current":0},{"wof:id":1477855857,"wof:name":"A5","mz:is_current":0},{"wof:id":1729792635,"wof:name":"A12","mz:is_current":0},{"wof:id":1729792649,"wof:name":"G1","mz:is_current":0},{"wof:id":1477855859,"wof:name":"A5B","mz:is_current":0},{"wof:id":1729792637,"wof:name":"A13","mz:is_current":0},{"wof:id":1729792639,"wof:name":"A14","mz:is_current":0},{"wof:id":1477855861,"wof:name":"A4","mz:is_current":0},{"wof:id":1729792651,"wof:name":"G2","mz:is_current":0},{"wof:id":1477855871,"wof:name":"A11B","mz:is_current":0},{"wof:id":1477855865,"wof:name":"A10A","mz:is_current":0},{"wof:id":1729792653,"wof:name":"G3","mz:is_current":0},{"wof:id":1477855867,"wof:name":"A2","mz:is_current":0},{"wof:id":1729792655,"wof:name":"G4","mz:is_current":0},{"wof:id":1477855873,"wof:name":"A3X","mz:is_current":0},{"wof:id":1477855869,"wof:name":"A12","mz:is_current":0},{"wof:id":1729792659,"wof:name":"G6","mz:is_current":0},{"wof:id":1729792657,"wof:name":"G5","mz:is_current":0},{"wof:id":1477855879,"wof:name":"A6","mz:is_current":0},{"wof:id":1477855877,"wof:name":"A7","mz:is_current":0},{"wof:id":1729792661,"wof:name":"G7","mz:is_current":0},{"wof:id":1477855883,"wof:name":"A8","mz:is_current":0},{"wof:id":1729792663,"wof:name":"G10","mz:is_current":0},{"wof:id":1729792667,"wof:name":"G8","mz:is_current":0},{"wof:id":1729792671,"wof:name":"G9","mz:is_current":0},{"wof:id":1729792669,"wof:name":"G11","mz:is_current":0},{"wof:id":1477855887,"wof:name":"G91","mz:is_current":0},{"wof:id":1477855893,"wof:name":"G101B","mz:is_current":0},{"wof:id":1477855911,"wof:name":"G94","mz:is_current":0},{"wof:id":1477855909,"wof:name":"G92","mz:is_current":0},{"wof:id":1477855915,"wof:name":"G99X","mz:is_current":0},{"wof:id":1729792731,"wof:name":"C1","mz:is_current":1},{"wof:id":1729792739,"wof:name":"B22","mz:is_current":0},{"wof:id":1729792729,"wof:name":"B24","mz:is_current":0},{"wof:id":1729792761,"wof:name":"B15","mz:is_current":0},{"wof:id":1729792759,"wof:name":"B3","mz:is_current":0},{"wof:id":1477881719,"wof:name":"B6","mz:is_current":0},{"wof:id":1477881721,"wof:name":"B7","mz:is_current":0},{"wof:id":1477855875,"wof:name":"A9","mz:is_current":0},{"wof:id":1477881731,"wof:name":"B13","mz:is_current":0},{"wof:id":1477881733,"wof:name":"B14","mz:is_current":0},{"wof:id":1477881727,"wof:name":"B12","mz:is_current":0},{"wof:id":1477921771,"wof:name":"F76A","mz:is_current":0},{"wof:id":1477921773,"wof:name":"F76B","mz:is_current":0},{"wof:id":1477921769,"wof:name":"D59C","mz:is_current":0},{"wof:id":1477921765,"wof:name":"D59A","mz:is_current":0},{"wof:id":1477930295,"wof:name":"A6","mz:is_current":0},{"wof:id":1477930321,"wof:name":"C4","mz:is_current":0},{"wof:id":1477930291,"wof:name":"A5","mz:is_current":0},{"wof:id":1477930331,"wof:name":"C8","mz:is_current":0},{"wof:id":1477930341,"wof:name":"D2","mz:is_current":0},{"wof:id":1477930343,"wof:name":"D3","mz:is_current":0},{"wof:id":1477930361,"wof:name":"D11","mz:is_current":0},{"wof:id":1477930355,"wof:name":"D8","mz:is_current":0},{"wof:id":1477930371,"wof:name":"D16","mz:is_current":0},{"wof:id":1477930375,"wof:name":"D18","mz:is_current":0},{"wof:id":1477930379,"wof:name":"E2","mz:is_current":0},{"wof:id":1477930393,"wof:name":"E8","mz:is_current":0},{"wof:id":1477930399,"wof:name":"E11","mz:is_current":0},{"wof:id":1477930405,"wof:name":"E13","mz:is_current":0},{"wof:id":1477930431,"wof:name":"F10","mz:is_current":0},{"wof:id":1745882093,"wof:name":"D2","mz:is_current":0},{"wof:id":1477930441,"wof:name":"F14","mz:is_current":0},{"wof:id":1745882101,"wof:name":"D6","mz:is_current":0},{"wof:id":1477930445,"wof:name":"F16","mz:is_current":0},{"wof:id":1477930461,"wof:name":"G1","mz:is_current":0},{"wof:id":1745882115,"wof:name":"D12","mz:is_current":0},{"wof:id":1745882111,"wof:name":"D11","mz:is_current":0},{"wof:id":1477930467,"wof:name":"G4","mz:is_current":0},{"wof:id":1477930481,"wof:name":"G10","mz:is_current":0},{"wof:id":1477930479,"wof:name":"G9","mz:is_current":0},{"wof:id":1745882147,"wof:name":"B8","mz:is_current":0},{"wof:id":1745882171,"wof:name":"B26","mz:is_current":0},{"wof:id":1745882183,"wof:name":"B4","mz:is_current":0},{"wof:id":1745882191,"wof:name":"B15","mz:is_current":0},{"wof:id":1746415337,"wof:name":"C10R","mz:is_current":1},{"wof:id":1745882211,"wof:name":"C8","mz:is_current":0},{"wof:id":1746415345,"wof:name":"G12V","mz:is_current":1},{"wof:id":1746415343,"wof:name":"G12S","mz:is_current":1},{"wof:id":1745882207,"wof:name":"C6","mz:is_current":0},{"wof:id":1746415353,"wof:name":"A1V","mz:is_current":1},{"wof:id":1746415361,"wof:name":"A13V","mz:is_current":1},{"wof:id":1745882247,"wof:name":"F1","mz:is_current":0},{"wof:id":1745882251,"wof:name":"F3","mz:is_current":0},{"wof:id":1745882261,"wof:name":"F6","mz:is_current":0},{"wof:id":1745882265,"wof:name":"F7","mz:is_current":0},{"wof:id":1745882267,"wof:name":"F9","mz:is_current":0},{"wof:id":1746415391,"wof:name":"A4R","mz:is_current":1},{"wof:id":1745882285,"wof:name":"F17","mz:is_current":0},{"wof:id":1746415393,"wof:name":"G14T","mz:is_current":1},{"wof:id":1745882291,"wof:name":"F19","mz:is_current":0},{"wof:id":1746415405,"wof:name":"F15K","mz:is_current":1},{"wof:id":1745882295,"wof:name":"F21","mz:is_current":0},{"wof:id":1746415425,"wof:name":"A14T","mz:is_current":1},{"wof:id":1746415415,"wof:name":"E11U","mz:is_current":1},{"wof:id":1745882321,"wof:name":"E13","mz:is_current":0},{"wof:id":1745882347,"wof:name":"A7","mz:is_current":0},{"wof:id":1745882363,"wof:name":"A3","mz:is_current":0},{"wof:id":1745882359,"wof:name":"A11","mz:is_current":0},{"wof:id":1763588131,"wof:name":"D3","mz:is_current":1},{"wof:id":1745882381,"wof:name":"A8","mz:is_current":0},{"wof:id":1763588139,"wof:name":"D6","mz:is_current":1},{"wof:id":1745882387,"wof:name":"A10","mz:is_current":0},{"wof:id":1745882393,"wof:name":"A13","mz:is_current":0},{"wof:id":1763588145,"wof:name":"D8","mz:is_current":1},{"wof:id":1745882411,"wof:name":"G4","mz:is_current":0},{"wof:id":1763588149,"wof:name":"D10","mz:is_current":1},{"wof:id":1763588161,"wof:name":"D17","mz:is_current":1},{"wof:id":1745882431,"wof:name":"G13","mz:is_current":0},{"wof:id":1763588127,"wof:name":"D2","mz:is_current":1},{"wof:id":1763588189,"wof:name":"B9","mz:is_current":1},{"wof:id":1763588179,"wof:name":"B6","mz:is_current":1},{"wof:id":1763588251,"wof:name":"C9","mz:is_current":1},{"wof:id":1763588255,"wof:name":"C11","mz:is_current":1},{"wof:id":1763588281,"wof:name":"E3","mz:is_current":1},{"wof:id":1763588273,"wof:name":"F5","mz:is_current":0},{"wof:id":1763588291,"wof:name":"F3A","mz:is_current":1},{"wof:id":1763588293,"wof:name":"F5","mz:is_current":1},{"wof:id":1763588299,"wof:name":"F8","mz:is_current":1},{"wof:id":1763588321,"wof:name":"F17","mz:is_current":1},{"wof:id":1763588309,"wof:name":"F13","mz:is_current":1},{"wof:id":1763588333,"wof:name":"F22","mz:is_current":1},{"wof:id":1763588345,"wof:name":"E8","mz:is_current":1},{"wof:id":1763588353,"wof:name":"E11","mz:is_current":1},{"wof:id":1763588401,"wof:name":"A1","mz:is_current":1},{"wof:id":1763588391,"wof:name":"A8","mz:is_current":0},{"wof:id":1763588407,"wof:name":"A4","mz:is_current":1},{"wof:id":1763588431,"wof:name":"A10","mz:is_current":1},{"wof:id":1763588441,"wof:name":"G2","mz:is_current":1},{"wof:id":1763588425,"wof:name":"A14","mz:is_current":1},{"wof:id":1763588419,"wof:name":"A12","mz:is_current":1},{"wof:id":1763588451,"wof:name":"G7","mz:is_current":1},{"wof:id":1763588459,"wof:name":"G11","mz:is_current":1}] +[{"wof:id":1729792619,"wof:name":"A5","mz:is_current":0},{"wof:id":1477881723,"wof:name":"B8","mz:is_current":0},{"wof:id":1477881725,"wof:name":"B9","mz:is_current":0},{"wof:id":1477881727,"wof:name":"B12","mz:is_current":0},{"wof:id":1477881733,"wof:name":"B14","mz:is_current":0},{"wof:id":1477881735,"wof:name":"B17","mz:is_current":0},{"wof:id":1477881737,"wof:name":"B18","mz:is_current":0},{"wof:id":1729792623,"wof:name":"A8","mz:is_current":0},{"wof:id":1729792625,"wof:name":"A7","mz:is_current":0},{"wof:id":1729792627,"wof:name":"A9","mz:is_current":0},{"wof:id":1729792633,"wof:name":"A11","mz:is_current":0},{"wof:id":1477930351,"wof:name":"D6","mz:is_current":0},{"wof:id":1477930371,"wof:name":"D16","mz:is_current":0},{"wof:id":1477930361,"wof:name":"D11","mz:is_current":0},{"wof:id":1477930353,"wof:name":"D7","mz:is_current":0},{"wof:id":1477930363,"wof:name":"D12","mz:is_current":0},{"wof:id":1477930355,"wof:name":"D8","mz:is_current":0},{"wof:id":1477930373,"wof:name":"D17","mz:is_current":0},{"wof:id":1477930367,"wof:name":"D14","mz:is_current":0},{"wof:id":1477930357,"wof:name":"D9","mz:is_current":0},{"wof:id":1477930359,"wof:name":"D10","mz:is_current":0},{"wof:id":1477930375,"wof:name":"D18","mz:is_current":0},{"wof:id":1477930369,"wof:name":"D15","mz:is_current":0},{"wof:id":1477930377,"wof:name":"E1","mz:is_current":0},{"wof:id":1729792649,"wof:name":"G1","mz:is_current":0},{"wof:id":1729792651,"wof:name":"G2","mz:is_current":0},{"wof:id":1729792663,"wof:name":"G10","mz:is_current":0},{"wof:id":1477930379,"wof:name":"E2","mz:is_current":0},{"wof:id":1729792653,"wof:name":"G3","mz:is_current":0},{"wof:id":1729792673,"wof:name":"G12","mz:is_current":0},{"wof:id":1729792675,"wof:name":"G13","mz:is_current":0},{"wof:id":1729792677,"wof:name":"G14","mz:is_current":0},{"wof:id":1729792667,"wof:name":"G8","mz:is_current":0},{"wof:id":1729792669,"wof:name":"G11","mz:is_current":0},{"wof:id":1729792655,"wof:name":"G4","mz:is_current":0},{"wof:id":1729792657,"wof:name":"G5","mz:is_current":0},{"wof:id":1729792659,"wof:name":"G6","mz:is_current":0},{"wof:id":1729792635,"wof:name":"A12","mz:is_current":0},{"wof:id":1729792731,"wof:name":"C1","mz:is_current":1},{"wof:id":1729792723,"wof:name":"B10","mz:is_current":0},{"wof:id":1729792733,"wof:name":"B26","mz:is_current":0},{"wof:id":1729792725,"wof:name":"B25","mz:is_current":0},{"wof:id":1729792735,"wof:name":"B1","mz:is_current":0},{"wof:id":1729792743,"wof:name":"B19","mz:is_current":0},{"wof:id":1729792739,"wof:name":"B22","mz:is_current":0},{"wof:id":1729792745,"wof:name":"B20","mz:is_current":0},{"wof:id":1729792639,"wof:name":"A14","mz:is_current":0},{"wof:id":1729792753,"wof:name":"B16","mz:is_current":0},{"wof:id":1729792727,"wof:name":"B11","mz:is_current":0},{"wof:id":1729792763,"wof:name":"B27","mz:is_current":0},{"wof:id":1729792757,"wof:name":"B2","mz:is_current":0},{"wof:id":1729792759,"wof:name":"B3","mz:is_current":0},{"wof:id":1729792729,"wof:name":"B24","mz:is_current":0},{"wof:id":1729792747,"wof:name":"B5","mz:is_current":0},{"wof:id":1729792749,"wof:name":"B4","mz:is_current":0},{"wof:id":1745882093,"wof:name":"D2","mz:is_current":0},{"wof:id":1745882095,"wof:name":"D3","mz:is_current":0},{"wof:id":1745882097,"wof:name":"D4","mz:is_current":0},{"wof:id":1745882099,"wof:name":"D5","mz:is_current":0},{"wof:id":1745882089,"wof:name":"D1","mz:is_current":0},{"wof:id":1745882103,"wof:name":"D7","mz:is_current":0},{"wof:id":1745882107,"wof:name":"D8","mz:is_current":0},{"wof:id":1745882111,"wof:name":"D11","mz:is_current":0},{"wof:id":1745882123,"wof:name":"D17","mz:is_current":0},{"wof:id":1745882113,"wof:name":"D10","mz:is_current":0},{"wof:id":1745882125,"wof:name":"D18","mz:is_current":0},{"wof:id":1745882115,"wof:name":"D12","mz:is_current":0},{"wof:id":1745882117,"wof:name":"D14","mz:is_current":0},{"wof:id":1745882119,"wof:name":"D15","mz:is_current":0},{"wof:id":1745882143,"wof:name":"B7","mz:is_current":0},{"wof:id":1745882147,"wof:name":"B8","mz:is_current":0},{"wof:id":1745882149,"wof:name":"B9","mz:is_current":0},{"wof:id":1745882153,"wof:name":"B13","mz:is_current":0},{"wof:id":1745882155,"wof:name":"B14","mz:is_current":0},{"wof:id":1745882165,"wof:name":"B25","mz:is_current":0},{"wof:id":1745882157,"wof:name":"B17","mz:is_current":0},{"wof:id":1745882167,"wof:name":"B11","mz:is_current":0},{"wof:id":1745882159,"wof:name":"B18","mz:is_current":0},{"wof:id":1745882169,"wof:name":"B24","mz:is_current":0},{"wof:id":1745882187,"wof:name":"B16","mz:is_current":0},{"wof:id":1745882171,"wof:name":"B26","mz:is_current":0},{"wof:id":1745882173,"wof:name":"B22","mz:is_current":0},{"wof:id":1745882189,"wof:name":"B3","mz:is_current":0},{"wof:id":1745882175,"wof:name":"B21","mz:is_current":0},{"wof:id":1745882177,"wof:name":"B19","mz:is_current":0},{"wof:id":1745882193,"wof:name":"B27","mz:is_current":0},{"wof:id":1745882179,"wof:name":"B20","mz:is_current":0},{"wof:id":1745882197,"wof:name":"C2","mz:is_current":0},{"wof:id":1745882203,"wof:name":"C3","mz:is_current":0},{"wof:id":1745882205,"wof:name":"C5","mz:is_current":0},{"wof:id":1745882213,"wof:name":"C9","mz:is_current":0},{"wof:id":1745882207,"wof:name":"C6","mz:is_current":0},{"wof:id":1745882215,"wof:name":"C10","mz:is_current":0},{"wof:id":1745882219,"wof:name":"C11","mz:is_current":0},{"wof:id":1745882209,"wof:name":"C7","mz:is_current":0},{"wof:id":1745882239,"wof:name":"F5","mz:is_current":0},{"wof:id":1745882243,"wof:name":"E2","mz:is_current":0},{"wof:id":1745882229,"wof:name":"B1","mz:is_current":1},{"wof:id":1745882251,"wof:name":"F3","mz:is_current":0},{"wof:id":1745882247,"wof:name":"F1","mz:is_current":0},{"wof:id":1745882255,"wof:name":"F4","mz:is_current":0},{"wof:id":1745882249,"wof:name":"F2","mz:is_current":0},{"wof:id":1745882259,"wof:name":"F5","mz:is_current":0},{"wof:id":1745882261,"wof:name":"F6","mz:is_current":0},{"wof:id":1745882265,"wof:name":"F7","mz:is_current":0},{"wof:id":1745882273,"wof:name":"F11","mz:is_current":0},{"wof:id":1745882267,"wof:name":"F9","mz:is_current":0},{"wof:id":1745882275,"wof:name":"F13","mz:is_current":0},{"wof:id":1745882269,"wof:name":"F10","mz:is_current":0},{"wof:id":1745882277,"wof:name":"F12","mz:is_current":0},{"wof:id":1745882283,"wof:name":"F16","mz:is_current":0},{"wof:id":1745882291,"wof:name":"F19","mz:is_current":0},{"wof:id":1745882285,"wof:name":"F17","mz:is_current":0},{"wof:id":1745882293,"wof:name":"F20","mz:is_current":0},{"wof:id":1745882287,"wof:name":"F18","mz:is_current":0},{"wof:id":1745882295,"wof:name":"F21","mz:is_current":0},{"wof:id":1745882303,"wof:name":"E5","mz:is_current":0},{"wof:id":1745882297,"wof:name":"F22","mz:is_current":0},{"wof:id":1745882305,"wof:name":"E6","mz:is_current":0},{"wof:id":1745882309,"wof:name":"E7","mz:is_current":0},{"wof:id":1745882313,"wof:name":"E9","mz:is_current":0},{"wof:id":1745882315,"wof:name":"E10","mz:is_current":0},{"wof:id":1745882317,"wof:name":"E11","mz:is_current":0},{"wof:id":1745882319,"wof:name":"E12","mz:is_current":0},{"wof:id":1745882345,"wof:name":"A5","mz:is_current":0},{"wof:id":1745882347,"wof:name":"A7","mz:is_current":0},{"wof:id":1745882349,"wof:name":"A6","mz:is_current":0},{"wof:id":1745882339,"wof:name":"A2","mz:is_current":0},{"wof:id":1745882353,"wof:name":"A9","mz:is_current":0},{"wof:id":1745882363,"wof:name":"A3","mz:is_current":0},{"wof:id":1745882357,"wof:name":"A12","mz:is_current":0},{"wof:id":1745882365,"wof:name":"A1","mz:is_current":0},{"wof:id":1745882359,"wof:name":"A11","mz:is_current":0},{"wof:id":1745882367,"wof:name":"A1","mz:is_current":0},{"wof:id":1745882381,"wof:name":"A8","mz:is_current":0},{"wof:id":1745882373,"wof:name":"A4","mz:is_current":0},{"wof:id":1745882383,"wof:name":"A7","mz:is_current":0},{"wof:id":1745882375,"wof:name":"A5","mz:is_current":0},{"wof:id":1745882377,"wof:name":"A6","mz:is_current":0},{"wof:id":1745882385,"wof:name":"A9","mz:is_current":0},{"wof:id":1745882393,"wof:name":"A13","mz:is_current":0},{"wof:id":1745882387,"wof:name":"A10","mz:is_current":0},{"wof:id":1745882395,"wof:name":"A14","mz:is_current":0},{"wof:id":1745882389,"wof:name":"A12","mz:is_current":0},{"wof:id":1745882399,"wof:name":"A15","mz:is_current":0},{"wof:id":1745882405,"wof:name":"G1","mz:is_current":0},{"wof:id":1745882411,"wof:name":"G4","mz:is_current":0},{"wof:id":1745882407,"wof:name":"G2","mz:is_current":0},{"wof:id":1745882409,"wof:name":"G3","mz:is_current":0},{"wof:id":1745882435,"wof:name":"G14","mz:is_current":0},{"wof:id":1745882421,"wof:name":"G10","mz:is_current":0},{"wof:id":1745882423,"wof:name":"G8","mz:is_current":0},{"wof:id":1745882425,"wof:name":"G11","mz:is_current":0},{"wof:id":1745882413,"wof:name":"G5","mz:is_current":0},{"wof:id":1745882417,"wof:name":"G6","mz:is_current":0},{"wof:id":1745882419,"wof:name":"G7","mz:is_current":0},{"wof:id":1746415339,"wof:name":"A13R","mz:is_current":1},{"wof:id":1746415345,"wof:name":"G12V","mz:is_current":1},{"wof:id":1746415347,"wof:name":"F15M","mz:is_current":1},{"wof:id":1746415349,"wof:name":"C4U","mz:is_current":1},{"wof:id":1746415353,"wof:name":"A1V","mz:is_current":1},{"wof:id":1746415355,"wof:name":"E13T","mz:is_current":1},{"wof:id":1746415357,"wof:name":"G13R","mz:is_current":1},{"wof:id":1746415363,"wof:name":"E10V","mz:is_current":1},{"wof:id":1746415365,"wof:name":"A1T","mz:is_current":1},{"wof:id":1746415367,"wof:name":"G11R","mz:is_current":1},{"wof:id":1746415369,"wof:name":"B23V","mz:is_current":1},{"wof:id":1746415373,"wof:name":"B27V","mz:is_current":1},{"wof:id":1746415375,"wof:name":"F15L","mz:is_current":1},{"wof:id":1746415379,"wof:name":"F15N","mz:is_current":1},{"wof:id":1746415383,"wof:name":"G104","mz:is_current":1},{"wof:id":1746415385,"wof:name":"G13S","mz:is_current":1},{"wof:id":1746415387,"wof:name":"G103","mz:is_current":1},{"wof:id":1746415393,"wof:name":"G14T","mz:is_current":1},{"wof:id":1746415389,"wof:name":"A6S","mz:is_current":1},{"wof:id":1746415399,"wof:name":"A6R","mz:is_current":1},{"wof:id":1746415401,"wof:name":"E3T","mz:is_current":1},{"wof:id":1746415415,"wof:name":"E11U","mz:is_current":1},{"wof:id":1746415403,"wof:name":"B20S","mz:is_current":1},{"wof:id":1746415417,"wof:name":"E13K","mz:is_current":1},{"wof:id":1746415405,"wof:name":"F15K","mz:is_current":1},{"wof:id":1746415419,"wof:name":"E10U","mz:is_current":1},{"wof:id":1746415421,"wof:name":"E3K","mz:is_current":1},{"wof:id":1746415409,"wof:name":"E11V","mz:is_current":1},{"wof:id":1746415423,"wof:name":"A4T","mz:is_current":1},{"wof:id":1745882427,"wof:name":"G9","mz:is_current":0},{"wof:id":1745882429,"wof:name":"G12","mz:is_current":0},{"wof:id":1763588135,"wof:name":"D4","mz:is_current":1},{"wof:id":1763588137,"wof:name":"D5","mz:is_current":1},{"wof:id":1763588139,"wof:name":"D6","mz:is_current":1},{"wof:id":1763588129,"wof:name":"D1","mz:is_current":1},{"wof:id":1763588155,"wof:name":"D14","mz:is_current":1},{"wof:id":1763588157,"wof:name":"D16","mz:is_current":1},{"wof:id":1763588141,"wof:name":"D7","mz:is_current":1},{"wof:id":1763588159,"wof:name":"D15","mz:is_current":1},{"wof:id":1763588161,"wof:name":"D17","mz:is_current":1},{"wof:id":1763588145,"wof:name":"D8","mz:is_current":1},{"wof:id":1763588147,"wof:name":"D11","mz:is_current":1},{"wof:id":1763588163,"wof:name":"D18","mz:is_current":1},{"wof:id":1763588149,"wof:name":"D10","mz:is_current":1},{"wof:id":1763588181,"wof:name":"B7","mz:is_current":1},{"wof:id":1763588183,"wof:name":"B8","mz:is_current":1},{"wof:id":1763588185,"wof:name":"B12","mz:is_current":1},{"wof:id":1763588179,"wof:name":"B6","mz:is_current":1},{"wof:id":1763588189,"wof:name":"B9","mz:is_current":1},{"wof:id":1763588193,"wof:name":"B14","mz:is_current":1},{"wof:id":1763588197,"wof:name":"B18","mz:is_current":1},{"wof:id":1763588201,"wof:name":"B25","mz:is_current":1},{"wof:id":1763588199,"wof:name":"B10","mz:is_current":1},{"wof:id":1763588203,"wof:name":"B11","mz:is_current":1},{"wof:id":1763588213,"wof:name":"B22","mz:is_current":1},{"wof:id":1763588207,"wof:name":"B24","mz:is_current":1},{"wof:id":1763588215,"wof:name":"B4","mz:is_current":1},{"wof:id":1763588209,"wof:name":"B26","mz:is_current":1},{"wof:id":1763588217,"wof:name":"B27","mz:is_current":1},{"wof:id":1763588219,"wof:name":"B21","mz:is_current":1},{"wof:id":1763588225,"wof:name":"B19","mz:is_current":1},{"wof:id":1763588235,"wof:name":"C2","mz:is_current":1},{"wof:id":1763588227,"wof:name":"B16","mz:is_current":1},{"wof:id":1763588237,"wof:name":"C4","mz:is_current":1},{"wof:id":1763588229,"wof:name":"B20","mz:is_current":1},{"wof:id":1763588239,"wof:name":"C3","mz:is_current":1},{"wof:id":1763588255,"wof:name":"C11","mz:is_current":1},{"wof:id":1763588243,"wof:name":"C5","mz:is_current":1},{"wof:id":1763588245,"wof:name":"C6","mz:is_current":1},{"wof:id":1763588247,"wof:name":"C8","mz:is_current":1},{"wof:id":1763588249,"wof:name":"C7","mz:is_current":1},{"wof:id":1763588273,"wof:name":"F5","mz:is_current":0},{"wof:id":1763588275,"wof:name":"E1","mz:is_current":1},{"wof:id":1763588267,"wof:name":"B2","mz:is_current":1},{"wof:id":1763588279,"wof:name":"E2","mz:is_current":1},{"wof:id":1763588283,"wof:name":"F1","mz:is_current":1},{"wof:id":1763588291,"wof:name":"F3A","mz:is_current":1},{"wof:id":1763588293,"wof:name":"F5","mz:is_current":1},{"wof:id":1763588285,"wof:name":"F3","mz:is_current":1},{"wof:id":1763588297,"wof:name":"F6","mz:is_current":1},{"wof:id":1763588287,"wof:name":"F2","mz:is_current":1},{"wof:id":1763588299,"wof:name":"F8","mz:is_current":1},{"wof:id":1763588289,"wof:name":"F4","mz:is_current":1},{"wof:id":1763588305,"wof:name":"F10","mz:is_current":1},{"wof:id":1763588311,"wof:name":"F12","mz:is_current":1},{"wof:id":1763588307,"wof:name":"F11","mz:is_current":1},{"wof:id":1763588315,"wof:name":"F14","mz:is_current":1},{"wof:id":1763588309,"wof:name":"F13","mz:is_current":1},{"wof:id":1763588317,"wof:name":"F15","mz:is_current":1},{"wof:id":1763588319,"wof:name":"F16","mz:is_current":1},{"wof:id":1763588323,"wof:name":"F18","mz:is_current":1},{"wof:id":1763588325,"wof:name":"F19","mz:is_current":1},{"wof:id":1763588337,"wof:name":"E4","mz:is_current":1},{"wof:id":1763588327,"wof:name":"F20","mz:is_current":1},{"wof:id":1763588339,"wof:name":"E5","mz:is_current":1},{"wof:id":1763588343,"wof:name":"E7","mz:is_current":1},{"wof:id":1746415425,"wof:name":"A14T","mz:is_current":1},{"wof:id":1763588329,"wof:name":"F21","mz:is_current":1},{"wof:id":1763588351,"wof:name":"E9","mz:is_current":1},{"wof:id":1763588347,"wof:name":"E10","mz:is_current":1},{"wof:id":1763588373,"wof:name":"A11","mz:is_current":0},{"wof:id":1763588375,"wof:name":"A10","mz:is_current":0},{"wof:id":1763588377,"wof:name":"A4","mz:is_current":0},{"wof:id":1763588379,"wof:name":"A9","mz:is_current":0},{"wof:id":1763588393,"wof:name":"A3","mz:is_current":1},{"wof:id":1763588383,"wof:name":"A7","mz:is_current":0},{"wof:id":1763588405,"wof:name":"A2","mz:is_current":1},{"wof:id":1763588353,"wof:name":"E11","mz:is_current":1},{"wof:id":1763588355,"wof:name":"E12","mz:is_current":1},{"wof:id":1763588407,"wof:name":"A4","mz:is_current":1},{"wof:id":1763588357,"wof:name":"E13","mz:is_current":1},{"wof:id":1763588409,"wof:name":"A5","mz:is_current":1},{"wof:id":1763588425,"wof:name":"A14","mz:is_current":1},{"wof:id":1763588413,"wof:name":"A8","mz:is_current":1},{"wof:id":1763588427,"wof:name":"A15","mz:is_current":1},{"wof:id":1763588429,"wof:name":"A11","mz:is_current":1},{"wof:id":1763588415,"wof:name":"A7","mz:is_current":0},{"wof:id":1763588419,"wof:name":"A12","mz:is_current":1},{"wof:id":1763588431,"wof:name":"A10","mz:is_current":1},{"wof:id":1763588443,"wof:name":"G3","mz:is_current":1},{"wof:id":1763588445,"wof:name":"G4","mz:is_current":1},{"wof:id":1763588437,"wof:name":"G1","mz:is_current":1},{"wof:id":1763588447,"wof:name":"G5","mz:is_current":1},{"wof:id":1763588453,"wof:name":"G10","mz:is_current":1},{"wof:id":1763588461,"wof:name":"G9","mz:is_current":1},{"wof:id":1763588463,"wof:name":"G12","mz:is_current":1},{"wof:id":1763588455,"wof:name":"G8","mz:is_current":1},{"wof:id":1763588465,"wof:name":"G13","mz:is_current":1},{"wof:id":1763588467,"wof:name":"G14","mz:is_current":1},{"wof:id":1763588459,"wof:name":"G11","mz:is_current":1},{"wof:id":1763588483,"wof:name":"B5","mz:is_current":1},{"wof:id":1763588395,"wof:name":"A5","mz:is_current":0},{"wof:id":1159157603,"wof:name":"A10A","mz:is_current":0},{"wof:id":1159157605,"wof:name":"A11B","mz:is_current":0},{"wof:id":1159157607,"wof:name":"A12","mz:is_current":0},{"wof:id":1159157609,"wof:name":"A2","mz:is_current":0},{"wof:id":1159157611,"wof:name":"A3A","mz:is_current":0},{"wof:id":1159157613,"wof:name":"A1","mz:is_current":0},{"wof:id":1159157615,"wof:name":"G101A","mz:is_current":0},{"wof:id":1159157617,"wof:name":"A1A","mz:is_current":0},{"wof:id":1159157621,"wof:name":"G95","mz:is_current":0},{"wof:id":1159157623,"wof:name":"G91","mz:is_current":0},{"wof:id":1159157625,"wof:name":"B22","mz:is_current":0},{"wof:id":1159157627,"wof:name":"A11","mz:is_current":0},{"wof:id":1159157629,"wof:name":"A11A","mz:is_current":0},{"wof:id":1763588387,"wof:name":"A2","mz:is_current":0},{"wof:id":1159157633,"wof:name":"A9","mz:is_current":0},{"wof:id":1159157631,"wof:name":"A8","mz:is_current":0},{"wof:id":1159157635,"wof:name":"A6","mz:is_current":0},{"wof:id":1159157639,"wof:name":"A7","mz:is_current":0},{"wof:id":1159157641,"wof:name":"A4","mz:is_current":0},{"wof:id":1159157643,"wof:name":"A5B","mz:is_current":0},{"wof:id":1159157645,"wof:name":"F79","mz:is_current":0},{"wof:id":1159157647,"wof:name":"E63","mz:is_current":0},{"wof:id":1159157649,"wof:name":"D53","mz:is_current":0},{"wof:id":1159157651,"wof:name":"D58B","mz:is_current":0},{"wof:id":1159157653,"wof:name":"E65","mz:is_current":0},{"wof:id":1159157657,"wof:name":"G96","mz:is_current":0},{"wof:id":1159157659,"wof:name":"F73","mz:is_current":0},{"wof:id":1159157661,"wof:name":"C44","mz:is_current":0},{"wof:id":1159157663,"wof:name":"C46","mz:is_current":0},{"wof:id":1159157667,"wof:name":"A1B","mz:is_current":0},{"wof:id":1159157665,"wof:name":"F89","mz:is_current":0},{"wof:id":1159157669,"wof:name":"F73A","mz:is_current":0},{"wof:id":1159157671,"wof:name":"F86","mz:is_current":0},{"wof:id":1159157675,"wof:name":"F87","mz:is_current":0},{"wof:id":1159157677,"wof:name":"G102","mz:is_current":0},{"wof:id":1159157679,"wof:name":"G99A","mz:is_current":0},{"wof:id":1159157681,"wof:name":"G99B","mz:is_current":0},{"wof:id":1159157693,"wof:name":"F84D","mz:is_current":0},{"wof:id":1159157695,"wof:name":"F84C","mz:is_current":0},{"wof:id":1159157699,"wof:name":"E68","mz:is_current":0},{"wof:id":1159157697,"wof:name":"F74","mz:is_current":0},{"wof:id":1159157683,"wof:name":"G97","mz:is_current":0},{"wof:id":1159157685,"wof:name":"G100","mz:is_current":0},{"wof:id":1159157687,"wof:name":"G98","mz:is_current":0},{"wof:id":1159157689,"wof:name":"F84B","mz:is_current":0},{"wof:id":1159157711,"wof:name":"C42","mz:is_current":0},{"wof:id":1159157713,"wof:name":"B25","mz:is_current":0},{"wof:id":1159157715,"wof:name":"B24","mz:is_current":0},{"wof:id":1159157717,"wof:name":"A3","mz:is_current":0},{"wof:id":1159157719,"wof:name":"G101B","mz:is_current":0},{"wof:id":1159157721,"wof:name":"F70","mz:is_current":0},{"wof:id":1159157723,"wof:name":"F71A","mz:is_current":0},{"wof:id":1159157725,"wof:name":"F71B","mz:is_current":0},{"wof:id":1159157731,"wof:name":"F70A","mz:is_current":0},{"wof:id":1159157729,"wof:name":"F76","mz:is_current":0},{"wof:id":1159157735,"wof:name":"E65A","mz:is_current":0},{"wof:id":1159157737,"wof:name":"E64A","mz:is_current":0},{"wof:id":1159157739,"wof:name":"F77C","mz:is_current":0},{"wof:id":1159157733,"wof:name":"E67","mz:is_current":0},{"wof:id":1159157741,"wof:name":"F90","mz:is_current":0},{"wof:id":1159157743,"wof:name":"C48","mz:is_current":0},{"wof:id":1159157747,"wof:name":"C41","mz:is_current":0},{"wof:id":1159157749,"wof:name":"F85","mz:is_current":0},{"wof:id":1159157751,"wof:name":"F88","mz:is_current":0},{"wof:id":1159157753,"wof:name":"C47","mz:is_current":0},{"wof:id":1159157755,"wof:name":"C45A","mz:is_current":0},{"wof:id":1159157757,"wof:name":"F81","mz:is_current":0},{"wof:id":1159157759,"wof:name":"E69","mz:is_current":0},{"wof:id":1159157701,"wof:name":"D50A","mz:is_current":0},{"wof:id":1159157707,"wof:name":"C45B","mz:is_current":0},{"wof:id":1159157703,"wof:name":"D51A","mz:is_current":0},{"wof:id":1159157705,"wof:name":"D51B","mz:is_current":0},{"wof:id":1159157783,"wof:name":"F75","mz:is_current":0},{"wof:id":1159157785,"wof:name":"E64","mz:is_current":0},{"wof:id":1159157791,"wof:name":"D58A","mz:is_current":0},{"wof:id":1159157789,"wof:name":"E66","mz:is_current":0},{"wof:id":1159157787,"wof:name":"E67A","mz:is_current":0},{"wof:id":1159157795,"wof:name":"D56B","mz:is_current":0},{"wof:id":1159157793,"wof:name":"D55","mz:is_current":0},{"wof:id":1159157801,"wof:name":"D57","mz:is_current":0},{"wof:id":1159157803,"wof:name":"C43","mz:is_current":0},{"wof:id":1159157805,"wof:name":"A5","mz:is_current":0},{"wof:id":1159157807,"wof:name":"A3B","mz:is_current":0},{"wof:id":1159157809,"wof:name":"B26","mz:is_current":0},{"wof:id":1159157797,"wof:name":"D56A","mz:is_current":0},{"wof:id":1159157811,"wof:name":"B27","mz:is_current":0},{"wof:id":1159157813,"wof:name":"B23","mz:is_current":0},{"wof:id":1159157819,"wof:name":"C48A","mz:is_current":0},{"wof:id":1159157815,"wof:name":"G99","mz:is_current":0},{"wof:id":1159157821,"wof:name":"F80","mz:is_current":0},{"wof:id":1159157823,"wof:name":"A10","mz:is_current":0},{"wof:id":1159157825,"wof:name":"F72","mz:is_current":0},{"wof:id":1159157829,"wof:name":"D52","mz:is_current":0},{"wof:id":1159157827,"wof:name":"G101","mz:is_current":0},{"wof:id":1159157837,"wof:name":"F84A","mz:is_current":0},{"wof:id":1159157831,"wof:name":"D54B","mz:is_current":0},{"wof:id":1159157833,"wof:name":"D54A","mz:is_current":0},{"wof:id":1159157843,"wof:name":"A3X","mz:is_current":0},{"wof:id":1159157845,"wof:name":"C42A","mz:is_current":0},{"wof:id":1159157841,"wof:name":"G99X","mz:is_current":0},{"wof:id":1159157839,"wof:name":"D50B","mz:is_current":0},{"wof:id":1159157847,"wof:name":"F77A","mz:is_current":0},{"wof:id":1159157849,"wof:name":"F87A","mz:is_current":0},{"wof:id":1159157851,"wof:name":"E62A","mz:is_current":0},{"wof:id":1159157857,"wof:name":"C40","mz:is_current":0},{"wof:id":1159157855,"wof:name":"F78","mz:is_current":0},{"wof:id":1159157859,"wof:name":"B28","mz:is_current":0},{"wof:id":1159157769,"wof:name":"F77B","mz:is_current":0},{"wof:id":1159157761,"wof:name":"F82","mz:is_current":0},{"wof:id":1159157767,"wof:name":"E61","mz:is_current":0},{"wof:id":1159157765,"wof:name":"E60","mz:is_current":0},{"wof:id":1159157861,"wof:name":"F83","mz:is_current":0},{"wof:id":1159157771,"wof:name":"E62","mz:is_current":0},{"wof:id":1159157773,"wof:name":"D59","mz:is_current":0},{"wof:id":1159157775,"wof:name":"G93","mz:is_current":0},{"wof:id":1159157779,"wof:name":"G92","mz:is_current":0},{"wof:id":1159157777,"wof:name":"G94","mz:is_current":0},{"wof:id":1477855621,"wof:name":"D50A","mz:is_current":0},{"wof:id":1477855615,"wof:name":"D52","mz:is_current":0},{"wof:id":1477855617,"wof:name":"D51A","mz:is_current":0},{"wof:id":1477855619,"wof:name":"D51B","mz:is_current":0},{"wof:id":1477855631,"wof:name":"D57","mz:is_current":0},{"wof:id":1477855641,"wof:name":"D54B","mz:is_current":0},{"wof:id":1477855633,"wof:name":"D59","mz:is_current":0},{"wof:id":1477855643,"wof:name":"D55","mz:is_current":0},{"wof:id":1477855635,"wof:name":"D53","mz:is_current":0},{"wof:id":1477855645,"wof:name":"D56A","mz:is_current":0},{"wof:id":1477855637,"wof:name":"D54A","mz:is_current":0},{"wof:id":1477855639,"wof:name":"D50B","mz:is_current":0},{"wof:id":1477855649,"wof:name":"D56B","mz:is_current":0},{"wof:id":1477855623,"wof:name":"D58B","mz:is_current":0},{"wof:id":1477855651,"wof:name":"D58A","mz:is_current":0},{"wof:id":1376996231,"wof:name":"B28","mz:is_current":0},{"wof:id":1477855671,"wof:name":"C45","mz:is_current":0},{"wof:id":1477855673,"wof:name":"C47","mz:is_current":0},{"wof:id":1477855675,"wof:name":"C45A","mz:is_current":0},{"wof:id":1477855681,"wof:name":"C42","mz:is_current":0},{"wof:id":1477855691,"wof:name":"C43","mz:is_current":0},{"wof:id":1477855677,"wof:name":"C48","mz:is_current":0},{"wof:id":1477855693,"wof:name":"C42A","mz:is_current":0},{"wof:id":1477855679,"wof:name":"C41","mz:is_current":0},{"wof:id":1477855687,"wof:name":"C46","mz:is_current":0},{"wof:id":1477855685,"wof:name":"C45B","mz:is_current":0},{"wof:id":1477855695,"wof:name":"C48A","mz:is_current":0},{"wof:id":1477855697,"wof:name":"C40","mz:is_current":0},{"wof:id":1477855689,"wof:name":"C44","mz:is_current":0},{"wof:id":1477855705,"wof:name":"F77","mz:is_current":0},{"wof:id":1477855711,"wof:name":"F74","mz:is_current":0},{"wof:id":1477855713,"wof:name":"F84C","mz:is_current":0},{"wof:id":1477855707,"wof:name":"F84","mz:is_current":0},{"wof:id":1477855709,"wof:name":"F84D","mz:is_current":0},{"wof:id":1477855715,"wof:name":"F71A","mz:is_current":0},{"wof:id":1477855721,"wof:name":"F71B","mz:is_current":0},{"wof:id":1477855717,"wof:name":"F76","mz:is_current":0},{"wof:id":1477855723,"wof:name":"F70","mz:is_current":0},{"wof:id":1477855733,"wof:name":"F81","mz:is_current":0},{"wof:id":1477855735,"wof:name":"F88","mz:is_current":0},{"wof:id":1477855739,"wof:name":"F85","mz:is_current":0},{"wof:id":1477855751,"wof:name":"F73A","mz:is_current":0},{"wof:id":1477855741,"wof:name":"F90","mz:is_current":0},{"wof:id":1477855743,"wof:name":"F77B","mz:is_current":0},{"wof:id":1477855753,"wof:name":"F89","mz:is_current":0},{"wof:id":1477855745,"wof:name":"F82","mz:is_current":0},{"wof:id":1477855747,"wof:name":"F72","mz:is_current":0},{"wof:id":1477855757,"wof:name":"F73","mz:is_current":0},{"wof:id":1477855759,"wof:name":"F84B","mz:is_current":0},{"wof:id":1477855749,"wof:name":"F80","mz:is_current":0},{"wof:id":1477855771,"wof:name":"F78","mz:is_current":0},{"wof:id":1477855761,"wof:name":"F83","mz:is_current":0},{"wof:id":1477855765,"wof:name":"F79","mz:is_current":0},{"wof:id":1477855775,"wof:name":"F87","mz:is_current":0},{"wof:id":1477855777,"wof:name":"F86","mz:is_current":0},{"wof:id":1477855779,"wof:name":"F77C","mz:is_current":0},{"wof:id":1477855767,"wof:name":"F87A","mz:is_current":0},{"wof:id":1477855769,"wof:name":"F77A","mz:is_current":0},{"wof:id":1477855763,"wof:name":"F75","mz:is_current":0},{"wof:id":1477855793,"wof:name":"E69","mz:is_current":0},{"wof:id":1477855795,"wof:name":"E61","mz:is_current":0},{"wof:id":1477855797,"wof:name":"E60","mz:is_current":0},{"wof:id":1477855799,"wof:name":"E65","mz:is_current":0},{"wof:id":1477855781,"wof:name":"F70A","mz:is_current":0},{"wof:id":1477855783,"wof:name":"F84A","mz:is_current":0},{"wof:id":1477855789,"wof:name":"E68","mz:is_current":0},{"wof:id":1477855815,"wof:name":"E67","mz:is_current":0},{"wof:id":1477855811,"wof:name":"E63","mz:is_current":0},{"wof:id":1477855813,"wof:name":"E62A","mz:is_current":0},{"wof:id":1477855819,"wof:name":"E65A","mz:is_current":0},{"wof:id":1477855817,"wof:name":"E64A","mz:is_current":0},{"wof:id":1477855837,"wof:name":"A11A","mz:is_current":0},{"wof:id":1477855839,"wof:name":"A11","mz:is_current":0},{"wof:id":1477855843,"wof:name":"A1A","mz:is_current":0},{"wof:id":1477855841,"wof:name":"A1","mz:is_current":0},{"wof:id":1477855847,"wof:name":"A3A","mz:is_current":0},{"wof:id":1477855851,"wof:name":"A10","mz:is_current":0},{"wof:id":1477855849,"wof:name":"A3","mz:is_current":0},{"wof:id":1477855853,"wof:name":"A1B","mz:is_current":0},{"wof:id":1477855855,"wof:name":"A3B","mz:is_current":0},{"wof:id":1477855859,"wof:name":"A5B","mz:is_current":0},{"wof:id":1477855857,"wof:name":"A5","mz:is_current":0},{"wof:id":1477855861,"wof:name":"A4","mz:is_current":0},{"wof:id":1477855865,"wof:name":"A10A","mz:is_current":0},{"wof:id":1477855867,"wof:name":"A2","mz:is_current":0},{"wof:id":1477855869,"wof:name":"A12","mz:is_current":0},{"wof:id":1477855873,"wof:name":"A3X","mz:is_current":0},{"wof:id":1477855875,"wof:name":"A9","mz:is_current":0},{"wof:id":1477855871,"wof:name":"A11B","mz:is_current":0},{"wof:id":1477855801,"wof:name":"E66","mz:is_current":0},{"wof:id":1477855805,"wof:name":"E64","mz:is_current":0},{"wof:id":1477855879,"wof:name":"A6","mz:is_current":0},{"wof:id":1477855877,"wof:name":"A7","mz:is_current":0},{"wof:id":1477855803,"wof:name":"E67A","mz:is_current":0},{"wof:id":1477855891,"wof:name":"G101A","mz:is_current":0},{"wof:id":1477855807,"wof:name":"E62","mz:is_current":0},{"wof:id":1477855893,"wof:name":"G101B","mz:is_current":0},{"wof:id":1477855895,"wof:name":"G101","mz:is_current":0},{"wof:id":1477855901,"wof:name":"G97","mz:is_current":0},{"wof:id":1477855897,"wof:name":"G96","mz:is_current":0},{"wof:id":1477855903,"wof:name":"G98","mz:is_current":0},{"wof:id":1477855905,"wof:name":"G100","mz:is_current":0},{"wof:id":1477855907,"wof:name":"G99B","mz:is_current":0},{"wof:id":1477855909,"wof:name":"G92","mz:is_current":0},{"wof:id":1477855913,"wof:name":"G93","mz:is_current":0},{"wof:id":1477855915,"wof:name":"G99X","mz:is_current":0},{"wof:id":1477855911,"wof:name":"G94","mz:is_current":0},{"wof:id":1477855919,"wof:name":"G99","mz:is_current":0},{"wof:id":1477855883,"wof:name":"A8","mz:is_current":0},{"wof:id":1477855921,"wof:name":"G99A","mz:is_current":0},{"wof:id":1477855887,"wof:name":"G91","mz:is_current":0},{"wof:id":1477855923,"wof:name":"G102","mz:is_current":0},{"wof:id":1477855889,"wof:name":"G95","mz:is_current":0},{"wof:id":1477921765,"wof:name":"D59A","mz:is_current":0},{"wof:id":1477921769,"wof:name":"D59C","mz:is_current":0},{"wof:id":1477921767,"wof:name":"D59B","mz:is_current":0},{"wof:id":1477921771,"wof:name":"F76A","mz:is_current":0},{"wof:id":1477921773,"wof:name":"F76B","mz:is_current":0},{"wof:id":1477930281,"wof:name":"A1","mz:is_current":0},{"wof:id":1477930283,"wof:name":"A2","mz:is_current":0},{"wof:id":1477930287,"wof:name":"A3","mz:is_current":0},{"wof:id":1477930291,"wof:name":"A5","mz:is_current":0},{"wof:id":1477930289,"wof:name":"A4","mz:is_current":0},{"wof:id":1477930295,"wof:name":"A6","mz:is_current":0},{"wof:id":1477930297,"wof:name":"A7","mz:is_current":0},{"wof:id":1477930299,"wof:name":"A8","mz:is_current":0},{"wof:id":1477930301,"wof:name":"A9","mz:is_current":0},{"wof:id":1477930303,"wof:name":"A10","mz:is_current":0},{"wof:id":1477930305,"wof:name":"A11","mz:is_current":0},{"wof:id":1477930307,"wof:name":"A12","mz:is_current":0},{"wof:id":1477930309,"wof:name":"A13","mz:is_current":0},{"wof:id":1477930313,"wof:name":"A14","mz:is_current":0},{"wof:id":1477930315,"wof:name":"A15","mz:is_current":0},{"wof:id":1477930317,"wof:name":"C2","mz:is_current":0},{"wof:id":1477930319,"wof:name":"C3","mz:is_current":0},{"wof:id":1477930333,"wof:name":"C9","mz:is_current":0},{"wof:id":1477930331,"wof:name":"C8","mz:is_current":0},{"wof:id":1477930337,"wof:name":"C11","mz:is_current":0},{"wof:id":1477930335,"wof:name":"C10","mz:is_current":0},{"wof:id":1477930341,"wof:name":"D2","mz:is_current":0},{"wof:id":1477930339,"wof:name":"D1","mz:is_current":0},{"wof:id":1477930343,"wof:name":"D3","mz:is_current":0},{"wof:id":1477930345,"wof:name":"D4","mz:is_current":0},{"wof:id":1477930349,"wof:name":"D5","mz:is_current":0},{"wof:id":1477930321,"wof:name":"C4","mz:is_current":0},{"wof:id":1477930323,"wof:name":"C5","mz:is_current":0},{"wof:id":1477930325,"wof:name":"C6","mz:is_current":0},{"wof:id":1477930327,"wof:name":"C7","mz:is_current":0},{"wof:id":1477930385,"wof:name":"E4","mz:is_current":0},{"wof:id":1477930387,"wof:name":"E5","mz:is_current":0},{"wof:id":1477930381,"wof:name":"E3","mz:is_current":0},{"wof:id":1477930389,"wof:name":"E6","mz:is_current":0},{"wof:id":1477930391,"wof:name":"E7","mz:is_current":0},{"wof:id":1477930393,"wof:name":"E8","mz:is_current":0},{"wof:id":1477930399,"wof:name":"E11","mz:is_current":0},{"wof:id":1477930397,"wof:name":"E10","mz:is_current":0},{"wof:id":1477930395,"wof:name":"E9","mz:is_current":0},{"wof:id":1477930403,"wof:name":"E12","mz:is_current":0},{"wof:id":1477930407,"wof:name":"F1","mz:is_current":0},{"wof:id":1477930405,"wof:name":"E13","mz:is_current":0},{"wof:id":1477930411,"wof:name":"F3","mz:is_current":0},{"wof:id":1477930413,"wof:name":"F3A","mz:is_current":0},{"wof:id":1477930417,"wof:name":"F5","mz:is_current":0},{"wof:id":1477930415,"wof:name":"F4","mz:is_current":0},{"wof:id":1477930421,"wof:name":"F5","mz:is_current":0},{"wof:id":1477930409,"wof:name":"F2","mz:is_current":0},{"wof:id":1477930423,"wof:name":"F6","mz:is_current":0},{"wof:id":1477930427,"wof:name":"F8","mz:is_current":0},{"wof:id":1477930431,"wof:name":"F10","mz:is_current":0},{"wof:id":1477930429,"wof:name":"F9","mz:is_current":0},{"wof:id":1477930435,"wof:name":"F12","mz:is_current":0},{"wof:id":1477930433,"wof:name":"F11","mz:is_current":0},{"wof:id":1477930439,"wof:name":"F13","mz:is_current":0},{"wof:id":1477930441,"wof:name":"F14","mz:is_current":0},{"wof:id":1477930443,"wof:name":"F15","mz:is_current":0},{"wof:id":1477930445,"wof:name":"F16","mz:is_current":0},{"wof:id":1477930447,"wof:name":"F17","mz:is_current":0},{"wof:id":1477930449,"wof:name":"F18","mz:is_current":0},{"wof:id":1477930451,"wof:name":"F19","mz:is_current":0},{"wof:id":1477930425,"wof:name":"F7","mz:is_current":0},{"wof:id":1477930453,"wof:name":"F20","mz:is_current":0},{"wof:id":1477930461,"wof:name":"G1","mz:is_current":0},{"wof:id":1477930457,"wof:name":"F21","mz:is_current":0},{"wof:id":1477930463,"wof:name":"G2","mz:is_current":0},{"wof:id":1477930459,"wof:name":"F22","mz:is_current":0},{"wof:id":1477930465,"wof:name":"G3","mz:is_current":0},{"wof:id":1477930467,"wof:name":"G4","mz:is_current":0},{"wof:id":1477930471,"wof:name":"G6","mz:is_current":0},{"wof:id":1477930475,"wof:name":"G7","mz:is_current":0},{"wof:id":1477930469,"wof:name":"G5","mz:is_current":0},{"wof:id":1477930477,"wof:name":"G8","mz:is_current":0},{"wof:id":1477930481,"wof:name":"G10","mz:is_current":0},{"wof:id":1477930479,"wof:name":"G9","mz:is_current":0},{"wof:id":1477930483,"wof:name":"G11","mz:is_current":0},{"wof:id":1477930485,"wof:name":"G12","mz:is_current":0},{"wof:id":1360832519,"wof:name":"C45","mz:is_current":0},{"wof:id":1477930487,"wof:name":"G13","mz:is_current":0},{"wof:id":1360832523,"wof:name":"F77","mz:is_current":0},{"wof:id":1360832521,"wof:name":"F84","mz:is_current":0},{"wof:id":1477930489,"wof:name":"G14","mz:is_current":0},{"wof:id":1729792393,"wof:name":"D1","mz:is_current":0},{"wof:id":1729792397,"wof:name":"D2","mz:is_current":0},{"wof:id":1729792401,"wof:name":"D4","mz:is_current":0},{"wof:id":1729792399,"wof:name":"D3","mz:is_current":0},{"wof:id":1729792403,"wof:name":"D5","mz:is_current":0},{"wof:id":1729792405,"wof:name":"D6","mz:is_current":0},{"wof:id":1729792409,"wof:name":"D8","mz:is_current":0},{"wof:id":1729792407,"wof:name":"D7","mz:is_current":0},{"wof:id":1729792411,"wof:name":"D9","mz:is_current":0},{"wof:id":1729792415,"wof:name":"D11","mz:is_current":0},{"wof:id":1729792417,"wof:name":"D10","mz:is_current":0},{"wof:id":1729792421,"wof:name":"D14","mz:is_current":0},{"wof:id":1729792423,"wof:name":"D15","mz:is_current":0},{"wof:id":1729792425,"wof:name":"D16","mz:is_current":0},{"wof:id":1729792419,"wof:name":"D12","mz:is_current":0},{"wof:id":1729792427,"wof:name":"D17","mz:is_current":0},{"wof:id":1729792429,"wof:name":"D18","mz:is_current":0},{"wof:id":1729792439,"wof:name":"B6","mz:is_current":0},{"wof:id":1729792441,"wof:name":"B7","mz:is_current":0},{"wof:id":1729792443,"wof:name":"B8","mz:is_current":0},{"wof:id":1729792445,"wof:name":"B9","mz:is_current":0},{"wof:id":1729792451,"wof:name":"B13","mz:is_current":0},{"wof:id":1729792447,"wof:name":"B12","mz:is_current":0},{"wof:id":1729792453,"wof:name":"B14","mz:is_current":0},{"wof:id":1729792457,"wof:name":"B18","mz:is_current":0},{"wof:id":1729792455,"wof:name":"B17","mz:is_current":0},{"wof:id":1729792461,"wof:name":"C2","mz:is_current":0},{"wof:id":1729792463,"wof:name":"C4","mz:is_current":0},{"wof:id":1729792469,"wof:name":"C5","mz:is_current":0},{"wof:id":1729792465,"wof:name":"C3","mz:is_current":0},{"wof:id":1729792471,"wof:name":"C6","mz:is_current":0},{"wof:id":1729792473,"wof:name":"C7","mz:is_current":0},{"wof:id":1729792475,"wof:name":"C8","mz:is_current":0},{"wof:id":1729792479,"wof:name":"C10","mz:is_current":0},{"wof:id":1729792481,"wof:name":"C11","mz:is_current":0},{"wof:id":1729792477,"wof:name":"C9","mz:is_current":0},{"wof:id":1729792491,"wof:name":"F5","mz:is_current":0},{"wof:id":1729792493,"wof:name":"E1","mz:is_current":0},{"wof:id":1729792495,"wof:name":"E2","mz:is_current":0},{"wof:id":1729792497,"wof:name":"E3","mz:is_current":0},{"wof:id":1729792499,"wof:name":"F1","mz:is_current":0},{"wof:id":1729792501,"wof:name":"F2","mz:is_current":0},{"wof:id":1729792505,"wof:name":"F3","mz:is_current":0},{"wof:id":1729792507,"wof:name":"F4","mz:is_current":0},{"wof:id":1729792509,"wof:name":"F3A","mz:is_current":0},{"wof:id":1729792511,"wof:name":"F5","mz:is_current":0},{"wof:id":1729792513,"wof:name":"F6","mz:is_current":0},{"wof:id":1729792515,"wof:name":"F7","mz:is_current":0},{"wof:id":1729792519,"wof:name":"F9","mz:is_current":0},{"wof:id":1729792523,"wof:name":"F10","mz:is_current":0},{"wof:id":1729792527,"wof:name":"F13","mz:is_current":0},{"wof:id":1729792529,"wof:name":"F12","mz:is_current":0},{"wof:id":1729792517,"wof:name":"F8","mz:is_current":0},{"wof:id":1729792531,"wof:name":"F14","mz:is_current":0},{"wof:id":1729792533,"wof:name":"F15","mz:is_current":0},{"wof:id":1729792541,"wof:name":"F18","mz:is_current":0},{"wof:id":1729792537,"wof:name":"F17","mz:is_current":0},{"wof:id":1729792535,"wof:name":"F16","mz:is_current":0},{"wof:id":1729792543,"wof:name":"F19","mz:is_current":0},{"wof:id":1729792545,"wof:name":"F20","mz:is_current":0},{"wof:id":1729792547,"wof:name":"F21","mz:is_current":0},{"wof:id":1729792549,"wof:name":"F22","mz:is_current":0},{"wof:id":1729792553,"wof:name":"E4","mz:is_current":0},{"wof:id":1729792555,"wof:name":"E5","mz:is_current":0},{"wof:id":1729792563,"wof:name":"E8","mz:is_current":0},{"wof:id":1729792565,"wof:name":"E9","mz:is_current":0},{"wof:id":1729792559,"wof:name":"E6","mz:is_current":0},{"wof:id":1729792567,"wof:name":"E10","mz:is_current":0},{"wof:id":1729792561,"wof:name":"E7","mz:is_current":0},{"wof:id":1729792571,"wof:name":"E12","mz:is_current":0},{"wof:id":1729792569,"wof:name":"E11","mz:is_current":0},{"wof:id":1729792573,"wof:name":"E13","mz:is_current":0},{"wof:id":1729792583,"wof:name":"A2","mz:is_current":0},{"wof:id":1729792585,"wof:name":"A4","mz:is_current":0},{"wof:id":1729792589,"wof:name":"A7","mz:is_current":0},{"wof:id":1729792587,"wof:name":"A5","mz:is_current":0},{"wof:id":1729792591,"wof:name":"A6","mz:is_current":0},{"wof:id":1729792595,"wof:name":"A10","mz:is_current":0},{"wof:id":1477881719,"wof:name":"B6","mz:is_current":0},{"wof:id":1729792599,"wof:name":"A8","mz:is_current":0},{"wof:id":1729792597,"wof:name":"A9","mz:is_current":0},{"wof:id":1729792605,"wof:name":"A3","mz:is_current":0},{"wof:id":1729792603,"wof:name":"A11","mz:is_current":0},{"wof:id":1729792601,"wof:name":"A12","mz:is_current":0},{"wof:id":1729792607,"wof:name":"A1","mz:is_current":0},{"wof:id":1729792609,"wof:name":"A1","mz:is_current":0},{"wof:id":1729792617,"wof:name":"A4","mz:is_current":0},{"wof:id":1729792613,"wof:name":"A2","mz:is_current":0},{"wof:id":1729792615,"wof:name":"A3","mz:is_current":0},{"wof:id":1477881721,"wof:name":"B7","mz:is_current":0},{"wof:id":1477881731,"wof:name":"B13","mz:is_current":0},{"wof:id":1729792631,"wof:name":"A10","mz:is_current":0},{"wof:id":1729792621,"wof:name":"A6","mz:is_current":0},{"wof:id":1729792671,"wof:name":"G9","mz:is_current":0},{"wof:id":1729792661,"wof:name":"G7","mz:is_current":0},{"wof:id":1729792641,"wof:name":"A15","mz:is_current":0},{"wof:id":1729792637,"wof:name":"A13","mz:is_current":0},{"wof:id":1729792525,"wof:name":"F11","mz:is_current":0},{"wof:id":1729792741,"wof:name":"B21","mz:is_current":0},{"wof:id":1729792751,"wof:name":"B23","mz:is_current":0},{"wof:id":1729792761,"wof:name":"B15","mz:is_current":0},{"wof:id":1745882105,"wof:name":"D9","mz:is_current":0},{"wof:id":1745882121,"wof:name":"D16","mz:is_current":0},{"wof:id":1745882101,"wof:name":"D6","mz:is_current":0},{"wof:id":1745882151,"wof:name":"B12","mz:is_current":0},{"wof:id":1745882161,"wof:name":"B10","mz:is_current":0},{"wof:id":1745882141,"wof:name":"B6","mz:is_current":0},{"wof:id":1745882183,"wof:name":"B4","mz:is_current":0},{"wof:id":1745882185,"wof:name":"B23","mz:is_current":0},{"wof:id":1745882191,"wof:name":"B15","mz:is_current":0},{"wof:id":1745882201,"wof:name":"C4","mz:is_current":0},{"wof:id":1745882211,"wof:name":"C8","mz:is_current":0},{"wof:id":1745882231,"wof:name":"B2","mz:is_current":0},{"wof:id":1745882241,"wof:name":"E1","mz:is_current":0},{"wof:id":1745882263,"wof:name":"F8","mz:is_current":0},{"wof:id":1745882245,"wof:name":"E3","mz:is_current":0},{"wof:id":1745882257,"wof:name":"F3A","mz:is_current":0},{"wof:id":1745882279,"wof:name":"F14","mz:is_current":0},{"wof:id":1745882281,"wof:name":"F15","mz:is_current":0},{"wof:id":1745882311,"wof:name":"E8","mz:is_current":0},{"wof:id":1745882301,"wof:name":"E4","mz:is_current":0},{"wof:id":1745882321,"wof:name":"E13","mz:is_current":0},{"wof:id":1745882341,"wof:name":"A4","mz:is_current":0},{"wof:id":1745882351,"wof:name":"A10","mz:is_current":0},{"wof:id":1745882355,"wof:name":"A8","mz:is_current":0},{"wof:id":1745882369,"wof:name":"A2","mz:is_current":0},{"wof:id":1745882391,"wof:name":"A11","mz:is_current":0},{"wof:id":1745882431,"wof:name":"G13","mz:is_current":0},{"wof:id":1746415343,"wof:name":"G12S","mz:is_current":1},{"wof:id":1746415337,"wof:name":"C10R","mz:is_current":1},{"wof:id":1746415351,"wof:name":"C10T","mz:is_current":1},{"wof:id":1745882371,"wof:name":"A3","mz:is_current":0},{"wof:id":1746415381,"wof:name":"A13S","mz:is_current":1},{"wof:id":1746415361,"wof:name":"A13V","mz:is_current":1},{"wof:id":1746415371,"wof:name":"A7T","mz:is_current":1},{"wof:id":1746415397,"wof:name":"G12T","mz:is_current":1},{"wof:id":1746415411,"wof:name":"C4R","mz:is_current":1},{"wof:id":1746415407,"wof:name":"G105","mz:is_current":1},{"wof:id":1746415391,"wof:name":"A4R","mz:is_current":1},{"wof:id":1763588131,"wof:name":"D3","mz:is_current":1},{"wof:id":1763588127,"wof:name":"D2","mz:is_current":1},{"wof:id":1763588153,"wof:name":"D12","mz:is_current":1},{"wof:id":1763588143,"wof:name":"D9","mz:is_current":1},{"wof:id":1763588191,"wof:name":"B13","mz:is_current":1},{"wof:id":1763588195,"wof:name":"B17","mz:is_current":1},{"wof:id":1763588211,"wof:name":"B15","mz:is_current":1},{"wof:id":1763588221,"wof:name":"B23","mz:is_current":1},{"wof:id":1763588251,"wof:name":"C9","mz:is_current":1},{"wof:id":1763588231,"wof:name":"B3","mz:is_current":1},{"wof:id":1763588253,"wof:name":"C10","mz:is_current":1},{"wof:id":1763588281,"wof:name":"E3","mz:is_current":1},{"wof:id":1763588301,"wof:name":"F7","mz:is_current":1},{"wof:id":1763588303,"wof:name":"F9","mz:is_current":1},{"wof:id":1763588345,"wof:name":"E8","mz:is_current":1},{"wof:id":1763588333,"wof:name":"F22","mz:is_current":1},{"wof:id":1763588321,"wof:name":"F17","mz:is_current":1},{"wof:id":1763588381,"wof:name":"A6","mz:is_current":0},{"wof:id":1763588341,"wof:name":"E6","mz:is_current":1},{"wof:id":1763588391,"wof:name":"A8","mz:is_current":0},{"wof:id":1763588423,"wof:name":"A13","mz:is_current":1},{"wof:id":1763588401,"wof:name":"A1","mz:is_current":1},{"wof:id":1763588417,"wof:name":"A9","mz:is_current":1},{"wof:id":1763588441,"wof:name":"G2","mz:is_current":1},{"wof:id":1763588451,"wof:name":"G7","mz:is_current":1},{"wof:id":1763588449,"wof:name":"G6","mz:is_current":1},{"wof:id":1763588397,"wof:name":"A12","mz:is_current":0},{"wof:id":1763588389,"wof:name":"A1","mz:is_current":0},{"wof:id":1763588399,"wof:name":"A3","mz:is_current":0},{"wof:id":1763588411,"wof:name":"A6","mz:is_current":1}] diff --git a/data/terminals.json b/data/terminals.json index 63360a4..6311f40 100644 --- a/data/terminals.json +++ b/data/terminals.json @@ -1 +1 @@ -[{"wof:id":1729792579,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0,"name:preferred":["International Terminal Building","ITB"]},{"wof:id":1745882085,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1745882137,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0,"name:preferred":["T1"]},{"wof:id":1763588123,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":1,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1763588175,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":1,"name:preferred":["T1"]},{"wof:id":1745882335,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0,"name:preferred":["International Terminal Building","ITB"]},{"wof:id":1763588269,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":1,"name:preferred":["T3"]},{"wof:id":1763588369,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":1,"name:preferred":["International Terminal Building","ITB"]},{"wof:id":1360521543,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1360521545,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1159554815,"sfomuseum:terminal_id":"SOUTH","wof:name":"South Terminal","mz:is_current":0},{"wof:id":1159554817,"sfomuseum:terminal_id":"SOUTH","wof:name":"South Terminal","mz:is_current":0},{"wof:id":1159554819,"sfomuseum:terminal_id":"NORTH","wof:name":"North Terminal","mz:is_current":0},{"wof:id":1159554827,"sfomuseum:terminal_id":"INTL","wof:name":"International Terminal","mz:is_current":0},{"wof:id":1159554821,"sfomuseum:terminal_id":"NORTH","wof:name":"North Terminal","mz:is_current":0},{"wof:id":1159396107,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0},{"wof:id":1159554829,"sfomuseum:terminal_id":"INTL","wof:name":"International Terminal","mz:is_current":0},{"wof:id":1159396109,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0},{"wof:id":1159396115,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0},{"wof:id":1159396127,"sfomuseum:terminal_id":"SOUTH","wof:name":"South Terminal","mz:is_current":0},{"wof:id":1159396129,"sfomuseum:terminal_id":"NORTH","wof:name":"North Terminal","mz:is_current":0},{"wof:id":1159396123,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0},{"wof:id":1159396121,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1159396131,"sfomuseum:terminal_id":"CENTRAL","wof:name":"Central Terminal","mz:is_current":0},{"wof:id":1159396133,"sfomuseum:terminal_id":"CENTRAL","wof:name":"Central Terminal","mz:is_current":0},{"wof:id":1159396135,"sfomuseum:terminal_id":"SOUTH","wof:name":"South Terminal","mz:is_current":0},{"wof:id":1159396139,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0},{"wof:id":1159396143,"sfomuseum:terminal_id":"SOUTH","wof:name":"South Terminal","mz:is_current":0},{"wof:id":1159396145,"sfomuseum:terminal_id":"NORTH","wof:name":"North Terminal","mz:is_current":0},{"wof:id":1159396141,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0},{"wof:id":1159396149,"sfomuseum:terminal_id":"CENTRAL","wof:name":"Central Terminal","mz:is_current":0},{"wof:id":1159396147,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0},{"wof:id":1159396151,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0},{"wof:id":1159396153,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0},{"wof:id":1159396163,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0},{"wof:id":1159396157,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0},{"wof:id":1159396165,"sfomuseum:terminal_id":"CENTRAL","wof:name":"Central Terminal","mz:is_current":0},{"wof:id":1159157307,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0,"name:preferred":["T3"]},{"wof:id":1159396167,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0},{"wof:id":1159396169,"sfomuseum:terminal_id":"SOUTH","wof:name":"South Terminal","mz:is_current":0},{"wof:id":1159396159,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0},{"wof:id":1159396171,"sfomuseum:terminal_id":"CENTRAL","wof:name":"Central Terminal","mz:is_current":0},{"wof:id":1159157317,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0,"name:preferred":["T1"]},{"wof:id":1159157325,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1159157333,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0,"name:preferred":["International Terminal Building","ITB"]},{"wof:id":1477855607,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1477855657,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0,"name:preferred":["T1"]},{"wof:id":1477855699,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0,"name:preferred":["T3"]},{"wof:id":1477855833,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0,"name:preferred":["International Terminal Building","ITB"]},{"wof:id":1729792389,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1729792435,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0,"name:preferred":["T1"]},{"wof:id":1729792487,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0,"name:preferred":["T3"]},{"wof:id":1745882233,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0,"name:preferred":["T3"]}] +[{"wof:id":1745882085,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1745882137,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0,"name:preferred":["T1"]},{"wof:id":1763588123,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":1,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1763588175,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":1,"name:preferred":["T1"]},{"wof:id":1763588369,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":1,"name:preferred":["International Terminal Building","ITB"]},{"wof:id":1745882335,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0,"name:preferred":["International Terminal Building","ITB"]},{"wof:id":1360521543,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1360521545,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1159157317,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0,"name:preferred":["T1"]},{"wof:id":1159157325,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1159157307,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0,"name:preferred":["T3"]},{"wof:id":1159157333,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0,"name:preferred":["International Terminal Building","ITB"]},{"wof:id":1159396107,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0},{"wof:id":1159396109,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0},{"wof:id":1159396115,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0},{"wof:id":1159396121,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1159396123,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0},{"wof:id":1159396127,"sfomuseum:terminal_id":"SOUTH","wof:name":"South Terminal","mz:is_current":0},{"wof:id":1159396129,"sfomuseum:terminal_id":"NORTH","wof:name":"North Terminal","mz:is_current":0},{"wof:id":1159396131,"sfomuseum:terminal_id":"CENTRAL","wof:name":"Central Terminal","mz:is_current":0},{"wof:id":1159396133,"sfomuseum:terminal_id":"CENTRAL","wof:name":"Central Terminal","mz:is_current":0},{"wof:id":1159396135,"sfomuseum:terminal_id":"SOUTH","wof:name":"South Terminal","mz:is_current":0},{"wof:id":1159396141,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0},{"wof:id":1159396139,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0},{"wof:id":1159396143,"sfomuseum:terminal_id":"SOUTH","wof:name":"South Terminal","mz:is_current":0},{"wof:id":1159396145,"sfomuseum:terminal_id":"NORTH","wof:name":"North Terminal","mz:is_current":0},{"wof:id":1159396147,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0},{"wof:id":1159396157,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0},{"wof:id":1159396153,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0},{"wof:id":1159396159,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0},{"wof:id":1159396163,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0},{"wof:id":1159396165,"sfomuseum:terminal_id":"CENTRAL","wof:name":"Central Terminal","mz:is_current":0},{"wof:id":1159396151,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0},{"wof:id":1159396167,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0},{"wof:id":1159396149,"sfomuseum:terminal_id":"CENTRAL","wof:name":"Central Terminal","mz:is_current":0},{"wof:id":1159396169,"sfomuseum:terminal_id":"SOUTH","wof:name":"South Terminal","mz:is_current":0},{"wof:id":1159396171,"sfomuseum:terminal_id":"CENTRAL","wof:name":"Central Terminal","mz:is_current":0},{"wof:id":1159554815,"sfomuseum:terminal_id":"SOUTH","wof:name":"South Terminal","mz:is_current":0},{"wof:id":1159554817,"sfomuseum:terminal_id":"SOUTH","wof:name":"South Terminal","mz:is_current":0},{"wof:id":1159554821,"sfomuseum:terminal_id":"NORTH","wof:name":"North Terminal","mz:is_current":0},{"wof:id":1159554819,"sfomuseum:terminal_id":"NORTH","wof:name":"North Terminal","mz:is_current":0},{"wof:id":1159554829,"sfomuseum:terminal_id":"INTL","wof:name":"International Terminal","mz:is_current":0},{"wof:id":1159554827,"sfomuseum:terminal_id":"INTL","wof:name":"International Terminal","mz:is_current":0},{"wof:id":1729792389,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1477855607,"sfomuseum:terminal_id":"T2","wof:name":"Terminal 2","mz:is_current":0,"name:preferred":["Terminal 2"],"name:variant":["T2"]},{"wof:id":1729792435,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0,"name:preferred":["T1"]},{"wof:id":1477855657,"sfomuseum:terminal_id":"T1","wof:name":"Terminal 1","mz:is_current":0,"name:preferred":["T1"]},{"wof:id":1477855699,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0,"name:preferred":["T3"]},{"wof:id":1729792487,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0,"name:preferred":["T3"]},{"wof:id":1729792579,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0,"name:preferred":["International Terminal Building","ITB"]},{"wof:id":1477855833,"sfomuseum:terminal_id":"ITB","wof:name":"International Terminal","mz:is_current":0,"name:preferred":["International Terminal Building","ITB"]},{"wof:id":1745882233,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":0,"name:preferred":["T3"]},{"wof:id":1763588269,"sfomuseum:terminal_id":"T3","wof:name":"Terminal 3","mz:is_current":1,"name:preferred":["T3"]}] diff --git a/galleries/compile.go b/galleries/compile.go index 21c9f1f..db29bf4 100644 --- a/galleries/compile.go +++ b/galleries/compile.go @@ -3,12 +3,13 @@ package galleries import ( "context" "fmt" + "io" + "sync" + "github.com/tidwall/gjson" "github.com/whosonfirst/go-whosonfirst-feature/properties" "github.com/whosonfirst/go-whosonfirst-iterate/v2/iterator" "github.com/whosonfirst/go-whosonfirst-uri" - "io" - "sync" ) // CompileGalleriesData will generate a list of `Gallery` struct to be used as the source data for an `SFOMuseumLookup` instance. diff --git a/galleries/galleries.go b/galleries/galleries.go index 526f73e..b40ede7 100644 --- a/galleries/galleries.go +++ b/galleries/galleries.go @@ -4,6 +4,7 @@ package galleries import ( "context" "fmt" + "github.com/sfomuseum/go-sfomuseum-architecture" ) diff --git a/galleries/geometry.go b/galleries/geometry.go index 4e56f6f..16683b9 100644 --- a/galleries/geometry.go +++ b/galleries/geometry.go @@ -3,6 +3,7 @@ package galleries import ( "context" "fmt" + "github.com/paulmach/orb" "github.com/paulmach/orb/geojson" "github.com/paulmach/orb/planar" diff --git a/galleries/lookup.go b/galleries/lookup.go index e922970..5ec097e 100644 --- a/galleries/lookup.go +++ b/galleries/lookup.go @@ -4,8 +4,6 @@ import ( "context" "encoding/json" "fmt" - "github.com/sfomuseum/go-sfomuseum-architecture" - "github.com/sfomuseum/go-sfomuseum-architecture/data" "io" _ "log" "net/http" @@ -14,6 +12,9 @@ import ( "strings" "sync" "sync/atomic" + + "github.com/sfomuseum/go-sfomuseum-architecture" + "github.com/sfomuseum/go-sfomuseum-architecture/data" ) const DATA_JSON string = "galleries.json" @@ -39,9 +40,13 @@ func init() { // NewLookup will return an `architecture.Lookup` instance. By default the lookup table is derived from precompiled (embedded) data in `data/galleries.json` // by passing in `sfomuseum://` as the URI. It is also possible to create a new lookup table with the following URI options: -// `sfomuseum://github` +// +// `sfomuseum://github` +// // This will cause the lookup table to be derived from the data stored at https://raw.githubusercontent.com/sfomuseum/go-sfomuseum-architecture/main/data/galleries.json. This might be desirable if there have been updates to the underlying data that are not reflected in the locally installed package's pre-compiled data. +// // `sfomuseum://iterator?uri={URI}&source={SOURCE}` +// // This will cause the lookup table to be derived, at runtime, from data emitted by a `whosonfirst/go-whosonfirst-iterate` instance. `{URI}` should be a valid `whosonfirst/go-whosonfirst-iterate/iterator` URI and `{SOURCE}` is one or more URIs for the iterator to process. func NewLookup(ctx context.Context, uri string) (architecture.Lookup, error) { diff --git a/galleries/lookup_test.go b/galleries/lookup_test.go index 58e4e4e..2fe894c 100644 --- a/galleries/lookup_test.go +++ b/galleries/lookup_test.go @@ -2,8 +2,9 @@ package galleries import ( "context" - "github.com/sfomuseum/go-sfomuseum-architecture" "testing" + + "github.com/sfomuseum/go-sfomuseum-architecture" ) func TestGalleriesLookup(t *testing.T) { @@ -21,7 +22,7 @@ func TestGalleriesLookup(t *testing.T) { */ wofid_tests := map[string]int64{ - "2D": 1729813699, // 2020~-2021-05-25 2D Sky Terrace Platform + "2D": 1745882459, // 2D Sky Terrace Platform } ctx := context.Background() diff --git a/gates/compile.go b/gates/compile.go index 1204125..818aa2f 100644 --- a/gates/compile.go +++ b/gates/compile.go @@ -3,11 +3,12 @@ package gates import ( "context" "fmt" + "io" + "sync" + "github.com/whosonfirst/go-whosonfirst-feature/properties" "github.com/whosonfirst/go-whosonfirst-iterate/v2/iterator" "github.com/whosonfirst/go-whosonfirst-uri" - "io" - "sync" ) // CompileGatesData will generate a list of `Gate` struct to be used as the source data for an `SFOMuseumLookup` instance. diff --git a/gates/gates.go b/gates/gates.go index c9b90d9..0f6b889 100644 --- a/gates/gates.go +++ b/gates/gates.go @@ -4,6 +4,7 @@ package gates import ( "context" "fmt" + "github.com/sfomuseum/go-sfomuseum-architecture" ) diff --git a/gates/lookup.go b/gates/lookup.go index 6427e4b..a37830c 100644 --- a/gates/lookup.go +++ b/gates/lookup.go @@ -4,8 +4,6 @@ import ( "context" "encoding/json" "fmt" - "github.com/sfomuseum/go-sfomuseum-architecture" - "github.com/sfomuseum/go-sfomuseum-architecture/data" "io" _ "log" "net/http" @@ -14,6 +12,9 @@ import ( "strings" "sync" "sync/atomic" + + "github.com/sfomuseum/go-sfomuseum-architecture" + "github.com/sfomuseum/go-sfomuseum-architecture/data" ) const DATA_JSON string = "gates.json" @@ -39,9 +40,13 @@ func init() { // NewLookup will return an `architecture.Lookup` instance. By default the lookup table is derived from precompiled (embedded) data in `data/gates.json` // by passing in `sfomuseum://` as the URI. It is also possible to create a new lookup table with the following URI options: -// `sfomuseum://github` +// +// `sfomuseum://github` +// // This will cause the lookup table to be derived from the data stored at https://raw.githubusercontent.com/sfomuseum/go-sfomuseum-architecture/main/data/gates.json. This might be desirable if there have been updates to the underlying data that are not reflected in the locally installed package's pre-compiled data. +// // `sfomuseum://iterator?uri={URI}&source={SOURCE}` +// // This will cause the lookup table to be derived, at runtime, from data emitted by a `whosonfirst/go-whosonfirst-iterate` instance. `{URI}` should be a valid `whosonfirst/go-whosonfirst-iterate/iterator` URI and `{SOURCE}` is one or more URIs for the iterator to process. func NewLookup(ctx context.Context, uri string) (architecture.Lookup, error) { diff --git a/gates/lookup_test.go b/gates/lookup_test.go index 3ae06bb..9e3b7b9 100644 --- a/gates/lookup_test.go +++ b/gates/lookup_test.go @@ -2,8 +2,9 @@ package gates import ( "context" - "github.com/sfomuseum/go-sfomuseum-architecture" "testing" + + "github.com/sfomuseum/go-sfomuseum-architecture" ) func TestGatesLookup(t *testing.T) { diff --git a/go.mod b/go.mod index 7ec8b06..1fa88a3 100644 --- a/go.mod +++ b/go.mod @@ -5,19 +5,19 @@ go 1.18 require ( github.com/aaronland/go-roster v1.0.0 github.com/aaronland/go-sqlite v0.2.2 - github.com/paulmach/orb v0.7.1 + github.com/paulmach/orb v0.9.0 github.com/sfomuseum/go-sfomuseum-writer/v3 v3.0.0 github.com/tidwall/gjson v1.14.4 github.com/whosonfirst/go-reader v1.0.2 - github.com/whosonfirst/go-whosonfirst-export/v2 v2.6.1 - github.com/whosonfirst/go-whosonfirst-feature v0.0.25 + github.com/whosonfirst/go-whosonfirst-export/v2 v2.7.0 + github.com/whosonfirst/go-whosonfirst-feature v0.0.26 github.com/whosonfirst/go-whosonfirst-id v1.2.0 github.com/whosonfirst/go-whosonfirst-iterate/v2 v2.3.1 github.com/whosonfirst/go-whosonfirst-reader v1.0.1 github.com/whosonfirst/go-whosonfirst-sqlite-features v0.10.1 github.com/whosonfirst/go-whosonfirst-sqlite-features-index v1.5.1 github.com/whosonfirst/go-whosonfirst-sqlite-index/v3 v3.0.0 - github.com/whosonfirst/go-whosonfirst-uri v1.2.0 + github.com/whosonfirst/go-whosonfirst-uri v1.3.0 github.com/whosonfirst/go-writer/v3 v3.1.0 ) @@ -53,5 +53,6 @@ require ( github.com/whosonfirst/go-whosonfirst-spr/v2 v2.3.3 // indirect github.com/whosonfirst/go-whosonfirst-writer/v3 v3.0.0 // indirect github.com/whosonfirst/walk v0.0.1 // indirect + go.mongodb.org/mongo-driver v1.11.1 // indirect go.uber.org/ratelimit v0.2.0 // indirect ) diff --git a/go.sum b/go.sum index 5c19d56..0f09e17 100644 --- a/go.sum +++ b/go.sum @@ -48,6 +48,9 @@ github.com/g8rswimmer/error-chain v1.0.0 h1:WnwnunlvqtGPHVHmBfbmUyAgrtag8Y6nNpwL github.com/g8rswimmer/error-chain v1.0.0/go.mod h1:XPJ/brUsL7yzc5VRlIxtf9GvoUqnOKVI9fg2MB5DWx8= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= @@ -57,20 +60,23 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A= github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM= github.com/paulmach/orb v0.6.0/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhmqB/A= github.com/paulmach/orb v0.7.0/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhmqB/A= -github.com/paulmach/orb v0.7.1 h1:Zha++Z5OX/l168sqHK3k4z18LDvr+YAO/VjK0ReQ9rU= -github.com/paulmach/orb v0.7.1/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhmqB/A= +github.com/paulmach/orb v0.9.0 h1:MwA1DqOKtvCgm7u9RZ/pnYejTeDJPnr0+0oFajBbJqk= +github.com/paulmach/orb v0.9.0/go.mod h1:SudmOk85SXtmXAB3sLGyJ6tZy/8pdfrV0o6ef98Xc30= github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -118,11 +124,11 @@ github.com/whosonfirst/go-rfc-5646 v0.1.0/go.mod h1:JZj//FV9YeV3fkyOY/82V53EMLQX github.com/whosonfirst/go-whosonfirst-crawl v0.2.1 h1:nNG7r7/4MaII/NM8Df2oqgfgVNBDoIKlseleoX1vw1Q= github.com/whosonfirst/go-whosonfirst-crawl v0.2.1/go.mod h1:MTD1TCgAkXlAtysPU98ylrz9Y5+ZCfRrsrBnRyiH/t8= github.com/whosonfirst/go-whosonfirst-export/v2 v2.4.5/go.mod h1:WETCjYIg2wlYc1KcnFgF7dKCZ/dUKO+SMEU4h0OXF+A= -github.com/whosonfirst/go-whosonfirst-export/v2 v2.6.1 h1:u2/HPnz8OwlTIeyuFogDLKMwHVg9CgNHvy5cEEynlxU= -github.com/whosonfirst/go-whosonfirst-export/v2 v2.6.1/go.mod h1:nOKxHWpoM31OvZoNxzPCbhK+CnMgTVsXnZvYNK/jwCA= +github.com/whosonfirst/go-whosonfirst-export/v2 v2.7.0 h1:WuneueMbfjVWKh4sESLBfSFm+0rhIsgYdy0K2JLeLm4= +github.com/whosonfirst/go-whosonfirst-export/v2 v2.7.0/go.mod h1:w0O954Le3iSTHX0Ivfg6SVuzd7oUne6QmELfsfhAjZc= github.com/whosonfirst/go-whosonfirst-feature v0.0.23/go.mod h1:3cvRigFFG2a99M64lZzfy5amHacWu8Os5fXZdGjPnLM= -github.com/whosonfirst/go-whosonfirst-feature v0.0.25 h1:6s2to+aWB9Fo+IcwSvsB2UiuymJPKSe8g0TwuRasLhE= -github.com/whosonfirst/go-whosonfirst-feature v0.0.25/go.mod h1:JTauqAjTuZDfOTHxv5hFUzknF0NGgxvHTT5maTej9Co= +github.com/whosonfirst/go-whosonfirst-feature v0.0.26 h1:Dba+7aNMzxAaSVh9WzlPdrYhwT8T03cjNANjZvhcNsY= +github.com/whosonfirst/go-whosonfirst-feature v0.0.26/go.mod h1:ntGT7tkg89WyEalg+Aocl0R27tPx2wBp7Prfx9a5tUg= github.com/whosonfirst/go-whosonfirst-flags v0.4.3/go.mod h1:pL17Ryo60FH8RYaQRgfu5XnxhrNRK3x+rn03TYD6Gc8= github.com/whosonfirst/go-whosonfirst-flags v0.4.4 h1:pwUnE8btx4Po6N5+uq0IrKVF0WraY5YW3tc3saIDg3A= github.com/whosonfirst/go-whosonfirst-flags v0.4.4/go.mod h1:C9X7vQvNR/u55AfOHYUT8o7dRACWV++ZV4B0kylnIaY= @@ -153,8 +159,9 @@ github.com/whosonfirst/go-whosonfirst-sqlite-index/v2 v2.0.1/go.mod h1:dZxoAGOI9 github.com/whosonfirst/go-whosonfirst-sqlite-index/v3 v3.0.0 h1:XezVmysv7nfskEBXqhTQDHMegANDlr7xUdLLVPdb6tk= github.com/whosonfirst/go-whosonfirst-sqlite-index/v3 v3.0.0/go.mod h1:lMCFs+pi80lM1ZyCYczXzCzXOazc4vJYKAsVpaGdTt8= github.com/whosonfirst/go-whosonfirst-uri v1.0.1/go.mod h1:8eaDVcc4v+HHHEDaRbApdmhPwM4/JQllw2PktvZcPVs= -github.com/whosonfirst/go-whosonfirst-uri v1.2.0 h1:lhmRsIhcpTr5HAo+kXKRGsSt76HTh3Ko/oTR2jpCm/o= github.com/whosonfirst/go-whosonfirst-uri v1.2.0/go.mod h1:CuVygTCUpMG945MMvqHyqxvc/L5YkDaMrrVpRFr7ZxY= +github.com/whosonfirst/go-whosonfirst-uri v1.3.0 h1:LYOVLqP9rWQxauYVkdw65j5LZxEi8OK0GHh/qCEpX4g= +github.com/whosonfirst/go-whosonfirst-uri v1.3.0/go.mod h1:CuVygTCUpMG945MMvqHyqxvc/L5YkDaMrrVpRFr7ZxY= github.com/whosonfirst/go-whosonfirst-writer/v3 v3.0.0 h1:snhEF7nNPP1E0reD8cbwRHdFpk9WaNmljvlZF6yFvU8= github.com/whosonfirst/go-whosonfirst-writer/v3 v3.0.0/go.mod h1:zr1HVHJ0Q8/azLtC0aeu8zgeALqPxrgPgxUe1SKnDyo= github.com/whosonfirst/go-writer/v3 v3.1.0 h1:lEZ6TIYvZb5NJ6e2OXYRM1j+MM2svKCSlb+6Vzbz+/M= @@ -162,8 +169,14 @@ github.com/whosonfirst/go-writer/v3 v3.1.0/go.mod h1:TmYoKR7RvrzJaj3eOgMhgXHFE+R github.com/whosonfirst/walk v0.0.1 h1:t0QrqGwOdPMSeovFZSXfiS0GIGHrRXK3Wb9z5Uhs2bg= github.com/whosonfirst/walk v0.0.1/go.mod h1:1KtP/VeooSlFOI61p+THc/C16Ra8Z5MjpjI0tsd3c1M= github.com/whosonfirst/warning v0.1.1/go.mod h1:/unEMzhB9YaMeEwTJpzLN3kM5LiSxdJhKEsf/OQhn6s= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8= +go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -173,6 +186,7 @@ go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6m golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -181,14 +195,22 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -202,8 +224,10 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/lookup.go b/lookup.go index 9812659..c84db99 100644 --- a/lookup.go +++ b/lookup.go @@ -2,8 +2,9 @@ package architecture import ( "context" - "github.com/aaronland/go-roster" "net/url" + + "github.com/aaronland/go-roster" ) type Lookup interface { diff --git a/terminals/compile.go b/terminals/compile.go index 4c43478..f2af3e3 100644 --- a/terminals/compile.go +++ b/terminals/compile.go @@ -3,13 +3,14 @@ package terminals import ( "context" "fmt" + "io" + "strings" + "sync" + "github.com/tidwall/gjson" "github.com/whosonfirst/go-whosonfirst-feature/properties" "github.com/whosonfirst/go-whosonfirst-iterate/v2/iterator" "github.com/whosonfirst/go-whosonfirst-uri" - "io" - "strings" - "sync" ) // CompileTerminalsData will generate a list of `Terminal` struct to be used as the source data for an `SFOMuseumLookup` instance. diff --git a/terminals/lookup.go b/terminals/lookup.go index 92fcfd0..24481da 100644 --- a/terminals/lookup.go +++ b/terminals/lookup.go @@ -4,8 +4,6 @@ import ( "context" "encoding/json" "fmt" - "github.com/sfomuseum/go-sfomuseum-architecture" - "github.com/sfomuseum/go-sfomuseum-architecture/data" "io" _ "log" "net/http" @@ -14,6 +12,9 @@ import ( "strings" "sync" "sync/atomic" + + "github.com/sfomuseum/go-sfomuseum-architecture" + "github.com/sfomuseum/go-sfomuseum-architecture/data" ) const DATA_JSON string = "terminals.json" @@ -39,9 +40,13 @@ func init() { // NewLookup will return an `architecture.Lookup` instance. By default the lookup table is derived from precompiled (embedded) data in `data/terminals.json` // by passing in `sfomuseum://` as the URI. It is also possible to create a new lookup table with the following URI options: -// `sfomuseum://github` +// +// `sfomuseum://github` +// // This will cause the lookup table to be derived from the data stored at https://raw.githubusercontent.com/sfomuseum/go-sfomuseum-architecture/main/data/terminals.json. This might be desirable if there have been updates to the underlying data that are not reflected in the locally installed package's pre-compiled data. +// // `sfomuseum://iterator?uri={URI}&source={SOURCE}` +// // This will cause the lookup table to be derived, at runtime, from data emitted by a `whosonfirst/go-whosonfirst-iterate` instance. `{URI}` should be a valid `whosonfirst/go-whosonfirst-iterate/iterator` URI and `{SOURCE}` is one or more URIs for the iterator to process. func NewLookup(ctx context.Context, uri string) (architecture.Lookup, error) { diff --git a/terminals/lookup_test.go b/terminals/lookup_test.go index 08e7ff6..5a82d1c 100644 --- a/terminals/lookup_test.go +++ b/terminals/lookup_test.go @@ -2,8 +2,9 @@ package terminals import ( "context" - "github.com/sfomuseum/go-sfomuseum-architecture" "testing" + + "github.com/sfomuseum/go-sfomuseum-architecture" ) func TestTerminalsLookup(t *testing.T) { diff --git a/terminals/terminals.go b/terminals/terminals.go index 0bfa849..99d0979 100644 --- a/terminals/terminals.go +++ b/terminals/terminals.go @@ -4,6 +4,7 @@ package terminals import ( "context" "fmt" + "github.com/sfomuseum/go-sfomuseum-architecture" ) diff --git a/vendor/github.com/paulmach/orb/CHANGELOG.md b/vendor/github.com/paulmach/orb/CHANGELOG.md index 5691ca1..70db8e8 100644 --- a/vendor/github.com/paulmach/orb/CHANGELOG.md +++ b/vendor/github.com/paulmach/orb/CHANGELOG.md @@ -2,6 +2,27 @@ All notable changes to this project will be documented in this file. +## [v0.9.0](https://github.com/paulmach/orb/compare/v0.8.0...v0.9.0) - 2023-02-19 + +### Added + +- geojson: marshal/unmarshal BSON [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/123 + +## [v0.8.0](https://github.com/paulmach/orb/compare/v0.7.1...v0.8.0) - 2023-01-05 + +### Fixed + +- quadtree: fix bad sort due to pointer allocation issue by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/115 +- geojson: ensure geometry unmarshal errors get returned by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/117 +- encoding/mvt: remove use of crypto/md5 to compare marshalling in tests by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/118 +- encoding/wkt: fix panic for some invalid wkt data by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/119 + +### Other + +- fix typo by [@rubenpoppe](https://github.com/rubenpoppe) in https://github.com/paulmach/orb/pull/107 +- Fixed a small twister in README.md by [@Timahawk](https://github.com/Timahawk) in https://github.com/paulmach/orb/pull/108 +- update github ci to use go 1.19 by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/116 + ## [v0.7.1](https://github.com/paulmach/orb/compare/v0.7.0...v0.7.1) - 2022-05-16 No changes diff --git a/vendor/github.com/paulmach/orb/README.md b/vendor/github.com/paulmach/orb/README.md index 8d0e515..03fe463 100644 --- a/vendor/github.com/paulmach/orb/README.md +++ b/vendor/github.com/paulmach/orb/README.md @@ -2,7 +2,7 @@ Package `orb` defines a set of types for working with 2d geo and planar/projected geometric data in Golang. There are a set of sub-packages that use these types to do interesting things. -They each provider their own README with extra info. +They each provide their own README with extra info. ## Interesting features @@ -111,6 +111,8 @@ The library supports third party "encoding/json" replacements such [github.com/json-iterator/go](https://github.com/json-iterator/go). See the [geojson](geojson) readme for more details. +The types also support BSON so they can be used directly when working with MongoDB. + ## Mapbox Vector Tiles The [encoding/mvt](encoding/mvt) sub-package implements Marshalling and @@ -138,10 +140,10 @@ layers.Simplify(simplify.DouglasPeucker(1.0)) layers.RemoveEmpty(1.0, 2.0) // encoding using the Mapbox Vector Tile protobuf encoding. -data, err := layers.Marshal() // this data is NOT gzipped. +data, err := mvt.Marshal(layers) // this data is NOT gzipped. // Sometimes MVT data is stored and transfered gzip compressed. In that case: -data, err := layers.MarshalGzipped() +data, err := mvt.MarshalGzipped(layers) ``` ## Decoding WKB/EWKB from a database query diff --git a/vendor/github.com/paulmach/orb/encoding/wkt/unmarshal.go b/vendor/github.com/paulmach/orb/encoding/wkt/unmarshal.go index de259fd..e615352 100644 --- a/vendor/github.com/paulmach/orb/encoding/wkt/unmarshal.go +++ b/vendor/github.com/paulmach/orb/encoding/wkt/unmarshal.go @@ -122,6 +122,9 @@ func UnmarshalCollection(s string) (p orb.Collection, err error) { // trimSpaceBrackets trim space and brackets func trimSpaceBrackets(s string) string { s = strings.Trim(s, " ") + if len(s) == 0 { + return "" + } if s[0] == '(' { s = s[1:] } @@ -187,6 +190,9 @@ func Unmarshal(s string) (geom orb.Geometry, err error) { return orb.Collection{}, nil } s = strings.Replace(s, "GEOMETRYCOLLECTION", "", -1) + if len(s) == 0 { + return nil, ErrNotWKT + } c := orb.Collection{} ms := splitGeometryCollection(s) if len(ms) == 0 { diff --git a/vendor/github.com/paulmach/orb/geojson/README.md b/vendor/github.com/paulmach/orb/geojson/README.md index 2a5c8c7..07ca932 100644 --- a/vendor/github.com/paulmach/orb/geojson/README.md +++ b/vendor/github.com/paulmach/orb/geojson/README.md @@ -2,10 +2,15 @@ This package **encodes and decodes** [GeoJSON](http://geojson.org/) into Go structs using the geometries in the [orb](https://github.com/paulmach/orb) package. -Supports both the [json.Marshaler](http://golang.org/pkg/encoding/json/#Marshaler) and -[json.Unmarshaler](http://golang.org/pkg/encoding/json/#Unmarshaler) interfaces. + +Supports both the [json.Marshaler](https://pkg.go.dev/encoding/json#Marshaler) and +[json.Unmarshaler](https://pkg.go.dev/encoding/json#Unmarshaler) interfaces. The package also provides helper functions such as `UnmarshalFeatureCollection` and `UnmarshalFeature`. +The types also support BSON via the [bson.Marshaler](https://pkg.go.dev/go.mongodb.org/mongo-driver/bson#Marshaler) and +[bson.Unmarshaler](https://pkg.go.dev/go.mongodb.org/mongo-driver/bson#Unmarshaler) interfaces. +These types can be used directly when working with MongoDB. + ## Unmarshalling (JSON -> Go) ```go diff --git a/vendor/github.com/paulmach/orb/geojson/feature.go b/vendor/github.com/paulmach/orb/geojson/feature.go index 7230678..68b1f8f 100644 --- a/vendor/github.com/paulmach/orb/geojson/feature.go +++ b/vendor/github.com/paulmach/orb/geojson/feature.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/paulmach/orb" + "go.mongodb.org/mongo-driver/bson" ) // A Feature corresponds to GeoJSON feature object @@ -37,7 +38,18 @@ var _ orb.Pointer = &Feature{} // It will handle the encoding of all the child geometries. // Alternately one can call json.Marshal(f) directly for the same result. func (f Feature) MarshalJSON() ([]byte, error) { - jf := &jsonFeature{ + return marshalJSON(newFeatureDoc(&f)) +} + +// MarshalBSON converts the feature object into the proper JSON. +// It will handle the encoding of all the child geometries. +// Alternately one can call json.Marshal(f) directly for the same result. +func (f Feature) MarshalBSON() ([]byte, error) { + return bson.Marshal(newFeatureDoc(&f)) +} + +func newFeatureDoc(f *Feature) *featureDoc { + doc := &featureDoc{ ID: f.ID, Type: "Feature", Properties: f.Properties, @@ -45,11 +57,11 @@ func (f Feature) MarshalJSON() ([]byte, error) { Geometry: NewGeometry(f.Geometry), } - if len(jf.Properties) == 0 { - jf.Properties = nil + if len(doc.Properties) == 0 { + doc.Properties = nil } - return marshalJSON(jf) + return doc } // UnmarshalFeature decodes the data into a GeoJSON feature. @@ -67,39 +79,54 @@ func UnmarshalFeature(data []byte) (*Feature, error) { // UnmarshalJSON handles the correct unmarshalling of the data // into the orb.Geometry types. func (f *Feature) UnmarshalJSON(data []byte) error { - jf := &jsonFeature{} - err := unmarshalJSON(data, &jf) + doc := &featureDoc{} + err := unmarshalJSON(data, &doc) + if err != nil { + return err + } + + return featureUnmarshalFinish(doc, f) +} + +// UnmarshalBSON will unmarshal a BSON document created with bson.Marshal. +func (f *Feature) UnmarshalBSON(data []byte) error { + doc := &featureDoc{} + err := bson.Unmarshal(data, &doc) if err != nil { return err } - if jf.Type != "Feature" { - return fmt.Errorf("geojson: not a feature: type=%s", jf.Type) + return featureUnmarshalFinish(doc, f) +} + +func featureUnmarshalFinish(doc *featureDoc, f *Feature) error { + if doc.Type != "Feature" { + return fmt.Errorf("geojson: not a feature: type=%s", doc.Type) } var g orb.Geometry - if jf.Geometry != nil { - if jf.Geometry.Coordinates == nil && jf.Geometry.Geometries == nil { + if doc.Geometry != nil { + if doc.Geometry.Coordinates == nil && doc.Geometry.Geometries == nil { return ErrInvalidGeometry } - g = jf.Geometry.Geometry() + g = doc.Geometry.Geometry() } *f = Feature{ - ID: jf.ID, - Type: jf.Type, - Properties: jf.Properties, - BBox: jf.BBox, + ID: doc.ID, + Type: doc.Type, + Properties: doc.Properties, + BBox: doc.BBox, Geometry: g, } return nil } -type jsonFeature struct { - ID interface{} `json:"id,omitempty"` - Type string `json:"type"` - BBox BBox `json:"bbox,omitempty"` - Geometry *Geometry `json:"geometry"` - Properties Properties `json:"properties"` +type featureDoc struct { + ID interface{} `json:"id,omitempty" bson:"id"` + Type string `json:"type" bson:"type"` + BBox BBox `json:"bbox,omitempty" bson:"bbox,omitempty"` + Geometry *Geometry `json:"geometry" bson:"geometry"` + Properties Properties `json:"properties" bson:"properties"` } diff --git a/vendor/github.com/paulmach/orb/geojson/feature_collection.go b/vendor/github.com/paulmach/orb/geojson/feature_collection.go index 113c8ee..0449f35 100644 --- a/vendor/github.com/paulmach/orb/geojson/feature_collection.go +++ b/vendor/github.com/paulmach/orb/geojson/feature_collection.go @@ -8,6 +8,8 @@ package geojson import ( "fmt" + + "go.mongodb.org/mongo-driver/bson" ) const featureCollection = "FeatureCollection" @@ -44,6 +46,21 @@ func (fc *FeatureCollection) Append(feature *Feature) *FeatureCollection { // Items in the ExtraMembers map will be included in the base of the // feature collection object. func (fc FeatureCollection) MarshalJSON() ([]byte, error) { + m := newFeatureCollectionDoc(fc) + return marshalJSON(m) +} + +// MarshalBSON converts the feature collection object into a BSON document +// represented by bytes. It will handle the encoding of all the child features +// and geometries. +// Items in the ExtraMembers map will be included in the base of the +// feature collection object. +func (fc FeatureCollection) MarshalBSON() ([]byte, error) { + m := newFeatureCollectionDoc(fc) + return bson.Marshal(m) +} + +func newFeatureCollectionDoc(fc FeatureCollection) map[string]interface{} { var tmp map[string]interface{} if fc.ExtraMembers != nil { tmp = fc.ExtraMembers.Clone() @@ -62,7 +79,7 @@ func (fc FeatureCollection) MarshalJSON() ([]byte, error) { tmp["features"] = fc.Features } - return marshalJSON(tmp) + return tmp } // UnmarshalJSON decodes the data into a GeoJSON feature collection. @@ -114,6 +131,52 @@ func (fc *FeatureCollection) UnmarshalJSON(data []byte) error { return nil } +// UnmarshalBSON will unmarshal a BSON document created with bson.Marshal. +// Extra/foreign members will be put into the `ExtraMembers` attribute. +func (fc *FeatureCollection) UnmarshalBSON(data []byte) error { + tmp := make(map[string]bson.RawValue, 4) + + err := bson.Unmarshal(data, &tmp) + if err != nil { + return err + } + + *fc = FeatureCollection{} + for key, value := range tmp { + switch key { + case "type": + fc.Type, _ = bson.RawValue(value).StringValueOK() + case "bbox": + err := value.Unmarshal(&fc.BBox) + if err != nil { + return err + } + case "features": + err := value.Unmarshal(&fc.Features) + if err != nil { + return err + } + default: + if fc.ExtraMembers == nil { + fc.ExtraMembers = Properties{} + } + + var val interface{} + err := value.Unmarshal(&val) + if err != nil { + return err + } + fc.ExtraMembers[key] = val + } + } + + if fc.Type != featureCollection { + return fmt.Errorf("geojson: not a feature collection: type=%s", fc.Type) + } + + return nil +} + // UnmarshalFeatureCollection decodes the data into a GeoJSON feature collection. // Alternately one can call json.Unmarshal(fc) directly for the same result. func UnmarshalFeatureCollection(data []byte) (*FeatureCollection, error) { diff --git a/vendor/github.com/paulmach/orb/geojson/geometry.go b/vendor/github.com/paulmach/orb/geojson/geometry.go index 4574cd0..1524521 100644 --- a/vendor/github.com/paulmach/orb/geojson/geometry.go +++ b/vendor/github.com/paulmach/orb/geojson/geometry.go @@ -4,6 +4,8 @@ import ( "errors" "github.com/paulmach/orb" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/bsontype" ) // ErrInvalidGeometry will be returned if a the json of the geometry is invalid. @@ -43,7 +45,7 @@ func NewGeometry(g orb.Geometry) *Geometry { // Geometry returns the orb.Geometry for the geojson Geometry. // This will convert the "Geometries" into a orb.Collection if applicable. -func (g Geometry) Geometry() orb.Geometry { +func (g *Geometry) Geometry() orb.Geometry { if g.Coordinates != nil { return g.Coordinates } @@ -55,13 +57,40 @@ func (g Geometry) Geometry() orb.Geometry { return c } -// MarshalJSON will marshal the geometry into the correct json structure. -func (g Geometry) MarshalJSON() ([]byte, error) { +// MarshalJSON will marshal the geometry into the correct JSON structure. +func (g *Geometry) MarshalJSON() ([]byte, error) { if g.Coordinates == nil && len(g.Geometries) == 0 { return []byte(`null`), nil } - ng := &jsonGeometryMarshall{} + ng := newGeometryMarshallDoc(g) + return marshalJSON(ng) +} + +// MarshalBSON will convert the geometry into a BSON document with the structure +// of a GeoJSON Geometry. This function is used when the geometry is the top level +// document to be marshalled. +func (g *Geometry) MarshalBSON() ([]byte, error) { + ng := newGeometryMarshallDoc(g) + return bson.Marshal(ng) +} + +// MarshalBSONValue will marshal the geometry into a BSON value +// with the structure of a GeoJSON Geometry. +func (g *Geometry) MarshalBSONValue() (bsontype.Type, []byte, error) { + // implementing MarshalBSONValue allows us to marshal into a null value + // needed to match behavior with the JSON marshalling. + + if g.Coordinates == nil && len(g.Geometries) == 0 { + return bsontype.Null, nil, nil + } + + ng := newGeometryMarshallDoc(g) + return bson.MarshalValue(ng) +} + +func newGeometryMarshallDoc(g *Geometry) *geometryMarshallDoc { + ng := &geometryMarshallDoc{} switch g := g.Coordinates.(type) { case orb.Ring: ng.Coordinates = orb.Polygon{g} @@ -86,10 +115,10 @@ func (g Geometry) MarshalJSON() ([]byte, error) { ng.Type = orb.Collection{}.GeoJSONType() } - return marshalJSON(ng) + return ng } -// UnmarshalGeometry decodes the data into a GeoJSON feature. +// UnmarshalGeometry decodes the JSON data into a GeoJSON feature. // Alternately one can call json.Unmarshal(g) directly for the same result. func UnmarshalGeometry(data []byte) (*Geometry, error) { g := &Geometry{} @@ -101,7 +130,7 @@ func UnmarshalGeometry(data []byte) (*Geometry, error) { return g, nil } -// UnmarshalJSON will unmarshal the correct geometry from the json structure. +// UnmarshalJSON will unmarshal the correct geometry from the JSON structure. func (g *Geometry) UnmarshalJSON(data []byte) error { jg := &jsonGeometry{} err := unmarshalJSON(data, jg) @@ -113,26 +142,44 @@ func (g *Geometry) UnmarshalJSON(data []byte) error { case "Point": p := orb.Point{} err = unmarshalJSON(jg.Coordinates, &p) + if err != nil { + return err + } g.Coordinates = p case "MultiPoint": mp := orb.MultiPoint{} err = unmarshalJSON(jg.Coordinates, &mp) + if err != nil { + return err + } g.Coordinates = mp case "LineString": ls := orb.LineString{} err = unmarshalJSON(jg.Coordinates, &ls) + if err != nil { + return err + } g.Coordinates = ls case "MultiLineString": mls := orb.MultiLineString{} err = unmarshalJSON(jg.Coordinates, &mls) + if err != nil { + return err + } g.Coordinates = mls case "Polygon": p := orb.Polygon{} err = unmarshalJSON(jg.Coordinates, &p) + if err != nil { + return err + } g.Coordinates = p case "MultiPolygon": mp := orb.MultiPolygon{} err = unmarshalJSON(jg.Coordinates, &mp) + if err != nil { + return err + } g.Coordinates = mp case "GeometryCollection": g.Geometries = jg.Geometries @@ -145,6 +192,69 @@ func (g *Geometry) UnmarshalJSON(data []byte) error { return nil } +// UnmarshalBSON will unmarshal a BSON document created with bson.Marshal. +func (g *Geometry) UnmarshalBSON(data []byte) error { + bg := &bsonGeometry{} + err := bson.Unmarshal(data, bg) + if err != nil { + return err + } + + switch bg.Type { + case "Point": + p := orb.Point{} + err = bg.Coordinates.Unmarshal(&p) + if err != nil { + return err + } + g.Coordinates = p + case "MultiPoint": + mp := orb.MultiPoint{} + err = bg.Coordinates.Unmarshal(&mp) + if err != nil { + return err + } + g.Coordinates = mp + case "LineString": + ls := orb.LineString{} + + err = bg.Coordinates.Unmarshal(&ls) + if err != nil { + return err + } + g.Coordinates = ls + case "MultiLineString": + mls := orb.MultiLineString{} + err = bg.Coordinates.Unmarshal(&mls) + if err != nil { + return err + } + g.Coordinates = mls + case "Polygon": + p := orb.Polygon{} + err = bg.Coordinates.Unmarshal(&p) + if err != nil { + return err + } + g.Coordinates = p + case "MultiPolygon": + mp := orb.MultiPolygon{} + err = bg.Coordinates.Unmarshal(&mp) + if err != nil { + return err + } + g.Coordinates = mp + case "GeometryCollection": + g.Geometries = bg.Geometries + default: + return ErrInvalidGeometry + } + + g.Type = g.Geometry().GeoJSONType() + + return nil +} + // A Point is a helper type that will marshal to/from a GeoJSON Point geometry. type Point orb.Point @@ -155,7 +265,12 @@ func (p Point) Geometry() orb.Geometry { // MarshalJSON will convert the Point into a GeoJSON Point geometry. func (p Point) MarshalJSON() ([]byte, error) { - return marshalJSON(Geometry{Coordinates: orb.Point(p)}) + return marshalJSON(&Geometry{Coordinates: orb.Point(p)}) +} + +// MarshalBSON will convert the Point into a BSON value following the GeoJSON Point structure. +func (p Point) MarshalBSON() ([]byte, error) { + return bson.Marshal(&Geometry{Coordinates: orb.Point(p)}) } // UnmarshalJSON will unmarshal the GeoJSON Point geometry. @@ -175,6 +290,23 @@ func (p *Point) UnmarshalJSON(data []byte) error { return nil } +// UnmarshalBSON will unmarshal GeoJSON Point geometry. +func (p *Point) UnmarshalBSON(data []byte) error { + g := &Geometry{} + err := bson.Unmarshal(data, &g) + if err != nil { + return err + } + + point, ok := g.Coordinates.(orb.Point) + if !ok { + return errors.New("geojson: not a Point type") + } + + *p = Point(point) + return nil +} + // A MultiPoint is a helper type that will marshal to/from a GeoJSON MultiPoint geometry. type MultiPoint orb.MultiPoint @@ -185,7 +317,12 @@ func (mp MultiPoint) Geometry() orb.Geometry { // MarshalJSON will convert the MultiPoint into a GeoJSON MultiPoint geometry. func (mp MultiPoint) MarshalJSON() ([]byte, error) { - return marshalJSON(Geometry{Coordinates: orb.MultiPoint(mp)}) + return marshalJSON(&Geometry{Coordinates: orb.MultiPoint(mp)}) +} + +// MarshalBSON will convert the MultiPoint into a GeoJSON MultiPoint geometry BSON. +func (mp MultiPoint) MarshalBSON() ([]byte, error) { + return bson.Marshal(&Geometry{Coordinates: orb.MultiPoint(mp)}) } // UnmarshalJSON will unmarshal the GeoJSON MultiPoint geometry. @@ -205,6 +342,23 @@ func (mp *MultiPoint) UnmarshalJSON(data []byte) error { return nil } +// UnmarshalBSON will unmarshal the GeoJSON MultiPoint geometry. +func (mp *MultiPoint) UnmarshalBSON(data []byte) error { + g := &Geometry{} + err := bson.Unmarshal(data, &g) + if err != nil { + return err + } + + multiPoint, ok := g.Coordinates.(orb.MultiPoint) + if !ok { + return errors.New("geojson: not a MultiPoint type") + } + + *mp = MultiPoint(multiPoint) + return nil +} + // A LineString is a helper type that will marshal to/from a GeoJSON LineString geometry. type LineString orb.LineString @@ -215,7 +369,12 @@ func (ls LineString) Geometry() orb.Geometry { // MarshalJSON will convert the LineString into a GeoJSON LineString geometry. func (ls LineString) MarshalJSON() ([]byte, error) { - return marshalJSON(Geometry{Coordinates: orb.LineString(ls)}) + return marshalJSON(&Geometry{Coordinates: orb.LineString(ls)}) +} + +// MarshalBSON will convert the LineString into a GeoJSON LineString geometry. +func (ls LineString) MarshalBSON() ([]byte, error) { + return bson.Marshal(&Geometry{Coordinates: orb.LineString(ls)}) } // UnmarshalJSON will unmarshal the GeoJSON MultiPoint geometry. @@ -235,6 +394,23 @@ func (ls *LineString) UnmarshalJSON(data []byte) error { return nil } +// UnmarshalBSON will unmarshal the GeoJSON MultiPoint geometry. +func (ls *LineString) UnmarshalBSON(data []byte) error { + g := &Geometry{} + err := bson.Unmarshal(data, &g) + if err != nil { + return err + } + + lineString, ok := g.Coordinates.(orb.LineString) + if !ok { + return errors.New("geojson: not a LineString type") + } + + *ls = LineString(lineString) + return nil +} + // A MultiLineString is a helper type that will marshal to/from a GeoJSON MultiLineString geometry. type MultiLineString orb.MultiLineString @@ -245,7 +421,12 @@ func (mls MultiLineString) Geometry() orb.Geometry { // MarshalJSON will convert the MultiLineString into a GeoJSON MultiLineString geometry. func (mls MultiLineString) MarshalJSON() ([]byte, error) { - return marshalJSON(Geometry{Coordinates: orb.MultiLineString(mls)}) + return marshalJSON(&Geometry{Coordinates: orb.MultiLineString(mls)}) +} + +// MarshalBSON will convert the MultiLineString into a GeoJSON MultiLineString geometry. +func (mls MultiLineString) MarshalBSON() ([]byte, error) { + return bson.Marshal(&Geometry{Coordinates: orb.MultiLineString(mls)}) } // UnmarshalJSON will unmarshal the GeoJSON MultiPoint geometry. @@ -265,6 +446,23 @@ func (mls *MultiLineString) UnmarshalJSON(data []byte) error { return nil } +// UnmarshalBSON will unmarshal the GeoJSON MultiPoint geometry. +func (mls *MultiLineString) UnmarshalBSON(data []byte) error { + g := &Geometry{} + err := bson.Unmarshal(data, &g) + if err != nil { + return err + } + + multilineString, ok := g.Coordinates.(orb.MultiLineString) + if !ok { + return errors.New("geojson: not a MultiLineString type") + } + + *mls = MultiLineString(multilineString) + return nil +} + // A Polygon is a helper type that will marshal to/from a GeoJSON Polygon geometry. type Polygon orb.Polygon @@ -275,7 +473,12 @@ func (p Polygon) Geometry() orb.Geometry { // MarshalJSON will convert the Polygon into a GeoJSON Polygon geometry. func (p Polygon) MarshalJSON() ([]byte, error) { - return marshalJSON(Geometry{Coordinates: orb.Polygon(p)}) + return marshalJSON(&Geometry{Coordinates: orb.Polygon(p)}) +} + +// MarshalBSON will convert the Polygon into a GeoJSON Polygon geometry. +func (p Polygon) MarshalBSON() ([]byte, error) { + return bson.Marshal(&Geometry{Coordinates: orb.Polygon(p)}) } // UnmarshalJSON will unmarshal the GeoJSON Polygon geometry. @@ -295,6 +498,23 @@ func (p *Polygon) UnmarshalJSON(data []byte) error { return nil } +// UnmarshalBSON will unmarshal the GeoJSON Polygon geometry. +func (p *Polygon) UnmarshalBSON(data []byte) error { + g := &Geometry{} + err := bson.Unmarshal(data, &g) + if err != nil { + return err + } + + polygon, ok := g.Coordinates.(orb.Polygon) + if !ok { + return errors.New("geojson: not a Polygon type") + } + + *p = Polygon(polygon) + return nil +} + // A MultiPolygon is a helper type that will marshal to/from a GeoJSON MultiPolygon geometry. type MultiPolygon orb.MultiPolygon @@ -305,7 +525,12 @@ func (mp MultiPolygon) Geometry() orb.Geometry { // MarshalJSON will convert the MultiPolygon into a GeoJSON MultiPolygon geometry. func (mp MultiPolygon) MarshalJSON() ([]byte, error) { - return marshalJSON(Geometry{Coordinates: orb.MultiPolygon(mp)}) + return marshalJSON(&Geometry{Coordinates: orb.MultiPolygon(mp)}) +} + +// MarshalBSON will convert the MultiPolygon into a GeoJSON MultiPolygon geometry. +func (mp MultiPolygon) MarshalBSON() ([]byte, error) { + return bson.Marshal(&Geometry{Coordinates: orb.MultiPolygon(mp)}) } // UnmarshalJSON will unmarshal the GeoJSON MultiPolygon geometry. @@ -325,14 +550,37 @@ func (mp *MultiPolygon) UnmarshalJSON(data []byte) error { return nil } +// UnmarshalBSON will unmarshal the GeoJSON MultiPolygon geometry. +func (mp *MultiPolygon) UnmarshalBSON(data []byte) error { + g := &Geometry{} + err := bson.Unmarshal(data, &g) + if err != nil { + return err + } + + multiPolygon, ok := g.Coordinates.(orb.MultiPolygon) + if !ok { + return errors.New("geojson: not a MultiPolygon type") + } + + *mp = MultiPolygon(multiPolygon) + return nil +} + +type bsonGeometry struct { + Type string `json:"type" bson:"type"` + Coordinates bson.RawValue `json:"coordinates" bson:"coordinates"` + Geometries []*Geometry `json:"geometries,omitempty" bson:"geometries"` +} + type jsonGeometry struct { Type string `json:"type"` Coordinates nocopyRawMessage `json:"coordinates"` Geometries []*Geometry `json:"geometries,omitempty"` } -type jsonGeometryMarshall struct { - Type string `json:"type"` - Coordinates orb.Geometry `json:"coordinates,omitempty"` - Geometries []*Geometry `json:"geometries,omitempty"` +type geometryMarshallDoc struct { + Type string `json:"type" bson:"type"` + Coordinates orb.Geometry `json:"coordinates,omitempty" bson:"coordinates,omitempty"` + Geometries []*Geometry `json:"geometries,omitempty" bson:"geometries,omitempty"` } diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-export/v2/export.go b/vendor/github.com/whosonfirst/go-whosonfirst-export/v2/export.go index 718752b..9e64afd 100644 --- a/vendor/github.com/whosonfirst/go-whosonfirst-export/v2/export.go +++ b/vendor/github.com/whosonfirst/go-whosonfirst-export/v2/export.go @@ -3,10 +3,12 @@ package export import ( "bytes" "encoding/json" - _ "fmt" + "fmt" "io" + _ "log" "github.com/whosonfirst/go-whosonfirst-export/v2/properties" + "github.com/whosonfirst/go-whosonfirst-feature/alt" format "github.com/whosonfirst/go-whosonfirst-format" ) @@ -14,35 +16,32 @@ func Export(feature []byte, opts *Options, wr io.Writer) error { var err error - feature, err = prepareWithoutTimestamps(feature, opts) + feature, err = Prepare(feature, opts) if err != nil { - return err - } - - feature, err = prepareTimestamps(feature, opts) - - if err != nil { - return err + return fmt.Errorf("Failed to prepare feature, %w", err) } feature, err = Format(feature, opts) if err != nil { - return err + return fmt.Errorf("Failed to format feature, %w", err) } r := bytes.NewReader(feature) _, err = io.Copy(wr, r) - return err + if err != nil { + return fmt.Errorf("Failed to copy feature to writer, %w", err) + } + + return nil } // ExportChanged returns a boolean which indicates whether the file was changed // by comparing it to the `existingFeature` byte slice, before the lastmodified // timestamp is incremented. If the `feature` is identical to `existingFeature` // it doesn't write to the `io.Writer`. - func ExportChanged(feature []byte, existingFeature []byte, opts *Options, wr io.Writer) (changed bool, err error) { changed = false @@ -84,16 +83,19 @@ func ExportChanged(feature []byte, existingFeature []byte, opts *Options, wr io. } func Prepare(feature []byte, opts *Options) ([]byte, error) { + var err error feature, err = prepareWithoutTimestamps(feature, opts) + if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to prepare without timestamps, %w", err) } feature, err = prepareTimestamps(feature, opts) + if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to prepare with timestamps, %w", err) } return feature, nil @@ -107,54 +109,83 @@ func Format(feature []byte, opts *Options) ([]byte, error) { func prepareWithoutTimestamps(feature []byte, opts *Options) ([]byte, error) { + if alt.IsAlt(feature) { + return prepareWithoutTimestampsAsAlternateGeometry(feature, opts) + } + var err error feature, err = properties.EnsureWOFId(feature, opts.IDProvider) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure wof:id, %w", err) } feature, err = properties.EnsureRequired(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure required properties, %w", err) } feature, err = properties.EnsureEDTF(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure EDTF properties, %w", err) } feature, err = properties.EnsureParentId(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure parent ID, %w", err) } feature, err = properties.EnsureHierarchy(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure hierarchy, %w", err) } feature, err = properties.EnsureBelongsTo(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure belongs to, %w", err) } feature, err = properties.EnsureSupersedes(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure supersedes, %w", err) } feature, err = properties.EnsureSupersededBy(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure superseded by, %w", err) + } + + return feature, nil +} + +func prepareWithoutTimestampsAsAlternateGeometry(feature []byte, opts *Options) ([]byte, error) { + + var err error + + feature, err = properties.EnsureWOFId(feature, opts.IDProvider) + + if err != nil { + return nil, fmt.Errorf("Failed to ensure wof:id, %w", err) + } + + feature, err = properties.EnsureRequired(feature) + + if err != nil { + return nil, fmt.Errorf("Failed to ensure required properties, %w", err) + } + + feature, err = properties.EnsureSourceAltLabel(feature) + + if err != nil { + return nil, fmt.Errorf("Failed to ensure src:alt_label, %w", err) } return feature, nil diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-export/v2/properties/alt.go b/vendor/github.com/whosonfirst/go-whosonfirst-export/v2/properties/alt.go new file mode 100644 index 0000000..3511ed4 --- /dev/null +++ b/vendor/github.com/whosonfirst/go-whosonfirst-export/v2/properties/alt.go @@ -0,0 +1,22 @@ +package properties + +import ( + "fmt" + + wof_properties "github.com/whosonfirst/go-whosonfirst-feature/properties" +) + +func EnsureSourceAltLabel(feature []byte) ([]byte, error) { + + label, err := wof_properties.AltLabel(feature) + + if err != nil { + return nil, fmt.Errorf("Failed to derive src:alt_label, %w", err) + } + + if label == "" { + return nil, fmt.Errorf("Invalid or empty src:alt_label property") + } + + return feature, nil +} diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-export/v2/properties/properties.go b/vendor/github.com/whosonfirst/go-whosonfirst-export/v2/properties/properties.go index 0db7661..eeb317f 100644 --- a/vendor/github.com/whosonfirst/go-whosonfirst-export/v2/properties/properties.go +++ b/vendor/github.com/whosonfirst/go-whosonfirst-export/v2/properties/properties.go @@ -1,5 +1,9 @@ package properties +import ( + "fmt" +) + func EnsureRequired(feature []byte) ([]byte, error) { var err error @@ -7,19 +11,19 @@ func EnsureRequired(feature []byte) ([]byte, error) { feature, err = EnsureName(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure wof:name, %w", err) } feature, err = EnsurePlacetype(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure placetype, %w", err) } feature, err = EnsureGeom(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure geometry, %w", err) } return feature, nil @@ -32,19 +36,19 @@ func EnsureGeom(feature []byte) ([]byte, error) { feature, err = EnsureSrcGeom(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure src:geom, %w", err) } feature, err = EnsureGeomHash(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure geom:hash, %w", err) } feature, err = EnsureGeomCoords(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure geometry coordinates, %w", err) } return feature, nil @@ -57,13 +61,13 @@ func EnsureTimestamps(feature []byte) ([]byte, error) { feature, err = EnsureCreated(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure wof:created, %w", err) } feature, err = EnsureLastModified(feature) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to ensure wof:lastmodified, %w", err) } return feature, nil diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-uri/doc.go b/vendor/github.com/whosonfirst/go-whosonfirst-uri/doc.go index 2257177..eb16aad 100644 --- a/vendor/github.com/whosonfirst/go-whosonfirst-uri/doc.go +++ b/vendor/github.com/whosonfirst/go-whosonfirst-uri/doc.go @@ -32,7 +32,7 @@ // rel_path, _ := uri.Id2RelPath(101736545, args) // abs_path, _ := uri.Id2AbsPath("/usr/local/data", 101736545, args) // -//Produces: +// Produces: // // 101736545-alt-mapzen-display-1024.geojson // 101/736/545/101736545-alt-mapzen-display-1024.geojson diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-uri/uri.go b/vendor/github.com/whosonfirst/go-whosonfirst-uri/uri.go index e457941..f5ce92b 100644 --- a/vendor/github.com/whosonfirst/go-whosonfirst-uri/uri.go +++ b/vendor/github.com/whosonfirst/go-whosonfirst-uri/uri.go @@ -95,6 +95,32 @@ func NewAlternateURIArgs(source string, function string, extras ...string) *URIA return &u } +// Return a `URIArgs` struct representing an alternate geometry derive from 'label' (which is expected to +// be the value of a valid "src:alt_label" or "src:geom_alt" property. +func NewAlternateURIArgsFromAltLabel(label string) (*URIArgs, error) { + + parts := strings.Split(label, "-") + + if len(parts) < 1 { + return nil, fmt.Errorf("Invalid alt label") + } + + source := parts[0] + function := "" + extras := make([]string, 0) + + if len(parts) > 1 { + function = parts[1] + } + + if len(parts) > 2 { + extras = parts[2:] + } + + uri_args := NewAlternateURIArgs(source, function, extras...) + return uri_args, nil +} + // See also: https://github.com/whosonfirst/whosonfirst-cookbook/blob/master/how_to/creating_alt_geometries.md // Id2Fname parses a Who's On First ID and one or more URIArgs instances (in practice just one instance) in to a filename. diff --git a/vendor/go.mongodb.org/mongo-driver/LICENSE b/vendor/go.mongodb.org/mongo-driver/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bson.go b/vendor/go.mongodb.org/mongo-driver/bson/bson.go new file mode 100644 index 0000000..a0d8185 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bson.go @@ -0,0 +1,50 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Based on gopkg.in/mgo.v2/bson by Gustavo Niemeyer +// See THIRD-PARTY-NOTICES for original license terms. + +package bson // import "go.mongodb.org/mongo-driver/bson" + +import ( + "go.mongodb.org/mongo-driver/bson/primitive" +) + +// Zeroer allows custom struct types to implement a report of zero +// state. All struct types that don't implement Zeroer or where IsZero +// returns false are considered to be not zero. +type Zeroer interface { + IsZero() bool +} + +// D is an ordered representation of a BSON document. This type should be used when the order of the elements matters, +// such as MongoDB command documents. If the order of the elements does not matter, an M should be used instead. +// +// A D should not be constructed with duplicate key names, as that can cause undefined server behavior. +// +// Example usage: +// +// bson.D{{"foo", "bar"}, {"hello", "world"}, {"pi", 3.14159}} +type D = primitive.D + +// E represents a BSON element for a D. It is usually used inside a D. +type E = primitive.E + +// M is an unordered representation of a BSON document. This type should be used when the order of the elements does not +// matter. This type is handled as a regular map[string]interface{} when encoding and decoding. Elements will be +// serialized in an undefined, random order. If the order of the elements matters, a D should be used instead. +// +// Example usage: +// +// bson.M{"foo": "bar", "hello": "world", "pi": 3.14159} +type M = primitive.M + +// An A is an ordered representation of a BSON array. +// +// Example usage: +// +// bson.A{"bar", "world", 3.14159, bson.D{{"qux", 12345}}} +type A = primitive.A diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go new file mode 100644 index 0000000..4e24f9e --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go @@ -0,0 +1,50 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "reflect" + + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +// ArrayCodec is the Codec used for bsoncore.Array values. +type ArrayCodec struct{} + +var defaultArrayCodec = NewArrayCodec() + +// NewArrayCodec returns an ArrayCodec. +func NewArrayCodec() *ArrayCodec { + return &ArrayCodec{} +} + +// EncodeValue is the ValueEncoder for bsoncore.Array values. +func (ac *ArrayCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tCoreArray { + return ValueEncoderError{Name: "CoreArrayEncodeValue", Types: []reflect.Type{tCoreArray}, Received: val} + } + + arr := val.Interface().(bsoncore.Array) + return bsonrw.Copier{}.CopyArrayFromBytes(vw, arr) +} + +// DecodeValue is the ValueDecoder for bsoncore.Array values. +func (ac *ArrayCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tCoreArray { + return ValueDecoderError{Name: "CoreArrayDecodeValue", Types: []reflect.Type{tCoreArray}, Received: val} + } + + if val.IsNil() { + val.Set(reflect.MakeSlice(val.Type(), 0, 0)) + } + + val.SetLen(0) + arr, err := bsonrw.Copier{}.AppendArrayBytes(val.Interface().(bsoncore.Array), vr) + val.Set(reflect.ValueOf(arr)) + return err +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go new file mode 100644 index 0000000..098ed69 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go @@ -0,0 +1,238 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec // import "go.mongodb.org/mongo-driver/bson/bsoncodec" + +import ( + "fmt" + "reflect" + "strings" + + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/bson/bsontype" + "go.mongodb.org/mongo-driver/bson/primitive" +) + +var ( + emptyValue = reflect.Value{} +) + +// Marshaler is an interface implemented by types that can marshal themselves +// into a BSON document represented as bytes. The bytes returned must be a valid +// BSON document if the error is nil. +type Marshaler interface { + MarshalBSON() ([]byte, error) +} + +// ValueMarshaler is an interface implemented by types that can marshal +// themselves into a BSON value as bytes. The type must be the valid type for +// the bytes returned. The bytes and byte type together must be valid if the +// error is nil. +type ValueMarshaler interface { + MarshalBSONValue() (bsontype.Type, []byte, error) +} + +// Unmarshaler is an interface implemented by types that can unmarshal a BSON +// document representation of themselves. The BSON bytes can be assumed to be +// valid. UnmarshalBSON must copy the BSON bytes if it wishes to retain the data +// after returning. +type Unmarshaler interface { + UnmarshalBSON([]byte) error +} + +// ValueUnmarshaler is an interface implemented by types that can unmarshal a +// BSON value representation of themselves. The BSON bytes and type can be +// assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it +// wishes to retain the data after returning. +type ValueUnmarshaler interface { + UnmarshalBSONValue(bsontype.Type, []byte) error +} + +// ValueEncoderError is an error returned from a ValueEncoder when the provided value can't be +// encoded by the ValueEncoder. +type ValueEncoderError struct { + Name string + Types []reflect.Type + Kinds []reflect.Kind + Received reflect.Value +} + +func (vee ValueEncoderError) Error() string { + typeKinds := make([]string, 0, len(vee.Types)+len(vee.Kinds)) + for _, t := range vee.Types { + typeKinds = append(typeKinds, t.String()) + } + for _, k := range vee.Kinds { + if k == reflect.Map { + typeKinds = append(typeKinds, "map[string]*") + continue + } + typeKinds = append(typeKinds, k.String()) + } + received := vee.Received.Kind().String() + if vee.Received.IsValid() { + received = vee.Received.Type().String() + } + return fmt.Sprintf("%s can only encode valid %s, but got %s", vee.Name, strings.Join(typeKinds, ", "), received) +} + +// ValueDecoderError is an error returned from a ValueDecoder when the provided value can't be +// decoded by the ValueDecoder. +type ValueDecoderError struct { + Name string + Types []reflect.Type + Kinds []reflect.Kind + Received reflect.Value +} + +func (vde ValueDecoderError) Error() string { + typeKinds := make([]string, 0, len(vde.Types)+len(vde.Kinds)) + for _, t := range vde.Types { + typeKinds = append(typeKinds, t.String()) + } + for _, k := range vde.Kinds { + if k == reflect.Map { + typeKinds = append(typeKinds, "map[string]*") + continue + } + typeKinds = append(typeKinds, k.String()) + } + received := vde.Received.Kind().String() + if vde.Received.IsValid() { + received = vde.Received.Type().String() + } + return fmt.Sprintf("%s can only decode valid and settable %s, but got %s", vde.Name, strings.Join(typeKinds, ", "), received) +} + +// EncodeContext is the contextual information required for a Codec to encode a +// value. +type EncodeContext struct { + *Registry + MinSize bool +} + +// DecodeContext is the contextual information required for a Codec to decode a +// value. +type DecodeContext struct { + *Registry + Truncate bool + + // Ancestor is the type of a containing document. This is mainly used to determine what type + // should be used when decoding an embedded document into an empty interface. For example, if + // Ancestor is a bson.M, BSON embedded document values being decoded into an empty interface + // will be decoded into a bson.M. + // + // Deprecated: Use DefaultDocumentM or DefaultDocumentD instead. + Ancestor reflect.Type + + // defaultDocumentType specifies the Go type to decode top-level and nested BSON documents into. In particular, the + // usage for this field is restricted to data typed as "interface{}" or "map[string]interface{}". If DocumentType is + // set to a type that a BSON document cannot be unmarshaled into (e.g. "string"), unmarshalling will result in an + // error. DocumentType overrides the Ancestor field. + defaultDocumentType reflect.Type +} + +// DefaultDocumentM will decode empty documents using the primitive.M type. This behavior is restricted to data typed as +// "interface{}" or "map[string]interface{}". +func (dc *DecodeContext) DefaultDocumentM() { + dc.defaultDocumentType = reflect.TypeOf(primitive.M{}) +} + +// DefaultDocumentD will decode empty documents using the primitive.D type. This behavior is restricted to data typed as +// "interface{}" or "map[string]interface{}". +func (dc *DecodeContext) DefaultDocumentD() { + dc.defaultDocumentType = reflect.TypeOf(primitive.D{}) +} + +// ValueCodec is the interface that groups the methods to encode and decode +// values. +type ValueCodec interface { + ValueEncoder + ValueDecoder +} + +// ValueEncoder is the interface implemented by types that can handle the encoding of a value. +type ValueEncoder interface { + EncodeValue(EncodeContext, bsonrw.ValueWriter, reflect.Value) error +} + +// ValueEncoderFunc is an adapter function that allows a function with the correct signature to be +// used as a ValueEncoder. +type ValueEncoderFunc func(EncodeContext, bsonrw.ValueWriter, reflect.Value) error + +// EncodeValue implements the ValueEncoder interface. +func (fn ValueEncoderFunc) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + return fn(ec, vw, val) +} + +// ValueDecoder is the interface implemented by types that can handle the decoding of a value. +type ValueDecoder interface { + DecodeValue(DecodeContext, bsonrw.ValueReader, reflect.Value) error +} + +// ValueDecoderFunc is an adapter function that allows a function with the correct signature to be +// used as a ValueDecoder. +type ValueDecoderFunc func(DecodeContext, bsonrw.ValueReader, reflect.Value) error + +// DecodeValue implements the ValueDecoder interface. +func (fn ValueDecoderFunc) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + return fn(dc, vr, val) +} + +// typeDecoder is the interface implemented by types that can handle the decoding of a value given its type. +type typeDecoder interface { + decodeType(DecodeContext, bsonrw.ValueReader, reflect.Type) (reflect.Value, error) +} + +// typeDecoderFunc is an adapter function that allows a function with the correct signature to be used as a typeDecoder. +type typeDecoderFunc func(DecodeContext, bsonrw.ValueReader, reflect.Type) (reflect.Value, error) + +func (fn typeDecoderFunc) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + return fn(dc, vr, t) +} + +// decodeAdapter allows two functions with the correct signatures to be used as both a ValueDecoder and typeDecoder. +type decodeAdapter struct { + ValueDecoderFunc + typeDecoderFunc +} + +var _ ValueDecoder = decodeAdapter{} +var _ typeDecoder = decodeAdapter{} + +// decodeTypeOrValue calls decoder.decodeType is decoder is a typeDecoder. Otherwise, it allocates a new element of type +// t and calls decoder.DecodeValue on it. +func decodeTypeOrValue(decoder ValueDecoder, dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + td, _ := decoder.(typeDecoder) + return decodeTypeOrValueWithInfo(decoder, td, dc, vr, t, true) +} + +func decodeTypeOrValueWithInfo(vd ValueDecoder, td typeDecoder, dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type, convert bool) (reflect.Value, error) { + if td != nil { + val, err := td.decodeType(dc, vr, t) + if err == nil && convert && val.Type() != t { + // This conversion step is necessary for slices and maps. If a user declares variables like: + // + // type myBool bool + // var m map[string]myBool + // + // and tries to decode BSON bytes into the map, the decoding will fail if this conversion is not present + // because we'll try to assign a value of type bool to one of type myBool. + val = val.Convert(t) + } + return val, err + } + + val := reflect.New(t).Elem() + err := vd.DecodeValue(dc, vr, val) + return val, err +} + +// CodecZeroer is the interface implemented by Codecs that can also determine if +// a value of the type that would be encoded is zero. +type CodecZeroer interface { + IsTypeZero(interface{}) bool +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go new file mode 100644 index 0000000..5a916cc --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go @@ -0,0 +1,111 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "fmt" + "reflect" + + "go.mongodb.org/mongo-driver/bson/bsonoptions" + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/bson/bsontype" +) + +// ByteSliceCodec is the Codec used for []byte values. +type ByteSliceCodec struct { + EncodeNilAsEmpty bool +} + +var ( + defaultByteSliceCodec = NewByteSliceCodec() + + _ ValueCodec = defaultByteSliceCodec + _ typeDecoder = defaultByteSliceCodec +) + +// NewByteSliceCodec returns a StringCodec with options opts. +func NewByteSliceCodec(opts ...*bsonoptions.ByteSliceCodecOptions) *ByteSliceCodec { + byteSliceOpt := bsonoptions.MergeByteSliceCodecOptions(opts...) + codec := ByteSliceCodec{} + if byteSliceOpt.EncodeNilAsEmpty != nil { + codec.EncodeNilAsEmpty = *byteSliceOpt.EncodeNilAsEmpty + } + return &codec +} + +// EncodeValue is the ValueEncoder for []byte. +func (bsc *ByteSliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tByteSlice { + return ValueEncoderError{Name: "ByteSliceEncodeValue", Types: []reflect.Type{tByteSlice}, Received: val} + } + if val.IsNil() && !bsc.EncodeNilAsEmpty { + return vw.WriteNull() + } + return vw.WriteBinary(val.Interface().([]byte)) +} + +func (bsc *ByteSliceCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tByteSlice { + return emptyValue, ValueDecoderError{ + Name: "ByteSliceDecodeValue", + Types: []reflect.Type{tByteSlice}, + Received: reflect.Zero(t), + } + } + + var data []byte + var err error + switch vrType := vr.Type(); vrType { + case bsontype.String: + str, err := vr.ReadString() + if err != nil { + return emptyValue, err + } + data = []byte(str) + case bsontype.Symbol: + sym, err := vr.ReadSymbol() + if err != nil { + return emptyValue, err + } + data = []byte(sym) + case bsontype.Binary: + var subtype byte + data, subtype, err = vr.ReadBinary() + if err != nil { + return emptyValue, err + } + if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld { + return emptyValue, decodeBinaryError{subtype: subtype, typeName: "[]byte"} + } + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a []byte", vrType) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(data), nil +} + +// DecodeValue is the ValueDecoder for []byte. +func (bsc *ByteSliceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tByteSlice { + return ValueDecoderError{Name: "ByteSliceDecodeValue", Types: []reflect.Type{tByteSlice}, Received: val} + } + + elem, err := bsc.decodeType(dc, vr, tByteSlice) + if err != nil { + return err + } + + val.Set(elem) + return nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/cond_addr_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/cond_addr_codec.go new file mode 100644 index 0000000..cb8180f --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/cond_addr_codec.go @@ -0,0 +1,63 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "reflect" + + "go.mongodb.org/mongo-driver/bson/bsonrw" +) + +// condAddrEncoder is the encoder used when a pointer to the encoding value has an encoder. +type condAddrEncoder struct { + canAddrEnc ValueEncoder + elseEnc ValueEncoder +} + +var _ ValueEncoder = (*condAddrEncoder)(nil) + +// newCondAddrEncoder returns an condAddrEncoder. +func newCondAddrEncoder(canAddrEnc, elseEnc ValueEncoder) *condAddrEncoder { + encoder := condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc} + return &encoder +} + +// EncodeValue is the ValueEncoderFunc for a value that may be addressable. +func (cae *condAddrEncoder) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if val.CanAddr() { + return cae.canAddrEnc.EncodeValue(ec, vw, val) + } + if cae.elseEnc != nil { + return cae.elseEnc.EncodeValue(ec, vw, val) + } + return ErrNoEncoder{Type: val.Type()} +} + +// condAddrDecoder is the decoder used when a pointer to the value has a decoder. +type condAddrDecoder struct { + canAddrDec ValueDecoder + elseDec ValueDecoder +} + +var _ ValueDecoder = (*condAddrDecoder)(nil) + +// newCondAddrDecoder returns an CondAddrDecoder. +func newCondAddrDecoder(canAddrDec, elseDec ValueDecoder) *condAddrDecoder { + decoder := condAddrDecoder{canAddrDec: canAddrDec, elseDec: elseDec} + return &decoder +} + +// DecodeValue is the ValueDecoderFunc for a value that may be addressable. +func (cad *condAddrDecoder) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if val.CanAddr() { + return cad.canAddrDec.DecodeValue(dc, vr, val) + } + if cad.elseDec != nil { + return cad.elseDec.DecodeValue(dc, vr, val) + } + return ErrNoDecoder{Type: val.Type()} +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go new file mode 100644 index 0000000..e95cab5 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go @@ -0,0 +1,1729 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "encoding/json" + "errors" + "fmt" + "math" + "net/url" + "reflect" + "strconv" + "time" + + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/bson/bsontype" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +var ( + defaultValueDecoders DefaultValueDecoders + errCannotTruncate = errors.New("float64 can only be truncated to an integer type when truncation is enabled") +) + +type decodeBinaryError struct { + subtype byte + typeName string +} + +func (d decodeBinaryError) Error() string { + return fmt.Sprintf("only binary values with subtype 0x00 or 0x02 can be decoded into %s, but got subtype %v", d.typeName, d.subtype) +} + +func newDefaultStructCodec() *StructCodec { + codec, err := NewStructCodec(DefaultStructTagParser) + if err != nil { + // This function is called from the codec registration path, so errors can't be propagated. If there's an error + // constructing the StructCodec, we panic to avoid losing it. + panic(fmt.Errorf("error creating default StructCodec: %v", err)) + } + return codec +} + +// DefaultValueDecoders is a namespace type for the default ValueDecoders used +// when creating a registry. +type DefaultValueDecoders struct{} + +// RegisterDefaultDecoders will register the decoder methods attached to DefaultValueDecoders with +// the provided RegistryBuilder. +// +// There is no support for decoding map[string]interface{} because there is no decoder for +// interface{}, so users must either register this decoder themselves or use the +// EmptyInterfaceDecoder available in the bson package. +func (dvd DefaultValueDecoders) RegisterDefaultDecoders(rb *RegistryBuilder) { + if rb == nil { + panic(errors.New("argument to RegisterDefaultDecoders must not be nil")) + } + + intDecoder := decodeAdapter{dvd.IntDecodeValue, dvd.intDecodeType} + floatDecoder := decodeAdapter{dvd.FloatDecodeValue, dvd.floatDecodeType} + + rb. + RegisterTypeDecoder(tD, ValueDecoderFunc(dvd.DDecodeValue)). + RegisterTypeDecoder(tBinary, decodeAdapter{dvd.BinaryDecodeValue, dvd.binaryDecodeType}). + RegisterTypeDecoder(tUndefined, decodeAdapter{dvd.UndefinedDecodeValue, dvd.undefinedDecodeType}). + RegisterTypeDecoder(tDateTime, decodeAdapter{dvd.DateTimeDecodeValue, dvd.dateTimeDecodeType}). + RegisterTypeDecoder(tNull, decodeAdapter{dvd.NullDecodeValue, dvd.nullDecodeType}). + RegisterTypeDecoder(tRegex, decodeAdapter{dvd.RegexDecodeValue, dvd.regexDecodeType}). + RegisterTypeDecoder(tDBPointer, decodeAdapter{dvd.DBPointerDecodeValue, dvd.dBPointerDecodeType}). + RegisterTypeDecoder(tTimestamp, decodeAdapter{dvd.TimestampDecodeValue, dvd.timestampDecodeType}). + RegisterTypeDecoder(tMinKey, decodeAdapter{dvd.MinKeyDecodeValue, dvd.minKeyDecodeType}). + RegisterTypeDecoder(tMaxKey, decodeAdapter{dvd.MaxKeyDecodeValue, dvd.maxKeyDecodeType}). + RegisterTypeDecoder(tJavaScript, decodeAdapter{dvd.JavaScriptDecodeValue, dvd.javaScriptDecodeType}). + RegisterTypeDecoder(tSymbol, decodeAdapter{dvd.SymbolDecodeValue, dvd.symbolDecodeType}). + RegisterTypeDecoder(tByteSlice, defaultByteSliceCodec). + RegisterTypeDecoder(tTime, defaultTimeCodec). + RegisterTypeDecoder(tEmpty, defaultEmptyInterfaceCodec). + RegisterTypeDecoder(tCoreArray, defaultArrayCodec). + RegisterTypeDecoder(tOID, decodeAdapter{dvd.ObjectIDDecodeValue, dvd.objectIDDecodeType}). + RegisterTypeDecoder(tDecimal, decodeAdapter{dvd.Decimal128DecodeValue, dvd.decimal128DecodeType}). + RegisterTypeDecoder(tJSONNumber, decodeAdapter{dvd.JSONNumberDecodeValue, dvd.jsonNumberDecodeType}). + RegisterTypeDecoder(tURL, decodeAdapter{dvd.URLDecodeValue, dvd.urlDecodeType}). + RegisterTypeDecoder(tCoreDocument, ValueDecoderFunc(dvd.CoreDocumentDecodeValue)). + RegisterTypeDecoder(tCodeWithScope, decodeAdapter{dvd.CodeWithScopeDecodeValue, dvd.codeWithScopeDecodeType}). + RegisterDefaultDecoder(reflect.Bool, decodeAdapter{dvd.BooleanDecodeValue, dvd.booleanDecodeType}). + RegisterDefaultDecoder(reflect.Int, intDecoder). + RegisterDefaultDecoder(reflect.Int8, intDecoder). + RegisterDefaultDecoder(reflect.Int16, intDecoder). + RegisterDefaultDecoder(reflect.Int32, intDecoder). + RegisterDefaultDecoder(reflect.Int64, intDecoder). + RegisterDefaultDecoder(reflect.Uint, defaultUIntCodec). + RegisterDefaultDecoder(reflect.Uint8, defaultUIntCodec). + RegisterDefaultDecoder(reflect.Uint16, defaultUIntCodec). + RegisterDefaultDecoder(reflect.Uint32, defaultUIntCodec). + RegisterDefaultDecoder(reflect.Uint64, defaultUIntCodec). + RegisterDefaultDecoder(reflect.Float32, floatDecoder). + RegisterDefaultDecoder(reflect.Float64, floatDecoder). + RegisterDefaultDecoder(reflect.Array, ValueDecoderFunc(dvd.ArrayDecodeValue)). + RegisterDefaultDecoder(reflect.Map, defaultMapCodec). + RegisterDefaultDecoder(reflect.Slice, defaultSliceCodec). + RegisterDefaultDecoder(reflect.String, defaultStringCodec). + RegisterDefaultDecoder(reflect.Struct, newDefaultStructCodec()). + RegisterDefaultDecoder(reflect.Ptr, NewPointerCodec()). + RegisterTypeMapEntry(bsontype.Double, tFloat64). + RegisterTypeMapEntry(bsontype.String, tString). + RegisterTypeMapEntry(bsontype.Array, tA). + RegisterTypeMapEntry(bsontype.Binary, tBinary). + RegisterTypeMapEntry(bsontype.Undefined, tUndefined). + RegisterTypeMapEntry(bsontype.ObjectID, tOID). + RegisterTypeMapEntry(bsontype.Boolean, tBool). + RegisterTypeMapEntry(bsontype.DateTime, tDateTime). + RegisterTypeMapEntry(bsontype.Regex, tRegex). + RegisterTypeMapEntry(bsontype.DBPointer, tDBPointer). + RegisterTypeMapEntry(bsontype.JavaScript, tJavaScript). + RegisterTypeMapEntry(bsontype.Symbol, tSymbol). + RegisterTypeMapEntry(bsontype.CodeWithScope, tCodeWithScope). + RegisterTypeMapEntry(bsontype.Int32, tInt32). + RegisterTypeMapEntry(bsontype.Int64, tInt64). + RegisterTypeMapEntry(bsontype.Timestamp, tTimestamp). + RegisterTypeMapEntry(bsontype.Decimal128, tDecimal). + RegisterTypeMapEntry(bsontype.MinKey, tMinKey). + RegisterTypeMapEntry(bsontype.MaxKey, tMaxKey). + RegisterTypeMapEntry(bsontype.Type(0), tD). + RegisterTypeMapEntry(bsontype.EmbeddedDocument, tD). + RegisterHookDecoder(tValueUnmarshaler, ValueDecoderFunc(dvd.ValueUnmarshalerDecodeValue)). + RegisterHookDecoder(tUnmarshaler, ValueDecoderFunc(dvd.UnmarshalerDecodeValue)) +} + +// DDecodeValue is the ValueDecoderFunc for primitive.D instances. +func (dvd DefaultValueDecoders) DDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.IsValid() || !val.CanSet() || val.Type() != tD { + return ValueDecoderError{Name: "DDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} + } + + switch vrType := vr.Type(); vrType { + case bsontype.Type(0), bsontype.EmbeddedDocument: + dc.Ancestor = tD + case bsontype.Null: + val.Set(reflect.Zero(val.Type())) + return vr.ReadNull() + default: + return fmt.Errorf("cannot decode %v into a primitive.D", vrType) + } + + dr, err := vr.ReadDocument() + if err != nil { + return err + } + + decoder, err := dc.LookupDecoder(tEmpty) + if err != nil { + return err + } + tEmptyTypeDecoder, _ := decoder.(typeDecoder) + + // Use the elements in the provided value if it's non nil. Otherwise, allocate a new D instance. + var elems primitive.D + if !val.IsNil() { + val.SetLen(0) + elems = val.Interface().(primitive.D) + } else { + elems = make(primitive.D, 0) + } + + for { + key, elemVr, err := dr.ReadElement() + if err == bsonrw.ErrEOD { + break + } else if err != nil { + return err + } + + // Pass false for convert because we don't need to call reflect.Value.Convert for tEmpty. + elem, err := decodeTypeOrValueWithInfo(decoder, tEmptyTypeDecoder, dc, elemVr, tEmpty, false) + if err != nil { + return err + } + + elems = append(elems, primitive.E{Key: key, Value: elem.Interface()}) + } + + val.Set(reflect.ValueOf(elems)) + return nil +} + +func (dvd DefaultValueDecoders) booleanDecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t.Kind() != reflect.Bool { + return emptyValue, ValueDecoderError{ + Name: "BooleanDecodeValue", + Kinds: []reflect.Kind{reflect.Bool}, + Received: reflect.Zero(t), + } + } + + var b bool + var err error + switch vrType := vr.Type(); vrType { + case bsontype.Int32: + i32, err := vr.ReadInt32() + if err != nil { + return emptyValue, err + } + b = (i32 != 0) + case bsontype.Int64: + i64, err := vr.ReadInt64() + if err != nil { + return emptyValue, err + } + b = (i64 != 0) + case bsontype.Double: + f64, err := vr.ReadDouble() + if err != nil { + return emptyValue, err + } + b = (f64 != 0) + case bsontype.Boolean: + b, err = vr.ReadBoolean() + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a boolean", vrType) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(b), nil +} + +// BooleanDecodeValue is the ValueDecoderFunc for bool types. +func (dvd DefaultValueDecoders) BooleanDecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.IsValid() || !val.CanSet() || val.Kind() != reflect.Bool { + return ValueDecoderError{Name: "BooleanDecodeValue", Kinds: []reflect.Kind{reflect.Bool}, Received: val} + } + + elem, err := dvd.booleanDecodeType(dctx, vr, val.Type()) + if err != nil { + return err + } + + val.SetBool(elem.Bool()) + return nil +} + +func (DefaultValueDecoders) intDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + var i64 int64 + var err error + switch vrType := vr.Type(); vrType { + case bsontype.Int32: + i32, err := vr.ReadInt32() + if err != nil { + return emptyValue, err + } + i64 = int64(i32) + case bsontype.Int64: + i64, err = vr.ReadInt64() + if err != nil { + return emptyValue, err + } + case bsontype.Double: + f64, err := vr.ReadDouble() + if err != nil { + return emptyValue, err + } + if !dc.Truncate && math.Floor(f64) != f64 { + return emptyValue, errCannotTruncate + } + if f64 > float64(math.MaxInt64) { + return emptyValue, fmt.Errorf("%g overflows int64", f64) + } + i64 = int64(f64) + case bsontype.Boolean: + b, err := vr.ReadBoolean() + if err != nil { + return emptyValue, err + } + if b { + i64 = 1 + } + case bsontype.Null: + if err = vr.ReadNull(); err != nil { + return emptyValue, err + } + case bsontype.Undefined: + if err = vr.ReadUndefined(); err != nil { + return emptyValue, err + } + default: + return emptyValue, fmt.Errorf("cannot decode %v into an integer type", vrType) + } + + switch t.Kind() { + case reflect.Int8: + if i64 < math.MinInt8 || i64 > math.MaxInt8 { + return emptyValue, fmt.Errorf("%d overflows int8", i64) + } + + return reflect.ValueOf(int8(i64)), nil + case reflect.Int16: + if i64 < math.MinInt16 || i64 > math.MaxInt16 { + return emptyValue, fmt.Errorf("%d overflows int16", i64) + } + + return reflect.ValueOf(int16(i64)), nil + case reflect.Int32: + if i64 < math.MinInt32 || i64 > math.MaxInt32 { + return emptyValue, fmt.Errorf("%d overflows int32", i64) + } + + return reflect.ValueOf(int32(i64)), nil + case reflect.Int64: + return reflect.ValueOf(i64), nil + case reflect.Int: + if int64(int(i64)) != i64 { // Can we fit this inside of an int + return emptyValue, fmt.Errorf("%d overflows int", i64) + } + + return reflect.ValueOf(int(i64)), nil + default: + return emptyValue, ValueDecoderError{ + Name: "IntDecodeValue", + Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int}, + Received: reflect.Zero(t), + } + } +} + +// IntDecodeValue is the ValueDecoderFunc for int types. +func (dvd DefaultValueDecoders) IntDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() { + return ValueDecoderError{ + Name: "IntDecodeValue", + Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int}, + Received: val, + } + } + + elem, err := dvd.intDecodeType(dc, vr, val.Type()) + if err != nil { + return err + } + + val.SetInt(elem.Int()) + return nil +} + +// UintDecodeValue is the ValueDecoderFunc for uint types. +// +// Deprecated: UintDecodeValue is not registered by default. Use UintCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) UintDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + var i64 int64 + var err error + switch vr.Type() { + case bsontype.Int32: + i32, err := vr.ReadInt32() + if err != nil { + return err + } + i64 = int64(i32) + case bsontype.Int64: + i64, err = vr.ReadInt64() + if err != nil { + return err + } + case bsontype.Double: + f64, err := vr.ReadDouble() + if err != nil { + return err + } + if !dc.Truncate && math.Floor(f64) != f64 { + return errors.New("UintDecodeValue can only truncate float64 to an integer type when truncation is enabled") + } + if f64 > float64(math.MaxInt64) { + return fmt.Errorf("%g overflows int64", f64) + } + i64 = int64(f64) + case bsontype.Boolean: + b, err := vr.ReadBoolean() + if err != nil { + return err + } + if b { + i64 = 1 + } + default: + return fmt.Errorf("cannot decode %v into an integer type", vr.Type()) + } + + if !val.CanSet() { + return ValueDecoderError{ + Name: "UintDecodeValue", + Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, + Received: val, + } + } + + switch val.Kind() { + case reflect.Uint8: + if i64 < 0 || i64 > math.MaxUint8 { + return fmt.Errorf("%d overflows uint8", i64) + } + case reflect.Uint16: + if i64 < 0 || i64 > math.MaxUint16 { + return fmt.Errorf("%d overflows uint16", i64) + } + case reflect.Uint32: + if i64 < 0 || i64 > math.MaxUint32 { + return fmt.Errorf("%d overflows uint32", i64) + } + case reflect.Uint64: + if i64 < 0 { + return fmt.Errorf("%d overflows uint64", i64) + } + case reflect.Uint: + if i64 < 0 || int64(uint(i64)) != i64 { // Can we fit this inside of an uint + return fmt.Errorf("%d overflows uint", i64) + } + default: + return ValueDecoderError{ + Name: "UintDecodeValue", + Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, + Received: val, + } + } + + val.SetUint(uint64(i64)) + return nil +} + +func (dvd DefaultValueDecoders) floatDecodeType(ec DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + var f float64 + var err error + switch vrType := vr.Type(); vrType { + case bsontype.Int32: + i32, err := vr.ReadInt32() + if err != nil { + return emptyValue, err + } + f = float64(i32) + case bsontype.Int64: + i64, err := vr.ReadInt64() + if err != nil { + return emptyValue, err + } + f = float64(i64) + case bsontype.Double: + f, err = vr.ReadDouble() + if err != nil { + return emptyValue, err + } + case bsontype.Boolean: + b, err := vr.ReadBoolean() + if err != nil { + return emptyValue, err + } + if b { + f = 1 + } + case bsontype.Null: + if err = vr.ReadNull(); err != nil { + return emptyValue, err + } + case bsontype.Undefined: + if err = vr.ReadUndefined(); err != nil { + return emptyValue, err + } + default: + return emptyValue, fmt.Errorf("cannot decode %v into a float32 or float64 type", vrType) + } + + switch t.Kind() { + case reflect.Float32: + if !ec.Truncate && float64(float32(f)) != f { + return emptyValue, errCannotTruncate + } + + return reflect.ValueOf(float32(f)), nil + case reflect.Float64: + return reflect.ValueOf(f), nil + default: + return emptyValue, ValueDecoderError{ + Name: "FloatDecodeValue", + Kinds: []reflect.Kind{reflect.Float32, reflect.Float64}, + Received: reflect.Zero(t), + } + } +} + +// FloatDecodeValue is the ValueDecoderFunc for float types. +func (dvd DefaultValueDecoders) FloatDecodeValue(ec DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() { + return ValueDecoderError{ + Name: "FloatDecodeValue", + Kinds: []reflect.Kind{reflect.Float32, reflect.Float64}, + Received: val, + } + } + + elem, err := dvd.floatDecodeType(ec, vr, val.Type()) + if err != nil { + return err + } + + val.SetFloat(elem.Float()) + return nil +} + +// StringDecodeValue is the ValueDecoderFunc for string types. +// +// Deprecated: StringDecodeValue is not registered by default. Use StringCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) StringDecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + var str string + var err error + switch vr.Type() { + // TODO(GODRIVER-577): Handle JavaScript and Symbol BSON types when allowed. + case bsontype.String: + str, err = vr.ReadString() + if err != nil { + return err + } + default: + return fmt.Errorf("cannot decode %v into a string type", vr.Type()) + } + if !val.CanSet() || val.Kind() != reflect.String { + return ValueDecoderError{Name: "StringDecodeValue", Kinds: []reflect.Kind{reflect.String}, Received: val} + } + + val.SetString(str) + return nil +} + +func (DefaultValueDecoders) javaScriptDecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tJavaScript { + return emptyValue, ValueDecoderError{ + Name: "JavaScriptDecodeValue", + Types: []reflect.Type{tJavaScript}, + Received: reflect.Zero(t), + } + } + + var js string + var err error + switch vrType := vr.Type(); vrType { + case bsontype.JavaScript: + js, err = vr.ReadJavascript() + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a primitive.JavaScript", vrType) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(primitive.JavaScript(js)), nil +} + +// JavaScriptDecodeValue is the ValueDecoderFunc for the primitive.JavaScript type. +func (dvd DefaultValueDecoders) JavaScriptDecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tJavaScript { + return ValueDecoderError{Name: "JavaScriptDecodeValue", Types: []reflect.Type{tJavaScript}, Received: val} + } + + elem, err := dvd.javaScriptDecodeType(dctx, vr, tJavaScript) + if err != nil { + return err + } + + val.SetString(elem.String()) + return nil +} + +func (DefaultValueDecoders) symbolDecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tSymbol { + return emptyValue, ValueDecoderError{ + Name: "SymbolDecodeValue", + Types: []reflect.Type{tSymbol}, + Received: reflect.Zero(t), + } + } + + var symbol string + var err error + switch vrType := vr.Type(); vrType { + case bsontype.String: + symbol, err = vr.ReadString() + case bsontype.Symbol: + symbol, err = vr.ReadSymbol() + case bsontype.Binary: + data, subtype, err := vr.ReadBinary() + if err != nil { + return emptyValue, err + } + + if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld { + return emptyValue, decodeBinaryError{subtype: subtype, typeName: "primitive.Symbol"} + } + symbol = string(data) + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a primitive.Symbol", vrType) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(primitive.Symbol(symbol)), nil +} + +// SymbolDecodeValue is the ValueDecoderFunc for the primitive.Symbol type. +func (dvd DefaultValueDecoders) SymbolDecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tSymbol { + return ValueDecoderError{Name: "SymbolDecodeValue", Types: []reflect.Type{tSymbol}, Received: val} + } + + elem, err := dvd.symbolDecodeType(dctx, vr, tSymbol) + if err != nil { + return err + } + + val.SetString(elem.String()) + return nil +} + +func (DefaultValueDecoders) binaryDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tBinary { + return emptyValue, ValueDecoderError{ + Name: "BinaryDecodeValue", + Types: []reflect.Type{tBinary}, + Received: reflect.Zero(t), + } + } + + var data []byte + var subtype byte + var err error + switch vrType := vr.Type(); vrType { + case bsontype.Binary: + data, subtype, err = vr.ReadBinary() + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a Binary", vrType) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(primitive.Binary{Subtype: subtype, Data: data}), nil +} + +// BinaryDecodeValue is the ValueDecoderFunc for Binary. +func (dvd DefaultValueDecoders) BinaryDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tBinary { + return ValueDecoderError{Name: "BinaryDecodeValue", Types: []reflect.Type{tBinary}, Received: val} + } + + elem, err := dvd.binaryDecodeType(dc, vr, tBinary) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +func (DefaultValueDecoders) undefinedDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tUndefined { + return emptyValue, ValueDecoderError{ + Name: "UndefinedDecodeValue", + Types: []reflect.Type{tUndefined}, + Received: reflect.Zero(t), + } + } + + var err error + switch vrType := vr.Type(); vrType { + case bsontype.Undefined: + err = vr.ReadUndefined() + case bsontype.Null: + err = vr.ReadNull() + default: + return emptyValue, fmt.Errorf("cannot decode %v into an Undefined", vr.Type()) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(primitive.Undefined{}), nil +} + +// UndefinedDecodeValue is the ValueDecoderFunc for Undefined. +func (dvd DefaultValueDecoders) UndefinedDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tUndefined { + return ValueDecoderError{Name: "UndefinedDecodeValue", Types: []reflect.Type{tUndefined}, Received: val} + } + + elem, err := dvd.undefinedDecodeType(dc, vr, tUndefined) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +// Accept both 12-byte string and pretty-printed 24-byte hex string formats. +func (dvd DefaultValueDecoders) objectIDDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tOID { + return emptyValue, ValueDecoderError{ + Name: "ObjectIDDecodeValue", + Types: []reflect.Type{tOID}, + Received: reflect.Zero(t), + } + } + + var oid primitive.ObjectID + var err error + switch vrType := vr.Type(); vrType { + case bsontype.ObjectID: + oid, err = vr.ReadObjectID() + if err != nil { + return emptyValue, err + } + case bsontype.String: + str, err := vr.ReadString() + if err != nil { + return emptyValue, err + } + if oid, err = primitive.ObjectIDFromHex(str); err == nil { + break + } + if len(str) != 12 { + return emptyValue, fmt.Errorf("an ObjectID string must be exactly 12 bytes long (got %v)", len(str)) + } + byteArr := []byte(str) + copy(oid[:], byteArr) + case bsontype.Null: + if err = vr.ReadNull(); err != nil { + return emptyValue, err + } + case bsontype.Undefined: + if err = vr.ReadUndefined(); err != nil { + return emptyValue, err + } + default: + return emptyValue, fmt.Errorf("cannot decode %v into an ObjectID", vrType) + } + + return reflect.ValueOf(oid), nil +} + +// ObjectIDDecodeValue is the ValueDecoderFunc for primitive.ObjectID. +func (dvd DefaultValueDecoders) ObjectIDDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tOID { + return ValueDecoderError{Name: "ObjectIDDecodeValue", Types: []reflect.Type{tOID}, Received: val} + } + + elem, err := dvd.objectIDDecodeType(dc, vr, tOID) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +func (DefaultValueDecoders) dateTimeDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tDateTime { + return emptyValue, ValueDecoderError{ + Name: "DateTimeDecodeValue", + Types: []reflect.Type{tDateTime}, + Received: reflect.Zero(t), + } + } + + var dt int64 + var err error + switch vrType := vr.Type(); vrType { + case bsontype.DateTime: + dt, err = vr.ReadDateTime() + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a DateTime", vrType) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(primitive.DateTime(dt)), nil +} + +// DateTimeDecodeValue is the ValueDecoderFunc for DateTime. +func (dvd DefaultValueDecoders) DateTimeDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tDateTime { + return ValueDecoderError{Name: "DateTimeDecodeValue", Types: []reflect.Type{tDateTime}, Received: val} + } + + elem, err := dvd.dateTimeDecodeType(dc, vr, tDateTime) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +func (DefaultValueDecoders) nullDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tNull { + return emptyValue, ValueDecoderError{ + Name: "NullDecodeValue", + Types: []reflect.Type{tNull}, + Received: reflect.Zero(t), + } + } + + var err error + switch vrType := vr.Type(); vrType { + case bsontype.Undefined: + err = vr.ReadUndefined() + case bsontype.Null: + err = vr.ReadNull() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a Null", vr.Type()) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(primitive.Null{}), nil +} + +// NullDecodeValue is the ValueDecoderFunc for Null. +func (dvd DefaultValueDecoders) NullDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tNull { + return ValueDecoderError{Name: "NullDecodeValue", Types: []reflect.Type{tNull}, Received: val} + } + + elem, err := dvd.nullDecodeType(dc, vr, tNull) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +func (DefaultValueDecoders) regexDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tRegex { + return emptyValue, ValueDecoderError{ + Name: "RegexDecodeValue", + Types: []reflect.Type{tRegex}, + Received: reflect.Zero(t), + } + } + + var pattern, options string + var err error + switch vrType := vr.Type(); vrType { + case bsontype.Regex: + pattern, options, err = vr.ReadRegex() + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a Regex", vrType) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(primitive.Regex{Pattern: pattern, Options: options}), nil +} + +// RegexDecodeValue is the ValueDecoderFunc for Regex. +func (dvd DefaultValueDecoders) RegexDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tRegex { + return ValueDecoderError{Name: "RegexDecodeValue", Types: []reflect.Type{tRegex}, Received: val} + } + + elem, err := dvd.regexDecodeType(dc, vr, tRegex) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +func (DefaultValueDecoders) dBPointerDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tDBPointer { + return emptyValue, ValueDecoderError{ + Name: "DBPointerDecodeValue", + Types: []reflect.Type{tDBPointer}, + Received: reflect.Zero(t), + } + } + + var ns string + var pointer primitive.ObjectID + var err error + switch vrType := vr.Type(); vrType { + case bsontype.DBPointer: + ns, pointer, err = vr.ReadDBPointer() + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a DBPointer", vrType) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(primitive.DBPointer{DB: ns, Pointer: pointer}), nil +} + +// DBPointerDecodeValue is the ValueDecoderFunc for DBPointer. +func (dvd DefaultValueDecoders) DBPointerDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tDBPointer { + return ValueDecoderError{Name: "DBPointerDecodeValue", Types: []reflect.Type{tDBPointer}, Received: val} + } + + elem, err := dvd.dBPointerDecodeType(dc, vr, tDBPointer) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +func (DefaultValueDecoders) timestampDecodeType(dc DecodeContext, vr bsonrw.ValueReader, reflectType reflect.Type) (reflect.Value, error) { + if reflectType != tTimestamp { + return emptyValue, ValueDecoderError{ + Name: "TimestampDecodeValue", + Types: []reflect.Type{tTimestamp}, + Received: reflect.Zero(reflectType), + } + } + + var t, incr uint32 + var err error + switch vrType := vr.Type(); vrType { + case bsontype.Timestamp: + t, incr, err = vr.ReadTimestamp() + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a Timestamp", vrType) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(primitive.Timestamp{T: t, I: incr}), nil +} + +// TimestampDecodeValue is the ValueDecoderFunc for Timestamp. +func (dvd DefaultValueDecoders) TimestampDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tTimestamp { + return ValueDecoderError{Name: "TimestampDecodeValue", Types: []reflect.Type{tTimestamp}, Received: val} + } + + elem, err := dvd.timestampDecodeType(dc, vr, tTimestamp) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +func (DefaultValueDecoders) minKeyDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tMinKey { + return emptyValue, ValueDecoderError{ + Name: "MinKeyDecodeValue", + Types: []reflect.Type{tMinKey}, + Received: reflect.Zero(t), + } + } + + var err error + switch vrType := vr.Type(); vrType { + case bsontype.MinKey: + err = vr.ReadMinKey() + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a MinKey", vr.Type()) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(primitive.MinKey{}), nil +} + +// MinKeyDecodeValue is the ValueDecoderFunc for MinKey. +func (dvd DefaultValueDecoders) MinKeyDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tMinKey { + return ValueDecoderError{Name: "MinKeyDecodeValue", Types: []reflect.Type{tMinKey}, Received: val} + } + + elem, err := dvd.minKeyDecodeType(dc, vr, tMinKey) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +func (DefaultValueDecoders) maxKeyDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tMaxKey { + return emptyValue, ValueDecoderError{ + Name: "MaxKeyDecodeValue", + Types: []reflect.Type{tMaxKey}, + Received: reflect.Zero(t), + } + } + + var err error + switch vrType := vr.Type(); vrType { + case bsontype.MaxKey: + err = vr.ReadMaxKey() + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a MaxKey", vr.Type()) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(primitive.MaxKey{}), nil +} + +// MaxKeyDecodeValue is the ValueDecoderFunc for MaxKey. +func (dvd DefaultValueDecoders) MaxKeyDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tMaxKey { + return ValueDecoderError{Name: "MaxKeyDecodeValue", Types: []reflect.Type{tMaxKey}, Received: val} + } + + elem, err := dvd.maxKeyDecodeType(dc, vr, tMaxKey) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +func (dvd DefaultValueDecoders) decimal128DecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tDecimal { + return emptyValue, ValueDecoderError{ + Name: "Decimal128DecodeValue", + Types: []reflect.Type{tDecimal}, + Received: reflect.Zero(t), + } + } + + var d128 primitive.Decimal128 + var err error + switch vrType := vr.Type(); vrType { + case bsontype.Decimal128: + d128, err = vr.ReadDecimal128() + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a primitive.Decimal128", vr.Type()) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(d128), nil +} + +// Decimal128DecodeValue is the ValueDecoderFunc for primitive.Decimal128. +func (dvd DefaultValueDecoders) Decimal128DecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tDecimal { + return ValueDecoderError{Name: "Decimal128DecodeValue", Types: []reflect.Type{tDecimal}, Received: val} + } + + elem, err := dvd.decimal128DecodeType(dctx, vr, tDecimal) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +func (dvd DefaultValueDecoders) jsonNumberDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tJSONNumber { + return emptyValue, ValueDecoderError{ + Name: "JSONNumberDecodeValue", + Types: []reflect.Type{tJSONNumber}, + Received: reflect.Zero(t), + } + } + + var jsonNum json.Number + var err error + switch vrType := vr.Type(); vrType { + case bsontype.Double: + f64, err := vr.ReadDouble() + if err != nil { + return emptyValue, err + } + jsonNum = json.Number(strconv.FormatFloat(f64, 'f', -1, 64)) + case bsontype.Int32: + i32, err := vr.ReadInt32() + if err != nil { + return emptyValue, err + } + jsonNum = json.Number(strconv.FormatInt(int64(i32), 10)) + case bsontype.Int64: + i64, err := vr.ReadInt64() + if err != nil { + return emptyValue, err + } + jsonNum = json.Number(strconv.FormatInt(i64, 10)) + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a json.Number", vrType) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(jsonNum), nil +} + +// JSONNumberDecodeValue is the ValueDecoderFunc for json.Number. +func (dvd DefaultValueDecoders) JSONNumberDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tJSONNumber { + return ValueDecoderError{Name: "JSONNumberDecodeValue", Types: []reflect.Type{tJSONNumber}, Received: val} + } + + elem, err := dvd.jsonNumberDecodeType(dc, vr, tJSONNumber) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +func (dvd DefaultValueDecoders) urlDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tURL { + return emptyValue, ValueDecoderError{ + Name: "URLDecodeValue", + Types: []reflect.Type{tURL}, + Received: reflect.Zero(t), + } + } + + urlPtr := &url.URL{} + var err error + switch vrType := vr.Type(); vrType { + case bsontype.String: + var str string // Declare str here to avoid shadowing err during the ReadString call. + str, err = vr.ReadString() + if err != nil { + return emptyValue, err + } + + urlPtr, err = url.Parse(str) + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a *url.URL", vrType) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(urlPtr).Elem(), nil +} + +// URLDecodeValue is the ValueDecoderFunc for url.URL. +func (dvd DefaultValueDecoders) URLDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tURL { + return ValueDecoderError{Name: "URLDecodeValue", Types: []reflect.Type{tURL}, Received: val} + } + + elem, err := dvd.urlDecodeType(dc, vr, tURL) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +// TimeDecodeValue is the ValueDecoderFunc for time.Time. +// +// Deprecated: TimeDecodeValue is not registered by default. Use TimeCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) TimeDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if vr.Type() != bsontype.DateTime { + return fmt.Errorf("cannot decode %v into a time.Time", vr.Type()) + } + + dt, err := vr.ReadDateTime() + if err != nil { + return err + } + + if !val.CanSet() || val.Type() != tTime { + return ValueDecoderError{Name: "TimeDecodeValue", Types: []reflect.Type{tTime}, Received: val} + } + + val.Set(reflect.ValueOf(time.Unix(dt/1000, dt%1000*1000000).UTC())) + return nil +} + +// ByteSliceDecodeValue is the ValueDecoderFunc for []byte. +// +// Deprecated: ByteSliceDecodeValue is not registered by default. Use ByteSliceCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) ByteSliceDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if vr.Type() != bsontype.Binary && vr.Type() != bsontype.Null { + return fmt.Errorf("cannot decode %v into a []byte", vr.Type()) + } + + if !val.CanSet() || val.Type() != tByteSlice { + return ValueDecoderError{Name: "ByteSliceDecodeValue", Types: []reflect.Type{tByteSlice}, Received: val} + } + + if vr.Type() == bsontype.Null { + val.Set(reflect.Zero(val.Type())) + return vr.ReadNull() + } + + data, subtype, err := vr.ReadBinary() + if err != nil { + return err + } + if subtype != 0x00 { + return fmt.Errorf("ByteSliceDecodeValue can only be used to decode subtype 0x00 for %s, got %v", bsontype.Binary, subtype) + } + + val.Set(reflect.ValueOf(data)) + return nil +} + +// MapDecodeValue is the ValueDecoderFunc for map[string]* types. +// +// Deprecated: MapDecodeValue is not registered by default. Use MapCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) MapDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Kind() != reflect.Map || val.Type().Key().Kind() != reflect.String { + return ValueDecoderError{Name: "MapDecodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val} + } + + switch vr.Type() { + case bsontype.Type(0), bsontype.EmbeddedDocument: + case bsontype.Null: + val.Set(reflect.Zero(val.Type())) + return vr.ReadNull() + default: + return fmt.Errorf("cannot decode %v into a %s", vr.Type(), val.Type()) + } + + dr, err := vr.ReadDocument() + if err != nil { + return err + } + + if val.IsNil() { + val.Set(reflect.MakeMap(val.Type())) + } + + eType := val.Type().Elem() + decoder, err := dc.LookupDecoder(eType) + if err != nil { + return err + } + + if eType == tEmpty { + dc.Ancestor = val.Type() + } + + keyType := val.Type().Key() + for { + key, vr, err := dr.ReadElement() + if err == bsonrw.ErrEOD { + break + } + if err != nil { + return err + } + + elem := reflect.New(eType).Elem() + + err = decoder.DecodeValue(dc, vr, elem) + if err != nil { + return err + } + + val.SetMapIndex(reflect.ValueOf(key).Convert(keyType), elem) + } + return nil +} + +// ArrayDecodeValue is the ValueDecoderFunc for array types. +func (dvd DefaultValueDecoders) ArrayDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.IsValid() || val.Kind() != reflect.Array { + return ValueDecoderError{Name: "ArrayDecodeValue", Kinds: []reflect.Kind{reflect.Array}, Received: val} + } + + switch vrType := vr.Type(); vrType { + case bsontype.Array: + case bsontype.Type(0), bsontype.EmbeddedDocument: + if val.Type().Elem() != tE { + return fmt.Errorf("cannot decode document into %s", val.Type()) + } + case bsontype.Binary: + if val.Type().Elem() != tByte { + return fmt.Errorf("ArrayDecodeValue can only be used to decode binary into a byte array, got %v", vrType) + } + data, subtype, err := vr.ReadBinary() + if err != nil { + return err + } + if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld { + return fmt.Errorf("ArrayDecodeValue can only be used to decode subtype 0x00 or 0x02 for %s, got %v", bsontype.Binary, subtype) + } + + if len(data) > val.Len() { + return fmt.Errorf("more elements returned in array than can fit inside %s", val.Type()) + } + + for idx, elem := range data { + val.Index(idx).Set(reflect.ValueOf(elem)) + } + return nil + case bsontype.Null: + val.Set(reflect.Zero(val.Type())) + return vr.ReadNull() + case bsontype.Undefined: + val.Set(reflect.Zero(val.Type())) + return vr.ReadUndefined() + default: + return fmt.Errorf("cannot decode %v into an array", vrType) + } + + var elemsFunc func(DecodeContext, bsonrw.ValueReader, reflect.Value) ([]reflect.Value, error) + switch val.Type().Elem() { + case tE: + elemsFunc = dvd.decodeD + default: + elemsFunc = dvd.decodeDefault + } + + elems, err := elemsFunc(dc, vr, val) + if err != nil { + return err + } + + if len(elems) > val.Len() { + return fmt.Errorf("more elements returned in array than can fit inside %s, got %v elements", val.Type(), len(elems)) + } + + for idx, elem := range elems { + val.Index(idx).Set(elem) + } + + return nil +} + +// SliceDecodeValue is the ValueDecoderFunc for slice types. +// +// Deprecated: SliceDecodeValue is not registered by default. Use SliceCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) SliceDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Kind() != reflect.Slice { + return ValueDecoderError{Name: "SliceDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} + } + + switch vr.Type() { + case bsontype.Array: + case bsontype.Null: + val.Set(reflect.Zero(val.Type())) + return vr.ReadNull() + case bsontype.Type(0), bsontype.EmbeddedDocument: + if val.Type().Elem() != tE { + return fmt.Errorf("cannot decode document into %s", val.Type()) + } + default: + return fmt.Errorf("cannot decode %v into a slice", vr.Type()) + } + + var elemsFunc func(DecodeContext, bsonrw.ValueReader, reflect.Value) ([]reflect.Value, error) + switch val.Type().Elem() { + case tE: + dc.Ancestor = val.Type() + elemsFunc = dvd.decodeD + default: + elemsFunc = dvd.decodeDefault + } + + elems, err := elemsFunc(dc, vr, val) + if err != nil { + return err + } + + if val.IsNil() { + val.Set(reflect.MakeSlice(val.Type(), 0, len(elems))) + } + + val.SetLen(0) + val.Set(reflect.Append(val, elems...)) + + return nil +} + +// ValueUnmarshalerDecodeValue is the ValueDecoderFunc for ValueUnmarshaler implementations. +func (dvd DefaultValueDecoders) ValueUnmarshalerDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.IsValid() || (!val.Type().Implements(tValueUnmarshaler) && !reflect.PtrTo(val.Type()).Implements(tValueUnmarshaler)) { + return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val} + } + + if val.Kind() == reflect.Ptr && val.IsNil() { + if !val.CanSet() { + return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val} + } + val.Set(reflect.New(val.Type().Elem())) + } + + if !val.Type().Implements(tValueUnmarshaler) { + if !val.CanAddr() { + return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val} + } + val = val.Addr() // If the type doesn't implement the interface, a pointer to it must. + } + + t, src, err := bsonrw.Copier{}.CopyValueToBytes(vr) + if err != nil { + return err + } + + fn := val.Convert(tValueUnmarshaler).MethodByName("UnmarshalBSONValue") + errVal := fn.Call([]reflect.Value{reflect.ValueOf(t), reflect.ValueOf(src)})[0] + if !errVal.IsNil() { + return errVal.Interface().(error) + } + return nil +} + +// UnmarshalerDecodeValue is the ValueDecoderFunc for Unmarshaler implementations. +func (dvd DefaultValueDecoders) UnmarshalerDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.IsValid() || (!val.Type().Implements(tUnmarshaler) && !reflect.PtrTo(val.Type()).Implements(tUnmarshaler)) { + return ValueDecoderError{Name: "UnmarshalerDecodeValue", Types: []reflect.Type{tUnmarshaler}, Received: val} + } + + if val.Kind() == reflect.Ptr && val.IsNil() { + if !val.CanSet() { + return ValueDecoderError{Name: "UnmarshalerDecodeValue", Types: []reflect.Type{tUnmarshaler}, Received: val} + } + val.Set(reflect.New(val.Type().Elem())) + } + + _, src, err := bsonrw.Copier{}.CopyValueToBytes(vr) + if err != nil { + return err + } + + // If the target Go value is a pointer and the BSON field value is empty, set the value to the + // zero value of the pointer (nil) and don't call UnmarshalBSON. UnmarshalBSON has no way to + // change the pointer value from within the function (only the value at the pointer address), + // so it can't set the pointer to "nil" itself. Since the most common Go value for an empty BSON + // field value is "nil", we set "nil" here and don't call UnmarshalBSON. This behavior matches + // the behavior of the Go "encoding/json" unmarshaler when the target Go value is a pointer and + // the JSON field value is "null". + if val.Kind() == reflect.Ptr && len(src) == 0 { + val.Set(reflect.Zero(val.Type())) + return nil + } + + if !val.Type().Implements(tUnmarshaler) { + if !val.CanAddr() { + return ValueDecoderError{Name: "UnmarshalerDecodeValue", Types: []reflect.Type{tUnmarshaler}, Received: val} + } + val = val.Addr() // If the type doesn't implement the interface, a pointer to it must. + } + + fn := val.Convert(tUnmarshaler).MethodByName("UnmarshalBSON") + errVal := fn.Call([]reflect.Value{reflect.ValueOf(src)})[0] + if !errVal.IsNil() { + return errVal.Interface().(error) + } + return nil +} + +// EmptyInterfaceDecodeValue is the ValueDecoderFunc for interface{}. +// +// Deprecated: EmptyInterfaceDecodeValue is not registered by default. Use EmptyInterfaceCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) EmptyInterfaceDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tEmpty { + return ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: val} + } + + rtype, err := dc.LookupTypeMapEntry(vr.Type()) + if err != nil { + switch vr.Type() { + case bsontype.EmbeddedDocument: + if dc.Ancestor != nil { + rtype = dc.Ancestor + break + } + rtype = tD + case bsontype.Null: + val.Set(reflect.Zero(val.Type())) + return vr.ReadNull() + default: + return err + } + } + + decoder, err := dc.LookupDecoder(rtype) + if err != nil { + return err + } + + elem := reflect.New(rtype).Elem() + err = decoder.DecodeValue(dc, vr, elem) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +// CoreDocumentDecodeValue is the ValueDecoderFunc for bsoncore.Document. +func (DefaultValueDecoders) CoreDocumentDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tCoreDocument { + return ValueDecoderError{Name: "CoreDocumentDecodeValue", Types: []reflect.Type{tCoreDocument}, Received: val} + } + + if val.IsNil() { + val.Set(reflect.MakeSlice(val.Type(), 0, 0)) + } + + val.SetLen(0) + + cdoc, err := bsonrw.Copier{}.AppendDocumentBytes(val.Interface().(bsoncore.Document), vr) + val.Set(reflect.ValueOf(cdoc)) + return err +} + +func (dvd DefaultValueDecoders) decodeDefault(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) ([]reflect.Value, error) { + elems := make([]reflect.Value, 0) + + ar, err := vr.ReadArray() + if err != nil { + return nil, err + } + + eType := val.Type().Elem() + + decoder, err := dc.LookupDecoder(eType) + if err != nil { + return nil, err + } + eTypeDecoder, _ := decoder.(typeDecoder) + + idx := 0 + for { + vr, err := ar.ReadValue() + if err == bsonrw.ErrEOA { + break + } + if err != nil { + return nil, err + } + + elem, err := decodeTypeOrValueWithInfo(decoder, eTypeDecoder, dc, vr, eType, true) + if err != nil { + return nil, newDecodeError(strconv.Itoa(idx), err) + } + elems = append(elems, elem) + idx++ + } + + return elems, nil +} + +func (dvd DefaultValueDecoders) readCodeWithScope(dc DecodeContext, vr bsonrw.ValueReader) (primitive.CodeWithScope, error) { + var cws primitive.CodeWithScope + + code, dr, err := vr.ReadCodeWithScope() + if err != nil { + return cws, err + } + + scope := reflect.New(tD).Elem() + elems, err := dvd.decodeElemsFromDocumentReader(dc, dr) + if err != nil { + return cws, err + } + + scope.Set(reflect.MakeSlice(tD, 0, len(elems))) + scope.Set(reflect.Append(scope, elems...)) + + cws = primitive.CodeWithScope{ + Code: primitive.JavaScript(code), + Scope: scope.Interface().(primitive.D), + } + return cws, nil +} + +func (dvd DefaultValueDecoders) codeWithScopeDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tCodeWithScope { + return emptyValue, ValueDecoderError{ + Name: "CodeWithScopeDecodeValue", + Types: []reflect.Type{tCodeWithScope}, + Received: reflect.Zero(t), + } + } + + var cws primitive.CodeWithScope + var err error + switch vrType := vr.Type(); vrType { + case bsontype.CodeWithScope: + cws, err = dvd.readCodeWithScope(dc, vr) + case bsontype.Null: + err = vr.ReadNull() + case bsontype.Undefined: + err = vr.ReadUndefined() + default: + return emptyValue, fmt.Errorf("cannot decode %v into a primitive.CodeWithScope", vrType) + } + if err != nil { + return emptyValue, err + } + + return reflect.ValueOf(cws), nil +} + +// CodeWithScopeDecodeValue is the ValueDecoderFunc for CodeWithScope. +func (dvd DefaultValueDecoders) CodeWithScopeDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tCodeWithScope { + return ValueDecoderError{Name: "CodeWithScopeDecodeValue", Types: []reflect.Type{tCodeWithScope}, Received: val} + } + + elem, err := dvd.codeWithScopeDecodeType(dc, vr, tCodeWithScope) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +func (dvd DefaultValueDecoders) decodeD(dc DecodeContext, vr bsonrw.ValueReader, _ reflect.Value) ([]reflect.Value, error) { + switch vr.Type() { + case bsontype.Type(0), bsontype.EmbeddedDocument: + default: + return nil, fmt.Errorf("cannot decode %v into a D", vr.Type()) + } + + dr, err := vr.ReadDocument() + if err != nil { + return nil, err + } + + return dvd.decodeElemsFromDocumentReader(dc, dr) +} + +func (DefaultValueDecoders) decodeElemsFromDocumentReader(dc DecodeContext, dr bsonrw.DocumentReader) ([]reflect.Value, error) { + decoder, err := dc.LookupDecoder(tEmpty) + if err != nil { + return nil, err + } + + elems := make([]reflect.Value, 0) + for { + key, vr, err := dr.ReadElement() + if err == bsonrw.ErrEOD { + break + } + if err != nil { + return nil, err + } + + val := reflect.New(tEmpty).Elem() + err = decoder.DecodeValue(dc, vr, val) + if err != nil { + return nil, newDecodeError(key, err) + } + + elems = append(elems, reflect.ValueOf(primitive.E{Key: key, Value: val.Interface()})) + } + + return elems, nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go new file mode 100644 index 0000000..6bdb43c --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go @@ -0,0 +1,766 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "encoding/json" + "errors" + "fmt" + "math" + "net/url" + "reflect" + "sync" + "time" + + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/bson/bsontype" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +var defaultValueEncoders DefaultValueEncoders + +var bvwPool = bsonrw.NewBSONValueWriterPool() + +var errInvalidValue = errors.New("cannot encode invalid element") + +var sliceWriterPool = sync.Pool{ + New: func() interface{} { + sw := make(bsonrw.SliceWriter, 0) + return &sw + }, +} + +func encodeElement(ec EncodeContext, dw bsonrw.DocumentWriter, e primitive.E) error { + vw, err := dw.WriteDocumentElement(e.Key) + if err != nil { + return err + } + + if e.Value == nil { + return vw.WriteNull() + } + encoder, err := ec.LookupEncoder(reflect.TypeOf(e.Value)) + if err != nil { + return err + } + + err = encoder.EncodeValue(ec, vw, reflect.ValueOf(e.Value)) + if err != nil { + return err + } + return nil +} + +// DefaultValueEncoders is a namespace type for the default ValueEncoders used +// when creating a registry. +type DefaultValueEncoders struct{} + +// RegisterDefaultEncoders will register the encoder methods attached to DefaultValueEncoders with +// the provided RegistryBuilder. +func (dve DefaultValueEncoders) RegisterDefaultEncoders(rb *RegistryBuilder) { + if rb == nil { + panic(errors.New("argument to RegisterDefaultEncoders must not be nil")) + } + rb. + RegisterTypeEncoder(tByteSlice, defaultByteSliceCodec). + RegisterTypeEncoder(tTime, defaultTimeCodec). + RegisterTypeEncoder(tEmpty, defaultEmptyInterfaceCodec). + RegisterTypeEncoder(tCoreArray, defaultArrayCodec). + RegisterTypeEncoder(tOID, ValueEncoderFunc(dve.ObjectIDEncodeValue)). + RegisterTypeEncoder(tDecimal, ValueEncoderFunc(dve.Decimal128EncodeValue)). + RegisterTypeEncoder(tJSONNumber, ValueEncoderFunc(dve.JSONNumberEncodeValue)). + RegisterTypeEncoder(tURL, ValueEncoderFunc(dve.URLEncodeValue)). + RegisterTypeEncoder(tJavaScript, ValueEncoderFunc(dve.JavaScriptEncodeValue)). + RegisterTypeEncoder(tSymbol, ValueEncoderFunc(dve.SymbolEncodeValue)). + RegisterTypeEncoder(tBinary, ValueEncoderFunc(dve.BinaryEncodeValue)). + RegisterTypeEncoder(tUndefined, ValueEncoderFunc(dve.UndefinedEncodeValue)). + RegisterTypeEncoder(tDateTime, ValueEncoderFunc(dve.DateTimeEncodeValue)). + RegisterTypeEncoder(tNull, ValueEncoderFunc(dve.NullEncodeValue)). + RegisterTypeEncoder(tRegex, ValueEncoderFunc(dve.RegexEncodeValue)). + RegisterTypeEncoder(tDBPointer, ValueEncoderFunc(dve.DBPointerEncodeValue)). + RegisterTypeEncoder(tTimestamp, ValueEncoderFunc(dve.TimestampEncodeValue)). + RegisterTypeEncoder(tMinKey, ValueEncoderFunc(dve.MinKeyEncodeValue)). + RegisterTypeEncoder(tMaxKey, ValueEncoderFunc(dve.MaxKeyEncodeValue)). + RegisterTypeEncoder(tCoreDocument, ValueEncoderFunc(dve.CoreDocumentEncodeValue)). + RegisterTypeEncoder(tCodeWithScope, ValueEncoderFunc(dve.CodeWithScopeEncodeValue)). + RegisterDefaultEncoder(reflect.Bool, ValueEncoderFunc(dve.BooleanEncodeValue)). + RegisterDefaultEncoder(reflect.Int, ValueEncoderFunc(dve.IntEncodeValue)). + RegisterDefaultEncoder(reflect.Int8, ValueEncoderFunc(dve.IntEncodeValue)). + RegisterDefaultEncoder(reflect.Int16, ValueEncoderFunc(dve.IntEncodeValue)). + RegisterDefaultEncoder(reflect.Int32, ValueEncoderFunc(dve.IntEncodeValue)). + RegisterDefaultEncoder(reflect.Int64, ValueEncoderFunc(dve.IntEncodeValue)). + RegisterDefaultEncoder(reflect.Uint, defaultUIntCodec). + RegisterDefaultEncoder(reflect.Uint8, defaultUIntCodec). + RegisterDefaultEncoder(reflect.Uint16, defaultUIntCodec). + RegisterDefaultEncoder(reflect.Uint32, defaultUIntCodec). + RegisterDefaultEncoder(reflect.Uint64, defaultUIntCodec). + RegisterDefaultEncoder(reflect.Float32, ValueEncoderFunc(dve.FloatEncodeValue)). + RegisterDefaultEncoder(reflect.Float64, ValueEncoderFunc(dve.FloatEncodeValue)). + RegisterDefaultEncoder(reflect.Array, ValueEncoderFunc(dve.ArrayEncodeValue)). + RegisterDefaultEncoder(reflect.Map, defaultMapCodec). + RegisterDefaultEncoder(reflect.Slice, defaultSliceCodec). + RegisterDefaultEncoder(reflect.String, defaultStringCodec). + RegisterDefaultEncoder(reflect.Struct, newDefaultStructCodec()). + RegisterDefaultEncoder(reflect.Ptr, NewPointerCodec()). + RegisterHookEncoder(tValueMarshaler, ValueEncoderFunc(dve.ValueMarshalerEncodeValue)). + RegisterHookEncoder(tMarshaler, ValueEncoderFunc(dve.MarshalerEncodeValue)). + RegisterHookEncoder(tProxy, ValueEncoderFunc(dve.ProxyEncodeValue)) +} + +// BooleanEncodeValue is the ValueEncoderFunc for bool types. +func (dve DefaultValueEncoders) BooleanEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Kind() != reflect.Bool { + return ValueEncoderError{Name: "BooleanEncodeValue", Kinds: []reflect.Kind{reflect.Bool}, Received: val} + } + return vw.WriteBoolean(val.Bool()) +} + +func fitsIn32Bits(i int64) bool { + return math.MinInt32 <= i && i <= math.MaxInt32 +} + +// IntEncodeValue is the ValueEncoderFunc for int types. +func (dve DefaultValueEncoders) IntEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + switch val.Kind() { + case reflect.Int8, reflect.Int16, reflect.Int32: + return vw.WriteInt32(int32(val.Int())) + case reflect.Int: + i64 := val.Int() + if fitsIn32Bits(i64) { + return vw.WriteInt32(int32(i64)) + } + return vw.WriteInt64(i64) + case reflect.Int64: + i64 := val.Int() + if ec.MinSize && fitsIn32Bits(i64) { + return vw.WriteInt32(int32(i64)) + } + return vw.WriteInt64(i64) + } + + return ValueEncoderError{ + Name: "IntEncodeValue", + Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int}, + Received: val, + } +} + +// UintEncodeValue is the ValueEncoderFunc for uint types. +// +// Deprecated: UintEncodeValue is not registered by default. Use UintCodec.EncodeValue instead. +func (dve DefaultValueEncoders) UintEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + switch val.Kind() { + case reflect.Uint8, reflect.Uint16: + return vw.WriteInt32(int32(val.Uint())) + case reflect.Uint, reflect.Uint32, reflect.Uint64: + u64 := val.Uint() + if ec.MinSize && u64 <= math.MaxInt32 { + return vw.WriteInt32(int32(u64)) + } + if u64 > math.MaxInt64 { + return fmt.Errorf("%d overflows int64", u64) + } + return vw.WriteInt64(int64(u64)) + } + + return ValueEncoderError{ + Name: "UintEncodeValue", + Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, + Received: val, + } +} + +// FloatEncodeValue is the ValueEncoderFunc for float types. +func (dve DefaultValueEncoders) FloatEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + switch val.Kind() { + case reflect.Float32, reflect.Float64: + return vw.WriteDouble(val.Float()) + } + + return ValueEncoderError{Name: "FloatEncodeValue", Kinds: []reflect.Kind{reflect.Float32, reflect.Float64}, Received: val} +} + +// StringEncodeValue is the ValueEncoderFunc for string types. +// +// Deprecated: StringEncodeValue is not registered by default. Use StringCodec.EncodeValue instead. +func (dve DefaultValueEncoders) StringEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if val.Kind() != reflect.String { + return ValueEncoderError{ + Name: "StringEncodeValue", + Kinds: []reflect.Kind{reflect.String}, + Received: val, + } + } + + return vw.WriteString(val.String()) +} + +// ObjectIDEncodeValue is the ValueEncoderFunc for primitive.ObjectID. +func (dve DefaultValueEncoders) ObjectIDEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tOID { + return ValueEncoderError{Name: "ObjectIDEncodeValue", Types: []reflect.Type{tOID}, Received: val} + } + return vw.WriteObjectID(val.Interface().(primitive.ObjectID)) +} + +// Decimal128EncodeValue is the ValueEncoderFunc for primitive.Decimal128. +func (dve DefaultValueEncoders) Decimal128EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tDecimal { + return ValueEncoderError{Name: "Decimal128EncodeValue", Types: []reflect.Type{tDecimal}, Received: val} + } + return vw.WriteDecimal128(val.Interface().(primitive.Decimal128)) +} + +// JSONNumberEncodeValue is the ValueEncoderFunc for json.Number. +func (dve DefaultValueEncoders) JSONNumberEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tJSONNumber { + return ValueEncoderError{Name: "JSONNumberEncodeValue", Types: []reflect.Type{tJSONNumber}, Received: val} + } + jsnum := val.Interface().(json.Number) + + // Attempt int first, then float64 + if i64, err := jsnum.Int64(); err == nil { + return dve.IntEncodeValue(ec, vw, reflect.ValueOf(i64)) + } + + f64, err := jsnum.Float64() + if err != nil { + return err + } + + return dve.FloatEncodeValue(ec, vw, reflect.ValueOf(f64)) +} + +// URLEncodeValue is the ValueEncoderFunc for url.URL. +func (dve DefaultValueEncoders) URLEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tURL { + return ValueEncoderError{Name: "URLEncodeValue", Types: []reflect.Type{tURL}, Received: val} + } + u := val.Interface().(url.URL) + return vw.WriteString(u.String()) +} + +// TimeEncodeValue is the ValueEncoderFunc for time.TIme. +// +// Deprecated: TimeEncodeValue is not registered by default. Use TimeCodec.EncodeValue instead. +func (dve DefaultValueEncoders) TimeEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tTime { + return ValueEncoderError{Name: "TimeEncodeValue", Types: []reflect.Type{tTime}, Received: val} + } + tt := val.Interface().(time.Time) + dt := primitive.NewDateTimeFromTime(tt) + return vw.WriteDateTime(int64(dt)) +} + +// ByteSliceEncodeValue is the ValueEncoderFunc for []byte. +// +// Deprecated: ByteSliceEncodeValue is not registered by default. Use ByteSliceCodec.EncodeValue instead. +func (dve DefaultValueEncoders) ByteSliceEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tByteSlice { + return ValueEncoderError{Name: "ByteSliceEncodeValue", Types: []reflect.Type{tByteSlice}, Received: val} + } + if val.IsNil() { + return vw.WriteNull() + } + return vw.WriteBinary(val.Interface().([]byte)) +} + +// MapEncodeValue is the ValueEncoderFunc for map[string]* types. +// +// Deprecated: MapEncodeValue is not registered by default. Use MapCodec.EncodeValue instead. +func (dve DefaultValueEncoders) MapEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Kind() != reflect.Map || val.Type().Key().Kind() != reflect.String { + return ValueEncoderError{Name: "MapEncodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val} + } + + if val.IsNil() { + // If we have a nill map but we can't WriteNull, that means we're probably trying to encode + // to a TopLevel document. We can't currently tell if this is what actually happened, but if + // there's a deeper underlying problem, the error will also be returned from WriteDocument, + // so just continue. The operations on a map reflection value are valid, so we can call + // MapKeys within mapEncodeValue without a problem. + err := vw.WriteNull() + if err == nil { + return nil + } + } + + dw, err := vw.WriteDocument() + if err != nil { + return err + } + + return dve.mapEncodeValue(ec, dw, val, nil) +} + +// mapEncodeValue handles encoding of the values of a map. The collisionFn returns +// true if the provided key exists, this is mainly used for inline maps in the +// struct codec. +func (dve DefaultValueEncoders) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, val reflect.Value, collisionFn func(string) bool) error { + + elemType := val.Type().Elem() + encoder, err := ec.LookupEncoder(elemType) + if err != nil && elemType.Kind() != reflect.Interface { + return err + } + + keys := val.MapKeys() + for _, key := range keys { + if collisionFn != nil && collisionFn(key.String()) { + return fmt.Errorf("Key %s of inlined map conflicts with a struct field name", key) + } + + currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.MapIndex(key)) + if lookupErr != nil && lookupErr != errInvalidValue { + return lookupErr + } + + vw, err := dw.WriteDocumentElement(key.String()) + if err != nil { + return err + } + + if lookupErr == errInvalidValue { + err = vw.WriteNull() + if err != nil { + return err + } + continue + } + + err = currEncoder.EncodeValue(ec, vw, currVal) + if err != nil { + return err + } + } + + return dw.WriteDocumentEnd() +} + +// ArrayEncodeValue is the ValueEncoderFunc for array types. +func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Kind() != reflect.Array { + return ValueEncoderError{Name: "ArrayEncodeValue", Kinds: []reflect.Kind{reflect.Array}, Received: val} + } + + // If we have a []primitive.E we want to treat it as a document instead of as an array. + if val.Type().Elem() == tE { + dw, err := vw.WriteDocument() + if err != nil { + return err + } + + for idx := 0; idx < val.Len(); idx++ { + e := val.Index(idx).Interface().(primitive.E) + err = encodeElement(ec, dw, e) + if err != nil { + return err + } + } + + return dw.WriteDocumentEnd() + } + + // If we have a []byte we want to treat it as a binary instead of as an array. + if val.Type().Elem() == tByte { + var byteSlice []byte + for idx := 0; idx < val.Len(); idx++ { + byteSlice = append(byteSlice, val.Index(idx).Interface().(byte)) + } + return vw.WriteBinary(byteSlice) + } + + aw, err := vw.WriteArray() + if err != nil { + return err + } + + elemType := val.Type().Elem() + encoder, err := ec.LookupEncoder(elemType) + if err != nil && elemType.Kind() != reflect.Interface { + return err + } + + for idx := 0; idx < val.Len(); idx++ { + currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx)) + if lookupErr != nil && lookupErr != errInvalidValue { + return lookupErr + } + + vw, err := aw.WriteArrayElement() + if err != nil { + return err + } + + if lookupErr == errInvalidValue { + err = vw.WriteNull() + if err != nil { + return err + } + continue + } + + err = currEncoder.EncodeValue(ec, vw, currVal) + if err != nil { + return err + } + } + return aw.WriteArrayEnd() +} + +// SliceEncodeValue is the ValueEncoderFunc for slice types. +// +// Deprecated: SliceEncodeValue is not registered by default. Use SliceCodec.EncodeValue instead. +func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Kind() != reflect.Slice { + return ValueEncoderError{Name: "SliceEncodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} + } + + if val.IsNil() { + return vw.WriteNull() + } + + // If we have a []primitive.E we want to treat it as a document instead of as an array. + if val.Type().ConvertibleTo(tD) { + d := val.Convert(tD).Interface().(primitive.D) + + dw, err := vw.WriteDocument() + if err != nil { + return err + } + + for _, e := range d { + err = encodeElement(ec, dw, e) + if err != nil { + return err + } + } + + return dw.WriteDocumentEnd() + } + + aw, err := vw.WriteArray() + if err != nil { + return err + } + + elemType := val.Type().Elem() + encoder, err := ec.LookupEncoder(elemType) + if err != nil && elemType.Kind() != reflect.Interface { + return err + } + + for idx := 0; idx < val.Len(); idx++ { + currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx)) + if lookupErr != nil && lookupErr != errInvalidValue { + return lookupErr + } + + vw, err := aw.WriteArrayElement() + if err != nil { + return err + } + + if lookupErr == errInvalidValue { + err = vw.WriteNull() + if err != nil { + return err + } + continue + } + + err = currEncoder.EncodeValue(ec, vw, currVal) + if err != nil { + return err + } + } + return aw.WriteArrayEnd() +} + +func (dve DefaultValueEncoders) lookupElementEncoder(ec EncodeContext, origEncoder ValueEncoder, currVal reflect.Value) (ValueEncoder, reflect.Value, error) { + if origEncoder != nil || (currVal.Kind() != reflect.Interface) { + return origEncoder, currVal, nil + } + currVal = currVal.Elem() + if !currVal.IsValid() { + return nil, currVal, errInvalidValue + } + currEncoder, err := ec.LookupEncoder(currVal.Type()) + + return currEncoder, currVal, err +} + +// EmptyInterfaceEncodeValue is the ValueEncoderFunc for interface{}. +// +// Deprecated: EmptyInterfaceEncodeValue is not registered by default. Use EmptyInterfaceCodec.EncodeValue instead. +func (dve DefaultValueEncoders) EmptyInterfaceEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tEmpty { + return ValueEncoderError{Name: "EmptyInterfaceEncodeValue", Types: []reflect.Type{tEmpty}, Received: val} + } + + if val.IsNil() { + return vw.WriteNull() + } + encoder, err := ec.LookupEncoder(val.Elem().Type()) + if err != nil { + return err + } + + return encoder.EncodeValue(ec, vw, val.Elem()) +} + +// ValueMarshalerEncodeValue is the ValueEncoderFunc for ValueMarshaler implementations. +func (dve DefaultValueEncoders) ValueMarshalerEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + // Either val or a pointer to val must implement ValueMarshaler + switch { + case !val.IsValid(): + return ValueEncoderError{Name: "ValueMarshalerEncodeValue", Types: []reflect.Type{tValueMarshaler}, Received: val} + case val.Type().Implements(tValueMarshaler): + // If ValueMarshaler is implemented on a concrete type, make sure that val isn't a nil pointer + if isImplementationNil(val, tValueMarshaler) { + return vw.WriteNull() + } + case reflect.PtrTo(val.Type()).Implements(tValueMarshaler) && val.CanAddr(): + val = val.Addr() + default: + return ValueEncoderError{Name: "ValueMarshalerEncodeValue", Types: []reflect.Type{tValueMarshaler}, Received: val} + } + + fn := val.Convert(tValueMarshaler).MethodByName("MarshalBSONValue") + returns := fn.Call(nil) + if !returns[2].IsNil() { + return returns[2].Interface().(error) + } + t, data := returns[0].Interface().(bsontype.Type), returns[1].Interface().([]byte) + return bsonrw.Copier{}.CopyValueFromBytes(vw, t, data) +} + +// MarshalerEncodeValue is the ValueEncoderFunc for Marshaler implementations. +func (dve DefaultValueEncoders) MarshalerEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + // Either val or a pointer to val must implement Marshaler + switch { + case !val.IsValid(): + return ValueEncoderError{Name: "MarshalerEncodeValue", Types: []reflect.Type{tMarshaler}, Received: val} + case val.Type().Implements(tMarshaler): + // If Marshaler is implemented on a concrete type, make sure that val isn't a nil pointer + if isImplementationNil(val, tMarshaler) { + return vw.WriteNull() + } + case reflect.PtrTo(val.Type()).Implements(tMarshaler) && val.CanAddr(): + val = val.Addr() + default: + return ValueEncoderError{Name: "MarshalerEncodeValue", Types: []reflect.Type{tMarshaler}, Received: val} + } + + fn := val.Convert(tMarshaler).MethodByName("MarshalBSON") + returns := fn.Call(nil) + if !returns[1].IsNil() { + return returns[1].Interface().(error) + } + data := returns[0].Interface().([]byte) + return bsonrw.Copier{}.CopyValueFromBytes(vw, bsontype.EmbeddedDocument, data) +} + +// ProxyEncodeValue is the ValueEncoderFunc for Proxy implementations. +func (dve DefaultValueEncoders) ProxyEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + // Either val or a pointer to val must implement Proxy + switch { + case !val.IsValid(): + return ValueEncoderError{Name: "ProxyEncodeValue", Types: []reflect.Type{tProxy}, Received: val} + case val.Type().Implements(tProxy): + // If Proxy is implemented on a concrete type, make sure that val isn't a nil pointer + if isImplementationNil(val, tProxy) { + return vw.WriteNull() + } + case reflect.PtrTo(val.Type()).Implements(tProxy) && val.CanAddr(): + val = val.Addr() + default: + return ValueEncoderError{Name: "ProxyEncodeValue", Types: []reflect.Type{tProxy}, Received: val} + } + + fn := val.Convert(tProxy).MethodByName("ProxyBSON") + returns := fn.Call(nil) + if !returns[1].IsNil() { + return returns[1].Interface().(error) + } + data := returns[0] + var encoder ValueEncoder + var err error + if data.Elem().IsValid() { + encoder, err = ec.LookupEncoder(data.Elem().Type()) + } else { + encoder, err = ec.LookupEncoder(nil) + } + if err != nil { + return err + } + return encoder.EncodeValue(ec, vw, data.Elem()) +} + +// JavaScriptEncodeValue is the ValueEncoderFunc for the primitive.JavaScript type. +func (DefaultValueEncoders) JavaScriptEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tJavaScript { + return ValueEncoderError{Name: "JavaScriptEncodeValue", Types: []reflect.Type{tJavaScript}, Received: val} + } + + return vw.WriteJavascript(val.String()) +} + +// SymbolEncodeValue is the ValueEncoderFunc for the primitive.Symbol type. +func (DefaultValueEncoders) SymbolEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tSymbol { + return ValueEncoderError{Name: "SymbolEncodeValue", Types: []reflect.Type{tSymbol}, Received: val} + } + + return vw.WriteSymbol(val.String()) +} + +// BinaryEncodeValue is the ValueEncoderFunc for Binary. +func (DefaultValueEncoders) BinaryEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tBinary { + return ValueEncoderError{Name: "BinaryEncodeValue", Types: []reflect.Type{tBinary}, Received: val} + } + b := val.Interface().(primitive.Binary) + + return vw.WriteBinaryWithSubtype(b.Data, b.Subtype) +} + +// UndefinedEncodeValue is the ValueEncoderFunc for Undefined. +func (DefaultValueEncoders) UndefinedEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tUndefined { + return ValueEncoderError{Name: "UndefinedEncodeValue", Types: []reflect.Type{tUndefined}, Received: val} + } + + return vw.WriteUndefined() +} + +// DateTimeEncodeValue is the ValueEncoderFunc for DateTime. +func (DefaultValueEncoders) DateTimeEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tDateTime { + return ValueEncoderError{Name: "DateTimeEncodeValue", Types: []reflect.Type{tDateTime}, Received: val} + } + + return vw.WriteDateTime(val.Int()) +} + +// NullEncodeValue is the ValueEncoderFunc for Null. +func (DefaultValueEncoders) NullEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tNull { + return ValueEncoderError{Name: "NullEncodeValue", Types: []reflect.Type{tNull}, Received: val} + } + + return vw.WriteNull() +} + +// RegexEncodeValue is the ValueEncoderFunc for Regex. +func (DefaultValueEncoders) RegexEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tRegex { + return ValueEncoderError{Name: "RegexEncodeValue", Types: []reflect.Type{tRegex}, Received: val} + } + + regex := val.Interface().(primitive.Regex) + + return vw.WriteRegex(regex.Pattern, regex.Options) +} + +// DBPointerEncodeValue is the ValueEncoderFunc for DBPointer. +func (DefaultValueEncoders) DBPointerEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tDBPointer { + return ValueEncoderError{Name: "DBPointerEncodeValue", Types: []reflect.Type{tDBPointer}, Received: val} + } + + dbp := val.Interface().(primitive.DBPointer) + + return vw.WriteDBPointer(dbp.DB, dbp.Pointer) +} + +// TimestampEncodeValue is the ValueEncoderFunc for Timestamp. +func (DefaultValueEncoders) TimestampEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tTimestamp { + return ValueEncoderError{Name: "TimestampEncodeValue", Types: []reflect.Type{tTimestamp}, Received: val} + } + + ts := val.Interface().(primitive.Timestamp) + + return vw.WriteTimestamp(ts.T, ts.I) +} + +// MinKeyEncodeValue is the ValueEncoderFunc for MinKey. +func (DefaultValueEncoders) MinKeyEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tMinKey { + return ValueEncoderError{Name: "MinKeyEncodeValue", Types: []reflect.Type{tMinKey}, Received: val} + } + + return vw.WriteMinKey() +} + +// MaxKeyEncodeValue is the ValueEncoderFunc for MaxKey. +func (DefaultValueEncoders) MaxKeyEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tMaxKey { + return ValueEncoderError{Name: "MaxKeyEncodeValue", Types: []reflect.Type{tMaxKey}, Received: val} + } + + return vw.WriteMaxKey() +} + +// CoreDocumentEncodeValue is the ValueEncoderFunc for bsoncore.Document. +func (DefaultValueEncoders) CoreDocumentEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tCoreDocument { + return ValueEncoderError{Name: "CoreDocumentEncodeValue", Types: []reflect.Type{tCoreDocument}, Received: val} + } + + cdoc := val.Interface().(bsoncore.Document) + + return bsonrw.Copier{}.CopyDocumentFromBytes(vw, cdoc) +} + +// CodeWithScopeEncodeValue is the ValueEncoderFunc for CodeWithScope. +func (dve DefaultValueEncoders) CodeWithScopeEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tCodeWithScope { + return ValueEncoderError{Name: "CodeWithScopeEncodeValue", Types: []reflect.Type{tCodeWithScope}, Received: val} + } + + cws := val.Interface().(primitive.CodeWithScope) + + dw, err := vw.WriteCodeWithScope(string(cws.Code)) + if err != nil { + return err + } + + sw := sliceWriterPool.Get().(*bsonrw.SliceWriter) + defer sliceWriterPool.Put(sw) + *sw = (*sw)[:0] + + scopeVW := bvwPool.Get(sw) + defer bvwPool.Put(scopeVW) + + encoder, err := ec.LookupEncoder(reflect.TypeOf(cws.Scope)) + if err != nil { + return err + } + + err = encoder.EncodeValue(ec, scopeVW, reflect.ValueOf(cws.Scope)) + if err != nil { + return err + } + + err = bsonrw.Copier{}.CopyBytesToDocumentWriter(dw, *sw) + if err != nil { + return err + } + return dw.WriteDocumentEnd() +} + +// isImplementationNil returns if val is a nil pointer and inter is implemented on a concrete type +func isImplementationNil(val reflect.Value, inter reflect.Type) bool { + vt := val.Type() + for vt.Kind() == reflect.Ptr { + vt = vt.Elem() + } + return vt.Implements(inter) && val.Kind() == reflect.Ptr && val.IsNil() +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go new file mode 100644 index 0000000..5f903eb --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go @@ -0,0 +1,90 @@ +// Copyright (C) MongoDB, Inc. 2022-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// Package bsoncodec provides a system for encoding values to BSON representations and decoding +// values from BSON representations. This package considers both binary BSON and ExtendedJSON as +// BSON representations. The types in this package enable a flexible system for handling this +// encoding and decoding. +// +// The codec system is composed of two parts: +// +// 1) ValueEncoders and ValueDecoders that handle encoding and decoding Go values to and from BSON +// representations. +// +// 2) A Registry that holds these ValueEncoders and ValueDecoders and provides methods for +// retrieving them. +// +// # ValueEncoders and ValueDecoders +// +// The ValueEncoder interface is implemented by types that can encode a provided Go type to BSON. +// The value to encode is provided as a reflect.Value and a bsonrw.ValueWriter is used within the +// EncodeValue method to actually create the BSON representation. For convenience, ValueEncoderFunc +// is provided to allow use of a function with the correct signature as a ValueEncoder. An +// EncodeContext instance is provided to allow implementations to lookup further ValueEncoders and +// to provide configuration information. +// +// The ValueDecoder interface is the inverse of the ValueEncoder. Implementations should ensure that +// the value they receive is settable. Similar to ValueEncoderFunc, ValueDecoderFunc is provided to +// allow the use of a function with the correct signature as a ValueDecoder. A DecodeContext +// instance is provided and serves similar functionality to the EncodeContext. +// +// # Registry and RegistryBuilder +// +// A Registry is an immutable store for ValueEncoders, ValueDecoders, and a type map. See the Registry type +// documentation for examples of registering various custom encoders and decoders. A Registry can be constructed using a +// RegistryBuilder, which handles three main types of codecs: +// +// 1. Type encoders/decoders - These can be registered using the RegisterTypeEncoder and RegisterTypeDecoder methods. +// The registered codec will be invoked when encoding/decoding a value whose type matches the registered type exactly. +// If the registered type is an interface, the codec will be invoked when encoding or decoding values whose type is the +// interface, but not for values with concrete types that implement the interface. +// +// 2. Hook encoders/decoders - These can be registered using the RegisterHookEncoder and RegisterHookDecoder methods. +// These methods only accept interface types and the registered codecs will be invoked when encoding or decoding values +// whose types implement the interface. An example of a hook defined by the driver is bson.Marshaler. The driver will +// call the MarshalBSON method for any value whose type implements bson.Marshaler, regardless of the value's concrete +// type. +// +// 3. Type map entries - This can be used to associate a BSON type with a Go type. These type associations are used when +// decoding into a bson.D/bson.M or a struct field of type interface{}. For example, by default, BSON int32 and int64 +// values decode as Go int32 and int64 instances, respectively, when decoding into a bson.D. The following code would +// change the behavior so these values decode as Go int instances instead: +// +// intType := reflect.TypeOf(int(0)) +// registryBuilder.RegisterTypeMapEntry(bsontype.Int32, intType).RegisterTypeMapEntry(bsontype.Int64, intType) +// +// 4. Kind encoder/decoders - These can be registered using the RegisterDefaultEncoder and RegisterDefaultDecoder +// methods. The registered codec will be invoked when encoding or decoding values whose reflect.Kind matches the +// registered reflect.Kind as long as the value's type doesn't match a registered type or hook encoder/decoder first. +// These methods should be used to change the behavior for all values for a specific kind. +// +// # Registry Lookup Procedure +// +// When looking up an encoder in a Registry, the precedence rules are as follows: +// +// 1. A type encoder registered for the exact type of the value. +// +// 2. A hook encoder registered for an interface that is implemented by the value or by a pointer to the value. If the +// value matches multiple hooks (e.g. the type implements bsoncodec.Marshaler and bsoncodec.ValueMarshaler), the first +// one registered will be selected. Note that registries constructed using bson.NewRegistryBuilder have driver-defined +// hooks registered for the bsoncodec.Marshaler, bsoncodec.ValueMarshaler, and bsoncodec.Proxy interfaces, so those +// will take precedence over any new hooks. +// +// 3. A kind encoder registered for the value's kind. +// +// If all of these lookups fail to find an encoder, an error of type ErrNoEncoder is returned. The same precedence +// rules apply for decoders, with the exception that an error of type ErrNoDecoder will be returned if no decoder is +// found. +// +// # DefaultValueEncoders and DefaultValueDecoders +// +// The DefaultValueEncoders and DefaultValueDecoders types provide a full set of ValueEncoders and +// ValueDecoders for handling a wide range of Go types, including all of the types within the +// primitive package. To make registering these codecs easier, a helper method on each type is +// provided. For the DefaultValueEncoders type the method is called RegisterDefaultEncoders and for +// the DefaultValueDecoders type the method is called RegisterDefaultDecoders, this method also +// handles registering type map entries for each BSON type. +package bsoncodec diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go new file mode 100644 index 0000000..eda417c --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go @@ -0,0 +1,147 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "reflect" + + "go.mongodb.org/mongo-driver/bson/bsonoptions" + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/bson/bsontype" + "go.mongodb.org/mongo-driver/bson/primitive" +) + +// EmptyInterfaceCodec is the Codec used for interface{} values. +type EmptyInterfaceCodec struct { + DecodeBinaryAsSlice bool +} + +var ( + defaultEmptyInterfaceCodec = NewEmptyInterfaceCodec() + + _ ValueCodec = defaultEmptyInterfaceCodec + _ typeDecoder = defaultEmptyInterfaceCodec +) + +// NewEmptyInterfaceCodec returns a EmptyInterfaceCodec with options opts. +func NewEmptyInterfaceCodec(opts ...*bsonoptions.EmptyInterfaceCodecOptions) *EmptyInterfaceCodec { + interfaceOpt := bsonoptions.MergeEmptyInterfaceCodecOptions(opts...) + + codec := EmptyInterfaceCodec{} + if interfaceOpt.DecodeBinaryAsSlice != nil { + codec.DecodeBinaryAsSlice = *interfaceOpt.DecodeBinaryAsSlice + } + return &codec +} + +// EncodeValue is the ValueEncoderFunc for interface{}. +func (eic EmptyInterfaceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tEmpty { + return ValueEncoderError{Name: "EmptyInterfaceEncodeValue", Types: []reflect.Type{tEmpty}, Received: val} + } + + if val.IsNil() { + return vw.WriteNull() + } + encoder, err := ec.LookupEncoder(val.Elem().Type()) + if err != nil { + return err + } + + return encoder.EncodeValue(ec, vw, val.Elem()) +} + +func (eic EmptyInterfaceCodec) getEmptyInterfaceDecodeType(dc DecodeContext, valueType bsontype.Type) (reflect.Type, error) { + isDocument := valueType == bsontype.Type(0) || valueType == bsontype.EmbeddedDocument + if isDocument { + if dc.defaultDocumentType != nil { + // If the bsontype is an embedded document and the DocumentType is set on the DecodeContext, then return + // that type. + return dc.defaultDocumentType, nil + } + if dc.Ancestor != nil { + // Using ancestor information rather than looking up the type map entry forces consistent decoding. + // If we're decoding into a bson.D, subdocuments should also be decoded as bson.D, even if a type map entry + // has been registered. + return dc.Ancestor, nil + } + } + + rtype, err := dc.LookupTypeMapEntry(valueType) + if err == nil { + return rtype, nil + } + + if isDocument { + // For documents, fallback to looking up a type map entry for bsontype.Type(0) or bsontype.EmbeddedDocument, + // depending on the original valueType. + var lookupType bsontype.Type + switch valueType { + case bsontype.Type(0): + lookupType = bsontype.EmbeddedDocument + case bsontype.EmbeddedDocument: + lookupType = bsontype.Type(0) + } + + rtype, err = dc.LookupTypeMapEntry(lookupType) + if err == nil { + return rtype, nil + } + } + + return nil, err +} + +func (eic EmptyInterfaceCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tEmpty { + return emptyValue, ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: reflect.Zero(t)} + } + + rtype, err := eic.getEmptyInterfaceDecodeType(dc, vr.Type()) + if err != nil { + switch vr.Type() { + case bsontype.Null: + return reflect.Zero(t), vr.ReadNull() + default: + return emptyValue, err + } + } + + decoder, err := dc.LookupDecoder(rtype) + if err != nil { + return emptyValue, err + } + + elem, err := decodeTypeOrValue(decoder, dc, vr, rtype) + if err != nil { + return emptyValue, err + } + + if eic.DecodeBinaryAsSlice && rtype == tBinary { + binElem := elem.Interface().(primitive.Binary) + if binElem.Subtype == bsontype.BinaryGeneric || binElem.Subtype == bsontype.BinaryBinaryOld { + elem = reflect.ValueOf(binElem.Data) + } + } + + return elem, nil +} + +// DecodeValue is the ValueDecoderFunc for interface{}. +func (eic EmptyInterfaceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tEmpty { + return ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: val} + } + + elem, err := eic.decodeType(dc, vr, val.Type()) + if err != nil { + return err + } + + val.Set(elem) + return nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go new file mode 100644 index 0000000..e1fbef9 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go @@ -0,0 +1,309 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "encoding" + "fmt" + "reflect" + "strconv" + + "go.mongodb.org/mongo-driver/bson/bsonoptions" + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/bson/bsontype" +) + +var defaultMapCodec = NewMapCodec() + +// MapCodec is the Codec used for map values. +type MapCodec struct { + DecodeZerosMap bool + EncodeNilAsEmpty bool + EncodeKeysWithStringer bool +} + +var _ ValueCodec = &MapCodec{} + +// KeyMarshaler is the interface implemented by an object that can marshal itself into a string key. +// This applies to types used as map keys and is similar to encoding.TextMarshaler. +type KeyMarshaler interface { + MarshalKey() (key string, err error) +} + +// KeyUnmarshaler is the interface implemented by an object that can unmarshal a string representation +// of itself. This applies to types used as map keys and is similar to encoding.TextUnmarshaler. +// +// UnmarshalKey must be able to decode the form generated by MarshalKey. +// UnmarshalKey must copy the text if it wishes to retain the text +// after returning. +type KeyUnmarshaler interface { + UnmarshalKey(key string) error +} + +// NewMapCodec returns a MapCodec with options opts. +func NewMapCodec(opts ...*bsonoptions.MapCodecOptions) *MapCodec { + mapOpt := bsonoptions.MergeMapCodecOptions(opts...) + + codec := MapCodec{} + if mapOpt.DecodeZerosMap != nil { + codec.DecodeZerosMap = *mapOpt.DecodeZerosMap + } + if mapOpt.EncodeNilAsEmpty != nil { + codec.EncodeNilAsEmpty = *mapOpt.EncodeNilAsEmpty + } + if mapOpt.EncodeKeysWithStringer != nil { + codec.EncodeKeysWithStringer = *mapOpt.EncodeKeysWithStringer + } + return &codec +} + +// EncodeValue is the ValueEncoder for map[*]* types. +func (mc *MapCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Kind() != reflect.Map { + return ValueEncoderError{Name: "MapEncodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val} + } + + if val.IsNil() && !mc.EncodeNilAsEmpty { + // If we have a nil map but we can't WriteNull, that means we're probably trying to encode + // to a TopLevel document. We can't currently tell if this is what actually happened, but if + // there's a deeper underlying problem, the error will also be returned from WriteDocument, + // so just continue. The operations on a map reflection value are valid, so we can call + // MapKeys within mapEncodeValue without a problem. + err := vw.WriteNull() + if err == nil { + return nil + } + } + + dw, err := vw.WriteDocument() + if err != nil { + return err + } + + return mc.mapEncodeValue(ec, dw, val, nil) +} + +// mapEncodeValue handles encoding of the values of a map. The collisionFn returns +// true if the provided key exists, this is mainly used for inline maps in the +// struct codec. +func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, val reflect.Value, collisionFn func(string) bool) error { + + elemType := val.Type().Elem() + encoder, err := ec.LookupEncoder(elemType) + if err != nil && elemType.Kind() != reflect.Interface { + return err + } + + keys := val.MapKeys() + for _, key := range keys { + keyStr, err := mc.encodeKey(key) + if err != nil { + return err + } + + if collisionFn != nil && collisionFn(keyStr) { + return fmt.Errorf("Key %s of inlined map conflicts with a struct field name", key) + } + + currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.MapIndex(key)) + if lookupErr != nil && lookupErr != errInvalidValue { + return lookupErr + } + + vw, err := dw.WriteDocumentElement(keyStr) + if err != nil { + return err + } + + if lookupErr == errInvalidValue { + err = vw.WriteNull() + if err != nil { + return err + } + continue + } + + err = currEncoder.EncodeValue(ec, vw, currVal) + if err != nil { + return err + } + } + + return dw.WriteDocumentEnd() +} + +// DecodeValue is the ValueDecoder for map[string/decimal]* types. +func (mc *MapCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if val.Kind() != reflect.Map || (!val.CanSet() && val.IsNil()) { + return ValueDecoderError{Name: "MapDecodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val} + } + + switch vrType := vr.Type(); vrType { + case bsontype.Type(0), bsontype.EmbeddedDocument: + case bsontype.Null: + val.Set(reflect.Zero(val.Type())) + return vr.ReadNull() + case bsontype.Undefined: + val.Set(reflect.Zero(val.Type())) + return vr.ReadUndefined() + default: + return fmt.Errorf("cannot decode %v into a %s", vrType, val.Type()) + } + + dr, err := vr.ReadDocument() + if err != nil { + return err + } + + if val.IsNil() { + val.Set(reflect.MakeMap(val.Type())) + } + + if val.Len() > 0 && mc.DecodeZerosMap { + clearMap(val) + } + + eType := val.Type().Elem() + decoder, err := dc.LookupDecoder(eType) + if err != nil { + return err + } + eTypeDecoder, _ := decoder.(typeDecoder) + + if eType == tEmpty { + dc.Ancestor = val.Type() + } + + keyType := val.Type().Key() + + for { + key, vr, err := dr.ReadElement() + if err == bsonrw.ErrEOD { + break + } + if err != nil { + return err + } + + k, err := mc.decodeKey(key, keyType) + if err != nil { + return err + } + + elem, err := decodeTypeOrValueWithInfo(decoder, eTypeDecoder, dc, vr, eType, true) + if err != nil { + return newDecodeError(key, err) + } + + val.SetMapIndex(k, elem) + } + return nil +} + +func clearMap(m reflect.Value) { + var none reflect.Value + for _, k := range m.MapKeys() { + m.SetMapIndex(k, none) + } +} + +func (mc *MapCodec) encodeKey(val reflect.Value) (string, error) { + if mc.EncodeKeysWithStringer { + return fmt.Sprint(val), nil + } + + // keys of any string type are used directly + if val.Kind() == reflect.String { + return val.String(), nil + } + // KeyMarshalers are marshaled + if km, ok := val.Interface().(KeyMarshaler); ok { + if val.Kind() == reflect.Ptr && val.IsNil() { + return "", nil + } + buf, err := km.MarshalKey() + if err == nil { + return buf, nil + } + return "", err + } + // keys implement encoding.TextMarshaler are marshaled. + if km, ok := val.Interface().(encoding.TextMarshaler); ok { + if val.Kind() == reflect.Ptr && val.IsNil() { + return "", nil + } + + buf, err := km.MarshalText() + if err != nil { + return "", err + } + + return string(buf), nil + } + + switch val.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return strconv.FormatInt(val.Int(), 10), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return strconv.FormatUint(val.Uint(), 10), nil + } + return "", fmt.Errorf("unsupported key type: %v", val.Type()) +} + +var keyUnmarshalerType = reflect.TypeOf((*KeyUnmarshaler)(nil)).Elem() +var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() + +func (mc *MapCodec) decodeKey(key string, keyType reflect.Type) (reflect.Value, error) { + keyVal := reflect.ValueOf(key) + var err error + switch { + // First, if EncodeKeysWithStringer is not enabled, try to decode withKeyUnmarshaler + case !mc.EncodeKeysWithStringer && reflect.PtrTo(keyType).Implements(keyUnmarshalerType): + keyVal = reflect.New(keyType) + v := keyVal.Interface().(KeyUnmarshaler) + err = v.UnmarshalKey(key) + keyVal = keyVal.Elem() + // Try to decode encoding.TextUnmarshalers. + case reflect.PtrTo(keyType).Implements(textUnmarshalerType): + keyVal = reflect.New(keyType) + v := keyVal.Interface().(encoding.TextUnmarshaler) + err = v.UnmarshalText([]byte(key)) + keyVal = keyVal.Elem() + // Otherwise, go to type specific behavior + default: + switch keyType.Kind() { + case reflect.String: + keyVal = reflect.ValueOf(key).Convert(keyType) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + n, parseErr := strconv.ParseInt(key, 10, 64) + if parseErr != nil || reflect.Zero(keyType).OverflowInt(n) { + err = fmt.Errorf("failed to unmarshal number key %v", key) + } + keyVal = reflect.ValueOf(n).Convert(keyType) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + n, parseErr := strconv.ParseUint(key, 10, 64) + if parseErr != nil || reflect.Zero(keyType).OverflowUint(n) { + err = fmt.Errorf("failed to unmarshal number key %v", key) + break + } + keyVal = reflect.ValueOf(n).Convert(keyType) + case reflect.Float32, reflect.Float64: + if mc.EncodeKeysWithStringer { + parsed, err := strconv.ParseFloat(key, 64) + if err != nil { + return keyVal, fmt.Errorf("Map key is defined to be a decimal type (%v) but got error %v", keyType.Kind(), err) + } + keyVal = reflect.ValueOf(parsed) + break + } + fallthrough + default: + return keyVal, fmt.Errorf("unsupported key type: %v", keyType) + } + } + return keyVal, err +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/mode.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/mode.go new file mode 100644 index 0000000..fbd9f0a --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/mode.go @@ -0,0 +1,65 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import "fmt" + +type mode int + +const ( + _ mode = iota + mTopLevel + mDocument + mArray + mValue + mElement + mCodeWithScope + mSpacer +) + +func (m mode) String() string { + var str string + + switch m { + case mTopLevel: + str = "TopLevel" + case mDocument: + str = "DocumentMode" + case mArray: + str = "ArrayMode" + case mValue: + str = "ValueMode" + case mElement: + str = "ElementMode" + case mCodeWithScope: + str = "CodeWithScopeMode" + case mSpacer: + str = "CodeWithScopeSpacerFrame" + default: + str = "UnknownMode" + } + + return str +} + +// TransitionError is an error returned when an invalid progressing a +// ValueReader or ValueWriter state machine occurs. +type TransitionError struct { + parent mode + current mode + destination mode +} + +func (te TransitionError) Error() string { + if te.destination == mode(0) { + return fmt.Sprintf("invalid state transition: cannot read/write value while in %s", te.current) + } + if te.parent == mode(0) { + return fmt.Sprintf("invalid state transition: %s -> %s", te.current, te.destination) + } + return fmt.Sprintf("invalid state transition: %s -> %s; parent %s", te.current, te.destination, te.parent) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go new file mode 100644 index 0000000..616a3e7 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go @@ -0,0 +1,109 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "reflect" + "sync" + + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/bson/bsontype" +) + +var _ ValueEncoder = &PointerCodec{} +var _ ValueDecoder = &PointerCodec{} + +// PointerCodec is the Codec used for pointers. +type PointerCodec struct { + ecache map[reflect.Type]ValueEncoder + dcache map[reflect.Type]ValueDecoder + l sync.RWMutex +} + +// NewPointerCodec returns a PointerCodec that has been initialized. +func NewPointerCodec() *PointerCodec { + return &PointerCodec{ + ecache: make(map[reflect.Type]ValueEncoder), + dcache: make(map[reflect.Type]ValueDecoder), + } +} + +// EncodeValue handles encoding a pointer by either encoding it to BSON Null if the pointer is nil +// or looking up an encoder for the type of value the pointer points to. +func (pc *PointerCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if val.Kind() != reflect.Ptr { + if !val.IsValid() { + return vw.WriteNull() + } + return ValueEncoderError{Name: "PointerCodec.EncodeValue", Kinds: []reflect.Kind{reflect.Ptr}, Received: val} + } + + if val.IsNil() { + return vw.WriteNull() + } + + pc.l.RLock() + enc, ok := pc.ecache[val.Type()] + pc.l.RUnlock() + if ok { + if enc == nil { + return ErrNoEncoder{Type: val.Type()} + } + return enc.EncodeValue(ec, vw, val.Elem()) + } + + enc, err := ec.LookupEncoder(val.Type().Elem()) + pc.l.Lock() + pc.ecache[val.Type()] = enc + pc.l.Unlock() + if err != nil { + return err + } + + return enc.EncodeValue(ec, vw, val.Elem()) +} + +// DecodeValue handles decoding a pointer by looking up a decoder for the type it points to and +// using that to decode. If the BSON value is Null, this method will set the pointer to nil. +func (pc *PointerCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Kind() != reflect.Ptr { + return ValueDecoderError{Name: "PointerCodec.DecodeValue", Kinds: []reflect.Kind{reflect.Ptr}, Received: val} + } + + if vr.Type() == bsontype.Null { + val.Set(reflect.Zero(val.Type())) + return vr.ReadNull() + } + if vr.Type() == bsontype.Undefined { + val.Set(reflect.Zero(val.Type())) + return vr.ReadUndefined() + } + + if val.IsNil() { + val.Set(reflect.New(val.Type().Elem())) + } + + pc.l.RLock() + dec, ok := pc.dcache[val.Type()] + pc.l.RUnlock() + if ok { + if dec == nil { + return ErrNoDecoder{Type: val.Type()} + } + return dec.DecodeValue(dc, vr, val.Elem()) + } + + dec, err := dc.LookupDecoder(val.Type().Elem()) + pc.l.Lock() + pc.dcache[val.Type()] = dec + pc.l.Unlock() + if err != nil { + return err + } + + return dec.DecodeValue(dc, vr, val.Elem()) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/proxy.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/proxy.go new file mode 100644 index 0000000..4cf2b01 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/proxy.go @@ -0,0 +1,14 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +// Proxy is an interface implemented by types that cannot themselves be directly encoded. Types +// that implement this interface with have ProxyBSON called during the encoding process and that +// value will be encoded in place for the implementer. +type Proxy interface { + ProxyBSON() (interface{}, error) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go new file mode 100644 index 0000000..8064402 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go @@ -0,0 +1,469 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "errors" + "fmt" + "reflect" + "sync" + + "go.mongodb.org/mongo-driver/bson/bsontype" +) + +// ErrNilType is returned when nil is passed to either LookupEncoder or LookupDecoder. +var ErrNilType = errors.New("cannot perform a decoder lookup on ") + +// ErrNotPointer is returned when a non-pointer type is provided to LookupDecoder. +var ErrNotPointer = errors.New("non-pointer provided to LookupDecoder") + +// ErrNoEncoder is returned when there wasn't an encoder available for a type. +type ErrNoEncoder struct { + Type reflect.Type +} + +func (ene ErrNoEncoder) Error() string { + if ene.Type == nil { + return "no encoder found for " + } + return "no encoder found for " + ene.Type.String() +} + +// ErrNoDecoder is returned when there wasn't a decoder available for a type. +type ErrNoDecoder struct { + Type reflect.Type +} + +func (end ErrNoDecoder) Error() string { + return "no decoder found for " + end.Type.String() +} + +// ErrNoTypeMapEntry is returned when there wasn't a type available for the provided BSON type. +type ErrNoTypeMapEntry struct { + Type bsontype.Type +} + +func (entme ErrNoTypeMapEntry) Error() string { + return "no type map entry found for " + entme.Type.String() +} + +// ErrNotInterface is returned when the provided type is not an interface. +var ErrNotInterface = errors.New("The provided type is not an interface") + +// A RegistryBuilder is used to build a Registry. This type is not goroutine +// safe. +type RegistryBuilder struct { + typeEncoders map[reflect.Type]ValueEncoder + interfaceEncoders []interfaceValueEncoder + kindEncoders map[reflect.Kind]ValueEncoder + + typeDecoders map[reflect.Type]ValueDecoder + interfaceDecoders []interfaceValueDecoder + kindDecoders map[reflect.Kind]ValueDecoder + + typeMap map[bsontype.Type]reflect.Type +} + +// A Registry is used to store and retrieve codecs for types and interfaces. This type is the main +// typed passed around and Encoders and Decoders are constructed from it. +type Registry struct { + typeEncoders map[reflect.Type]ValueEncoder + typeDecoders map[reflect.Type]ValueDecoder + + interfaceEncoders []interfaceValueEncoder + interfaceDecoders []interfaceValueDecoder + + kindEncoders map[reflect.Kind]ValueEncoder + kindDecoders map[reflect.Kind]ValueDecoder + + typeMap map[bsontype.Type]reflect.Type + + mu sync.RWMutex +} + +// NewRegistryBuilder creates a new empty RegistryBuilder. +func NewRegistryBuilder() *RegistryBuilder { + return &RegistryBuilder{ + typeEncoders: make(map[reflect.Type]ValueEncoder), + typeDecoders: make(map[reflect.Type]ValueDecoder), + + interfaceEncoders: make([]interfaceValueEncoder, 0), + interfaceDecoders: make([]interfaceValueDecoder, 0), + + kindEncoders: make(map[reflect.Kind]ValueEncoder), + kindDecoders: make(map[reflect.Kind]ValueDecoder), + + typeMap: make(map[bsontype.Type]reflect.Type), + } +} + +func buildDefaultRegistry() *Registry { + rb := NewRegistryBuilder() + defaultValueEncoders.RegisterDefaultEncoders(rb) + defaultValueDecoders.RegisterDefaultDecoders(rb) + return rb.Build() +} + +// RegisterCodec will register the provided ValueCodec for the provided type. +func (rb *RegistryBuilder) RegisterCodec(t reflect.Type, codec ValueCodec) *RegistryBuilder { + rb.RegisterTypeEncoder(t, codec) + rb.RegisterTypeDecoder(t, codec) + return rb +} + +// RegisterTypeEncoder will register the provided ValueEncoder for the provided type. +// +// The type will be used directly, so an encoder can be registered for a type and a different encoder can be registered +// for a pointer to that type. +// +// If the given type is an interface, the encoder will be called when marshalling a type that is that interface. It +// will not be called when marshalling a non-interface type that implements the interface. +func (rb *RegistryBuilder) RegisterTypeEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder { + rb.typeEncoders[t] = enc + return rb +} + +// RegisterHookEncoder will register an encoder for the provided interface type t. This encoder will be called when +// marshalling a type if the type implements t or a pointer to the type implements t. If the provided type is not +// an interface (i.e. t.Kind() != reflect.Interface), this method will panic. +func (rb *RegistryBuilder) RegisterHookEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder { + if t.Kind() != reflect.Interface { + panicStr := fmt.Sprintf("RegisterHookEncoder expects a type with kind reflect.Interface, "+ + "got type %s with kind %s", t, t.Kind()) + panic(panicStr) + } + + for idx, encoder := range rb.interfaceEncoders { + if encoder.i == t { + rb.interfaceEncoders[idx].ve = enc + return rb + } + } + + rb.interfaceEncoders = append(rb.interfaceEncoders, interfaceValueEncoder{i: t, ve: enc}) + return rb +} + +// RegisterTypeDecoder will register the provided ValueDecoder for the provided type. +// +// The type will be used directly, so a decoder can be registered for a type and a different decoder can be registered +// for a pointer to that type. +// +// If the given type is an interface, the decoder will be called when unmarshalling into a type that is that interface. +// It will not be called when unmarshalling into a non-interface type that implements the interface. +func (rb *RegistryBuilder) RegisterTypeDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder { + rb.typeDecoders[t] = dec + return rb +} + +// RegisterHookDecoder will register an decoder for the provided interface type t. This decoder will be called when +// unmarshalling into a type if the type implements t or a pointer to the type implements t. If the provided type is not +// an interface (i.e. t.Kind() != reflect.Interface), this method will panic. +func (rb *RegistryBuilder) RegisterHookDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder { + if t.Kind() != reflect.Interface { + panicStr := fmt.Sprintf("RegisterHookDecoder expects a type with kind reflect.Interface, "+ + "got type %s with kind %s", t, t.Kind()) + panic(panicStr) + } + + for idx, decoder := range rb.interfaceDecoders { + if decoder.i == t { + rb.interfaceDecoders[idx].vd = dec + return rb + } + } + + rb.interfaceDecoders = append(rb.interfaceDecoders, interfaceValueDecoder{i: t, vd: dec}) + return rb +} + +// RegisterEncoder registers the provided type and encoder pair. +// +// Deprecated: Use RegisterTypeEncoder or RegisterHookEncoder instead. +func (rb *RegistryBuilder) RegisterEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder { + if t == tEmpty { + rb.typeEncoders[t] = enc + return rb + } + switch t.Kind() { + case reflect.Interface: + for idx, ir := range rb.interfaceEncoders { + if ir.i == t { + rb.interfaceEncoders[idx].ve = enc + return rb + } + } + + rb.interfaceEncoders = append(rb.interfaceEncoders, interfaceValueEncoder{i: t, ve: enc}) + default: + rb.typeEncoders[t] = enc + } + return rb +} + +// RegisterDecoder registers the provided type and decoder pair. +// +// Deprecated: Use RegisterTypeDecoder or RegisterHookDecoder instead. +func (rb *RegistryBuilder) RegisterDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder { + if t == nil { + rb.typeDecoders[nil] = dec + return rb + } + if t == tEmpty { + rb.typeDecoders[t] = dec + return rb + } + switch t.Kind() { + case reflect.Interface: + for idx, ir := range rb.interfaceDecoders { + if ir.i == t { + rb.interfaceDecoders[idx].vd = dec + return rb + } + } + + rb.interfaceDecoders = append(rb.interfaceDecoders, interfaceValueDecoder{i: t, vd: dec}) + default: + rb.typeDecoders[t] = dec + } + return rb +} + +// RegisterDefaultEncoder will registr the provided ValueEncoder to the provided +// kind. +func (rb *RegistryBuilder) RegisterDefaultEncoder(kind reflect.Kind, enc ValueEncoder) *RegistryBuilder { + rb.kindEncoders[kind] = enc + return rb +} + +// RegisterDefaultDecoder will register the provided ValueDecoder to the +// provided kind. +func (rb *RegistryBuilder) RegisterDefaultDecoder(kind reflect.Kind, dec ValueDecoder) *RegistryBuilder { + rb.kindDecoders[kind] = dec + return rb +} + +// RegisterTypeMapEntry will register the provided type to the BSON type. The primary usage for this +// mapping is decoding situations where an empty interface is used and a default type needs to be +// created and decoded into. +// +// By default, BSON documents will decode into interface{} values as bson.D. To change the default type for BSON +// documents, a type map entry for bsontype.EmbeddedDocument should be registered. For example, to force BSON documents +// to decode to bson.Raw, use the following code: +// +// rb.RegisterTypeMapEntry(bsontype.EmbeddedDocument, reflect.TypeOf(bson.Raw{})) +func (rb *RegistryBuilder) RegisterTypeMapEntry(bt bsontype.Type, rt reflect.Type) *RegistryBuilder { + rb.typeMap[bt] = rt + return rb +} + +// Build creates a Registry from the current state of this RegistryBuilder. +func (rb *RegistryBuilder) Build() *Registry { + registry := new(Registry) + + registry.typeEncoders = make(map[reflect.Type]ValueEncoder) + for t, enc := range rb.typeEncoders { + registry.typeEncoders[t] = enc + } + + registry.typeDecoders = make(map[reflect.Type]ValueDecoder) + for t, dec := range rb.typeDecoders { + registry.typeDecoders[t] = dec + } + + registry.interfaceEncoders = make([]interfaceValueEncoder, len(rb.interfaceEncoders)) + copy(registry.interfaceEncoders, rb.interfaceEncoders) + + registry.interfaceDecoders = make([]interfaceValueDecoder, len(rb.interfaceDecoders)) + copy(registry.interfaceDecoders, rb.interfaceDecoders) + + registry.kindEncoders = make(map[reflect.Kind]ValueEncoder) + for kind, enc := range rb.kindEncoders { + registry.kindEncoders[kind] = enc + } + + registry.kindDecoders = make(map[reflect.Kind]ValueDecoder) + for kind, dec := range rb.kindDecoders { + registry.kindDecoders[kind] = dec + } + + registry.typeMap = make(map[bsontype.Type]reflect.Type) + for bt, rt := range rb.typeMap { + registry.typeMap[bt] = rt + } + + return registry +} + +// LookupEncoder inspects the registry for an encoder for the given type. The lookup precedence works as follows: +// +// 1. An encoder registered for the exact type. If the given type represents an interface, an encoder registered using +// RegisterTypeEncoder for the interface will be selected. +// +// 2. An encoder registered using RegisterHookEncoder for an interface implemented by the type or by a pointer to the +// type. +// +// 3. An encoder registered for the reflect.Kind of the value. +// +// If no encoder is found, an error of type ErrNoEncoder is returned. +func (r *Registry) LookupEncoder(t reflect.Type) (ValueEncoder, error) { + encodererr := ErrNoEncoder{Type: t} + r.mu.RLock() + enc, found := r.lookupTypeEncoder(t) + r.mu.RUnlock() + if found { + if enc == nil { + return nil, ErrNoEncoder{Type: t} + } + return enc, nil + } + + enc, found = r.lookupInterfaceEncoder(t, true) + if found { + r.mu.Lock() + r.typeEncoders[t] = enc + r.mu.Unlock() + return enc, nil + } + + if t == nil { + r.mu.Lock() + r.typeEncoders[t] = nil + r.mu.Unlock() + return nil, encodererr + } + + enc, found = r.kindEncoders[t.Kind()] + if !found { + r.mu.Lock() + r.typeEncoders[t] = nil + r.mu.Unlock() + return nil, encodererr + } + + r.mu.Lock() + r.typeEncoders[t] = enc + r.mu.Unlock() + return enc, nil +} + +func (r *Registry) lookupTypeEncoder(t reflect.Type) (ValueEncoder, bool) { + enc, found := r.typeEncoders[t] + return enc, found +} + +func (r *Registry) lookupInterfaceEncoder(t reflect.Type, allowAddr bool) (ValueEncoder, bool) { + if t == nil { + return nil, false + } + for _, ienc := range r.interfaceEncoders { + if t.Implements(ienc.i) { + return ienc.ve, true + } + if allowAddr && t.Kind() != reflect.Ptr && reflect.PtrTo(t).Implements(ienc.i) { + // if *t implements an interface, this will catch if t implements an interface further ahead + // in interfaceEncoders + defaultEnc, found := r.lookupInterfaceEncoder(t, false) + if !found { + defaultEnc = r.kindEncoders[t.Kind()] + } + return newCondAddrEncoder(ienc.ve, defaultEnc), true + } + } + return nil, false +} + +// LookupDecoder inspects the registry for an decoder for the given type. The lookup precedence works as follows: +// +// 1. A decoder registered for the exact type. If the given type represents an interface, a decoder registered using +// RegisterTypeDecoder for the interface will be selected. +// +// 2. A decoder registered using RegisterHookDecoder for an interface implemented by the type or by a pointer to the +// type. +// +// 3. A decoder registered for the reflect.Kind of the value. +// +// If no decoder is found, an error of type ErrNoDecoder is returned. +func (r *Registry) LookupDecoder(t reflect.Type) (ValueDecoder, error) { + if t == nil { + return nil, ErrNilType + } + decodererr := ErrNoDecoder{Type: t} + r.mu.RLock() + dec, found := r.lookupTypeDecoder(t) + r.mu.RUnlock() + if found { + if dec == nil { + return nil, ErrNoDecoder{Type: t} + } + return dec, nil + } + + dec, found = r.lookupInterfaceDecoder(t, true) + if found { + r.mu.Lock() + r.typeDecoders[t] = dec + r.mu.Unlock() + return dec, nil + } + + dec, found = r.kindDecoders[t.Kind()] + if !found { + r.mu.Lock() + r.typeDecoders[t] = nil + r.mu.Unlock() + return nil, decodererr + } + + r.mu.Lock() + r.typeDecoders[t] = dec + r.mu.Unlock() + return dec, nil +} + +func (r *Registry) lookupTypeDecoder(t reflect.Type) (ValueDecoder, bool) { + dec, found := r.typeDecoders[t] + return dec, found +} + +func (r *Registry) lookupInterfaceDecoder(t reflect.Type, allowAddr bool) (ValueDecoder, bool) { + for _, idec := range r.interfaceDecoders { + if t.Implements(idec.i) { + return idec.vd, true + } + if allowAddr && t.Kind() != reflect.Ptr && reflect.PtrTo(t).Implements(idec.i) { + // if *t implements an interface, this will catch if t implements an interface further ahead + // in interfaceDecoders + defaultDec, found := r.lookupInterfaceDecoder(t, false) + if !found { + defaultDec = r.kindDecoders[t.Kind()] + } + return newCondAddrDecoder(idec.vd, defaultDec), true + } + } + return nil, false +} + +// LookupTypeMapEntry inspects the registry's type map for a Go type for the corresponding BSON +// type. If no type is found, ErrNoTypeMapEntry is returned. +func (r *Registry) LookupTypeMapEntry(bt bsontype.Type) (reflect.Type, error) { + t, ok := r.typeMap[bt] + if !ok || t == nil { + return nil, ErrNoTypeMapEntry{Type: bt} + } + return t, nil +} + +type interfaceValueEncoder struct { + i reflect.Type + ve ValueEncoder +} + +type interfaceValueDecoder struct { + i reflect.Type + vd ValueDecoder +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go new file mode 100644 index 0000000..3c1b6b8 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go @@ -0,0 +1,199 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "fmt" + "reflect" + + "go.mongodb.org/mongo-driver/bson/bsonoptions" + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/bson/bsontype" + "go.mongodb.org/mongo-driver/bson/primitive" +) + +var defaultSliceCodec = NewSliceCodec() + +// SliceCodec is the Codec used for slice values. +type SliceCodec struct { + EncodeNilAsEmpty bool +} + +var _ ValueCodec = &MapCodec{} + +// NewSliceCodec returns a MapCodec with options opts. +func NewSliceCodec(opts ...*bsonoptions.SliceCodecOptions) *SliceCodec { + sliceOpt := bsonoptions.MergeSliceCodecOptions(opts...) + + codec := SliceCodec{} + if sliceOpt.EncodeNilAsEmpty != nil { + codec.EncodeNilAsEmpty = *sliceOpt.EncodeNilAsEmpty + } + return &codec +} + +// EncodeValue is the ValueEncoder for slice types. +func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Kind() != reflect.Slice { + return ValueEncoderError{Name: "SliceEncodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} + } + + if val.IsNil() && !sc.EncodeNilAsEmpty { + return vw.WriteNull() + } + + // If we have a []byte we want to treat it as a binary instead of as an array. + if val.Type().Elem() == tByte { + var byteSlice []byte + for idx := 0; idx < val.Len(); idx++ { + byteSlice = append(byteSlice, val.Index(idx).Interface().(byte)) + } + return vw.WriteBinary(byteSlice) + } + + // If we have a []primitive.E we want to treat it as a document instead of as an array. + if val.Type().ConvertibleTo(tD) { + d := val.Convert(tD).Interface().(primitive.D) + + dw, err := vw.WriteDocument() + if err != nil { + return err + } + + for _, e := range d { + err = encodeElement(ec, dw, e) + if err != nil { + return err + } + } + + return dw.WriteDocumentEnd() + } + + aw, err := vw.WriteArray() + if err != nil { + return err + } + + elemType := val.Type().Elem() + encoder, err := ec.LookupEncoder(elemType) + if err != nil && elemType.Kind() != reflect.Interface { + return err + } + + for idx := 0; idx < val.Len(); idx++ { + currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.Index(idx)) + if lookupErr != nil && lookupErr != errInvalidValue { + return lookupErr + } + + vw, err := aw.WriteArrayElement() + if err != nil { + return err + } + + if lookupErr == errInvalidValue { + err = vw.WriteNull() + if err != nil { + return err + } + continue + } + + err = currEncoder.EncodeValue(ec, vw, currVal) + if err != nil { + return err + } + } + return aw.WriteArrayEnd() +} + +// DecodeValue is the ValueDecoder for slice types. +func (sc *SliceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Kind() != reflect.Slice { + return ValueDecoderError{Name: "SliceDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} + } + + switch vrType := vr.Type(); vrType { + case bsontype.Array: + case bsontype.Null: + val.Set(reflect.Zero(val.Type())) + return vr.ReadNull() + case bsontype.Undefined: + val.Set(reflect.Zero(val.Type())) + return vr.ReadUndefined() + case bsontype.Type(0), bsontype.EmbeddedDocument: + if val.Type().Elem() != tE { + return fmt.Errorf("cannot decode document into %s", val.Type()) + } + case bsontype.Binary: + if val.Type().Elem() != tByte { + return fmt.Errorf("SliceDecodeValue can only decode a binary into a byte array, got %v", vrType) + } + data, subtype, err := vr.ReadBinary() + if err != nil { + return err + } + if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld { + return fmt.Errorf("SliceDecodeValue can only be used to decode subtype 0x00 or 0x02 for %s, got %v", bsontype.Binary, subtype) + } + + if val.IsNil() { + val.Set(reflect.MakeSlice(val.Type(), 0, len(data))) + } + + val.SetLen(0) + for _, elem := range data { + val.Set(reflect.Append(val, reflect.ValueOf(elem))) + } + return nil + case bsontype.String: + if sliceType := val.Type().Elem(); sliceType != tByte { + return fmt.Errorf("SliceDecodeValue can only decode a string into a byte array, got %v", sliceType) + } + str, err := vr.ReadString() + if err != nil { + return err + } + byteStr := []byte(str) + + if val.IsNil() { + val.Set(reflect.MakeSlice(val.Type(), 0, len(byteStr))) + } + + val.SetLen(0) + for _, elem := range byteStr { + val.Set(reflect.Append(val, reflect.ValueOf(elem))) + } + return nil + default: + return fmt.Errorf("cannot decode %v into a slice", vrType) + } + + var elemsFunc func(DecodeContext, bsonrw.ValueReader, reflect.Value) ([]reflect.Value, error) + switch val.Type().Elem() { + case tE: + dc.Ancestor = val.Type() + elemsFunc = defaultValueDecoders.decodeD + default: + elemsFunc = defaultValueDecoders.decodeDefault + } + + elems, err := elemsFunc(dc, vr, val) + if err != nil { + return err + } + + if val.IsNil() { + val.Set(reflect.MakeSlice(val.Type(), 0, len(elems))) + } + + val.SetLen(0) + val.Set(reflect.Append(val, elems...)) + + return nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go new file mode 100644 index 0000000..5332b7c --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go @@ -0,0 +1,119 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "fmt" + "reflect" + + "go.mongodb.org/mongo-driver/bson/bsonoptions" + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/bson/bsontype" +) + +// StringCodec is the Codec used for struct values. +type StringCodec struct { + DecodeObjectIDAsHex bool +} + +var ( + defaultStringCodec = NewStringCodec() + + _ ValueCodec = defaultStringCodec + _ typeDecoder = defaultStringCodec +) + +// NewStringCodec returns a StringCodec with options opts. +func NewStringCodec(opts ...*bsonoptions.StringCodecOptions) *StringCodec { + stringOpt := bsonoptions.MergeStringCodecOptions(opts...) + return &StringCodec{*stringOpt.DecodeObjectIDAsHex} +} + +// EncodeValue is the ValueEncoder for string types. +func (sc *StringCodec) EncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if val.Kind() != reflect.String { + return ValueEncoderError{ + Name: "StringEncodeValue", + Kinds: []reflect.Kind{reflect.String}, + Received: val, + } + } + + return vw.WriteString(val.String()) +} + +func (sc *StringCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t.Kind() != reflect.String { + return emptyValue, ValueDecoderError{ + Name: "StringDecodeValue", + Kinds: []reflect.Kind{reflect.String}, + Received: reflect.Zero(t), + } + } + + var str string + var err error + switch vr.Type() { + case bsontype.String: + str, err = vr.ReadString() + if err != nil { + return emptyValue, err + } + case bsontype.ObjectID: + oid, err := vr.ReadObjectID() + if err != nil { + return emptyValue, err + } + if sc.DecodeObjectIDAsHex { + str = oid.Hex() + } else { + byteArray := [12]byte(oid) + str = string(byteArray[:]) + } + case bsontype.Symbol: + str, err = vr.ReadSymbol() + if err != nil { + return emptyValue, err + } + case bsontype.Binary: + data, subtype, err := vr.ReadBinary() + if err != nil { + return emptyValue, err + } + if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld { + return emptyValue, decodeBinaryError{subtype: subtype, typeName: "string"} + } + str = string(data) + case bsontype.Null: + if err = vr.ReadNull(); err != nil { + return emptyValue, err + } + case bsontype.Undefined: + if err = vr.ReadUndefined(); err != nil { + return emptyValue, err + } + default: + return emptyValue, fmt.Errorf("cannot decode %v into a string type", vr.Type()) + } + + return reflect.ValueOf(str), nil +} + +// DecodeValue is the ValueDecoder for string types. +func (sc *StringCodec) DecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Kind() != reflect.String { + return ValueDecoderError{Name: "StringDecodeValue", Kinds: []reflect.Kind{reflect.String}, Received: val} + } + + elem, err := sc.decodeType(dctx, vr, val.Type()) + if err != nil { + return err + } + + val.SetString(elem.String()) + return nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go new file mode 100644 index 0000000..be3f208 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go @@ -0,0 +1,664 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "errors" + "fmt" + "reflect" + "sort" + "strings" + "sync" + "time" + + "go.mongodb.org/mongo-driver/bson/bsonoptions" + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/bson/bsontype" +) + +// DecodeError represents an error that occurs when unmarshalling BSON bytes into a native Go type. +type DecodeError struct { + keys []string + wrapped error +} + +// Unwrap returns the underlying error +func (de *DecodeError) Unwrap() error { + return de.wrapped +} + +// Error implements the error interface. +func (de *DecodeError) Error() string { + // The keys are stored in reverse order because the de.keys slice is builtup while propagating the error up the + // stack of BSON keys, so we call de.Keys(), which reverses them. + keyPath := strings.Join(de.Keys(), ".") + return fmt.Sprintf("error decoding key %s: %v", keyPath, de.wrapped) +} + +// Keys returns the BSON key path that caused an error as a slice of strings. The keys in the slice are in top-down +// order. For example, if the document being unmarshalled was {a: {b: {c: 1}}} and the value for c was supposed to be +// a string, the keys slice will be ["a", "b", "c"]. +func (de *DecodeError) Keys() []string { + reversedKeys := make([]string, 0, len(de.keys)) + for idx := len(de.keys) - 1; idx >= 0; idx-- { + reversedKeys = append(reversedKeys, de.keys[idx]) + } + + return reversedKeys +} + +// Zeroer allows custom struct types to implement a report of zero +// state. All struct types that don't implement Zeroer or where IsZero +// returns false are considered to be not zero. +type Zeroer interface { + IsZero() bool +} + +// StructCodec is the Codec used for struct values. +type StructCodec struct { + cache map[reflect.Type]*structDescription + l sync.RWMutex + parser StructTagParser + DecodeZeroStruct bool + DecodeDeepZeroInline bool + EncodeOmitDefaultStruct bool + AllowUnexportedFields bool + OverwriteDuplicatedInlinedFields bool +} + +var _ ValueEncoder = &StructCodec{} +var _ ValueDecoder = &StructCodec{} + +// NewStructCodec returns a StructCodec that uses p for struct tag parsing. +func NewStructCodec(p StructTagParser, opts ...*bsonoptions.StructCodecOptions) (*StructCodec, error) { + if p == nil { + return nil, errors.New("a StructTagParser must be provided to NewStructCodec") + } + + structOpt := bsonoptions.MergeStructCodecOptions(opts...) + + codec := &StructCodec{ + cache: make(map[reflect.Type]*structDescription), + parser: p, + } + + if structOpt.DecodeZeroStruct != nil { + codec.DecodeZeroStruct = *structOpt.DecodeZeroStruct + } + if structOpt.DecodeDeepZeroInline != nil { + codec.DecodeDeepZeroInline = *structOpt.DecodeDeepZeroInline + } + if structOpt.EncodeOmitDefaultStruct != nil { + codec.EncodeOmitDefaultStruct = *structOpt.EncodeOmitDefaultStruct + } + if structOpt.OverwriteDuplicatedInlinedFields != nil { + codec.OverwriteDuplicatedInlinedFields = *structOpt.OverwriteDuplicatedInlinedFields + } + if structOpt.AllowUnexportedFields != nil { + codec.AllowUnexportedFields = *structOpt.AllowUnexportedFields + } + + return codec, nil +} + +// EncodeValue handles encoding generic struct types. +func (sc *StructCodec) EncodeValue(r EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Kind() != reflect.Struct { + return ValueEncoderError{Name: "StructCodec.EncodeValue", Kinds: []reflect.Kind{reflect.Struct}, Received: val} + } + + sd, err := sc.describeStruct(r.Registry, val.Type()) + if err != nil { + return err + } + + dw, err := vw.WriteDocument() + if err != nil { + return err + } + var rv reflect.Value + for _, desc := range sd.fl { + if desc.inline == nil { + rv = val.Field(desc.idx) + } else { + rv, err = fieldByIndexErr(val, desc.inline) + if err != nil { + continue + } + } + + desc.encoder, rv, err = defaultValueEncoders.lookupElementEncoder(r, desc.encoder, rv) + + if err != nil && err != errInvalidValue { + return err + } + + if err == errInvalidValue { + if desc.omitEmpty { + continue + } + vw2, err := dw.WriteDocumentElement(desc.name) + if err != nil { + return err + } + err = vw2.WriteNull() + if err != nil { + return err + } + continue + } + + if desc.encoder == nil { + return ErrNoEncoder{Type: rv.Type()} + } + + encoder := desc.encoder + + var isZero bool + rvInterface := rv.Interface() + if cz, ok := encoder.(CodecZeroer); ok { + isZero = cz.IsTypeZero(rvInterface) + } else if rv.Kind() == reflect.Interface { + // sc.isZero will not treat an interface rv as an interface, so we need to check for the zero interface separately. + isZero = rv.IsNil() + } else { + isZero = sc.isZero(rvInterface) + } + if desc.omitEmpty && isZero { + continue + } + + vw2, err := dw.WriteDocumentElement(desc.name) + if err != nil { + return err + } + + ectx := EncodeContext{Registry: r.Registry, MinSize: desc.minSize} + err = encoder.EncodeValue(ectx, vw2, rv) + if err != nil { + return err + } + } + + if sd.inlineMap >= 0 { + rv := val.Field(sd.inlineMap) + collisionFn := func(key string) bool { + _, exists := sd.fm[key] + return exists + } + + return defaultMapCodec.mapEncodeValue(r, dw, rv, collisionFn) + } + + return dw.WriteDocumentEnd() +} + +func newDecodeError(key string, original error) error { + de, ok := original.(*DecodeError) + if !ok { + return &DecodeError{ + keys: []string{key}, + wrapped: original, + } + } + + de.keys = append(de.keys, key) + return de +} + +// DecodeValue implements the Codec interface. +// By default, map types in val will not be cleared. If a map has existing key/value pairs, it will be extended with the new ones from vr. +// For slices, the decoder will set the length of the slice to zero and append all elements. The underlying array will not be cleared. +func (sc *StructCodec) DecodeValue(r DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Kind() != reflect.Struct { + return ValueDecoderError{Name: "StructCodec.DecodeValue", Kinds: []reflect.Kind{reflect.Struct}, Received: val} + } + + switch vrType := vr.Type(); vrType { + case bsontype.Type(0), bsontype.EmbeddedDocument: + case bsontype.Null: + if err := vr.ReadNull(); err != nil { + return err + } + + val.Set(reflect.Zero(val.Type())) + return nil + case bsontype.Undefined: + if err := vr.ReadUndefined(); err != nil { + return err + } + + val.Set(reflect.Zero(val.Type())) + return nil + default: + return fmt.Errorf("cannot decode %v into a %s", vrType, val.Type()) + } + + sd, err := sc.describeStruct(r.Registry, val.Type()) + if err != nil { + return err + } + + if sc.DecodeZeroStruct { + val.Set(reflect.Zero(val.Type())) + } + if sc.DecodeDeepZeroInline && sd.inline { + val.Set(deepZero(val.Type())) + } + + var decoder ValueDecoder + var inlineMap reflect.Value + if sd.inlineMap >= 0 { + inlineMap = val.Field(sd.inlineMap) + decoder, err = r.LookupDecoder(inlineMap.Type().Elem()) + if err != nil { + return err + } + } + + dr, err := vr.ReadDocument() + if err != nil { + return err + } + + for { + name, vr, err := dr.ReadElement() + if err == bsonrw.ErrEOD { + break + } + if err != nil { + return err + } + + fd, exists := sd.fm[name] + if !exists { + // if the original name isn't found in the struct description, try again with the name in lowercase + // this could match if a BSON tag isn't specified because by default, describeStruct lowercases all field + // names + fd, exists = sd.fm[strings.ToLower(name)] + } + + if !exists { + if sd.inlineMap < 0 { + // The encoding/json package requires a flag to return on error for non-existent fields. + // This functionality seems appropriate for the struct codec. + err = vr.Skip() + if err != nil { + return err + } + continue + } + + if inlineMap.IsNil() { + inlineMap.Set(reflect.MakeMap(inlineMap.Type())) + } + + elem := reflect.New(inlineMap.Type().Elem()).Elem() + r.Ancestor = inlineMap.Type() + err = decoder.DecodeValue(r, vr, elem) + if err != nil { + return err + } + inlineMap.SetMapIndex(reflect.ValueOf(name), elem) + continue + } + + var field reflect.Value + if fd.inline == nil { + field = val.Field(fd.idx) + } else { + field, err = getInlineField(val, fd.inline) + if err != nil { + return err + } + } + + if !field.CanSet() { // Being settable is a super set of being addressable. + innerErr := fmt.Errorf("field %v is not settable", field) + return newDecodeError(fd.name, innerErr) + } + if field.Kind() == reflect.Ptr && field.IsNil() { + field.Set(reflect.New(field.Type().Elem())) + } + field = field.Addr() + + dctx := DecodeContext{Registry: r.Registry, Truncate: fd.truncate || r.Truncate} + if fd.decoder == nil { + return newDecodeError(fd.name, ErrNoDecoder{Type: field.Elem().Type()}) + } + + err = fd.decoder.DecodeValue(dctx, vr, field.Elem()) + if err != nil { + return newDecodeError(fd.name, err) + } + } + + return nil +} + +func (sc *StructCodec) isZero(i interface{}) bool { + v := reflect.ValueOf(i) + + // check the value validity + if !v.IsValid() { + return true + } + + if z, ok := v.Interface().(Zeroer); ok && (v.Kind() != reflect.Ptr || !v.IsNil()) { + return z.IsZero() + } + + switch v.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + case reflect.Struct: + if sc.EncodeOmitDefaultStruct { + vt := v.Type() + if vt == tTime { + return v.Interface().(time.Time).IsZero() + } + for i := 0; i < v.NumField(); i++ { + if vt.Field(i).PkgPath != "" && !vt.Field(i).Anonymous { + continue // Private field + } + fld := v.Field(i) + if !sc.isZero(fld.Interface()) { + return false + } + } + return true + } + } + + return false +} + +type structDescription struct { + fm map[string]fieldDescription + fl []fieldDescription + inlineMap int + inline bool +} + +type fieldDescription struct { + name string // BSON key name + fieldName string // struct field name + idx int + omitEmpty bool + minSize bool + truncate bool + inline []int + encoder ValueEncoder + decoder ValueDecoder +} + +type byIndex []fieldDescription + +func (bi byIndex) Len() int { return len(bi) } + +func (bi byIndex) Swap(i, j int) { bi[i], bi[j] = bi[j], bi[i] } + +func (bi byIndex) Less(i, j int) bool { + // If a field is inlined, its index in the top level struct is stored at inline[0] + iIdx, jIdx := bi[i].idx, bi[j].idx + if len(bi[i].inline) > 0 { + iIdx = bi[i].inline[0] + } + if len(bi[j].inline) > 0 { + jIdx = bi[j].inline[0] + } + if iIdx != jIdx { + return iIdx < jIdx + } + for k, biik := range bi[i].inline { + if k >= len(bi[j].inline) { + return false + } + if biik != bi[j].inline[k] { + return biik < bi[j].inline[k] + } + } + return len(bi[i].inline) < len(bi[j].inline) +} + +func (sc *StructCodec) describeStruct(r *Registry, t reflect.Type) (*structDescription, error) { + // We need to analyze the struct, including getting the tags, collecting + // information about inlining, and create a map of the field name to the field. + sc.l.RLock() + ds, exists := sc.cache[t] + sc.l.RUnlock() + if exists { + return ds, nil + } + + numFields := t.NumField() + sd := &structDescription{ + fm: make(map[string]fieldDescription, numFields), + fl: make([]fieldDescription, 0, numFields), + inlineMap: -1, + } + + var fields []fieldDescription + for i := 0; i < numFields; i++ { + sf := t.Field(i) + if sf.PkgPath != "" && (!sc.AllowUnexportedFields || !sf.Anonymous) { + // field is private or unexported fields aren't allowed, ignore + continue + } + + sfType := sf.Type + encoder, err := r.LookupEncoder(sfType) + if err != nil { + encoder = nil + } + decoder, err := r.LookupDecoder(sfType) + if err != nil { + decoder = nil + } + + description := fieldDescription{ + fieldName: sf.Name, + idx: i, + encoder: encoder, + decoder: decoder, + } + + stags, err := sc.parser.ParseStructTags(sf) + if err != nil { + return nil, err + } + if stags.Skip { + continue + } + description.name = stags.Name + description.omitEmpty = stags.OmitEmpty + description.minSize = stags.MinSize + description.truncate = stags.Truncate + + if stags.Inline { + sd.inline = true + switch sfType.Kind() { + case reflect.Map: + if sd.inlineMap >= 0 { + return nil, errors.New("(struct " + t.String() + ") multiple inline maps") + } + if sfType.Key() != tString { + return nil, errors.New("(struct " + t.String() + ") inline map must have a string keys") + } + sd.inlineMap = description.idx + case reflect.Ptr: + sfType = sfType.Elem() + if sfType.Kind() != reflect.Struct { + return nil, fmt.Errorf("(struct %s) inline fields must be a struct, a struct pointer, or a map", t.String()) + } + fallthrough + case reflect.Struct: + inlinesf, err := sc.describeStruct(r, sfType) + if err != nil { + return nil, err + } + for _, fd := range inlinesf.fl { + if fd.inline == nil { + fd.inline = []int{i, fd.idx} + } else { + fd.inline = append([]int{i}, fd.inline...) + } + fields = append(fields, fd) + + } + default: + return nil, fmt.Errorf("(struct %s) inline fields must be a struct, a struct pointer, or a map", t.String()) + } + continue + } + fields = append(fields, description) + } + + // Sort fieldDescriptions by name and use dominance rules to determine which should be added for each name + sort.Slice(fields, func(i, j int) bool { + x := fields + // sort field by name, breaking ties with depth, then + // breaking ties with index sequence. + if x[i].name != x[j].name { + return x[i].name < x[j].name + } + if len(x[i].inline) != len(x[j].inline) { + return len(x[i].inline) < len(x[j].inline) + } + return byIndex(x).Less(i, j) + }) + + for advance, i := 0, 0; i < len(fields); i += advance { + // One iteration per name. + // Find the sequence of fields with the name of this first field. + fi := fields[i] + name := fi.name + for advance = 1; i+advance < len(fields); advance++ { + fj := fields[i+advance] + if fj.name != name { + break + } + } + if advance == 1 { // Only one field with this name + sd.fl = append(sd.fl, fi) + sd.fm[name] = fi + continue + } + dominant, ok := dominantField(fields[i : i+advance]) + if !ok || !sc.OverwriteDuplicatedInlinedFields { + return nil, fmt.Errorf("struct %s has duplicated key %s", t.String(), name) + } + sd.fl = append(sd.fl, dominant) + sd.fm[name] = dominant + } + + sort.Sort(byIndex(sd.fl)) + + sc.l.Lock() + sc.cache[t] = sd + sc.l.Unlock() + + return sd, nil +} + +// dominantField looks through the fields, all of which are known to +// have the same name, to find the single field that dominates the +// others using Go's inlining rules. If there are multiple top-level +// fields, the boolean will be false: This condition is an error in Go +// and we skip all the fields. +func dominantField(fields []fieldDescription) (fieldDescription, bool) { + // The fields are sorted in increasing index-length order, then by presence of tag. + // That means that the first field is the dominant one. We need only check + // for error cases: two fields at top level. + if len(fields) > 1 && + len(fields[0].inline) == len(fields[1].inline) { + return fieldDescription{}, false + } + return fields[0], true +} + +func fieldByIndexErr(v reflect.Value, index []int) (result reflect.Value, err error) { + defer func() { + if recovered := recover(); recovered != nil { + switch r := recovered.(type) { + case string: + err = fmt.Errorf("%s", r) + case error: + err = r + } + } + }() + + result = v.FieldByIndex(index) + return +} + +func getInlineField(val reflect.Value, index []int) (reflect.Value, error) { + field, err := fieldByIndexErr(val, index) + if err == nil { + return field, nil + } + + // if parent of this element doesn't exist, fix its parent + inlineParent := index[:len(index)-1] + var fParent reflect.Value + if fParent, err = fieldByIndexErr(val, inlineParent); err != nil { + fParent, err = getInlineField(val, inlineParent) + if err != nil { + return fParent, err + } + } + fParent.Set(reflect.New(fParent.Type().Elem())) + + return fieldByIndexErr(val, index) +} + +// DeepZero returns recursive zero object +func deepZero(st reflect.Type) (result reflect.Value) { + result = reflect.Indirect(reflect.New(st)) + + if result.Kind() == reflect.Struct { + for i := 0; i < result.NumField(); i++ { + if f := result.Field(i); f.Kind() == reflect.Ptr { + if f.CanInterface() { + if ft := reflect.TypeOf(f.Interface()); ft.Elem().Kind() == reflect.Struct { + result.Field(i).Set(recursivePointerTo(deepZero(ft.Elem()))) + } + } + } + } + } + + return +} + +// recursivePointerTo calls reflect.New(v.Type) but recursively for its fields inside +func recursivePointerTo(v reflect.Value) reflect.Value { + v = reflect.Indirect(v) + result := reflect.New(v.Type()) + if v.Kind() == reflect.Struct { + for i := 0; i < v.NumField(); i++ { + if f := v.Field(i); f.Kind() == reflect.Ptr { + if f.Elem().Kind() == reflect.Struct { + result.Elem().Field(i).Set(recursivePointerTo(f)) + } + } + } + } + + return result +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go new file mode 100644 index 0000000..62708c5 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go @@ -0,0 +1,139 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "reflect" + "strings" +) + +// StructTagParser returns the struct tags for a given struct field. +type StructTagParser interface { + ParseStructTags(reflect.StructField) (StructTags, error) +} + +// StructTagParserFunc is an adapter that allows a generic function to be used +// as a StructTagParser. +type StructTagParserFunc func(reflect.StructField) (StructTags, error) + +// ParseStructTags implements the StructTagParser interface. +func (stpf StructTagParserFunc) ParseStructTags(sf reflect.StructField) (StructTags, error) { + return stpf(sf) +} + +// StructTags represents the struct tag fields that the StructCodec uses during +// the encoding and decoding process. +// +// In the case of a struct, the lowercased field name is used as the key for each exported +// field but this behavior may be changed using a struct tag. The tag may also contain flags to +// adjust the marshalling behavior for the field. +// +// The properties are defined below: +// +// OmitEmpty Only include the field if it's not set to the zero value for the type or to +// empty slices or maps. +// +// MinSize Marshal an integer of a type larger than 32 bits value as an int32, if that's +// feasible while preserving the numeric value. +// +// Truncate When unmarshaling a BSON double, it is permitted to lose precision to fit within +// a float32. +// +// Inline Inline the field, which must be a struct or a map, causing all of its fields +// or keys to be processed as if they were part of the outer struct. For maps, +// keys must not conflict with the bson keys of other struct fields. +// +// Skip This struct field should be skipped. This is usually denoted by parsing a "-" +// for the name. +// +// TODO(skriptble): Add tags for undefined as nil and for null as nil. +type StructTags struct { + Name string + OmitEmpty bool + MinSize bool + Truncate bool + Inline bool + Skip bool +} + +// DefaultStructTagParser is the StructTagParser used by the StructCodec by default. +// It will handle the bson struct tag. See the documentation for StructTags to see +// what each of the returned fields means. +// +// If there is no name in the struct tag fields, the struct field name is lowercased. +// The tag formats accepted are: +// +// "[][,[,]]" +// +// `(...) bson:"[][,[,]]" (...)` +// +// An example: +// +// type T struct { +// A bool +// B int "myb" +// C string "myc,omitempty" +// D string `bson:",omitempty" json:"jsonkey"` +// E int64 ",minsize" +// F int64 "myf,omitempty,minsize" +// } +// +// A struct tag either consisting entirely of '-' or with a bson key with a +// value consisting entirely of '-' will return a StructTags with Skip true and +// the remaining fields will be their default values. +var DefaultStructTagParser StructTagParserFunc = func(sf reflect.StructField) (StructTags, error) { + key := strings.ToLower(sf.Name) + tag, ok := sf.Tag.Lookup("bson") + if !ok && !strings.Contains(string(sf.Tag), ":") && len(sf.Tag) > 0 { + tag = string(sf.Tag) + } + return parseTags(key, tag) +} + +func parseTags(key string, tag string) (StructTags, error) { + var st StructTags + if tag == "-" { + st.Skip = true + return st, nil + } + + for idx, str := range strings.Split(tag, ",") { + if idx == 0 && str != "" { + key = str + } + switch str { + case "omitempty": + st.OmitEmpty = true + case "minsize": + st.MinSize = true + case "truncate": + st.Truncate = true + case "inline": + st.Inline = true + } + } + + st.Name = key + + return st, nil +} + +// JSONFallbackStructTagParser has the same behavior as DefaultStructTagParser +// but will also fallback to parsing the json tag instead on a field where the +// bson tag isn't available. +var JSONFallbackStructTagParser StructTagParserFunc = func(sf reflect.StructField) (StructTags, error) { + key := strings.ToLower(sf.Name) + tag, ok := sf.Tag.Lookup("bson") + if !ok { + tag, ok = sf.Tag.Lookup("json") + } + if !ok && !strings.Contains(string(sf.Tag), ":") && len(sf.Tag) > 0 { + tag = string(sf.Tag) + } + + return parseTags(key, tag) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go new file mode 100644 index 0000000..ec7e30f --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go @@ -0,0 +1,127 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "fmt" + "reflect" + "time" + + "go.mongodb.org/mongo-driver/bson/bsonoptions" + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/bson/bsontype" + "go.mongodb.org/mongo-driver/bson/primitive" +) + +const ( + timeFormatString = "2006-01-02T15:04:05.999Z07:00" +) + +// TimeCodec is the Codec used for time.Time values. +type TimeCodec struct { + UseLocalTimeZone bool +} + +var ( + defaultTimeCodec = NewTimeCodec() + + _ ValueCodec = defaultTimeCodec + _ typeDecoder = defaultTimeCodec +) + +// NewTimeCodec returns a TimeCodec with options opts. +func NewTimeCodec(opts ...*bsonoptions.TimeCodecOptions) *TimeCodec { + timeOpt := bsonoptions.MergeTimeCodecOptions(opts...) + + codec := TimeCodec{} + if timeOpt.UseLocalTimeZone != nil { + codec.UseLocalTimeZone = *timeOpt.UseLocalTimeZone + } + return &codec +} + +func (tc *TimeCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + if t != tTime { + return emptyValue, ValueDecoderError{ + Name: "TimeDecodeValue", + Types: []reflect.Type{tTime}, + Received: reflect.Zero(t), + } + } + + var timeVal time.Time + switch vrType := vr.Type(); vrType { + case bsontype.DateTime: + dt, err := vr.ReadDateTime() + if err != nil { + return emptyValue, err + } + timeVal = time.Unix(dt/1000, dt%1000*1000000) + case bsontype.String: + // assume strings are in the isoTimeFormat + timeStr, err := vr.ReadString() + if err != nil { + return emptyValue, err + } + timeVal, err = time.Parse(timeFormatString, timeStr) + if err != nil { + return emptyValue, err + } + case bsontype.Int64: + i64, err := vr.ReadInt64() + if err != nil { + return emptyValue, err + } + timeVal = time.Unix(i64/1000, i64%1000*1000000) + case bsontype.Timestamp: + t, _, err := vr.ReadTimestamp() + if err != nil { + return emptyValue, err + } + timeVal = time.Unix(int64(t), 0) + case bsontype.Null: + if err := vr.ReadNull(); err != nil { + return emptyValue, err + } + case bsontype.Undefined: + if err := vr.ReadUndefined(); err != nil { + return emptyValue, err + } + default: + return emptyValue, fmt.Errorf("cannot decode %v into a time.Time", vrType) + } + + if !tc.UseLocalTimeZone { + timeVal = timeVal.UTC() + } + return reflect.ValueOf(timeVal), nil +} + +// DecodeValue is the ValueDecoderFunc for time.Time. +func (tc *TimeCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() || val.Type() != tTime { + return ValueDecoderError{Name: "TimeDecodeValue", Types: []reflect.Type{tTime}, Received: val} + } + + elem, err := tc.decodeType(dc, vr, tTime) + if err != nil { + return err + } + + val.Set(elem) + return nil +} + +// EncodeValue is the ValueEncoderFunc for time.TIme. +func (tc *TimeCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + if !val.IsValid() || val.Type() != tTime { + return ValueEncoderError{Name: "TimeEncodeValue", Types: []reflect.Type{tTime}, Received: val} + } + tt := val.Interface().(time.Time) + dt := primitive.NewDateTimeFromTime(tt) + return vw.WriteDateTime(int64(dt)) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go new file mode 100644 index 0000000..07f4b70 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go @@ -0,0 +1,57 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "encoding/json" + "net/url" + "reflect" + "time" + + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +var tBool = reflect.TypeOf(false) +var tFloat64 = reflect.TypeOf(float64(0)) +var tInt32 = reflect.TypeOf(int32(0)) +var tInt64 = reflect.TypeOf(int64(0)) +var tString = reflect.TypeOf("") +var tTime = reflect.TypeOf(time.Time{}) + +var tEmpty = reflect.TypeOf((*interface{})(nil)).Elem() +var tByteSlice = reflect.TypeOf([]byte(nil)) +var tByte = reflect.TypeOf(byte(0x00)) +var tURL = reflect.TypeOf(url.URL{}) +var tJSONNumber = reflect.TypeOf(json.Number("")) + +var tValueMarshaler = reflect.TypeOf((*ValueMarshaler)(nil)).Elem() +var tValueUnmarshaler = reflect.TypeOf((*ValueUnmarshaler)(nil)).Elem() +var tMarshaler = reflect.TypeOf((*Marshaler)(nil)).Elem() +var tUnmarshaler = reflect.TypeOf((*Unmarshaler)(nil)).Elem() +var tProxy = reflect.TypeOf((*Proxy)(nil)).Elem() + +var tBinary = reflect.TypeOf(primitive.Binary{}) +var tUndefined = reflect.TypeOf(primitive.Undefined{}) +var tOID = reflect.TypeOf(primitive.ObjectID{}) +var tDateTime = reflect.TypeOf(primitive.DateTime(0)) +var tNull = reflect.TypeOf(primitive.Null{}) +var tRegex = reflect.TypeOf(primitive.Regex{}) +var tCodeWithScope = reflect.TypeOf(primitive.CodeWithScope{}) +var tDBPointer = reflect.TypeOf(primitive.DBPointer{}) +var tJavaScript = reflect.TypeOf(primitive.JavaScript("")) +var tSymbol = reflect.TypeOf(primitive.Symbol("")) +var tTimestamp = reflect.TypeOf(primitive.Timestamp{}) +var tDecimal = reflect.TypeOf(primitive.Decimal128{}) +var tMinKey = reflect.TypeOf(primitive.MinKey{}) +var tMaxKey = reflect.TypeOf(primitive.MaxKey{}) +var tD = reflect.TypeOf(primitive.D{}) +var tA = reflect.TypeOf(primitive.A{}) +var tE = reflect.TypeOf(primitive.E{}) + +var tCoreDocument = reflect.TypeOf(bsoncore.Document{}) +var tCoreArray = reflect.TypeOf(bsoncore.Array{}) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go new file mode 100644 index 0000000..0b21ce9 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go @@ -0,0 +1,173 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( + "fmt" + "math" + "reflect" + + "go.mongodb.org/mongo-driver/bson/bsonoptions" + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/bson/bsontype" +) + +// UIntCodec is the Codec used for uint values. +type UIntCodec struct { + EncodeToMinSize bool +} + +var ( + defaultUIntCodec = NewUIntCodec() + + _ ValueCodec = defaultUIntCodec + _ typeDecoder = defaultUIntCodec +) + +// NewUIntCodec returns a UIntCodec with options opts. +func NewUIntCodec(opts ...*bsonoptions.UIntCodecOptions) *UIntCodec { + uintOpt := bsonoptions.MergeUIntCodecOptions(opts...) + + codec := UIntCodec{} + if uintOpt.EncodeToMinSize != nil { + codec.EncodeToMinSize = *uintOpt.EncodeToMinSize + } + return &codec +} + +// EncodeValue is the ValueEncoder for uint types. +func (uic *UIntCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { + switch val.Kind() { + case reflect.Uint8, reflect.Uint16: + return vw.WriteInt32(int32(val.Uint())) + case reflect.Uint, reflect.Uint32, reflect.Uint64: + u64 := val.Uint() + + // If ec.MinSize or if encodeToMinSize is true for a non-uint64 value we should write val as an int32 + useMinSize := ec.MinSize || (uic.EncodeToMinSize && val.Kind() != reflect.Uint64) + + if u64 <= math.MaxInt32 && useMinSize { + return vw.WriteInt32(int32(u64)) + } + if u64 > math.MaxInt64 { + return fmt.Errorf("%d overflows int64", u64) + } + return vw.WriteInt64(int64(u64)) + } + + return ValueEncoderError{ + Name: "UintEncodeValue", + Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, + Received: val, + } +} + +func (uic *UIntCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { + var i64 int64 + var err error + switch vrType := vr.Type(); vrType { + case bsontype.Int32: + i32, err := vr.ReadInt32() + if err != nil { + return emptyValue, err + } + i64 = int64(i32) + case bsontype.Int64: + i64, err = vr.ReadInt64() + if err != nil { + return emptyValue, err + } + case bsontype.Double: + f64, err := vr.ReadDouble() + if err != nil { + return emptyValue, err + } + if !dc.Truncate && math.Floor(f64) != f64 { + return emptyValue, errCannotTruncate + } + if f64 > float64(math.MaxInt64) { + return emptyValue, fmt.Errorf("%g overflows int64", f64) + } + i64 = int64(f64) + case bsontype.Boolean: + b, err := vr.ReadBoolean() + if err != nil { + return emptyValue, err + } + if b { + i64 = 1 + } + case bsontype.Null: + if err = vr.ReadNull(); err != nil { + return emptyValue, err + } + case bsontype.Undefined: + if err = vr.ReadUndefined(); err != nil { + return emptyValue, err + } + default: + return emptyValue, fmt.Errorf("cannot decode %v into an integer type", vrType) + } + + switch t.Kind() { + case reflect.Uint8: + if i64 < 0 || i64 > math.MaxUint8 { + return emptyValue, fmt.Errorf("%d overflows uint8", i64) + } + + return reflect.ValueOf(uint8(i64)), nil + case reflect.Uint16: + if i64 < 0 || i64 > math.MaxUint16 { + return emptyValue, fmt.Errorf("%d overflows uint16", i64) + } + + return reflect.ValueOf(uint16(i64)), nil + case reflect.Uint32: + if i64 < 0 || i64 > math.MaxUint32 { + return emptyValue, fmt.Errorf("%d overflows uint32", i64) + } + + return reflect.ValueOf(uint32(i64)), nil + case reflect.Uint64: + if i64 < 0 { + return emptyValue, fmt.Errorf("%d overflows uint64", i64) + } + + return reflect.ValueOf(uint64(i64)), nil + case reflect.Uint: + if i64 < 0 || int64(uint(i64)) != i64 { // Can we fit this inside of an uint + return emptyValue, fmt.Errorf("%d overflows uint", i64) + } + + return reflect.ValueOf(uint(i64)), nil + default: + return emptyValue, ValueDecoderError{ + Name: "UintDecodeValue", + Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, + Received: reflect.Zero(t), + } + } +} + +// DecodeValue is the ValueDecoder for uint types. +func (uic *UIntCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { + if !val.CanSet() { + return ValueDecoderError{ + Name: "UintDecodeValue", + Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, + Received: val, + } + } + + elem, err := uic.decodeType(dc, vr, val.Type()) + if err != nil { + return err + } + + val.SetUint(elem.Uint()) + return nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/byte_slice_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/byte_slice_codec_options.go new file mode 100644 index 0000000..b1256a4 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/byte_slice_codec_options.go @@ -0,0 +1,38 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +// ByteSliceCodecOptions represents all possible options for byte slice encoding and decoding. +type ByteSliceCodecOptions struct { + EncodeNilAsEmpty *bool // Specifies if a nil byte slice should encode as an empty binary instead of null. Defaults to false. +} + +// ByteSliceCodec creates a new *ByteSliceCodecOptions +func ByteSliceCodec() *ByteSliceCodecOptions { + return &ByteSliceCodecOptions{} +} + +// SetEncodeNilAsEmpty specifies if a nil byte slice should encode as an empty binary instead of null. Defaults to false. +func (bs *ByteSliceCodecOptions) SetEncodeNilAsEmpty(b bool) *ByteSliceCodecOptions { + bs.EncodeNilAsEmpty = &b + return bs +} + +// MergeByteSliceCodecOptions combines the given *ByteSliceCodecOptions into a single *ByteSliceCodecOptions in a last one wins fashion. +func MergeByteSliceCodecOptions(opts ...*ByteSliceCodecOptions) *ByteSliceCodecOptions { + bs := ByteSliceCodec() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.EncodeNilAsEmpty != nil { + bs.EncodeNilAsEmpty = opt.EncodeNilAsEmpty + } + } + + return bs +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/doc.go new file mode 100644 index 0000000..c40973c --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/doc.go @@ -0,0 +1,8 @@ +// Copyright (C) MongoDB, Inc. 2022-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// Package bsonoptions defines the optional configurations for the BSON codecs. +package bsonoptions diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/empty_interface_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/empty_interface_codec_options.go new file mode 100644 index 0000000..6caaa00 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/empty_interface_codec_options.go @@ -0,0 +1,38 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +// EmptyInterfaceCodecOptions represents all possible options for interface{} encoding and decoding. +type EmptyInterfaceCodecOptions struct { + DecodeBinaryAsSlice *bool // Specifies if Old and Generic type binarys should default to []slice instead of primitive.Binary. Defaults to false. +} + +// EmptyInterfaceCodec creates a new *EmptyInterfaceCodecOptions +func EmptyInterfaceCodec() *EmptyInterfaceCodecOptions { + return &EmptyInterfaceCodecOptions{} +} + +// SetDecodeBinaryAsSlice specifies if Old and Generic type binarys should default to []slice instead of primitive.Binary. Defaults to false. +func (e *EmptyInterfaceCodecOptions) SetDecodeBinaryAsSlice(b bool) *EmptyInterfaceCodecOptions { + e.DecodeBinaryAsSlice = &b + return e +} + +// MergeEmptyInterfaceCodecOptions combines the given *EmptyInterfaceCodecOptions into a single *EmptyInterfaceCodecOptions in a last one wins fashion. +func MergeEmptyInterfaceCodecOptions(opts ...*EmptyInterfaceCodecOptions) *EmptyInterfaceCodecOptions { + e := EmptyInterfaceCodec() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.DecodeBinaryAsSlice != nil { + e.DecodeBinaryAsSlice = opt.DecodeBinaryAsSlice + } + } + + return e +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/map_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/map_codec_options.go new file mode 100644 index 0000000..7a6a880 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/map_codec_options.go @@ -0,0 +1,67 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +// MapCodecOptions represents all possible options for map encoding and decoding. +type MapCodecOptions struct { + DecodeZerosMap *bool // Specifies if the map should be zeroed before decoding into it. Defaults to false. + EncodeNilAsEmpty *bool // Specifies if a nil map should encode as an empty document instead of null. Defaults to false. + // Specifies how keys should be handled. If false, the behavior matches encoding/json, where the encoding key type must + // either be a string, an integer type, or implement bsoncodec.KeyMarshaler and the decoding key type must either be a + // string, an integer type, or implement bsoncodec.KeyUnmarshaler. If true, keys are encoded with fmt.Sprint() and the + // encoding key type must be a string, an integer type, or a float. If true, the use of Stringer will override + // TextMarshaler/TextUnmarshaler. Defaults to false. + EncodeKeysWithStringer *bool +} + +// MapCodec creates a new *MapCodecOptions +func MapCodec() *MapCodecOptions { + return &MapCodecOptions{} +} + +// SetDecodeZerosMap specifies if the map should be zeroed before decoding into it. Defaults to false. +func (t *MapCodecOptions) SetDecodeZerosMap(b bool) *MapCodecOptions { + t.DecodeZerosMap = &b + return t +} + +// SetEncodeNilAsEmpty specifies if a nil map should encode as an empty document instead of null. Defaults to false. +func (t *MapCodecOptions) SetEncodeNilAsEmpty(b bool) *MapCodecOptions { + t.EncodeNilAsEmpty = &b + return t +} + +// SetEncodeKeysWithStringer specifies how keys should be handled. If false, the behavior matches encoding/json, where the +// encoding key type must either be a string, an integer type, or implement bsoncodec.KeyMarshaler and the decoding key +// type must either be a string, an integer type, or implement bsoncodec.KeyUnmarshaler. If true, keys are encoded with +// fmt.Sprint() and the encoding key type must be a string, an integer type, or a float. If true, the use of Stringer +// will override TextMarshaler/TextUnmarshaler. Defaults to false. +func (t *MapCodecOptions) SetEncodeKeysWithStringer(b bool) *MapCodecOptions { + t.EncodeKeysWithStringer = &b + return t +} + +// MergeMapCodecOptions combines the given *MapCodecOptions into a single *MapCodecOptions in a last one wins fashion. +func MergeMapCodecOptions(opts ...*MapCodecOptions) *MapCodecOptions { + s := MapCodec() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.DecodeZerosMap != nil { + s.DecodeZerosMap = opt.DecodeZerosMap + } + if opt.EncodeNilAsEmpty != nil { + s.EncodeNilAsEmpty = opt.EncodeNilAsEmpty + } + if opt.EncodeKeysWithStringer != nil { + s.EncodeKeysWithStringer = opt.EncodeKeysWithStringer + } + } + + return s +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/slice_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/slice_codec_options.go new file mode 100644 index 0000000..ef965e4 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/slice_codec_options.go @@ -0,0 +1,38 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +// SliceCodecOptions represents all possible options for slice encoding and decoding. +type SliceCodecOptions struct { + EncodeNilAsEmpty *bool // Specifies if a nil slice should encode as an empty array instead of null. Defaults to false. +} + +// SliceCodec creates a new *SliceCodecOptions +func SliceCodec() *SliceCodecOptions { + return &SliceCodecOptions{} +} + +// SetEncodeNilAsEmpty specifies if a nil slice should encode as an empty array instead of null. Defaults to false. +func (s *SliceCodecOptions) SetEncodeNilAsEmpty(b bool) *SliceCodecOptions { + s.EncodeNilAsEmpty = &b + return s +} + +// MergeSliceCodecOptions combines the given *SliceCodecOptions into a single *SliceCodecOptions in a last one wins fashion. +func MergeSliceCodecOptions(opts ...*SliceCodecOptions) *SliceCodecOptions { + s := SliceCodec() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.EncodeNilAsEmpty != nil { + s.EncodeNilAsEmpty = opt.EncodeNilAsEmpty + } + } + + return s +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/string_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/string_codec_options.go new file mode 100644 index 0000000..65964f4 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/string_codec_options.go @@ -0,0 +1,41 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +var defaultDecodeOIDAsHex = true + +// StringCodecOptions represents all possible options for string encoding and decoding. +type StringCodecOptions struct { + DecodeObjectIDAsHex *bool // Specifies if we should decode ObjectID as the hex value. Defaults to true. +} + +// StringCodec creates a new *StringCodecOptions +func StringCodec() *StringCodecOptions { + return &StringCodecOptions{} +} + +// SetDecodeObjectIDAsHex specifies if object IDs should be decoded as their hex representation. If false, a string made +// from the raw object ID bytes will be used. Defaults to true. +func (t *StringCodecOptions) SetDecodeObjectIDAsHex(b bool) *StringCodecOptions { + t.DecodeObjectIDAsHex = &b + return t +} + +// MergeStringCodecOptions combines the given *StringCodecOptions into a single *StringCodecOptions in a last one wins fashion. +func MergeStringCodecOptions(opts ...*StringCodecOptions) *StringCodecOptions { + s := &StringCodecOptions{&defaultDecodeOIDAsHex} + for _, opt := range opts { + if opt == nil { + continue + } + if opt.DecodeObjectIDAsHex != nil { + s.DecodeObjectIDAsHex = opt.DecodeObjectIDAsHex + } + } + + return s +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/struct_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/struct_codec_options.go new file mode 100644 index 0000000..78d1dd8 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/struct_codec_options.go @@ -0,0 +1,87 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +var defaultOverwriteDuplicatedInlinedFields = true + +// StructCodecOptions represents all possible options for struct encoding and decoding. +type StructCodecOptions struct { + DecodeZeroStruct *bool // Specifies if structs should be zeroed before decoding into them. Defaults to false. + DecodeDeepZeroInline *bool // Specifies if structs should be recursively zeroed when a inline value is decoded. Defaults to false. + EncodeOmitDefaultStruct *bool // Specifies if default structs should be considered empty by omitempty. Defaults to false. + AllowUnexportedFields *bool // Specifies if unexported fields should be marshaled/unmarshaled. Defaults to false. + OverwriteDuplicatedInlinedFields *bool // Specifies if fields in inlined structs can be overwritten by higher level struct fields with the same key. Defaults to true. +} + +// StructCodec creates a new *StructCodecOptions +func StructCodec() *StructCodecOptions { + return &StructCodecOptions{} +} + +// SetDecodeZeroStruct specifies if structs should be zeroed before decoding into them. Defaults to false. +func (t *StructCodecOptions) SetDecodeZeroStruct(b bool) *StructCodecOptions { + t.DecodeZeroStruct = &b + return t +} + +// SetDecodeDeepZeroInline specifies if structs should be zeroed before decoding into them. Defaults to false. +func (t *StructCodecOptions) SetDecodeDeepZeroInline(b bool) *StructCodecOptions { + t.DecodeDeepZeroInline = &b + return t +} + +// SetEncodeOmitDefaultStruct specifies if default structs should be considered empty by omitempty. A default struct has all +// its values set to their default value. Defaults to false. +func (t *StructCodecOptions) SetEncodeOmitDefaultStruct(b bool) *StructCodecOptions { + t.EncodeOmitDefaultStruct = &b + return t +} + +// SetOverwriteDuplicatedInlinedFields specifies if inlined struct fields can be overwritten by higher level struct fields with the +// same bson key. When true and decoding, values will be written to the outermost struct with a matching key, and when +// encoding, keys will have the value of the top-most matching field. When false, decoding and encoding will error if +// there are duplicate keys after the struct is inlined. Defaults to true. +func (t *StructCodecOptions) SetOverwriteDuplicatedInlinedFields(b bool) *StructCodecOptions { + t.OverwriteDuplicatedInlinedFields = &b + return t +} + +// SetAllowUnexportedFields specifies if unexported fields should be marshaled/unmarshaled. Defaults to false. +func (t *StructCodecOptions) SetAllowUnexportedFields(b bool) *StructCodecOptions { + t.AllowUnexportedFields = &b + return t +} + +// MergeStructCodecOptions combines the given *StructCodecOptions into a single *StructCodecOptions in a last one wins fashion. +func MergeStructCodecOptions(opts ...*StructCodecOptions) *StructCodecOptions { + s := &StructCodecOptions{ + OverwriteDuplicatedInlinedFields: &defaultOverwriteDuplicatedInlinedFields, + } + for _, opt := range opts { + if opt == nil { + continue + } + + if opt.DecodeZeroStruct != nil { + s.DecodeZeroStruct = opt.DecodeZeroStruct + } + if opt.DecodeDeepZeroInline != nil { + s.DecodeDeepZeroInline = opt.DecodeDeepZeroInline + } + if opt.EncodeOmitDefaultStruct != nil { + s.EncodeOmitDefaultStruct = opt.EncodeOmitDefaultStruct + } + if opt.OverwriteDuplicatedInlinedFields != nil { + s.OverwriteDuplicatedInlinedFields = opt.OverwriteDuplicatedInlinedFields + } + if opt.AllowUnexportedFields != nil { + s.AllowUnexportedFields = opt.AllowUnexportedFields + } + } + + return s +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/time_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/time_codec_options.go new file mode 100644 index 0000000..13496d1 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/time_codec_options.go @@ -0,0 +1,38 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +// TimeCodecOptions represents all possible options for time.Time encoding and decoding. +type TimeCodecOptions struct { + UseLocalTimeZone *bool // Specifies if we should decode into the local time zone. Defaults to false. +} + +// TimeCodec creates a new *TimeCodecOptions +func TimeCodec() *TimeCodecOptions { + return &TimeCodecOptions{} +} + +// SetUseLocalTimeZone specifies if we should decode into the local time zone. Defaults to false. +func (t *TimeCodecOptions) SetUseLocalTimeZone(b bool) *TimeCodecOptions { + t.UseLocalTimeZone = &b + return t +} + +// MergeTimeCodecOptions combines the given *TimeCodecOptions into a single *TimeCodecOptions in a last one wins fashion. +func MergeTimeCodecOptions(opts ...*TimeCodecOptions) *TimeCodecOptions { + t := TimeCodec() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.UseLocalTimeZone != nil { + t.UseLocalTimeZone = opt.UseLocalTimeZone + } + } + + return t +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/uint_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/uint_codec_options.go new file mode 100644 index 0000000..e08b7f1 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/uint_codec_options.go @@ -0,0 +1,38 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +// UIntCodecOptions represents all possible options for uint encoding and decoding. +type UIntCodecOptions struct { + EncodeToMinSize *bool // Specifies if all uints except uint64 should be decoded to minimum size bsontype. Defaults to false. +} + +// UIntCodec creates a new *UIntCodecOptions +func UIntCodec() *UIntCodecOptions { + return &UIntCodecOptions{} +} + +// SetEncodeToMinSize specifies if all uints except uint64 should be decoded to minimum size bsontype. Defaults to false. +func (u *UIntCodecOptions) SetEncodeToMinSize(b bool) *UIntCodecOptions { + u.EncodeToMinSize = &b + return u +} + +// MergeUIntCodecOptions combines the given *UIntCodecOptions into a single *UIntCodecOptions in a last one wins fashion. +func MergeUIntCodecOptions(opts ...*UIntCodecOptions) *UIntCodecOptions { + u := UIntCodec() + for _, opt := range opts { + if opt == nil { + continue + } + if opt.EncodeToMinSize != nil { + u.EncodeToMinSize = opt.EncodeToMinSize + } + } + + return u +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go new file mode 100644 index 0000000..5cdf646 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go @@ -0,0 +1,445 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonrw + +import ( + "fmt" + "io" + + "go.mongodb.org/mongo-driver/bson/bsontype" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +// Copier is a type that allows copying between ValueReaders, ValueWriters, and +// []byte values. +type Copier struct{} + +// NewCopier creates a new copier with the given registry. If a nil registry is provided +// a default registry is used. +func NewCopier() Copier { + return Copier{} +} + +// CopyDocument handles copying a document from src to dst. +func CopyDocument(dst ValueWriter, src ValueReader) error { + return Copier{}.CopyDocument(dst, src) +} + +// CopyDocument handles copying one document from the src to the dst. +func (c Copier) CopyDocument(dst ValueWriter, src ValueReader) error { + dr, err := src.ReadDocument() + if err != nil { + return err + } + + dw, err := dst.WriteDocument() + if err != nil { + return err + } + + return c.copyDocumentCore(dw, dr) +} + +// CopyArrayFromBytes copies the values from a BSON array represented as a +// []byte to a ValueWriter. +func (c Copier) CopyArrayFromBytes(dst ValueWriter, src []byte) error { + aw, err := dst.WriteArray() + if err != nil { + return err + } + + err = c.CopyBytesToArrayWriter(aw, src) + if err != nil { + return err + } + + return aw.WriteArrayEnd() +} + +// CopyDocumentFromBytes copies the values from a BSON document represented as a +// []byte to a ValueWriter. +func (c Copier) CopyDocumentFromBytes(dst ValueWriter, src []byte) error { + dw, err := dst.WriteDocument() + if err != nil { + return err + } + + err = c.CopyBytesToDocumentWriter(dw, src) + if err != nil { + return err + } + + return dw.WriteDocumentEnd() +} + +type writeElementFn func(key string) (ValueWriter, error) + +// CopyBytesToArrayWriter copies the values from a BSON Array represented as a []byte to an +// ArrayWriter. +func (c Copier) CopyBytesToArrayWriter(dst ArrayWriter, src []byte) error { + wef := func(_ string) (ValueWriter, error) { + return dst.WriteArrayElement() + } + + return c.copyBytesToValueWriter(src, wef) +} + +// CopyBytesToDocumentWriter copies the values from a BSON document represented as a []byte to a +// DocumentWriter. +func (c Copier) CopyBytesToDocumentWriter(dst DocumentWriter, src []byte) error { + wef := func(key string) (ValueWriter, error) { + return dst.WriteDocumentElement(key) + } + + return c.copyBytesToValueWriter(src, wef) +} + +func (c Copier) copyBytesToValueWriter(src []byte, wef writeElementFn) error { + // TODO(skriptble): Create errors types here. Anything thats a tag should be a property. + length, rem, ok := bsoncore.ReadLength(src) + if !ok { + return fmt.Errorf("couldn't read length from src, not enough bytes. length=%d", len(src)) + } + if len(src) < int(length) { + return fmt.Errorf("length read exceeds number of bytes available. length=%d bytes=%d", len(src), length) + } + rem = rem[:length-4] + + var t bsontype.Type + var key string + var val bsoncore.Value + for { + t, rem, ok = bsoncore.ReadType(rem) + if !ok { + return io.EOF + } + if t == bsontype.Type(0) { + if len(rem) != 0 { + return fmt.Errorf("document end byte found before end of document. remaining bytes=%v", rem) + } + break + } + + key, rem, ok = bsoncore.ReadKey(rem) + if !ok { + return fmt.Errorf("invalid key found. remaining bytes=%v", rem) + } + + // write as either array element or document element using writeElementFn + vw, err := wef(key) + if err != nil { + return err + } + + val, rem, ok = bsoncore.ReadValue(rem, t) + if !ok { + return fmt.Errorf("not enough bytes available to read type. bytes=%d type=%s", len(rem), t) + } + err = c.CopyValueFromBytes(vw, t, val.Data) + if err != nil { + return err + } + } + return nil +} + +// CopyDocumentToBytes copies an entire document from the ValueReader and +// returns it as bytes. +func (c Copier) CopyDocumentToBytes(src ValueReader) ([]byte, error) { + return c.AppendDocumentBytes(nil, src) +} + +// AppendDocumentBytes functions the same as CopyDocumentToBytes, but will +// append the result to dst. +func (c Copier) AppendDocumentBytes(dst []byte, src ValueReader) ([]byte, error) { + if br, ok := src.(BytesReader); ok { + _, dst, err := br.ReadValueBytes(dst) + return dst, err + } + + vw := vwPool.Get().(*valueWriter) + defer vwPool.Put(vw) + + vw.reset(dst) + + err := c.CopyDocument(vw, src) + dst = vw.buf + return dst, err +} + +// AppendArrayBytes copies an array from the ValueReader to dst. +func (c Copier) AppendArrayBytes(dst []byte, src ValueReader) ([]byte, error) { + if br, ok := src.(BytesReader); ok { + _, dst, err := br.ReadValueBytes(dst) + return dst, err + } + + vw := vwPool.Get().(*valueWriter) + defer vwPool.Put(vw) + + vw.reset(dst) + + err := c.copyArray(vw, src) + dst = vw.buf + return dst, err +} + +// CopyValueFromBytes will write the value represtend by t and src to dst. +func (c Copier) CopyValueFromBytes(dst ValueWriter, t bsontype.Type, src []byte) error { + if wvb, ok := dst.(BytesWriter); ok { + return wvb.WriteValueBytes(t, src) + } + + vr := vrPool.Get().(*valueReader) + defer vrPool.Put(vr) + + vr.reset(src) + vr.pushElement(t) + + return c.CopyValue(dst, vr) +} + +// CopyValueToBytes copies a value from src and returns it as a bsontype.Type and a +// []byte. +func (c Copier) CopyValueToBytes(src ValueReader) (bsontype.Type, []byte, error) { + return c.AppendValueBytes(nil, src) +} + +// AppendValueBytes functions the same as CopyValueToBytes, but will append the +// result to dst. +func (c Copier) AppendValueBytes(dst []byte, src ValueReader) (bsontype.Type, []byte, error) { + if br, ok := src.(BytesReader); ok { + return br.ReadValueBytes(dst) + } + + vw := vwPool.Get().(*valueWriter) + defer vwPool.Put(vw) + + start := len(dst) + + vw.reset(dst) + vw.push(mElement) + + err := c.CopyValue(vw, src) + if err != nil { + return 0, dst, err + } + + return bsontype.Type(vw.buf[start]), vw.buf[start+2:], nil +} + +// CopyValue will copy a single value from src to dst. +func (c Copier) CopyValue(dst ValueWriter, src ValueReader) error { + var err error + switch src.Type() { + case bsontype.Double: + var f64 float64 + f64, err = src.ReadDouble() + if err != nil { + break + } + err = dst.WriteDouble(f64) + case bsontype.String: + var str string + str, err = src.ReadString() + if err != nil { + return err + } + err = dst.WriteString(str) + case bsontype.EmbeddedDocument: + err = c.CopyDocument(dst, src) + case bsontype.Array: + err = c.copyArray(dst, src) + case bsontype.Binary: + var data []byte + var subtype byte + data, subtype, err = src.ReadBinary() + if err != nil { + break + } + err = dst.WriteBinaryWithSubtype(data, subtype) + case bsontype.Undefined: + err = src.ReadUndefined() + if err != nil { + break + } + err = dst.WriteUndefined() + case bsontype.ObjectID: + var oid primitive.ObjectID + oid, err = src.ReadObjectID() + if err != nil { + break + } + err = dst.WriteObjectID(oid) + case bsontype.Boolean: + var b bool + b, err = src.ReadBoolean() + if err != nil { + break + } + err = dst.WriteBoolean(b) + case bsontype.DateTime: + var dt int64 + dt, err = src.ReadDateTime() + if err != nil { + break + } + err = dst.WriteDateTime(dt) + case bsontype.Null: + err = src.ReadNull() + if err != nil { + break + } + err = dst.WriteNull() + case bsontype.Regex: + var pattern, options string + pattern, options, err = src.ReadRegex() + if err != nil { + break + } + err = dst.WriteRegex(pattern, options) + case bsontype.DBPointer: + var ns string + var pointer primitive.ObjectID + ns, pointer, err = src.ReadDBPointer() + if err != nil { + break + } + err = dst.WriteDBPointer(ns, pointer) + case bsontype.JavaScript: + var js string + js, err = src.ReadJavascript() + if err != nil { + break + } + err = dst.WriteJavascript(js) + case bsontype.Symbol: + var symbol string + symbol, err = src.ReadSymbol() + if err != nil { + break + } + err = dst.WriteSymbol(symbol) + case bsontype.CodeWithScope: + var code string + var srcScope DocumentReader + code, srcScope, err = src.ReadCodeWithScope() + if err != nil { + break + } + + var dstScope DocumentWriter + dstScope, err = dst.WriteCodeWithScope(code) + if err != nil { + break + } + err = c.copyDocumentCore(dstScope, srcScope) + case bsontype.Int32: + var i32 int32 + i32, err = src.ReadInt32() + if err != nil { + break + } + err = dst.WriteInt32(i32) + case bsontype.Timestamp: + var t, i uint32 + t, i, err = src.ReadTimestamp() + if err != nil { + break + } + err = dst.WriteTimestamp(t, i) + case bsontype.Int64: + var i64 int64 + i64, err = src.ReadInt64() + if err != nil { + break + } + err = dst.WriteInt64(i64) + case bsontype.Decimal128: + var d128 primitive.Decimal128 + d128, err = src.ReadDecimal128() + if err != nil { + break + } + err = dst.WriteDecimal128(d128) + case bsontype.MinKey: + err = src.ReadMinKey() + if err != nil { + break + } + err = dst.WriteMinKey() + case bsontype.MaxKey: + err = src.ReadMaxKey() + if err != nil { + break + } + err = dst.WriteMaxKey() + default: + err = fmt.Errorf("Cannot copy unknown BSON type %s", src.Type()) + } + + return err +} + +func (c Copier) copyArray(dst ValueWriter, src ValueReader) error { + ar, err := src.ReadArray() + if err != nil { + return err + } + + aw, err := dst.WriteArray() + if err != nil { + return err + } + + for { + vr, err := ar.ReadValue() + if err == ErrEOA { + break + } + if err != nil { + return err + } + + vw, err := aw.WriteArrayElement() + if err != nil { + return err + } + + err = c.CopyValue(vw, vr) + if err != nil { + return err + } + } + + return aw.WriteArrayEnd() +} + +func (c Copier) copyDocumentCore(dw DocumentWriter, dr DocumentReader) error { + for { + key, vr, err := dr.ReadElement() + if err == ErrEOD { + break + } + if err != nil { + return err + } + + vw, err := dw.WriteDocumentElement(key) + if err != nil { + return err + } + + err = c.CopyValue(vw, vr) + if err != nil { + return err + } + } + + return dw.WriteDocumentEnd() +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/doc.go new file mode 100644 index 0000000..750b0d2 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/doc.go @@ -0,0 +1,9 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// Package bsonrw contains abstractions for reading and writing +// BSON and BSON like types from sources. +package bsonrw // import "go.mongodb.org/mongo-driver/bson/bsonrw" diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go new file mode 100644 index 0000000..54c76bf --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go @@ -0,0 +1,806 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonrw + +import ( + "encoding/base64" + "encoding/hex" + "errors" + "fmt" + "io" + "strings" + + "go.mongodb.org/mongo-driver/bson/bsontype" +) + +const maxNestingDepth = 200 + +// ErrInvalidJSON indicates the JSON input is invalid +var ErrInvalidJSON = errors.New("invalid JSON input") + +type jsonParseState byte + +const ( + jpsStartState jsonParseState = iota + jpsSawBeginObject + jpsSawEndObject + jpsSawBeginArray + jpsSawEndArray + jpsSawColon + jpsSawComma + jpsSawKey + jpsSawValue + jpsDoneState + jpsInvalidState +) + +type jsonParseMode byte + +const ( + jpmInvalidMode jsonParseMode = iota + jpmObjectMode + jpmArrayMode +) + +type extJSONValue struct { + t bsontype.Type + v interface{} +} + +type extJSONObject struct { + keys []string + values []*extJSONValue +} + +type extJSONParser struct { + js *jsonScanner + s jsonParseState + m []jsonParseMode + k string + v *extJSONValue + + err error + canonical bool + depth int + maxDepth int + + emptyObject bool + relaxedUUID bool +} + +// newExtJSONParser returns a new extended JSON parser, ready to to begin +// parsing from the first character of the argued json input. It will not +// perform any read-ahead and will therefore not report any errors about +// malformed JSON at this point. +func newExtJSONParser(r io.Reader, canonical bool) *extJSONParser { + return &extJSONParser{ + js: &jsonScanner{r: r}, + s: jpsStartState, + m: []jsonParseMode{}, + canonical: canonical, + maxDepth: maxNestingDepth, + } +} + +// peekType examines the next value and returns its BSON Type +func (ejp *extJSONParser) peekType() (bsontype.Type, error) { + var t bsontype.Type + var err error + initialState := ejp.s + + ejp.advanceState() + switch ejp.s { + case jpsSawValue: + t = ejp.v.t + case jpsSawBeginArray: + t = bsontype.Array + case jpsInvalidState: + err = ejp.err + case jpsSawComma: + // in array mode, seeing a comma means we need to progress again to actually observe a type + if ejp.peekMode() == jpmArrayMode { + return ejp.peekType() + } + case jpsSawEndArray: + // this would only be a valid state if we were in array mode, so return end-of-array error + err = ErrEOA + case jpsSawBeginObject: + // peek key to determine type + ejp.advanceState() + switch ejp.s { + case jpsSawEndObject: // empty embedded document + t = bsontype.EmbeddedDocument + ejp.emptyObject = true + case jpsInvalidState: + err = ejp.err + case jpsSawKey: + if initialState == jpsStartState { + return bsontype.EmbeddedDocument, nil + } + t = wrapperKeyBSONType(ejp.k) + + // if $uuid is encountered, parse as binary subtype 4 + if ejp.k == "$uuid" { + ejp.relaxedUUID = true + t = bsontype.Binary + } + + switch t { + case bsontype.JavaScript: + // just saw $code, need to check for $scope at same level + _, err = ejp.readValue(bsontype.JavaScript) + if err != nil { + break + } + + switch ejp.s { + case jpsSawEndObject: // type is TypeJavaScript + case jpsSawComma: + ejp.advanceState() + + if ejp.s == jpsSawKey && ejp.k == "$scope" { + t = bsontype.CodeWithScope + } else { + err = fmt.Errorf("invalid extended JSON: unexpected key %s in CodeWithScope object", ejp.k) + } + case jpsInvalidState: + err = ejp.err + default: + err = ErrInvalidJSON + } + case bsontype.CodeWithScope: + err = errors.New("invalid extended JSON: code with $scope must contain $code before $scope") + } + } + } + + return t, err +} + +// readKey parses the next key and its type and returns them +func (ejp *extJSONParser) readKey() (string, bsontype.Type, error) { + if ejp.emptyObject { + ejp.emptyObject = false + return "", 0, ErrEOD + } + + // advance to key (or return with error) + switch ejp.s { + case jpsStartState: + ejp.advanceState() + if ejp.s == jpsSawBeginObject { + ejp.advanceState() + } + case jpsSawBeginObject: + ejp.advanceState() + case jpsSawValue, jpsSawEndObject, jpsSawEndArray: + ejp.advanceState() + switch ejp.s { + case jpsSawBeginObject, jpsSawComma: + ejp.advanceState() + case jpsSawEndObject: + return "", 0, ErrEOD + case jpsDoneState: + return "", 0, io.EOF + case jpsInvalidState: + return "", 0, ejp.err + default: + return "", 0, ErrInvalidJSON + } + case jpsSawKey: // do nothing (key was peeked before) + default: + return "", 0, invalidRequestError("key") + } + + // read key + var key string + + switch ejp.s { + case jpsSawKey: + key = ejp.k + case jpsSawEndObject: + return "", 0, ErrEOD + case jpsInvalidState: + return "", 0, ejp.err + default: + return "", 0, invalidRequestError("key") + } + + // check for colon + ejp.advanceState() + if err := ensureColon(ejp.s, key); err != nil { + return "", 0, err + } + + // peek at the value to determine type + t, err := ejp.peekType() + if err != nil { + return "", 0, err + } + + return key, t, nil +} + +// readValue returns the value corresponding to the Type returned by peekType +func (ejp *extJSONParser) readValue(t bsontype.Type) (*extJSONValue, error) { + if ejp.s == jpsInvalidState { + return nil, ejp.err + } + + var v *extJSONValue + + switch t { + case bsontype.Null, bsontype.Boolean, bsontype.String: + if ejp.s != jpsSawValue { + return nil, invalidRequestError(t.String()) + } + v = ejp.v + case bsontype.Int32, bsontype.Int64, bsontype.Double: + // relaxed version allows these to be literal number values + if ejp.s == jpsSawValue { + v = ejp.v + break + } + fallthrough + case bsontype.Decimal128, bsontype.Symbol, bsontype.ObjectID, bsontype.MinKey, bsontype.MaxKey, bsontype.Undefined: + switch ejp.s { + case jpsSawKey: + // read colon + ejp.advanceState() + if err := ensureColon(ejp.s, ejp.k); err != nil { + return nil, err + } + + // read value + ejp.advanceState() + if ejp.s != jpsSawValue || !ejp.ensureExtValueType(t) { + return nil, invalidJSONErrorForType("value", t) + } + + v = ejp.v + + // read end object + ejp.advanceState() + if ejp.s != jpsSawEndObject { + return nil, invalidJSONErrorForType("} after value", t) + } + default: + return nil, invalidRequestError(t.String()) + } + case bsontype.Binary, bsontype.Regex, bsontype.Timestamp, bsontype.DBPointer: + if ejp.s != jpsSawKey { + return nil, invalidRequestError(t.String()) + } + // read colon + ejp.advanceState() + if err := ensureColon(ejp.s, ejp.k); err != nil { + return nil, err + } + + ejp.advanceState() + if t == bsontype.Binary && ejp.s == jpsSawValue { + // convert relaxed $uuid format + if ejp.relaxedUUID { + defer func() { ejp.relaxedUUID = false }() + uuid, err := ejp.v.parseSymbol() + if err != nil { + return nil, err + } + + // RFC 4122 defines the length of a UUID as 36 and the hyphens in a UUID as appearing + // in the 8th, 13th, 18th, and 23rd characters. + // + // See https://tools.ietf.org/html/rfc4122#section-3 + valid := len(uuid) == 36 && + string(uuid[8]) == "-" && + string(uuid[13]) == "-" && + string(uuid[18]) == "-" && + string(uuid[23]) == "-" + if !valid { + return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding length and hyphens") + } + + // remove hyphens + uuidNoHyphens := strings.Replace(uuid, "-", "", -1) + if len(uuidNoHyphens) != 32 { + return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding length and hyphens") + } + + // convert hex to bytes + bytes, err := hex.DecodeString(uuidNoHyphens) + if err != nil { + return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding hex bytes: %v", err) + } + + ejp.advanceState() + if ejp.s != jpsSawEndObject { + return nil, invalidJSONErrorForType("$uuid and value and then }", bsontype.Binary) + } + + base64 := &extJSONValue{ + t: bsontype.String, + v: base64.StdEncoding.EncodeToString(bytes), + } + subType := &extJSONValue{ + t: bsontype.String, + v: "04", + } + + v = &extJSONValue{ + t: bsontype.EmbeddedDocument, + v: &extJSONObject{ + keys: []string{"base64", "subType"}, + values: []*extJSONValue{base64, subType}, + }, + } + + break + } + + // convert legacy $binary format + base64 := ejp.v + + ejp.advanceState() + if ejp.s != jpsSawComma { + return nil, invalidJSONErrorForType(",", bsontype.Binary) + } + + ejp.advanceState() + key, t, err := ejp.readKey() + if err != nil { + return nil, err + } + if key != "$type" { + return nil, invalidJSONErrorForType("$type", bsontype.Binary) + } + + subType, err := ejp.readValue(t) + if err != nil { + return nil, err + } + + ejp.advanceState() + if ejp.s != jpsSawEndObject { + return nil, invalidJSONErrorForType("2 key-value pairs and then }", bsontype.Binary) + } + + v = &extJSONValue{ + t: bsontype.EmbeddedDocument, + v: &extJSONObject{ + keys: []string{"base64", "subType"}, + values: []*extJSONValue{base64, subType}, + }, + } + break + } + + // read KV pairs + if ejp.s != jpsSawBeginObject { + return nil, invalidJSONErrorForType("{", t) + } + + keys, vals, err := ejp.readObject(2, true) + if err != nil { + return nil, err + } + + ejp.advanceState() + if ejp.s != jpsSawEndObject { + return nil, invalidJSONErrorForType("2 key-value pairs and then }", t) + } + + v = &extJSONValue{t: bsontype.EmbeddedDocument, v: &extJSONObject{keys: keys, values: vals}} + + case bsontype.DateTime: + switch ejp.s { + case jpsSawValue: + v = ejp.v + case jpsSawKey: + // read colon + ejp.advanceState() + if err := ensureColon(ejp.s, ejp.k); err != nil { + return nil, err + } + + ejp.advanceState() + switch ejp.s { + case jpsSawBeginObject: + keys, vals, err := ejp.readObject(1, true) + if err != nil { + return nil, err + } + v = &extJSONValue{t: bsontype.EmbeddedDocument, v: &extJSONObject{keys: keys, values: vals}} + case jpsSawValue: + if ejp.canonical { + return nil, invalidJSONError("{") + } + v = ejp.v + default: + if ejp.canonical { + return nil, invalidJSONErrorForType("object", t) + } + return nil, invalidJSONErrorForType("ISO-8601 Internet Date/Time Format as described in RFC-3339", t) + } + + ejp.advanceState() + if ejp.s != jpsSawEndObject { + return nil, invalidJSONErrorForType("value and then }", t) + } + default: + return nil, invalidRequestError(t.String()) + } + case bsontype.JavaScript: + switch ejp.s { + case jpsSawKey: + // read colon + ejp.advanceState() + if err := ensureColon(ejp.s, ejp.k); err != nil { + return nil, err + } + + // read value + ejp.advanceState() + if ejp.s != jpsSawValue { + return nil, invalidJSONErrorForType("value", t) + } + v = ejp.v + + // read end object or comma and just return + ejp.advanceState() + case jpsSawEndObject: + v = ejp.v + default: + return nil, invalidRequestError(t.String()) + } + case bsontype.CodeWithScope: + if ejp.s == jpsSawKey && ejp.k == "$scope" { + v = ejp.v // this is the $code string from earlier + + // read colon + ejp.advanceState() + if err := ensureColon(ejp.s, ejp.k); err != nil { + return nil, err + } + + // read { + ejp.advanceState() + if ejp.s != jpsSawBeginObject { + return nil, invalidJSONError("$scope to be embedded document") + } + } else { + return nil, invalidRequestError(t.String()) + } + case bsontype.EmbeddedDocument, bsontype.Array: + return nil, invalidRequestError(t.String()) + } + + return v, nil +} + +// readObject is a utility method for reading full objects of known (or expected) size +// it is useful for extended JSON types such as binary, datetime, regex, and timestamp +func (ejp *extJSONParser) readObject(numKeys int, started bool) ([]string, []*extJSONValue, error) { + keys := make([]string, numKeys) + vals := make([]*extJSONValue, numKeys) + + if !started { + ejp.advanceState() + if ejp.s != jpsSawBeginObject { + return nil, nil, invalidJSONError("{") + } + } + + for i := 0; i < numKeys; i++ { + key, t, err := ejp.readKey() + if err != nil { + return nil, nil, err + } + + switch ejp.s { + case jpsSawKey: + v, err := ejp.readValue(t) + if err != nil { + return nil, nil, err + } + + keys[i] = key + vals[i] = v + case jpsSawValue: + keys[i] = key + vals[i] = ejp.v + default: + return nil, nil, invalidJSONError("value") + } + } + + ejp.advanceState() + if ejp.s != jpsSawEndObject { + return nil, nil, invalidJSONError("}") + } + + return keys, vals, nil +} + +// advanceState reads the next JSON token from the scanner and transitions +// from the current state based on that token's type +func (ejp *extJSONParser) advanceState() { + if ejp.s == jpsDoneState || ejp.s == jpsInvalidState { + return + } + + jt, err := ejp.js.nextToken() + + if err != nil { + ejp.err = err + ejp.s = jpsInvalidState + return + } + + valid := ejp.validateToken(jt.t) + if !valid { + ejp.err = unexpectedTokenError(jt) + ejp.s = jpsInvalidState + return + } + + switch jt.t { + case jttBeginObject: + ejp.s = jpsSawBeginObject + ejp.pushMode(jpmObjectMode) + ejp.depth++ + + if ejp.depth > ejp.maxDepth { + ejp.err = nestingDepthError(jt.p, ejp.depth) + ejp.s = jpsInvalidState + } + case jttEndObject: + ejp.s = jpsSawEndObject + ejp.depth-- + + if ejp.popMode() != jpmObjectMode { + ejp.err = unexpectedTokenError(jt) + ejp.s = jpsInvalidState + } + case jttBeginArray: + ejp.s = jpsSawBeginArray + ejp.pushMode(jpmArrayMode) + case jttEndArray: + ejp.s = jpsSawEndArray + + if ejp.popMode() != jpmArrayMode { + ejp.err = unexpectedTokenError(jt) + ejp.s = jpsInvalidState + } + case jttColon: + ejp.s = jpsSawColon + case jttComma: + ejp.s = jpsSawComma + case jttEOF: + ejp.s = jpsDoneState + if len(ejp.m) != 0 { + ejp.err = unexpectedTokenError(jt) + ejp.s = jpsInvalidState + } + case jttString: + switch ejp.s { + case jpsSawComma: + if ejp.peekMode() == jpmArrayMode { + ejp.s = jpsSawValue + ejp.v = extendJSONToken(jt) + return + } + fallthrough + case jpsSawBeginObject: + ejp.s = jpsSawKey + ejp.k = jt.v.(string) + return + } + fallthrough + default: + ejp.s = jpsSawValue + ejp.v = extendJSONToken(jt) + } +} + +var jpsValidTransitionTokens = map[jsonParseState]map[jsonTokenType]bool{ + jpsStartState: { + jttBeginObject: true, + jttBeginArray: true, + jttInt32: true, + jttInt64: true, + jttDouble: true, + jttString: true, + jttBool: true, + jttNull: true, + jttEOF: true, + }, + jpsSawBeginObject: { + jttEndObject: true, + jttString: true, + }, + jpsSawEndObject: { + jttEndObject: true, + jttEndArray: true, + jttComma: true, + jttEOF: true, + }, + jpsSawBeginArray: { + jttBeginObject: true, + jttBeginArray: true, + jttEndArray: true, + jttInt32: true, + jttInt64: true, + jttDouble: true, + jttString: true, + jttBool: true, + jttNull: true, + }, + jpsSawEndArray: { + jttEndObject: true, + jttEndArray: true, + jttComma: true, + jttEOF: true, + }, + jpsSawColon: { + jttBeginObject: true, + jttBeginArray: true, + jttInt32: true, + jttInt64: true, + jttDouble: true, + jttString: true, + jttBool: true, + jttNull: true, + }, + jpsSawComma: { + jttBeginObject: true, + jttBeginArray: true, + jttInt32: true, + jttInt64: true, + jttDouble: true, + jttString: true, + jttBool: true, + jttNull: true, + }, + jpsSawKey: { + jttColon: true, + }, + jpsSawValue: { + jttEndObject: true, + jttEndArray: true, + jttComma: true, + jttEOF: true, + }, + jpsDoneState: {}, + jpsInvalidState: {}, +} + +func (ejp *extJSONParser) validateToken(jtt jsonTokenType) bool { + switch ejp.s { + case jpsSawEndObject: + // if we are at depth zero and the next token is a '{', + // we can consider it valid only if we are not in array mode. + if jtt == jttBeginObject && ejp.depth == 0 { + return ejp.peekMode() != jpmArrayMode + } + case jpsSawComma: + switch ejp.peekMode() { + // the only valid next token after a comma inside a document is a string (a key) + case jpmObjectMode: + return jtt == jttString + case jpmInvalidMode: + return false + } + } + + _, ok := jpsValidTransitionTokens[ejp.s][jtt] + return ok +} + +// ensureExtValueType returns true if the current value has the expected +// value type for single-key extended JSON types. For example, +// {"$numberInt": v} v must be TypeString +func (ejp *extJSONParser) ensureExtValueType(t bsontype.Type) bool { + switch t { + case bsontype.MinKey, bsontype.MaxKey: + return ejp.v.t == bsontype.Int32 + case bsontype.Undefined: + return ejp.v.t == bsontype.Boolean + case bsontype.Int32, bsontype.Int64, bsontype.Double, bsontype.Decimal128, bsontype.Symbol, bsontype.ObjectID: + return ejp.v.t == bsontype.String + default: + return false + } +} + +func (ejp *extJSONParser) pushMode(m jsonParseMode) { + ejp.m = append(ejp.m, m) +} + +func (ejp *extJSONParser) popMode() jsonParseMode { + l := len(ejp.m) + if l == 0 { + return jpmInvalidMode + } + + m := ejp.m[l-1] + ejp.m = ejp.m[:l-1] + + return m +} + +func (ejp *extJSONParser) peekMode() jsonParseMode { + l := len(ejp.m) + if l == 0 { + return jpmInvalidMode + } + + return ejp.m[l-1] +} + +func extendJSONToken(jt *jsonToken) *extJSONValue { + var t bsontype.Type + + switch jt.t { + case jttInt32: + t = bsontype.Int32 + case jttInt64: + t = bsontype.Int64 + case jttDouble: + t = bsontype.Double + case jttString: + t = bsontype.String + case jttBool: + t = bsontype.Boolean + case jttNull: + t = bsontype.Null + default: + return nil + } + + return &extJSONValue{t: t, v: jt.v} +} + +func ensureColon(s jsonParseState, key string) error { + if s != jpsSawColon { + return fmt.Errorf("invalid JSON input: missing colon after key \"%s\"", key) + } + + return nil +} + +func invalidRequestError(s string) error { + return fmt.Errorf("invalid request to read %s", s) +} + +func invalidJSONError(expected string) error { + return fmt.Errorf("invalid JSON input; expected %s", expected) +} + +func invalidJSONErrorForType(expected string, t bsontype.Type) error { + return fmt.Errorf("invalid JSON input; expected %s for %s", expected, t) +} + +func unexpectedTokenError(jt *jsonToken) error { + switch jt.t { + case jttInt32, jttInt64, jttDouble: + return fmt.Errorf("invalid JSON input; unexpected number (%v) at position %d", jt.v, jt.p) + case jttString: + return fmt.Errorf("invalid JSON input; unexpected string (\"%v\") at position %d", jt.v, jt.p) + case jttBool: + return fmt.Errorf("invalid JSON input; unexpected boolean literal (%v) at position %d", jt.v, jt.p) + case jttNull: + return fmt.Errorf("invalid JSON input; unexpected null literal at position %d", jt.p) + case jttEOF: + return fmt.Errorf("invalid JSON input; unexpected end of input at position %d", jt.p) + default: + return fmt.Errorf("invalid JSON input; unexpected %c at position %d", jt.v.(byte), jt.p) + } +} + +func nestingDepthError(p, depth int) error { + return fmt.Errorf("invalid JSON input; nesting too deep (%d levels) at position %d", depth, p) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go new file mode 100644 index 0000000..35832d7 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go @@ -0,0 +1,644 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonrw + +import ( + "fmt" + "io" + "sync" + + "go.mongodb.org/mongo-driver/bson/bsontype" + "go.mongodb.org/mongo-driver/bson/primitive" +) + +// ExtJSONValueReaderPool is a pool for ValueReaders that read ExtJSON. +type ExtJSONValueReaderPool struct { + pool sync.Pool +} + +// NewExtJSONValueReaderPool instantiates a new ExtJSONValueReaderPool. +func NewExtJSONValueReaderPool() *ExtJSONValueReaderPool { + return &ExtJSONValueReaderPool{ + pool: sync.Pool{ + New: func() interface{} { + return new(extJSONValueReader) + }, + }, + } +} + +// Get retrieves a ValueReader from the pool and uses src as the underlying ExtJSON. +func (bvrp *ExtJSONValueReaderPool) Get(r io.Reader, canonical bool) (ValueReader, error) { + vr := bvrp.pool.Get().(*extJSONValueReader) + return vr.reset(r, canonical) +} + +// Put inserts a ValueReader into the pool. If the ValueReader is not a ExtJSON ValueReader nothing +// is inserted into the pool and ok will be false. +func (bvrp *ExtJSONValueReaderPool) Put(vr ValueReader) (ok bool) { + bvr, ok := vr.(*extJSONValueReader) + if !ok { + return false + } + + bvr, _ = bvr.reset(nil, false) + bvrp.pool.Put(bvr) + return true +} + +type ejvrState struct { + mode mode + vType bsontype.Type + depth int +} + +// extJSONValueReader is for reading extended JSON. +type extJSONValueReader struct { + p *extJSONParser + + stack []ejvrState + frame int +} + +// NewExtJSONValueReader creates a new ValueReader from a given io.Reader +// It will interpret the JSON of r as canonical or relaxed according to the +// given canonical flag +func NewExtJSONValueReader(r io.Reader, canonical bool) (ValueReader, error) { + return newExtJSONValueReader(r, canonical) +} + +func newExtJSONValueReader(r io.Reader, canonical bool) (*extJSONValueReader, error) { + ejvr := new(extJSONValueReader) + return ejvr.reset(r, canonical) +} + +func (ejvr *extJSONValueReader) reset(r io.Reader, canonical bool) (*extJSONValueReader, error) { + p := newExtJSONParser(r, canonical) + typ, err := p.peekType() + + if err != nil { + return nil, ErrInvalidJSON + } + + var m mode + switch typ { + case bsontype.EmbeddedDocument: + m = mTopLevel + case bsontype.Array: + m = mArray + default: + m = mValue + } + + stack := make([]ejvrState, 1, 5) + stack[0] = ejvrState{ + mode: m, + vType: typ, + } + return &extJSONValueReader{ + p: p, + stack: stack, + }, nil +} + +func (ejvr *extJSONValueReader) advanceFrame() { + if ejvr.frame+1 >= len(ejvr.stack) { // We need to grow the stack + length := len(ejvr.stack) + if length+1 >= cap(ejvr.stack) { + // double it + buf := make([]ejvrState, 2*cap(ejvr.stack)+1) + copy(buf, ejvr.stack) + ejvr.stack = buf + } + ejvr.stack = ejvr.stack[:length+1] + } + ejvr.frame++ + + // Clean the stack + ejvr.stack[ejvr.frame].mode = 0 + ejvr.stack[ejvr.frame].vType = 0 + ejvr.stack[ejvr.frame].depth = 0 +} + +func (ejvr *extJSONValueReader) pushDocument() { + ejvr.advanceFrame() + + ejvr.stack[ejvr.frame].mode = mDocument + ejvr.stack[ejvr.frame].depth = ejvr.p.depth +} + +func (ejvr *extJSONValueReader) pushCodeWithScope() { + ejvr.advanceFrame() + + ejvr.stack[ejvr.frame].mode = mCodeWithScope +} + +func (ejvr *extJSONValueReader) pushArray() { + ejvr.advanceFrame() + + ejvr.stack[ejvr.frame].mode = mArray +} + +func (ejvr *extJSONValueReader) push(m mode, t bsontype.Type) { + ejvr.advanceFrame() + + ejvr.stack[ejvr.frame].mode = m + ejvr.stack[ejvr.frame].vType = t +} + +func (ejvr *extJSONValueReader) pop() { + switch ejvr.stack[ejvr.frame].mode { + case mElement, mValue: + ejvr.frame-- + case mDocument, mArray, mCodeWithScope: + ejvr.frame -= 2 // we pop twice to jump over the vrElement: vrDocument -> vrElement -> vrDocument/TopLevel/etc... + } +} + +func (ejvr *extJSONValueReader) skipObject() { + // read entire object until depth returns to 0 (last ending } or ] seen) + depth := 1 + for depth > 0 { + ejvr.p.advanceState() + + // If object is empty, raise depth and continue. When emptyObject is true, the + // parser has already read both the opening and closing brackets of an empty + // object ("{}"), so the next valid token will be part of the parent document, + // not part of the nested document. + // + // If there is a comma, there are remaining fields, emptyObject must be set back + // to false, and comma must be skipped with advanceState(). + if ejvr.p.emptyObject { + if ejvr.p.s == jpsSawComma { + ejvr.p.emptyObject = false + ejvr.p.advanceState() + } + depth-- + continue + } + + switch ejvr.p.s { + case jpsSawBeginObject, jpsSawBeginArray: + depth++ + case jpsSawEndObject, jpsSawEndArray: + depth-- + } + } +} + +func (ejvr *extJSONValueReader) invalidTransitionErr(destination mode, name string, modes []mode) error { + te := TransitionError{ + name: name, + current: ejvr.stack[ejvr.frame].mode, + destination: destination, + modes: modes, + action: "read", + } + if ejvr.frame != 0 { + te.parent = ejvr.stack[ejvr.frame-1].mode + } + return te +} + +func (ejvr *extJSONValueReader) typeError(t bsontype.Type) error { + return fmt.Errorf("positioned on %s, but attempted to read %s", ejvr.stack[ejvr.frame].vType, t) +} + +func (ejvr *extJSONValueReader) ensureElementValue(t bsontype.Type, destination mode, callerName string, addModes ...mode) error { + switch ejvr.stack[ejvr.frame].mode { + case mElement, mValue: + if ejvr.stack[ejvr.frame].vType != t { + return ejvr.typeError(t) + } + default: + modes := []mode{mElement, mValue} + if addModes != nil { + modes = append(modes, addModes...) + } + return ejvr.invalidTransitionErr(destination, callerName, modes) + } + + return nil +} + +func (ejvr *extJSONValueReader) Type() bsontype.Type { + return ejvr.stack[ejvr.frame].vType +} + +func (ejvr *extJSONValueReader) Skip() error { + switch ejvr.stack[ejvr.frame].mode { + case mElement, mValue: + default: + return ejvr.invalidTransitionErr(0, "Skip", []mode{mElement, mValue}) + } + + defer ejvr.pop() + + t := ejvr.stack[ejvr.frame].vType + switch t { + case bsontype.Array, bsontype.EmbeddedDocument, bsontype.CodeWithScope: + // read entire array, doc or CodeWithScope + ejvr.skipObject() + default: + _, err := ejvr.p.readValue(t) + if err != nil { + return err + } + } + + return nil +} + +func (ejvr *extJSONValueReader) ReadArray() (ArrayReader, error) { + switch ejvr.stack[ejvr.frame].mode { + case mTopLevel: // allow reading array from top level + case mArray: + return ejvr, nil + default: + if err := ejvr.ensureElementValue(bsontype.Array, mArray, "ReadArray", mTopLevel, mArray); err != nil { + return nil, err + } + } + + ejvr.pushArray() + + return ejvr, nil +} + +func (ejvr *extJSONValueReader) ReadBinary() (b []byte, btype byte, err error) { + if err := ejvr.ensureElementValue(bsontype.Binary, 0, "ReadBinary"); err != nil { + return nil, 0, err + } + + v, err := ejvr.p.readValue(bsontype.Binary) + if err != nil { + return nil, 0, err + } + + b, btype, err = v.parseBinary() + + ejvr.pop() + return b, btype, err +} + +func (ejvr *extJSONValueReader) ReadBoolean() (bool, error) { + if err := ejvr.ensureElementValue(bsontype.Boolean, 0, "ReadBoolean"); err != nil { + return false, err + } + + v, err := ejvr.p.readValue(bsontype.Boolean) + if err != nil { + return false, err + } + + if v.t != bsontype.Boolean { + return false, fmt.Errorf("expected type bool, but got type %s", v.t) + } + + ejvr.pop() + return v.v.(bool), nil +} + +func (ejvr *extJSONValueReader) ReadDocument() (DocumentReader, error) { + switch ejvr.stack[ejvr.frame].mode { + case mTopLevel: + return ejvr, nil + case mElement, mValue: + if ejvr.stack[ejvr.frame].vType != bsontype.EmbeddedDocument { + return nil, ejvr.typeError(bsontype.EmbeddedDocument) + } + + ejvr.pushDocument() + return ejvr, nil + default: + return nil, ejvr.invalidTransitionErr(mDocument, "ReadDocument", []mode{mTopLevel, mElement, mValue}) + } +} + +func (ejvr *extJSONValueReader) ReadCodeWithScope() (code string, dr DocumentReader, err error) { + if err = ejvr.ensureElementValue(bsontype.CodeWithScope, 0, "ReadCodeWithScope"); err != nil { + return "", nil, err + } + + v, err := ejvr.p.readValue(bsontype.CodeWithScope) + if err != nil { + return "", nil, err + } + + code, err = v.parseJavascript() + + ejvr.pushCodeWithScope() + return code, ejvr, err +} + +func (ejvr *extJSONValueReader) ReadDBPointer() (ns string, oid primitive.ObjectID, err error) { + if err = ejvr.ensureElementValue(bsontype.DBPointer, 0, "ReadDBPointer"); err != nil { + return "", primitive.NilObjectID, err + } + + v, err := ejvr.p.readValue(bsontype.DBPointer) + if err != nil { + return "", primitive.NilObjectID, err + } + + ns, oid, err = v.parseDBPointer() + + ejvr.pop() + return ns, oid, err +} + +func (ejvr *extJSONValueReader) ReadDateTime() (int64, error) { + if err := ejvr.ensureElementValue(bsontype.DateTime, 0, "ReadDateTime"); err != nil { + return 0, err + } + + v, err := ejvr.p.readValue(bsontype.DateTime) + if err != nil { + return 0, err + } + + d, err := v.parseDateTime() + + ejvr.pop() + return d, err +} + +func (ejvr *extJSONValueReader) ReadDecimal128() (primitive.Decimal128, error) { + if err := ejvr.ensureElementValue(bsontype.Decimal128, 0, "ReadDecimal128"); err != nil { + return primitive.Decimal128{}, err + } + + v, err := ejvr.p.readValue(bsontype.Decimal128) + if err != nil { + return primitive.Decimal128{}, err + } + + d, err := v.parseDecimal128() + + ejvr.pop() + return d, err +} + +func (ejvr *extJSONValueReader) ReadDouble() (float64, error) { + if err := ejvr.ensureElementValue(bsontype.Double, 0, "ReadDouble"); err != nil { + return 0, err + } + + v, err := ejvr.p.readValue(bsontype.Double) + if err != nil { + return 0, err + } + + d, err := v.parseDouble() + + ejvr.pop() + return d, err +} + +func (ejvr *extJSONValueReader) ReadInt32() (int32, error) { + if err := ejvr.ensureElementValue(bsontype.Int32, 0, "ReadInt32"); err != nil { + return 0, err + } + + v, err := ejvr.p.readValue(bsontype.Int32) + if err != nil { + return 0, err + } + + i, err := v.parseInt32() + + ejvr.pop() + return i, err +} + +func (ejvr *extJSONValueReader) ReadInt64() (int64, error) { + if err := ejvr.ensureElementValue(bsontype.Int64, 0, "ReadInt64"); err != nil { + return 0, err + } + + v, err := ejvr.p.readValue(bsontype.Int64) + if err != nil { + return 0, err + } + + i, err := v.parseInt64() + + ejvr.pop() + return i, err +} + +func (ejvr *extJSONValueReader) ReadJavascript() (code string, err error) { + if err = ejvr.ensureElementValue(bsontype.JavaScript, 0, "ReadJavascript"); err != nil { + return "", err + } + + v, err := ejvr.p.readValue(bsontype.JavaScript) + if err != nil { + return "", err + } + + code, err = v.parseJavascript() + + ejvr.pop() + return code, err +} + +func (ejvr *extJSONValueReader) ReadMaxKey() error { + if err := ejvr.ensureElementValue(bsontype.MaxKey, 0, "ReadMaxKey"); err != nil { + return err + } + + v, err := ejvr.p.readValue(bsontype.MaxKey) + if err != nil { + return err + } + + err = v.parseMinMaxKey("max") + + ejvr.pop() + return err +} + +func (ejvr *extJSONValueReader) ReadMinKey() error { + if err := ejvr.ensureElementValue(bsontype.MinKey, 0, "ReadMinKey"); err != nil { + return err + } + + v, err := ejvr.p.readValue(bsontype.MinKey) + if err != nil { + return err + } + + err = v.parseMinMaxKey("min") + + ejvr.pop() + return err +} + +func (ejvr *extJSONValueReader) ReadNull() error { + if err := ejvr.ensureElementValue(bsontype.Null, 0, "ReadNull"); err != nil { + return err + } + + v, err := ejvr.p.readValue(bsontype.Null) + if err != nil { + return err + } + + if v.t != bsontype.Null { + return fmt.Errorf("expected type null but got type %s", v.t) + } + + ejvr.pop() + return nil +} + +func (ejvr *extJSONValueReader) ReadObjectID() (primitive.ObjectID, error) { + if err := ejvr.ensureElementValue(bsontype.ObjectID, 0, "ReadObjectID"); err != nil { + return primitive.ObjectID{}, err + } + + v, err := ejvr.p.readValue(bsontype.ObjectID) + if err != nil { + return primitive.ObjectID{}, err + } + + oid, err := v.parseObjectID() + + ejvr.pop() + return oid, err +} + +func (ejvr *extJSONValueReader) ReadRegex() (pattern string, options string, err error) { + if err = ejvr.ensureElementValue(bsontype.Regex, 0, "ReadRegex"); err != nil { + return "", "", err + } + + v, err := ejvr.p.readValue(bsontype.Regex) + if err != nil { + return "", "", err + } + + pattern, options, err = v.parseRegex() + + ejvr.pop() + return pattern, options, err +} + +func (ejvr *extJSONValueReader) ReadString() (string, error) { + if err := ejvr.ensureElementValue(bsontype.String, 0, "ReadString"); err != nil { + return "", err + } + + v, err := ejvr.p.readValue(bsontype.String) + if err != nil { + return "", err + } + + if v.t != bsontype.String { + return "", fmt.Errorf("expected type string but got type %s", v.t) + } + + ejvr.pop() + return v.v.(string), nil +} + +func (ejvr *extJSONValueReader) ReadSymbol() (symbol string, err error) { + if err = ejvr.ensureElementValue(bsontype.Symbol, 0, "ReadSymbol"); err != nil { + return "", err + } + + v, err := ejvr.p.readValue(bsontype.Symbol) + if err != nil { + return "", err + } + + symbol, err = v.parseSymbol() + + ejvr.pop() + return symbol, err +} + +func (ejvr *extJSONValueReader) ReadTimestamp() (t uint32, i uint32, err error) { + if err = ejvr.ensureElementValue(bsontype.Timestamp, 0, "ReadTimestamp"); err != nil { + return 0, 0, err + } + + v, err := ejvr.p.readValue(bsontype.Timestamp) + if err != nil { + return 0, 0, err + } + + t, i, err = v.parseTimestamp() + + ejvr.pop() + return t, i, err +} + +func (ejvr *extJSONValueReader) ReadUndefined() error { + if err := ejvr.ensureElementValue(bsontype.Undefined, 0, "ReadUndefined"); err != nil { + return err + } + + v, err := ejvr.p.readValue(bsontype.Undefined) + if err != nil { + return err + } + + err = v.parseUndefined() + + ejvr.pop() + return err +} + +func (ejvr *extJSONValueReader) ReadElement() (string, ValueReader, error) { + switch ejvr.stack[ejvr.frame].mode { + case mTopLevel, mDocument, mCodeWithScope: + default: + return "", nil, ejvr.invalidTransitionErr(mElement, "ReadElement", []mode{mTopLevel, mDocument, mCodeWithScope}) + } + + name, t, err := ejvr.p.readKey() + + if err != nil { + if err == ErrEOD { + if ejvr.stack[ejvr.frame].mode == mCodeWithScope { + _, err := ejvr.p.peekType() + if err != nil { + return "", nil, err + } + } + + ejvr.pop() + } + + return "", nil, err + } + + ejvr.push(mElement, t) + return name, ejvr, nil +} + +func (ejvr *extJSONValueReader) ReadValue() (ValueReader, error) { + switch ejvr.stack[ejvr.frame].mode { + case mArray: + default: + return nil, ejvr.invalidTransitionErr(mValue, "ReadValue", []mode{mArray}) + } + + t, err := ejvr.p.peekType() + if err != nil { + if err == ErrEOA { + ejvr.pop() + } + + return nil, err + } + + ejvr.push(mValue, t) + return ejvr, nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_tables.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_tables.go new file mode 100644 index 0000000..ba39c96 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_tables.go @@ -0,0 +1,223 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Based on github.com/golang/go by The Go Authors +// See THIRD-PARTY-NOTICES for original license terms. + +package bsonrw + +import "unicode/utf8" + +// safeSet holds the value true if the ASCII character with the given array +// position can be represented inside a JSON string without any further +// escaping. +// +// All values are true except for the ASCII control characters (0-31), the +// double quote ("), and the backslash character ("\"). +var safeSet = [utf8.RuneSelf]bool{ + ' ': true, + '!': true, + '"': false, + '#': true, + '$': true, + '%': true, + '&': true, + '\'': true, + '(': true, + ')': true, + '*': true, + '+': true, + ',': true, + '-': true, + '.': true, + '/': true, + '0': true, + '1': true, + '2': true, + '3': true, + '4': true, + '5': true, + '6': true, + '7': true, + '8': true, + '9': true, + ':': true, + ';': true, + '<': true, + '=': true, + '>': true, + '?': true, + '@': true, + 'A': true, + 'B': true, + 'C': true, + 'D': true, + 'E': true, + 'F': true, + 'G': true, + 'H': true, + 'I': true, + 'J': true, + 'K': true, + 'L': true, + 'M': true, + 'N': true, + 'O': true, + 'P': true, + 'Q': true, + 'R': true, + 'S': true, + 'T': true, + 'U': true, + 'V': true, + 'W': true, + 'X': true, + 'Y': true, + 'Z': true, + '[': true, + '\\': false, + ']': true, + '^': true, + '_': true, + '`': true, + 'a': true, + 'b': true, + 'c': true, + 'd': true, + 'e': true, + 'f': true, + 'g': true, + 'h': true, + 'i': true, + 'j': true, + 'k': true, + 'l': true, + 'm': true, + 'n': true, + 'o': true, + 'p': true, + 'q': true, + 'r': true, + 's': true, + 't': true, + 'u': true, + 'v': true, + 'w': true, + 'x': true, + 'y': true, + 'z': true, + '{': true, + '|': true, + '}': true, + '~': true, + '\u007f': true, +} + +// htmlSafeSet holds the value true if the ASCII character with the given +// array position can be safely represented inside a JSON string, embedded +// inside of HTML