diff --git a/database.go b/database.go index c18cb2cd..47df2512 100644 --- a/database.go +++ b/database.go @@ -11,6 +11,7 @@ import ( "github.com/skelterjohn/geom" "github.com/whosonfirst/go-ioutil" wof_geojson "github.com/whosonfirst/go-whosonfirst-geojson-v2" + wof_feature "github.com/whosonfirst/go-whosonfirst-geojson-v2/feature" "github.com/whosonfirst/go-whosonfirst-log" "github.com/whosonfirst/go-whosonfirst-spatial" "github.com/whosonfirst/go-whosonfirst-spatial/database" @@ -631,7 +632,26 @@ func (r *SQLiteSpatialDatabase) ReaderURI(ctx context.Context, str_uri string) s // whosonfirst/go-writer interface func (r *SQLiteSpatialDatabase) Write(ctx context.Context, key string, fh io.ReadSeeker) (int64, error) { - return 0, fmt.Errorf("Not implemented") + + body, err := io.ReadAll(fh) + + if err != nil { + return 0, err + } + + f, err := wof_feature.LoadFeature(body) + + if err != nil { + return 0, err + } + + err = r.IndexFeature(ctx, f) + + if err != nil { + return 0, err + } + + return int64(len(body)), nil } func (r *SQLiteSpatialDatabase) WriterURI(ctx context.Context, str_uri string) string { diff --git a/go.mod b/go.mod index fa07b4d1..5f65ba07 100644 --- a/go.mod +++ b/go.mod @@ -6,13 +6,13 @@ require ( github.com/patrickmn/go-cache v2.1.0+incompatible github.com/sfomuseum/go-flags v0.8.2 github.com/skelterjohn/geom v0.0.0-20180103142417-96f3e8a219c5 - github.com/whosonfirst/go-ioutil v0.0.1 + github.com/whosonfirst/go-ioutil v1.0.0 github.com/whosonfirst/go-whosonfirst-geojson-v2 v0.16.3 github.com/whosonfirst/go-whosonfirst-log v0.1.0 - github.com/whosonfirst/go-whosonfirst-spatial v0.0.55 + github.com/whosonfirst/go-whosonfirst-spatial v0.0.56 github.com/whosonfirst/go-whosonfirst-spr/v2 v2.0.0 github.com/whosonfirst/go-whosonfirst-sqlite v0.1.7 github.com/whosonfirst/go-whosonfirst-sqlite-features v0.8.0 github.com/whosonfirst/go-whosonfirst-sqlite-spr v0.0.6 - github.com/whosonfirst/go-whosonfirst-uri v0.2.0 + github.com/whosonfirst/go-whosonfirst-uri v1.0.1 ) diff --git a/go.sum b/go.sum index 73adf281..6be0db6f 100644 --- a/go.sum +++ b/go.sum @@ -112,6 +112,9 @@ github.com/tidwall/gjson v1.7.1 h1:hwkZ6V1/EF8FxNhKJrIXQwSscyl2yWCZ1SkOCQYHSHA= github.com/tidwall/gjson v1.7.1/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= github.com/tidwall/gjson v1.7.2 h1:Mlc6J3RVIjBPiXounGdbdsk3WFwB195CLunMD/BtrOs= github.com/tidwall/gjson v1.7.2/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= +github.com/tidwall/gjson v1.7.4/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= +github.com/tidwall/gjson v1.7.5 h1:zmAN/xmX7OtpAkv4Ovfso60r/BiCi5IErCDYGNJu+uc= +github.com/tidwall/gjson v1.7.5/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= @@ -122,6 +125,8 @@ github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8= github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/sjson v1.1.5 h1:wsUceI/XDyZk3J1FUvuuYlK62zJv2HO2Pzb8A5EWdUE= github.com/tidwall/sjson v1.1.5/go.mod h1:VuJzsZnTowhSxWdOgsAnb886i4AjEyTkk7tNtsL7EYE= +github.com/tidwall/sjson v1.1.6 h1:8fDdlahON04OZBlTQCIatW8FstSFJz8oxidj5h0rmSQ= +github.com/tidwall/sjson v1.1.6/go.mod h1:KN3FZ7odvXIHPbJdhNorK/M9lWweVUbXsXXhrJ/kGOA= github.com/twpayne/go-geom v1.3.6 h1:O27mIXZnMYiZi0ZD8ewjs/IT/ZOFVbZHBzPjA9skdmg= github.com/twpayne/go-geom v1.3.6/go.mod h1:XTyWHR6+l9TUYONbbK4ImUTYbWDCu2ySSPrZmmiA0Pg= github.com/twpayne/go-kml v1.5.1/go.mod h1:kz8jAiIz6FIdU2Zjce9qGlVtgFYES9vt7BTPBHf5jl4= @@ -129,6 +134,8 @@ github.com/twpayne/go-polyline v1.0.0/go.mod h1:ICh24bcLYBX8CknfvNPKqoTbe+eg+MX1 github.com/twpayne/go-waypoint v0.0.0-20200706203930-b263a7f6e4e8/go.mod h1:qj5pHncxKhu9gxtZEYWypA/z097sxhFlbTyOyt9gcnU= github.com/whosonfirst/go-ioutil v0.0.1 h1:cCrEYen6NDvHfjzV2q4u/VB21u2kTOwDnUGRlMI8Z9o= github.com/whosonfirst/go-ioutil v0.0.1/go.mod h1:2dS1vWdAIkiHDvDF8fYyjv6k2NISmwaIjJJeEDBEdvg= +github.com/whosonfirst/go-ioutil v1.0.0 h1:sYpgJx7Wsp76e7PFGa8KKQBvWQW3+HMCWSJbKdD5m14= +github.com/whosonfirst/go-ioutil v1.0.0/go.mod h1:2dS1vWdAIkiHDvDF8fYyjv6k2NISmwaIjJJeEDBEdvg= github.com/whosonfirst/go-reader v0.5.0 h1:nx+ai0F6JXouw+7Dln34dmYglw+3sQ6sG4JZGOJ/sqA= github.com/whosonfirst/go-reader v0.5.0/go.mod h1:4ou/wZUss2CDZp27QK5ySDc8p98GVWvUiqqmwEprjgk= github.com/whosonfirst/go-rfc-5646 v0.1.0 h1:HNFPAem6v5De61PXLgbGzx9tfNOP83AAkVvm9WAddJY= @@ -154,6 +161,8 @@ github.com/whosonfirst/go-whosonfirst-hash v0.1.0 h1:FpnclPIb+8M1uhSXfl3z8nYcG/3 github.com/whosonfirst/go-whosonfirst-hash v0.1.0/go.mod h1:1ZdCFZTnQt5bwnsj2daB9yHilKOKToVh+Tyj/Z8TbUk= github.com/whosonfirst/go-whosonfirst-iterate v1.1.0 h1:mirgJrwyMS7Qdle3DpHCt9go1AG8lSP+tf0R/nxlmSQ= github.com/whosonfirst/go-whosonfirst-iterate v1.1.0/go.mod h1:ceLMHQ9s3naZLFcKeUvokP0Sw7/BmwuZJiaQt/mVO0I= +github.com/whosonfirst/go-whosonfirst-iterate v1.1.1 h1:7J8kq86bZgO2uUEJcSW7ciWTaoMC9k5obFQ90lp7ZpQ= +github.com/whosonfirst/go-whosonfirst-iterate v1.1.1/go.mod h1:ceLMHQ9s3naZLFcKeUvokP0Sw7/BmwuZJiaQt/mVO0I= github.com/whosonfirst/go-whosonfirst-log v0.1.0 h1:mWYI5hn16uyeLxBmPsLSvYV4rQKK/cxGVhM+bC2ZoGc= github.com/whosonfirst/go-whosonfirst-log v0.1.0/go.mod h1:pmgBbxZSnjGVy2nsUJBBMcFagxwIKLlmRsW7ClkXmac= github.com/whosonfirst/go-whosonfirst-names v0.1.0 h1:uXop/DwQqH60uDBZvHCPg1yRSQLScbm6VZyqcaED2KE= @@ -171,6 +180,8 @@ github.com/whosonfirst/go-whosonfirst-spatial v0.0.53 h1:x+pzkZA4hzTrQVoCfT7jagK github.com/whosonfirst/go-whosonfirst-spatial v0.0.53/go.mod h1:EapRzFWjj2w/vuPoqnQw2rlznIK0I/0t+9uIlf+Ordo= github.com/whosonfirst/go-whosonfirst-spatial v0.0.55 h1:KzPIlnEOwnA0lPL0icZ2XO2g90zGhpOmRCtwCKK3VW4= github.com/whosonfirst/go-whosonfirst-spatial v0.0.55/go.mod h1:EapRzFWjj2w/vuPoqnQw2rlznIK0I/0t+9uIlf+Ordo= +github.com/whosonfirst/go-whosonfirst-spatial v0.0.56 h1:vuYiiYHVmqVQvhMnUIayCRo4NaeqpgsFQLF6PRX2jQg= +github.com/whosonfirst/go-whosonfirst-spatial v0.0.56/go.mod h1:oFrukOaZll/Ix+V87sp4XQjhY5noR6JBe3gHE+qBOl8= github.com/whosonfirst/go-whosonfirst-spr/v2 v2.0.0 h1:UQ1n/uODS50mckZpXYe5GKm8XwoUUC1jRcNN8oiW2uc= github.com/whosonfirst/go-whosonfirst-spr/v2 v2.0.0/go.mod h1:tveSSFDn8XoiCeAMarSCn769lA6e3Y0/Qi8S19Jz7Gw= github.com/whosonfirst/go-whosonfirst-sqlite v0.1.7 h1:WZOGRgD2UmQWYOITWNpTWcccd+gbDW0oKRYDax43f6E= @@ -189,10 +200,13 @@ github.com/whosonfirst/go-whosonfirst-sqlite-spr v0.0.6 h1:9Y3P9YAYGJQogi7ZNic3u github.com/whosonfirst/go-whosonfirst-sqlite-spr v0.0.6/go.mod h1:av6zq/jP7ACZqJ2dYjCmBH5Oea+eLLLq9u1agmYvMP8= github.com/whosonfirst/go-whosonfirst-uri v0.2.0 h1:iODHdyvW+8IXqHZTixZ/9GEZy1dVKGj6dMRg7fn0d2M= github.com/whosonfirst/go-whosonfirst-uri v0.2.0/go.mod h1:8eaDVcc4v+HHHEDaRbApdmhPwM4/JQllw2PktvZcPVs= +github.com/whosonfirst/go-whosonfirst-uri v1.0.1 h1:hVEDRuW9WhqvTksDi092OO9UecX7PAMDrD47KPEqAg0= +github.com/whosonfirst/go-whosonfirst-uri v1.0.1/go.mod h1:8eaDVcc4v+HHHEDaRbApdmhPwM4/JQllw2PktvZcPVs= github.com/whosonfirst/go-writer v0.4.1 h1:pAZ/cwaCM129PfwYy28ggCIRfL98OkrYxNnAxz2dksg= github.com/whosonfirst/go-writer v0.4.1/go.mod h1:kFzhremCFtnkJdmviwJEPLFYKQ5+vq6ocJPxt1bHPFY= 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 h1:h29zL3VNL9VUHztkAAndzblhrDHyik9z47OuUR2Vovw= github.com/whosonfirst/warning v0.1.1/go.mod h1:/unEMzhB9YaMeEwTJpzLN3kM5LiSxdJhKEsf/OQhn6s= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= diff --git a/vendor/github.com/hashicorp/errwrap/LICENSE b/vendor/github.com/hashicorp/errwrap/LICENSE new file mode 100644 index 00000000..c33dcc7c --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/LICENSE @@ -0,0 +1,354 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by + the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/hashicorp/errwrap/README.md b/vendor/github.com/hashicorp/errwrap/README.md new file mode 100644 index 00000000..1c95f597 --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/README.md @@ -0,0 +1,89 @@ +# errwrap + +`errwrap` is a package for Go that formalizes the pattern of wrapping errors +and checking if an error contains another error. + +There is a common pattern in Go of taking a returned `error` value and +then wrapping it (such as with `fmt.Errorf`) before returning it. The problem +with this pattern is that you completely lose the original `error` structure. + +Arguably the _correct_ approach is that you should make a custom structure +implementing the `error` interface, and have the original error as a field +on that structure, such [as this example](http://golang.org/pkg/os/#PathError). +This is a good approach, but you have to know the entire chain of possible +rewrapping that happens, when you might just care about one. + +`errwrap` formalizes this pattern (it doesn't matter what approach you use +above) by giving a single interface for wrapping errors, checking if a specific +error is wrapped, and extracting that error. + +## Installation and Docs + +Install using `go get github.com/hashicorp/errwrap`. + +Full documentation is available at +http://godoc.org/github.com/hashicorp/errwrap + +## Usage + +#### Basic Usage + +Below is a very basic example of its usage: + +```go +// A function that always returns an error, but wraps it, like a real +// function might. +func tryOpen() error { + _, err := os.Open("/i/dont/exist") + if err != nil { + return errwrap.Wrapf("Doesn't exist: {{err}}", err) + } + + return nil +} + +func main() { + err := tryOpen() + + // We can use the Contains helpers to check if an error contains + // another error. It is safe to do this with a nil error, or with + // an error that doesn't even use the errwrap package. + if errwrap.Contains(err, ErrNotExist) { + // Do something + } + if errwrap.ContainsType(err, new(os.PathError)) { + // Do something + } + + // Or we can use the associated `Get` functions to just extract + // a specific error. This would return nil if that specific error doesn't + // exist. + perr := errwrap.GetType(err, new(os.PathError)) +} +``` + +#### Custom Types + +If you're already making custom types that properly wrap errors, then +you can get all the functionality of `errwraps.Contains` and such by +implementing the `Wrapper` interface with just one function. Example: + +```go +type AppError { + Code ErrorCode + Err error +} + +func (e *AppError) WrappedErrors() []error { + return []error{e.Err} +} +``` + +Now this works: + +```go +err := &AppError{Err: fmt.Errorf("an error")} +if errwrap.ContainsType(err, fmt.Errorf("")) { + // This will work! +} +``` diff --git a/vendor/github.com/hashicorp/errwrap/errwrap.go b/vendor/github.com/hashicorp/errwrap/errwrap.go new file mode 100644 index 00000000..a733bef1 --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/errwrap.go @@ -0,0 +1,169 @@ +// Package errwrap implements methods to formalize error wrapping in Go. +// +// All of the top-level functions that take an `error` are built to be able +// to take any error, not just wrapped errors. This allows you to use errwrap +// without having to type-check and type-cast everywhere. +package errwrap + +import ( + "errors" + "reflect" + "strings" +) + +// WalkFunc is the callback called for Walk. +type WalkFunc func(error) + +// Wrapper is an interface that can be implemented by custom types to +// have all the Contains, Get, etc. functions in errwrap work. +// +// When Walk reaches a Wrapper, it will call the callback for every +// wrapped error in addition to the wrapper itself. Since all the top-level +// functions in errwrap use Walk, this means that all those functions work +// with your custom type. +type Wrapper interface { + WrappedErrors() []error +} + +// Wrap defines that outer wraps inner, returning an error type that +// can be cleanly used with the other methods in this package, such as +// Contains, GetAll, etc. +// +// This function won't modify the error message at all (the outer message +// will be used). +func Wrap(outer, inner error) error { + return &wrappedError{ + Outer: outer, + Inner: inner, + } +} + +// Wrapf wraps an error with a formatting message. This is similar to using +// `fmt.Errorf` to wrap an error. If you're using `fmt.Errorf` to wrap +// errors, you should replace it with this. +// +// format is the format of the error message. The string '{{err}}' will +// be replaced with the original error message. +func Wrapf(format string, err error) error { + outerMsg := "" + if err != nil { + outerMsg = err.Error() + } + + outer := errors.New(strings.Replace( + format, "{{err}}", outerMsg, -1)) + + return Wrap(outer, err) +} + +// Contains checks if the given error contains an error with the +// message msg. If err is not a wrapped error, this will always return +// false unless the error itself happens to match this msg. +func Contains(err error, msg string) bool { + return len(GetAll(err, msg)) > 0 +} + +// ContainsType checks if the given error contains an error with +// the same concrete type as v. If err is not a wrapped error, this will +// check the err itself. +func ContainsType(err error, v interface{}) bool { + return len(GetAllType(err, v)) > 0 +} + +// Get is the same as GetAll but returns the deepest matching error. +func Get(err error, msg string) error { + es := GetAll(err, msg) + if len(es) > 0 { + return es[len(es)-1] + } + + return nil +} + +// GetType is the same as GetAllType but returns the deepest matching error. +func GetType(err error, v interface{}) error { + es := GetAllType(err, v) + if len(es) > 0 { + return es[len(es)-1] + } + + return nil +} + +// GetAll gets all the errors that might be wrapped in err with the +// given message. The order of the errors is such that the outermost +// matching error (the most recent wrap) is index zero, and so on. +func GetAll(err error, msg string) []error { + var result []error + + Walk(err, func(err error) { + if err.Error() == msg { + result = append(result, err) + } + }) + + return result +} + +// GetAllType gets all the errors that are the same type as v. +// +// The order of the return value is the same as described in GetAll. +func GetAllType(err error, v interface{}) []error { + var result []error + + var search string + if v != nil { + search = reflect.TypeOf(v).String() + } + Walk(err, func(err error) { + var needle string + if err != nil { + needle = reflect.TypeOf(err).String() + } + + if needle == search { + result = append(result, err) + } + }) + + return result +} + +// Walk walks all the wrapped errors in err and calls the callback. If +// err isn't a wrapped error, this will be called once for err. If err +// is a wrapped error, the callback will be called for both the wrapper +// that implements error as well as the wrapped error itself. +func Walk(err error, cb WalkFunc) { + if err == nil { + return + } + + switch e := err.(type) { + case *wrappedError: + cb(e.Outer) + Walk(e.Inner, cb) + case Wrapper: + cb(err) + + for _, err := range e.WrappedErrors() { + Walk(err, cb) + } + default: + cb(err) + } +} + +// wrappedError is an implementation of error that has both the +// outer and inner errors. +type wrappedError struct { + Outer error + Inner error +} + +func (w *wrappedError) Error() string { + return w.Outer.Error() +} + +func (w *wrappedError) WrappedErrors() []error { + return []error{w.Outer, w.Inner} +} diff --git a/vendor/github.com/hashicorp/go-multierror/.travis.yml b/vendor/github.com/hashicorp/go-multierror/.travis.yml new file mode 100644 index 00000000..304a8359 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/.travis.yml @@ -0,0 +1,12 @@ +sudo: false + +language: go + +go: + - 1.x + +branches: + only: + - master + +script: make test testrace diff --git a/vendor/github.com/hashicorp/go-multierror/LICENSE b/vendor/github.com/hashicorp/go-multierror/LICENSE new file mode 100644 index 00000000..82b4de97 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/LICENSE @@ -0,0 +1,353 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by + the Mozilla Public License, v. 2.0. diff --git a/vendor/github.com/hashicorp/go-multierror/Makefile b/vendor/github.com/hashicorp/go-multierror/Makefile new file mode 100644 index 00000000..b97cd6ed --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/Makefile @@ -0,0 +1,31 @@ +TEST?=./... + +default: test + +# test runs the test suite and vets the code. +test: generate + @echo "==> Running tests..." + @go list $(TEST) \ + | grep -v "/vendor/" \ + | xargs -n1 go test -timeout=60s -parallel=10 ${TESTARGS} + +# testrace runs the race checker +testrace: generate + @echo "==> Running tests (race)..." + @go list $(TEST) \ + | grep -v "/vendor/" \ + | xargs -n1 go test -timeout=60s -race ${TESTARGS} + +# updatedeps installs all the dependencies needed to run and build. +updatedeps: + @sh -c "'${CURDIR}/scripts/deps.sh' '${NAME}'" + +# generate runs `go generate` to build the dynamically generated source files. +generate: + @echo "==> Generating..." + @find . -type f -name '.DS_Store' -delete + @go list ./... \ + | grep -v "/vendor/" \ + | xargs -n1 go generate + +.PHONY: default test testrace updatedeps generate diff --git a/vendor/github.com/hashicorp/go-multierror/README.md b/vendor/github.com/hashicorp/go-multierror/README.md new file mode 100644 index 00000000..ead5830f --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/README.md @@ -0,0 +1,97 @@ +# go-multierror + +[![Build Status](http://img.shields.io/travis/hashicorp/go-multierror.svg?style=flat-square)][travis] +[![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs] + +[travis]: https://travis-ci.org/hashicorp/go-multierror +[godocs]: https://godoc.org/github.com/hashicorp/go-multierror + +`go-multierror` is a package for Go that provides a mechanism for +representing a list of `error` values as a single `error`. + +This allows a function in Go to return an `error` that might actually +be a list of errors. If the caller knows this, they can unwrap the +list and access the errors. If the caller doesn't know, the error +formats to a nice human-readable format. + +`go-multierror` implements the +[errwrap](https://github.com/hashicorp/errwrap) interface so that it can +be used with that library, as well. + +## Installation and Docs + +Install using `go get github.com/hashicorp/go-multierror`. + +Full documentation is available at +http://godoc.org/github.com/hashicorp/go-multierror + +## Usage + +go-multierror is easy to use and purposely built to be unobtrusive in +existing Go applications/libraries that may not be aware of it. + +**Building a list of errors** + +The `Append` function is used to create a list of errors. This function +behaves a lot like the Go built-in `append` function: it doesn't matter +if the first argument is nil, a `multierror.Error`, or any other `error`, +the function behaves as you would expect. + +```go +var result error + +if err := step1(); err != nil { + result = multierror.Append(result, err) +} +if err := step2(); err != nil { + result = multierror.Append(result, err) +} + +return result +``` + +**Customizing the formatting of the errors** + +By specifying a custom `ErrorFormat`, you can customize the format +of the `Error() string` function: + +```go +var result *multierror.Error + +// ... accumulate errors here, maybe using Append + +if result != nil { + result.ErrorFormat = func([]error) string { + return "errors!" + } +} +``` + +**Accessing the list of errors** + +`multierror.Error` implements `error` so if the caller doesn't know about +multierror, it will work just fine. But if you're aware a multierror might +be returned, you can use type switches to access the list of errors: + +```go +if err := something(); err != nil { + if merr, ok := err.(*multierror.Error); ok { + // Use merr.Errors + } +} +``` + +**Returning a multierror only if there are errors** + +If you build a `multierror.Error`, you can use the `ErrorOrNil` function +to return an `error` implementation only if there are errors to return: + +```go +var result *multierror.Error + +// ... accumulate errors here + +// Return the `error` only if errors were added to the multierror, otherwise +// return nil since there are no errors. +return result.ErrorOrNil() +``` diff --git a/vendor/github.com/hashicorp/go-multierror/append.go b/vendor/github.com/hashicorp/go-multierror/append.go new file mode 100644 index 00000000..775b6e75 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/append.go @@ -0,0 +1,41 @@ +package multierror + +// Append is a helper function that will append more errors +// onto an Error in order to create a larger multi-error. +// +// If err is not a multierror.Error, then it will be turned into +// one. If any of the errs are multierr.Error, they will be flattened +// one level into err. +func Append(err error, errs ...error) *Error { + switch err := err.(type) { + case *Error: + // Typed nils can reach here, so initialize if we are nil + if err == nil { + err = new(Error) + } + + // Go through each error and flatten + for _, e := range errs { + switch e := e.(type) { + case *Error: + if e != nil { + err.Errors = append(err.Errors, e.Errors...) + } + default: + if e != nil { + err.Errors = append(err.Errors, e) + } + } + } + + return err + default: + newErrs := make([]error, 0, len(errs)+1) + if err != nil { + newErrs = append(newErrs, err) + } + newErrs = append(newErrs, errs...) + + return Append(&Error{}, newErrs...) + } +} diff --git a/vendor/github.com/hashicorp/go-multierror/flatten.go b/vendor/github.com/hashicorp/go-multierror/flatten.go new file mode 100644 index 00000000..aab8e9ab --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/flatten.go @@ -0,0 +1,26 @@ +package multierror + +// Flatten flattens the given error, merging any *Errors together into +// a single *Error. +func Flatten(err error) error { + // If it isn't an *Error, just return the error as-is + if _, ok := err.(*Error); !ok { + return err + } + + // Otherwise, make the result and flatten away! + flatErr := new(Error) + flatten(err, flatErr) + return flatErr +} + +func flatten(err error, flatErr *Error) { + switch err := err.(type) { + case *Error: + for _, e := range err.Errors { + flatten(e, flatErr) + } + default: + flatErr.Errors = append(flatErr.Errors, err) + } +} diff --git a/vendor/github.com/hashicorp/go-multierror/format.go b/vendor/github.com/hashicorp/go-multierror/format.go new file mode 100644 index 00000000..6c7a3cc9 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/format.go @@ -0,0 +1,27 @@ +package multierror + +import ( + "fmt" + "strings" +) + +// ErrorFormatFunc is a function callback that is called by Error to +// turn the list of errors into a string. +type ErrorFormatFunc func([]error) string + +// ListFormatFunc is a basic formatter that outputs the number of errors +// that occurred along with a bullet point list of the errors. +func ListFormatFunc(es []error) string { + if len(es) == 1 { + return fmt.Sprintf("1 error occurred:\n\n* %s", es[0]) + } + + points := make([]string, len(es)) + for i, err := range es { + points[i] = fmt.Sprintf("* %s", err) + } + + return fmt.Sprintf( + "%d errors occurred:\n\n%s", + len(es), strings.Join(points, "\n")) +} diff --git a/vendor/github.com/hashicorp/go-multierror/multierror.go b/vendor/github.com/hashicorp/go-multierror/multierror.go new file mode 100644 index 00000000..89b1422d --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/multierror.go @@ -0,0 +1,51 @@ +package multierror + +import ( + "fmt" +) + +// Error is an error type to track multiple errors. This is used to +// accumulate errors in cases and return them as a single "error". +type Error struct { + Errors []error + ErrorFormat ErrorFormatFunc +} + +func (e *Error) Error() string { + fn := e.ErrorFormat + if fn == nil { + fn = ListFormatFunc + } + + return fn(e.Errors) +} + +// ErrorOrNil returns an error interface if this Error represents +// a list of errors, or returns nil if the list of errors is empty. This +// function is useful at the end of accumulation to make sure that the value +// returned represents the existence of errors. +func (e *Error) ErrorOrNil() error { + if e == nil { + return nil + } + if len(e.Errors) == 0 { + return nil + } + + return e +} + +func (e *Error) GoString() string { + return fmt.Sprintf("*%#v", *e) +} + +// WrappedErrors returns the list of errors that this Error is wrapping. +// It is an implementation of the errwrap.Wrapper interface so that +// multierror.Error can be used with that library. +// +// This method is not safe to be called concurrently and is no different +// than accessing the Errors field directly. It is implemented only to +// satisfy the errwrap.Wrapper interface. +func (e *Error) WrappedErrors() []error { + return e.Errors +} diff --git a/vendor/github.com/hashicorp/go-multierror/prefix.go b/vendor/github.com/hashicorp/go-multierror/prefix.go new file mode 100644 index 00000000..5c477abe --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/prefix.go @@ -0,0 +1,37 @@ +package multierror + +import ( + "fmt" + + "github.com/hashicorp/errwrap" +) + +// Prefix is a helper function that will prefix some text +// to the given error. If the error is a multierror.Error, then +// it will be prefixed to each wrapped error. +// +// This is useful to use when appending multiple multierrors +// together in order to give better scoping. +func Prefix(err error, prefix string) error { + if err == nil { + return nil + } + + format := fmt.Sprintf("%s {{err}}", prefix) + switch err := err.(type) { + case *Error: + // Typed nils can reach here, so initialize if we are nil + if err == nil { + err = new(Error) + } + + // Wrap each of the errors + for i, e := range err.Errors { + err.Errors[i] = errwrap.Wrapf(format, e) + } + + return err + default: + return errwrap.Wrapf(format, err) + } +} diff --git a/vendor/github.com/paulmach/go.geojson/.travis.yml b/vendor/github.com/paulmach/go.geojson/.travis.yml new file mode 100644 index 00000000..45a1e09e --- /dev/null +++ b/vendor/github.com/paulmach/go.geojson/.travis.yml @@ -0,0 +1,13 @@ +language: go + +go: + - 1.7 + - tip + +after_script: + - FIXED=$(go vet ./... | wc -l); if [ $FIXED -gt 0 ]; then echo "go vet - $FIXED issues(s), please fix." && exit 2; fi + - FIXED=$(go fmt ./... | wc -l); if [ $FIXED -gt 0 ]; then echo "gofmt - $FIXED file(s) not formatted correctly, please run gofmt to fix this." && exit 2; fi + +script: + - go test -v + diff --git a/vendor/github.com/paulmach/go.geojson/LICENSE b/vendor/github.com/paulmach/go.geojson/LICENSE new file mode 100644 index 00000000..47c6e257 --- /dev/null +++ b/vendor/github.com/paulmach/go.geojson/LICENSE @@ -0,0 +1,18 @@ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/vendor/github.com/paulmach/go.geojson/README.md b/vendor/github.com/paulmach/go.geojson/README.md new file mode 100644 index 00000000..326c1af6 --- /dev/null +++ b/vendor/github.com/paulmach/go.geojson/README.md @@ -0,0 +1,108 @@ +go.geojson +========== + +Go.geojson is a package for **encoding and decoding** [GeoJSON](http://geojson.org/) into Go structs. +Supports both the [json.Marshaler](http://golang.org/pkg/encoding/json/#Marshaler) and [json.Unmarshaler](http://golang.org/pkg/encoding/json/#Unmarshaler) +interfaces as well as [sql.Scanner](http://golang.org/pkg/database/sql/#Scanner) for directly scanning PostGIS query results. +The package also provides helper functions such as `UnmarshalFeatureCollection`, `UnmarshalFeature` and `UnmarshalGeometry`. + +### Important +This package is best for lightweight interaction with GeoJSON. If you want to actually do +stuff with the geometry take a look at [orb/geojson](https://github.com/paulmach/orb/tree/master/geojson) which +decodes the geometries into [orb](https://github.com/paulmach/orb) types which you can do all sorts of things with. + +#### To install + + go get github.com/paulmach/go.geojson + +#### To use, imports as package name `geojson`: + + import "github.com/paulmach/go.geojson" + +[![Build Status](https://travis-ci.org/paulmach/go.geojson.svg?branch=master)](https://travis-ci.org/paulmach/go.geojson) +[![Godoc Reference](https://godoc.org/github.com/paulmach/go.geojson?status.svg)](https://godoc.org/github.com/paulmach/go.geojson) + +## Examples + +* #### Unmarshalling (JSON -> Go) + + go.geojson supports both the [json.Marshaler](http://golang.org/pkg/encoding/json/#Marshaler) and [json.Unmarshaler](http://golang.org/pkg/encoding/json/#Unmarshaler) interfaces as well as helper functions such as `UnmarshalFeatureCollection`, `UnmarshalFeature` and `UnmarshalGeometry`. + + // Feature Collection + rawFeatureJSON := []byte(` + { "type": "FeatureCollection", + "features": [ + { "type": "Feature", + "geometry": {"type": "Point", "coordinates": [102.0, 0.5]}, + "properties": {"prop0": "value0"} + } + ] + }`) + + fc1, err := geojson.UnmarshalFeatureCollection(rawFeatureJSON) + + fc2 := geojson.NewFeatureCollection() + err := json.Unmarshal(rawJSON, fc2) + + // Geometry + rawGeometryJSON := []byte(`{"type": "Point", "coordinates": [102.0, 0.5]}`) + g, err := geojson.UnmarshalGeometry(rawGeometryJSON) + + g.IsPoint() == true + g.Point == []float64{102.0, 0.5} + +* #### Marshalling (Go -> JSON) + + g := geojson.NewPointGeometry([]float64{1, 2}) + rawJSON, err := g.MarshalJSON() + + fc := geojson.NewFeatureCollection() + fc.AddFeature(geojson.NewPointFeature([]float64{1,2})) + rawJSON, err := fc.MarshalJSON() + +* #### Scanning PostGIS query results + + row := db.QueryRow("SELECT ST_AsGeoJSON(the_geom) FROM postgis_table) + + var geometry *geojson.Geometry + row.Scan(&geometry) + +* #### Dealing with different Geometry types + + A geometry can be of several types, causing problems in a statically typed language. + Thus there is a separate attribute on Geometry for each type. + See the [Geometry object](https://godoc.org/github.com/paulmach/go.geojson#Geometry) for more details. + + g := geojson.UnmarshalGeometry([]byte(` + { + "type": "LineString", + "coordinates": [ + [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0] + ] + }`)) + + switch { + case g.IsPoint(): + // do something with g.Point + case g.IsLineString(): + // do something with g.LineString + } + +## Feature Properties + +GeoJSON [Features](http://geojson.org/geojson-spec.html#feature-objects) can have properties of any type. +This can cause issues in a statically typed language such as Go. +So, included are some helper methods on the Feature object to ease the pain. + + // functions to do the casting for you + func (f Feature) PropertyBool(key string) (bool, error) { + func (f Feature) PropertyInt(key string) (int, error) { + func (f Feature) PropertyFloat64(key string) (float64, error) { + func (f Feature) PropertyString(key string) (string, error) { + + // functions that hide the error and let you define default + func (f Feature) PropertyMustBool(key string, def ...bool) bool { + func (f Feature) PropertyMustInt(key string, def ...int) int { + func (f Feature) PropertyMustFloat64(key string, def ...float64) float64 { + func (f Feature) PropertyMustString(key string, def ...string) string { + diff --git a/vendor/github.com/paulmach/go.geojson/boundingbox.go b/vendor/github.com/paulmach/go.geojson/boundingbox.go new file mode 100644 index 00000000..f61fc799 --- /dev/null +++ b/vendor/github.com/paulmach/go.geojson/boundingbox.go @@ -0,0 +1,28 @@ +package geojson + +import "fmt" + +func decodeBoundingBox(bb interface{}) ([]float64, error) { + if bb == nil { + return nil, nil + } + + switch f := bb.(type) { + case []float64: + return f, nil + case []interface{}: + bb := make([]float64, 0, 4) + for _, v := range f { + switch c := v.(type) { + case float64: + bb = append(bb, c) + default: + return nil, fmt.Errorf("bounding box coordinate not usable, got %T", v) + } + + } + return bb, nil + default: + return nil, fmt.Errorf("bounding box property not usable, got %T", bb) + } +} diff --git a/vendor/github.com/paulmach/go.geojson/feature.go b/vendor/github.com/paulmach/go.geojson/feature.go new file mode 100644 index 00000000..6c5ba648 --- /dev/null +++ b/vendor/github.com/paulmach/go.geojson/feature.go @@ -0,0 +1,96 @@ +package geojson + +import ( + "encoding/json" +) + +// A Feature corresponds to GeoJSON feature object +type Feature struct { + ID interface{} `json:"id,omitempty"` + Type string `json:"type"` + BoundingBox []float64 `json:"bbox,omitempty"` + Geometry *Geometry `json:"geometry"` + Properties map[string]interface{} `json:"properties"` + CRS map[string]interface{} `json:"crs,omitempty"` // Coordinate Reference System Objects are not currently supported +} + +// NewFeature creates and initializes a GeoJSON feature given the required attributes. +func NewFeature(geometry *Geometry) *Feature { + return &Feature{ + Type: "Feature", + Geometry: geometry, + Properties: make(map[string]interface{}), + } +} + +// NewPointFeature creates and initializes a GeoJSON feature with a point geometry using the given coordinate. +func NewPointFeature(coordinate []float64) *Feature { + return NewFeature(NewPointGeometry(coordinate)) +} + +// NewMultiPointFeature creates and initializes a GeoJSON feature with a multi-point geometry using the given coordinates. +func NewMultiPointFeature(coordinates ...[]float64) *Feature { + return NewFeature(NewMultiPointGeometry(coordinates...)) +} + +// NewLineStringFeature creates and initializes a GeoJSON feature with a line string geometry using the given coordinates. +func NewLineStringFeature(coordinates [][]float64) *Feature { + return NewFeature(NewLineStringGeometry(coordinates)) +} + +// NewMultiLineStringFeature creates and initializes a GeoJSON feature with a multi-line string geometry using the given lines. +func NewMultiLineStringFeature(lines ...[][]float64) *Feature { + return NewFeature(NewMultiLineStringGeometry(lines...)) +} + +// NewPolygonFeature creates and initializes a GeoJSON feature with a polygon geometry using the given polygon. +func NewPolygonFeature(polygon [][][]float64) *Feature { + return NewFeature(NewPolygonGeometry(polygon)) +} + +// NewMultiPolygonFeature creates and initializes a GeoJSON feature with a multi-polygon geometry using the given polygons. +func NewMultiPolygonFeature(polygons ...[][][]float64) *Feature { + return NewFeature(NewMultiPolygonGeometry(polygons...)) +} + +// NewCollectionFeature creates and initializes a GeoJSON feature with a geometry collection geometry using the given geometries. +func NewCollectionFeature(geometries ...*Geometry) *Feature { + return NewFeature(NewCollectionGeometry(geometries...)) +} + +// MarshalJSON 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) MarshalJSON() ([]byte, error) { + type feature Feature + + fea := &feature{ + ID: f.ID, + Type: "Feature", + Geometry: f.Geometry, + } + + if f.BoundingBox != nil && len(f.BoundingBox) != 0 { + fea.BoundingBox = f.BoundingBox + } + if f.Properties != nil && len(f.Properties) != 0 { + fea.Properties = f.Properties + } + if f.CRS != nil && len(f.CRS) != 0 { + fea.CRS = f.CRS + } + + return json.Marshal(fea) +} + +// UnmarshalFeature decodes the data into a GeoJSON feature. +// Alternately one can call json.Unmarshal(f) directly for the same result. +func UnmarshalFeature(data []byte) (*Feature, error) { + f := &Feature{} + err := json.Unmarshal(data, f) + if err != nil { + return nil, err + } + + return f, nil +} diff --git a/vendor/github.com/paulmach/go.geojson/feature_collection.go b/vendor/github.com/paulmach/go.geojson/feature_collection.go new file mode 100644 index 00000000..1a0af3ec --- /dev/null +++ b/vendor/github.com/paulmach/go.geojson/feature_collection.go @@ -0,0 +1,70 @@ +/* +Package geojson is a library for encoding and decoding GeoJSON into Go structs. +Supports both the json.Marshaler and json.Unmarshaler interfaces as well as helper functions +such as `UnmarshalFeatureCollection`, `UnmarshalFeature` and `UnmarshalGeometry`. +*/ +package geojson + +import ( + "encoding/json" +) + +// A FeatureCollection correlates to a GeoJSON feature collection. +type FeatureCollection struct { + Type string `json:"type"` + BoundingBox []float64 `json:"bbox,omitempty"` + Features []*Feature `json:"features"` + CRS map[string]interface{} `json:"crs,omitempty"` // Coordinate Reference System Objects are not currently supported +} + +// NewFeatureCollection creates and initializes a new feature collection. +func NewFeatureCollection() *FeatureCollection { + return &FeatureCollection{ + Type: "FeatureCollection", + Features: make([]*Feature, 0), + } +} + +// AddFeature appends a feature to the collection. +func (fc *FeatureCollection) AddFeature(feature *Feature) *FeatureCollection { + fc.Features = append(fc.Features, feature) + return fc +} + +// MarshalJSON converts the feature collection object into the proper JSON. +// It will handle the encoding of all the child features and geometries. +// Alternately one can call json.Marshal(fc) directly for the same result. +func (fc FeatureCollection) MarshalJSON() ([]byte, error) { + type featureCollection FeatureCollection + + fcol := &featureCollection{ + Type: "FeatureCollection", + } + + if fc.BoundingBox != nil && len(fc.BoundingBox) != 0 { + fcol.BoundingBox = fc.BoundingBox + } + + fcol.Features = fc.Features + if fcol.Features == nil { + fcol.Features = make([]*Feature, 0) // GeoJSON requires the feature attribute to be at least [] + } + + if fc.CRS != nil && len(fc.CRS) != 0 { + fcol.CRS = fc.CRS + } + + return json.Marshal(fcol) +} + +// 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) { + fc := &FeatureCollection{} + err := json.Unmarshal(data, fc) + if err != nil { + return nil, err + } + + return fc, nil +} diff --git a/vendor/github.com/paulmach/go.geojson/geometry.go b/vendor/github.com/paulmach/go.geojson/geometry.go new file mode 100644 index 00000000..0e16cb22 --- /dev/null +++ b/vendor/github.com/paulmach/go.geojson/geometry.go @@ -0,0 +1,347 @@ +package geojson + +import ( + "encoding/json" + "errors" + "fmt" +) + +// A GeometryType serves to enumerate the different GeoJSON geometry types. +type GeometryType string + +// The geometry types supported by GeoJSON 1.0 +const ( + GeometryPoint GeometryType = "Point" + GeometryMultiPoint GeometryType = "MultiPoint" + GeometryLineString GeometryType = "LineString" + GeometryMultiLineString GeometryType = "MultiLineString" + GeometryPolygon GeometryType = "Polygon" + GeometryMultiPolygon GeometryType = "MultiPolygon" + GeometryCollection GeometryType = "GeometryCollection" +) + +// A Geometry correlates to a GeoJSON geometry object. +type Geometry struct { + Type GeometryType `json:"type"` + BoundingBox []float64 `json:"bbox,omitempty"` + Point []float64 + MultiPoint [][]float64 + LineString [][]float64 + MultiLineString [][][]float64 + Polygon [][][]float64 + MultiPolygon [][][][]float64 + Geometries []*Geometry + CRS map[string]interface{} `json:"crs,omitempty"` // Coordinate Reference System Objects are not currently supported +} + +// NewPointGeometry creates and initializes a point geometry with the give coordinate. +func NewPointGeometry(coordinate []float64) *Geometry { + return &Geometry{ + Type: GeometryPoint, + Point: coordinate, + } +} + +// NewMultiPointGeometry creates and initializes a multi-point geometry with the given coordinates. +func NewMultiPointGeometry(coordinates ...[]float64) *Geometry { + return &Geometry{ + Type: GeometryMultiPoint, + MultiPoint: coordinates, + } +} + +// NewLineStringGeometry creates and initializes a line string geometry with the given coordinates. +func NewLineStringGeometry(coordinates [][]float64) *Geometry { + return &Geometry{ + Type: GeometryLineString, + LineString: coordinates, + } +} + +// NewMultiLineStringGeometry creates and initializes a multi-line string geometry with the given lines. +func NewMultiLineStringGeometry(lines ...[][]float64) *Geometry { + return &Geometry{ + Type: GeometryMultiLineString, + MultiLineString: lines, + } +} + +// NewPolygonGeometry creates and initializes a polygon geometry with the given polygon. +func NewPolygonGeometry(polygon [][][]float64) *Geometry { + return &Geometry{ + Type: GeometryPolygon, + Polygon: polygon, + } +} + +// NewMultiPolygonGeometry creates and initializes a multi-polygon geometry with the given polygons. +func NewMultiPolygonGeometry(polygons ...[][][]float64) *Geometry { + return &Geometry{ + Type: GeometryMultiPolygon, + MultiPolygon: polygons, + } +} + +// NewCollectionGeometry creates and initializes a geometry collection geometry with the given geometries. +func NewCollectionGeometry(geometries ...*Geometry) *Geometry { + return &Geometry{ + Type: GeometryCollection, + Geometries: geometries, + } +} + +// MarshalJSON converts the geometry object into the correct JSON. +// This fulfills the json.Marshaler interface. +func (g Geometry) MarshalJSON() ([]byte, error) { + // defining a struct here lets us define the order of the JSON elements. + type geometry struct { + Type GeometryType `json:"type"` + BoundingBox []float64 `json:"bbox,omitempty"` + Coordinates interface{} `json:"coordinates,omitempty"` + Geometries interface{} `json:"geometries,omitempty"` + CRS map[string]interface{} `json:"crs,omitempty"` + } + + geo := &geometry{ + Type: g.Type, + } + + if g.BoundingBox != nil && len(g.BoundingBox) != 0 { + geo.BoundingBox = g.BoundingBox + } + + switch g.Type { + case GeometryPoint: + geo.Coordinates = g.Point + case GeometryMultiPoint: + geo.Coordinates = g.MultiPoint + case GeometryLineString: + geo.Coordinates = g.LineString + case GeometryMultiLineString: + geo.Coordinates = g.MultiLineString + case GeometryPolygon: + geo.Coordinates = g.Polygon + case GeometryMultiPolygon: + geo.Coordinates = g.MultiPolygon + case GeometryCollection: + geo.Geometries = g.Geometries + } + + return json.Marshal(geo) +} + +// UnmarshalGeometry decodes the data into a GeoJSON geometry. +// Alternately one can call json.Unmarshal(g) directly for the same result. +func UnmarshalGeometry(data []byte) (*Geometry, error) { + g := &Geometry{} + err := json.Unmarshal(data, g) + if err != nil { + return nil, err + } + + return g, nil +} + +// UnmarshalJSON decodes the data into a GeoJSON geometry. +// This fulfills the json.Unmarshaler interface. +func (g *Geometry) UnmarshalJSON(data []byte) error { + var object map[string]interface{} + err := json.Unmarshal(data, &object) + if err != nil { + return err + } + + return decodeGeometry(g, object) +} + +// Scan implements the sql.Scanner interface allowing +// geometry structs to be passed into rows.Scan(...interface{}) +// The columns must be received as GeoJSON Geometry. +// When using PostGIS a spatial column would need to be wrapped in ST_AsGeoJSON. +func (g *Geometry) Scan(value interface{}) error { + var data []byte + + switch value.(type) { + case string: + data = []byte(value.(string)) + case []byte: + data = value.([]byte) + default: + return errors.New("unable to parse this type into geojson") + } + + return g.UnmarshalJSON(data) +} + +func decodeGeometry(g *Geometry, object map[string]interface{}) error { + t, ok := object["type"] + if !ok { + return errors.New("type property not defined") + } + + if s, ok := t.(string); ok { + g.Type = GeometryType(s) + } else { + return errors.New("type property not string") + } + + bb, err := decodeBoundingBox(object["bbox"]) + if err != nil { + return err + } + g.BoundingBox = bb + + switch g.Type { + case GeometryPoint: + g.Point, err = decodePosition(object["coordinates"]) + case GeometryMultiPoint: + g.MultiPoint, err = decodePositionSet(object["coordinates"]) + case GeometryLineString: + g.LineString, err = decodePositionSet(object["coordinates"]) + case GeometryMultiLineString: + g.MultiLineString, err = decodePathSet(object["coordinates"]) + case GeometryPolygon: + g.Polygon, err = decodePathSet(object["coordinates"]) + case GeometryMultiPolygon: + g.MultiPolygon, err = decodePolygonSet(object["coordinates"]) + case GeometryCollection: + g.Geometries, err = decodeGeometries(object["geometries"]) + } + + return err +} + +func decodePosition(data interface{}) ([]float64, error) { + coords, ok := data.([]interface{}) + if !ok { + return nil, fmt.Errorf("not a valid position, got %v", data) + } + + result := make([]float64, 0, len(coords)) + for _, coord := range coords { + if f, ok := coord.(float64); ok { + result = append(result, f) + } else { + return nil, fmt.Errorf("not a valid coordinate, got %v", coord) + } + } + + return result, nil +} + +func decodePositionSet(data interface{}) ([][]float64, error) { + points, ok := data.([]interface{}) + if !ok { + return nil, fmt.Errorf("not a valid set of positions, got %v", data) + } + + result := make([][]float64, 0, len(points)) + for _, point := range points { + if p, err := decodePosition(point); err == nil { + result = append(result, p) + } else { + return nil, err + } + } + + return result, nil +} + +func decodePathSet(data interface{}) ([][][]float64, error) { + sets, ok := data.([]interface{}) + if !ok { + return nil, fmt.Errorf("not a valid path, got %v", data) + } + + result := make([][][]float64, 0, len(sets)) + + for _, set := range sets { + if s, err := decodePositionSet(set); err == nil { + result = append(result, s) + } else { + return nil, err + } + } + + return result, nil +} + +func decodePolygonSet(data interface{}) ([][][][]float64, error) { + polygons, ok := data.([]interface{}) + if !ok { + return nil, fmt.Errorf("not a valid polygon, got %v", data) + } + + result := make([][][][]float64, 0, len(polygons)) + for _, polygon := range polygons { + if p, err := decodePathSet(polygon); err == nil { + result = append(result, p) + } else { + return nil, err + } + } + + return result, nil +} + +func decodeGeometries(data interface{}) ([]*Geometry, error) { + if vs, ok := data.([]interface{}); ok { + geometries := make([]*Geometry, 0, len(vs)) + for _, v := range vs { + g := &Geometry{} + + vmap, ok := v.(map[string]interface{}) + if !ok { + break + } + + err := decodeGeometry(g, vmap) + if err != nil { + return nil, err + } + + geometries = append(geometries, g) + } + + if len(geometries) == len(vs) { + return geometries, nil + } + } + + return nil, fmt.Errorf("not a valid set of geometries, got %v", data) +} + +// IsPoint returns true with the geometry object is a Point type. +func (g *Geometry) IsPoint() bool { + return g.Type == GeometryPoint +} + +// IsMultiPoint returns true with the geometry object is a MultiPoint type. +func (g *Geometry) IsMultiPoint() bool { + return g.Type == GeometryMultiPoint +} + +// IsLineString returns true with the geometry object is a LineString type. +func (g *Geometry) IsLineString() bool { + return g.Type == GeometryLineString +} + +// IsMultiLineString returns true with the geometry object is a LineString type. +func (g *Geometry) IsMultiLineString() bool { + return g.Type == GeometryMultiLineString +} + +// IsPolygon returns true with the geometry object is a Polygon type. +func (g *Geometry) IsPolygon() bool { + return g.Type == GeometryPolygon +} + +// IsMultiPolygon returns true with the geometry object is a MultiPolygon type. +func (g *Geometry) IsMultiPolygon() bool { + return g.Type == GeometryMultiPolygon +} + +// IsCollection returns true with the geometry object is a GeometryCollection type. +func (g *Geometry) IsCollection() bool { + return g.Type == GeometryCollection +} diff --git a/vendor/github.com/paulmach/go.geojson/properties.go b/vendor/github.com/paulmach/go.geojson/properties.go new file mode 100644 index 00000000..d71eed90 --- /dev/null +++ b/vendor/github.com/paulmach/go.geojson/properties.go @@ -0,0 +1,127 @@ +package geojson + +import ( + "fmt" +) + +// SetProperty provides the inverse of all the property functions +// and is here for consistency. +func (f *Feature) SetProperty(key string, value interface{}) { + if f.Properties == nil { + f.Properties = make(map[string]interface{}) + } + f.Properties[key] = value +} + +// PropertyBool type asserts a property to `bool`. +func (f *Feature) PropertyBool(key string) (bool, error) { + if b, ok := (f.Properties[key]).(bool); ok { + return b, nil + } + return false, fmt.Errorf("type assertion of `%s` to bool failed", key) +} + +// PropertyInt type asserts a property to `int`. +func (f *Feature) PropertyInt(key string) (int, error) { + if i, ok := (f.Properties[key]).(int); ok { + return i, nil + } + + if i, ok := (f.Properties[key]).(float64); ok { + return int(i), nil + } + + return 0, fmt.Errorf("type assertion of `%s` to int failed", key) +} + +// PropertyFloat64 type asserts a property to `float64`. +func (f *Feature) PropertyFloat64(key string) (float64, error) { + if i, ok := (f.Properties[key]).(float64); ok { + return i, nil + } + return 0, fmt.Errorf("type assertion of `%s` to float64 failed", key) +} + +// PropertyString type asserts a property to `string`. +func (f *Feature) PropertyString(key string) (string, error) { + if s, ok := (f.Properties[key]).(string); ok { + return s, nil + } + return "", fmt.Errorf("type assertion of `%s` to string failed", key) +} + +// PropertyMustBool guarantees the return of a `bool` (with optional default) +// +// useful when you explicitly want a `bool` in a single value return context: +// myFunc(f.PropertyMustBool("param1"), f.PropertyMustBool("optional_param", true)) +func (f *Feature) PropertyMustBool(key string, def ...bool) bool { + var defaul bool + + b, err := f.PropertyBool(key) + if err == nil { + return b + } + + if len(def) > 0 { + defaul = def[0] + } + + return defaul +} + +// PropertyMustInt guarantees the return of a `bool` (with optional default) +// +// useful when you explicitly want a `bool` in a single value return context: +// myFunc(f.PropertyMustInt("param1"), f.PropertyMustInt("optional_param", 123)) +func (f *Feature) PropertyMustInt(key string, def ...int) int { + var defaul int + + b, err := f.PropertyInt(key) + if err == nil { + return b + } + + if len(def) > 0 { + defaul = def[0] + } + + return defaul +} + +// PropertyMustFloat64 guarantees the return of a `bool` (with optional default) +// +// useful when you explicitly want a `bool` in a single value return context: +// myFunc(f.PropertyMustFloat64("param1"), f.PropertyMustFloat64("optional_param", 10.1)) +func (f *Feature) PropertyMustFloat64(key string, def ...float64) float64 { + var defaul float64 + + b, err := f.PropertyFloat64(key) + if err == nil { + return b + } + + if len(def) > 0 { + defaul = def[0] + } + + return defaul +} + +// PropertyMustString guarantees the return of a `bool` (with optional default) +// +// useful when you explicitly want a `bool` in a single value return context: +// myFunc(f.PropertyMustString("param1"), f.PropertyMustString("optional_param", "default")) +func (f *Feature) PropertyMustString(key string, def ...string) string { + var defaul string + + b, err := f.PropertyString(key) + if err == nil { + return b + } + + if len(def) > 0 { + defaul = def[0] + } + + return defaul +} diff --git a/vendor/github.com/tidwall/gjson/README.md b/vendor/github.com/tidwall/gjson/README.md index 80db5027..059570f9 100644 --- a/vendor/github.com/tidwall/gjson/README.md +++ b/vendor/github.com/tidwall/gjson/README.md @@ -150,10 +150,6 @@ result.Less(token Result, caseSensitive bool) bool The `result.Value()` function returns an `interface{}` which requires type assertion and is one of the following Go types: -The `result.Array()` function returns back an array of values. -If the result represents a non-existent value, then an empty array will be returned. -If the result is not a JSON array, the return value will be an array containing one result. - ```go boolean >> bool number >> float64 @@ -163,6 +159,10 @@ array >> []interface{} object >> map[string]interface{} ``` +The `result.Array()` function returns back an array of values. +If the result represents a non-existent value, then an empty array will be returned. +If the result is not a JSON array, the return value will be an array containing one result. + ### 64-bit integers The `result.Int()` and `result.Uint()` calls are capable of reading all 64 bits, allowing for large JSON integers. diff --git a/vendor/github.com/tidwall/gjson/SYNTAX.md b/vendor/github.com/tidwall/gjson/SYNTAX.md index 5ea0407f..86235b9b 100644 --- a/vendor/github.com/tidwall/gjson/SYNTAX.md +++ b/vendor/github.com/tidwall/gjson/SYNTAX.md @@ -77,14 +77,21 @@ Special purpose characters, such as `.`, `*`, and `?` can be escaped with `\`. fav\.movie "Deer Hunter" ``` -You'll also need to make sure that the `\` character is correctly escaped when hardcoding a path in source code. +You'll also need to make sure that the `\` character is correctly escaped when hardcoding a path in you source code. ```go -res := gjson.Get(json, "fav\\.movie") // must escape the slash -res := gjson.Get(json, `fav\.movie`) // no need to escape the slash +// Go +val := gjson.Get(json, "fav\\.movie") // must escape the slash +val := gjson.Get(json, `fav\.movie`) // no need to escape the slash +``` +```rust +// Rust +let val = gjson::get(json, "fav\\.movie") // must escape the slash +let val = gjson::get(json, r#"fav\.movie"#) // no need to escape the slash ``` + ### Arrays The `#` character allows for digging into JSON Arrays. @@ -248,6 +255,8 @@ gjson.AddModifier("case", func(json, arg string) string { "children.@case:lower.@reverse" ["jack","alex","sara"] ``` +*Note: Custom modifiers are not yet available in the Rust version* + ### Multipaths Starting with v1.3.0, GJSON added the ability to join multiple paths together diff --git a/vendor/github.com/tidwall/gjson/gjson.go b/vendor/github.com/tidwall/gjson/gjson.go index 3c63dc3a..a48b6873 100644 --- a/vendor/github.com/tidwall/gjson/gjson.go +++ b/vendor/github.com/tidwall/gjson/gjson.go @@ -714,10 +714,10 @@ type arrayPathResult struct { alogkey string query struct { on bool + all bool path string op string value string - all bool } } @@ -750,120 +750,27 @@ func parseArrayPath(path string) (r arrayPathResult) { } else if path[1] == '[' || path[1] == '(' { // query r.query.on = true - if true { - qpath, op, value, _, fi, ok := parseQuery(path[i:]) - if !ok { - // bad query, end now - break - } - r.query.path = qpath - r.query.op = op - r.query.value = value - i = fi - 1 - if i+1 < len(path) && path[i+1] == '#' { - r.query.all = true - } - } else { - var end byte - if path[1] == '[' { - end = ']' - } else { - end = ')' - } - i += 2 - // whitespace - for ; i < len(path); i++ { - if path[i] > ' ' { - break - } - } - s := i - for ; i < len(path); i++ { - if path[i] <= ' ' || - path[i] == '!' || - path[i] == '=' || - path[i] == '<' || - path[i] == '>' || - path[i] == '%' || - path[i] == end { - break - } - } - r.query.path = path[s:i] - // whitespace - for ; i < len(path); i++ { - if path[i] > ' ' { - break - } - } - if i < len(path) { - s = i - if path[i] == '!' { - if i < len(path)-1 && (path[i+1] == '=' || - path[i+1] == '%') { - i++ - } - } else if path[i] == '<' || path[i] == '>' { - if i < len(path)-1 && path[i+1] == '=' { - i++ - } - } else if path[i] == '=' { - if i < len(path)-1 && path[i+1] == '=' { - s++ - i++ - } - } - i++ - r.query.op = path[s:i] - // whitespace - for ; i < len(path); i++ { - if path[i] > ' ' { - break - } - } - s = i - for ; i < len(path); i++ { - if path[i] == '"' { - i++ - s2 := i - for ; i < len(path); i++ { - if path[i] > '\\' { - continue - } - if path[i] == '"' { - // look for an escaped slash - if path[i-1] == '\\' { - n := 0 - for j := i - 2; j > s2-1; j-- { - if path[j] != '\\' { - break - } - n++ - } - if n%2 == 0 { - continue - } - } - break - } - } - } else if path[i] == end { - if i+1 < len(path) && path[i+1] == '#' { - r.query.all = true - } - break - } - } - if i > len(path) { - i = len(path) - } - v := path[s:i] - for len(v) > 0 && v[len(v)-1] <= ' ' { - v = v[:len(v)-1] - } - r.query.value = v + qpath, op, value, _, fi, vesc, ok := + parseQuery(path[i:]) + if !ok { + // bad query, end now + break + } + if len(value) > 2 && value[0] == '"' && + value[len(value)-1] == '"' { + value = value[1 : len(value)-1] + if vesc { + value = unescape(value) } } + r.query.path = qpath + r.query.op = op + r.query.value = value + + i = fi - 1 + if i+1 < len(path) && path[i+1] == '#' { + r.query.all = true + } } } continue @@ -889,11 +796,11 @@ func parseArrayPath(path string) (r arrayPathResult) { // # middle // .cap # right func parseQuery(query string) ( - path, op, value, remain string, i int, ok bool, + path, op, value, remain string, i int, vesc, ok bool, ) { if len(query) < 2 || query[0] != '#' || (query[1] != '(' && query[1] != '[') { - return "", "", "", "", i, false + return "", "", "", "", i, false, false } i = 2 j := 0 // start of value part @@ -921,6 +828,7 @@ func parseQuery(query string) ( i++ for ; i < len(query); i++ { if query[i] == '\\' { + vesc = true i++ } else if query[i] == '"' { break @@ -929,7 +837,7 @@ func parseQuery(query string) ( } } if depth > 0 { - return "", "", "", "", i, false + return "", "", "", "", i, false, false } if j > 0 { path = trim(query[2:j]) @@ -966,7 +874,7 @@ func parseQuery(query string) ( path = trim(query[2:i]) remain = query[i+1:] } - return path, op, value, remain, i + 1, true + return path, op, value, remain, i + 1, vesc, true } func trim(s string) string { @@ -1266,9 +1174,6 @@ func parseObject(c *parseContext, i int, path string) (int, bool) { } func queryMatches(rp *arrayPathResult, value Result) bool { rpv := rp.query.value - if len(rpv) > 2 && rpv[0] == '"' && rpv[len(rpv)-1] == '"' { - rpv = rpv[1 : len(rpv)-1] - } if !value.Exists() { return false } @@ -1406,7 +1311,6 @@ func parseArray(c *parseContext, i int, path string) (int, bool) { } return false } - for i < len(c.json)+1 { if !rp.arrch { pmatch = partidx == h @@ -1608,10 +1512,17 @@ func parseArray(c *parseContext, i int, path string) (int, bool) { c.calcd = true return i + 1, true } - if len(multires) > 0 && !c.value.Exists() { - c.value = Result{ - Raw: string(append(multires, ']')), - Type: JSON, + if !c.value.Exists() { + if len(multires) > 0 { + c.value = Result{ + Raw: string(append(multires, ']')), + Type: JSON, + } + } else if rp.query.all { + c.value = Result{ + Raw: "[]", + Type: JSON, + } } } return i + 1, false @@ -2376,6 +2287,12 @@ func validnumber(data []byte, i int) (outi int, ok bool) { // sign if data[i] == '-' { i++ + if i == len(data) { + return i, false + } + if data[i] < '0' || data[i] > '9' { + return i, false + } } // int if i == len(data) { diff --git a/vendor/github.com/tidwall/sjson/README.md b/vendor/github.com/tidwall/sjson/README.md index 5ff00ee2..6b2e0920 100644 --- a/vendor/github.com/tidwall/sjson/README.md +++ b/vendor/github.com/tidwall/sjson/README.md @@ -8,7 +8,7 @@

set a json value quickly

-SJSON is a Go package that provides a [very fast](#performance) and simple way to set a value in a json document. The purpose for this library is to provide efficient json updating for the [SummitDB](https://github.com/tidwall/summitdb) project. +SJSON is a Go package that provides a [very fast](#performance) and simple way to set a value in a json document. For quickly retrieving json values check out [GJSON](https://github.com/tidwall/gjson). For a command line interface check out [JJ](https://github.com/tidwall/jj). diff --git a/vendor/github.com/tidwall/sjson/go.mod b/vendor/github.com/tidwall/sjson/go.mod index db5ae05b..e7fcb9de 100644 --- a/vendor/github.com/tidwall/sjson/go.mod +++ b/vendor/github.com/tidwall/sjson/go.mod @@ -3,6 +3,6 @@ module github.com/tidwall/sjson go 1.14 require ( - github.com/tidwall/gjson v1.6.8 - github.com/tidwall/pretty v1.0.2 + github.com/tidwall/gjson v1.7.4 + github.com/tidwall/pretty v1.1.0 ) diff --git a/vendor/github.com/tidwall/sjson/go.sum b/vendor/github.com/tidwall/sjson/go.sum index bf323c2a..7dd8de53 100644 --- a/vendor/github.com/tidwall/sjson/go.sum +++ b/vendor/github.com/tidwall/sjson/go.sum @@ -1,6 +1,6 @@ -github.com/tidwall/gjson v1.6.8 h1:CTmXMClGYPAmln7652e69B7OLXfTi5ABcPPwjIWUv7w= -github.com/tidwall/gjson v1.6.8/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= +github.com/tidwall/gjson v1.7.4 h1:19cchw8FOxkG5mdLRkGf9jqIqEyqdZhPqW60XfyFxk8= +github.com/tidwall/gjson v1.7.4/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU= -github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8= +github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= diff --git a/vendor/github.com/whosonfirst/go-ioutil/README.md b/vendor/github.com/whosonfirst/go-ioutil/README.md index 59920165..4fe61b3c 100644 --- a/vendor/github.com/whosonfirst/go-ioutil/README.md +++ b/vendor/github.com/whosonfirst/go-ioutil/README.md @@ -1,5 +1,42 @@ # go-ioutil -## Important +Go package for creating instances conforming to the Go 1.16 `io.ReadSeekCloser` interface from a variety of io.Read* instances that implement some but not all of the `io.Reader`, `io.Seeker` and `io.Closer` interfaces. -Work in progress. Documentation to follow. \ No newline at end of file +## Documentation + +[![Go Reference](https://pkg.go.dev/badge/github.com/whosonfirst/go-ioutil.svg)](https://pkg.go.dev/github.com/whosonfirst/go-ioutil) + +## Example + +``` +import ( + "bytes" + "github.com/whosonfirst/go-ioutil" + "io" + "log" +) + +func main(){ + + fh, _ := os.Open("README.md") + + rsc, _ := NewReadSeekCloser(fh) + + body, _ := io.ReadAll(rsc) + + rsc.Seek(0, 0) + + body2, _ := io.ReadAll(rsc) + + same := bytes.Equal(body, body2) + log.Printf("Same %t\n", same) + + rsc.Close() +} +``` + +_Error handling removed for brevity._ + +## See also + +* https://golang.org/pkg/io/#ReadSeekCloser \ No newline at end of file diff --git a/vendor/github.com/whosonfirst/go-ioutil/doc.go b/vendor/github.com/whosonfirst/go-ioutil/doc.go new file mode 100644 index 00000000..954c86d8 --- /dev/null +++ b/vendor/github.com/whosonfirst/go-ioutil/doc.go @@ -0,0 +1,29 @@ +// package ioutil provides methods for creating a new instance conforming to the Go 1.16 io.ReadSeekCloser interface from a variety of io.Read* instances that implement some but not all of the io.Reader, io.Seeker and io.Closer interfaces. +// +// Example +// +// import ( +// "bytes" +// "github.com/whosonfirst/go-ioutil" +// "io" +// "log" +// ) +// +// func main(){ +// +// fh, _ := os.Open("README.md") +// +// rsc, _ := NewReadSeekCloser(fh) +// +// body, _ := io.ReadAll(rsc) +// +// rsc.Seek(0, 0) +// +// body2, _ := io.ReadAll(rsc) +// +// same := bytes.Equal(body, body2) +// log.Printf("Same %t\n", same) +// +// rsc.Close() +// } +package ioutil diff --git a/vendor/github.com/whosonfirst/go-ioutil/readseekcloser.go b/vendor/github.com/whosonfirst/go-ioutil/readseekcloser.go index 805465a7..18bb37ea 100644 --- a/vendor/github.com/whosonfirst/go-ioutil/readseekcloser.go +++ b/vendor/github.com/whosonfirst/go-ioutil/readseekcloser.go @@ -10,6 +10,7 @@ import ( "sync" ) +// Type ReadSeekCloser implements the io.Reader, io.Seeker and io.Closer interfaces. type ReadSeekCloser struct { io.Reader io.Seeker @@ -22,6 +23,40 @@ type ReadSeekCloser struct { mu *sync.RWMutex } +// Create a new NewReadSeekCloser instance conforming to the Go 1.16 `io.ReadSeekCloser` interface. This method accepts the following types: io.ReadSeekCloser, io.Reader, io.ReadCloser and io.ReadSeeker. +func NewReadSeekCloser(fh interface{}) (io.ReadSeekCloser, error) { + + reader := true + seeker := false + closer := false + + switch fh.(type) { + case io.ReadSeekCloser: + return fh.(io.ReadSeekCloser), nil + case io.Reader: + // pass + case io.ReadCloser: + closer = true + case io.ReadSeeker: + seeker = true + default: + return nil, fmt.Errorf("Invalid or unsupported type") + } + + mu := new(sync.RWMutex) + + rsc := &ReadSeekCloser{ + reader: reader, + seeker: seeker, + closer: closer, + fh: fh, + mu: mu, + } + + return rsc, nil +} + +// Read implements the standard Read interface: it reads data from the pipe, blocking until a writer arrives or the write end is closed. If the write end is closed with an error, that error is returned as err; otherwise err is `io.EOF`. func (rsc *ReadSeekCloser) Read(p []byte) (n int, err error) { if rsc.seeker { @@ -37,6 +72,7 @@ func (rsc *ReadSeekCloser) Read(p []byte) (n int, err error) { return br.Read(p) } +// Close closes the reader; subsequent writes to the write half of the pipe will return the error `io.ErrClosedPipe`. func (rsc *ReadSeekCloser) Close() error { if rsc.closer { @@ -46,6 +82,7 @@ func (rsc *ReadSeekCloser) Close() error { return nil } +// Seek implements the `io.Seeker` interface. func (rsc *ReadSeekCloser) Seek(offset int64, whence int) (int64, error) { if rsc.seeker { @@ -81,36 +118,3 @@ func (rsc *ReadSeekCloser) bytesReader() (*bytes.Reader, error) { return br, nil } - -func NewReadSeekCloser(fh interface{}) (io.ReadSeekCloser, error) { - - reader := true - seeker := false - closer := false - - switch fh.(type) { - case io.ReadSeekCloser: - return fh.(io.ReadSeekCloser), nil - case io.Reader: - // pass - case io.ReadCloser: - closer = true - case io.ReadSeeker: - seeker = true - default: - return nil, fmt.Errorf("Invalid or unsupported type") - } - - mu := new(sync.RWMutex) - - rsc := &ReadSeekCloser{ - reader: reader, - seeker: seeker, - closer: closer, - fh: fh, - mu: mu, - } - - return rsc, nil - -} diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/edtf.go b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/edtf.go new file mode 100644 index 00000000..4e35319d --- /dev/null +++ b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/edtf.go @@ -0,0 +1,41 @@ +package feature + +import ( + "fmt" + "github.com/sfomuseum/go-edtf" +) + +var deprecated map[string]string + +func init() { + + deprecated = map[string]string{ + edtf.OPEN_2012: edtf.OPEN, + edtf.UNSPECIFIED_2012: edtf.UNSPECIFIED, + } + +} + +func isDeprecatedEDTF(edtf_str string) bool { + + for test, _ := range deprecated { + + if edtf_str == test { + return true + } + } + + return false +} + +func replaceDeprecatedEDTF(old string) (string, error) { + + new, ok := deprecated[old] + + if !ok { + err := fmt.Errorf("Unknown or unsupported EDTF string '%s' : %v", old, deprecated) + return "", err + } + + return new, nil +} diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/feature.go b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/feature.go new file mode 100644 index 00000000..28a71806 --- /dev/null +++ b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/feature.go @@ -0,0 +1,178 @@ +package feature + +import ( + "encoding/json" + "github.com/tidwall/gjson" + "github.com/whosonfirst/go-whosonfirst-geojson-v2" + "github.com/whosonfirst/go-whosonfirst-geojson-v2/utils" + "io" + "io/ioutil" + "os" +) + +// Feature + +func LoadFeature(body []byte) (geojson.Feature, error) { + + is_wof := isWOF(body) + is_alt := isAlt(body) + + if is_wof && is_alt { + return NewWOFAltFeature(body) + } else if is_wof { + return NewWOFFeature(body) + } else { + return NewGeoJSONFeature(body) + } +} + +func LoadFeatureFromReader(fh io.Reader) (geojson.Feature, error) { + + body, err := UnmarshalFeatureFromReader(fh) + + if err != nil { + return nil, err + } + + return LoadFeature(body) +} + +func LoadFeatureFromFile(path string) (geojson.Feature, error) { + + body, err := UnmarshalFeatureFromFile(path) + + if err != nil { + return nil, err + } + + return LoadFeature(body) +} + +// WOF + +func LoadWOFFeatureFromReader(fh io.Reader) (geojson.Feature, error) { + + body, err := UnmarshalFeatureFromReader(fh) + + if err != nil { + return nil, err + } + + return NewWOFFeature(body) +} + +func LoadWOFFeatureFromFile(path string) (geojson.Feature, error) { + + body, err := UnmarshalFeatureFromFile(path) + + if err != nil { + return nil, err + } + + return NewWOFFeature(body) +} + +func LoadWOFAltFeatureFromReader(fh io.Reader) (geojson.Feature, error) { + + body, err := UnmarshalFeatureFromReader(fh) + + if err != nil { + return nil, err + } + + return NewWOFAltFeature(body) +} + +func LoadWOFAltFeatureFromFile(path string) (geojson.Feature, error) { + + body, err := UnmarshalFeatureFromFile(path) + + if err != nil { + return nil, err + } + + return NewWOFAltFeature(body) +} + +// GeoJSON + +func LoadGeoJSONFeatureFromReader(fh io.Reader) (geojson.Feature, error) { + + body, err := UnmarshalFeatureFromReader(fh) + + if err != nil { + return nil, err + } + + return NewGeoJSONFeature(body) +} + +func LoadGeoJSONFeatureFromFile(path string) (geojson.Feature, error) { + + body, err := UnmarshalFeatureFromFile(path) + + if err != nil { + return nil, err + } + + return NewGeoJSONFeature(body) +} + +func UnmarshalFeature(body []byte) ([]byte, error) { + + var stub interface{} + err := json.Unmarshal(body, &stub) + + if err != nil { + return nil, err + } + + all := []string{ + "geometry", + "geometry.type", + "geometry.coordinates", + "type", + } + + err = utils.EnsureProperties(body, all) + + if err != nil { + return nil, err + } + + return body, nil +} + +func UnmarshalFeatureFromReader(fh io.Reader) ([]byte, error) { + + body, err := ioutil.ReadAll(fh) + + if err != nil { + return nil, err + } + + return UnmarshalFeature(body) +} + +func UnmarshalFeatureFromFile(path string) ([]byte, error) { + + fh, err := os.Open(path) + + if err != nil { + return nil, err + } + + defer fh.Close() + + return UnmarshalFeatureFromReader(fh) +} + +func isWOF(body []byte) bool { + wofid := gjson.GetBytes(body, "properties.wof:id") + return wofid.Exists() +} + +func isAlt(body []byte) bool { + alt_label := gjson.GetBytes(body, "properties.src:alt_label") + return alt_label.Exists() +} diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/geojson.go b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/geojson.go new file mode 100644 index 00000000..c6e4801d --- /dev/null +++ b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/geojson.go @@ -0,0 +1,263 @@ +package feature + +import ( + "encoding/json" + "github.com/sfomuseum/go-edtf" + "github.com/skelterjohn/geom" + "github.com/whosonfirst/go-whosonfirst-flags" + "github.com/whosonfirst/go-whosonfirst-geojson-v2" + "github.com/whosonfirst/go-whosonfirst-geojson-v2/geometry" + props_geom "github.com/whosonfirst/go-whosonfirst-geojson-v2/properties/geometry" + "github.com/whosonfirst/go-whosonfirst-geojson-v2/utils" + "github.com/whosonfirst/go-whosonfirst-spr/v2" + "strings" +) + +type GeoJSONFeature struct { + geojson.Feature + body []byte +} + +type GeoJSONStandardPlacesResult struct { + spr.StandardPlacesResult `json:",omitempty"` + SPRId string `json:"spr:id"` + SPRName string `json:"spr:name"` + SPRPlacetype string `json:"spr:placetype"` + SPRLatitude float64 `json:"spr:latitude"` + SPRLongitude float64 `json:"spr:longitude"` + SPRMinLatitude float64 `json:"spr:min_latitude"` + SPRMinLongitude float64 `json:"spr:min_longitude"` + SPRMaxLatitude float64 `json:"spr:max_latitude"` + SPRMaxLongitude float64 `json:"spr:max_longitude"` +} + +func NewGeoJSONFeature(body []byte) (geojson.Feature, error) { + + var stub interface{} + err := json.Unmarshal(body, &stub) + + if err != nil { + return nil, err + } + + f := GeoJSONFeature{ + body: body, + } + + return &f, nil +} + +func (f *GeoJSONFeature) ContainsCoord(c geom.Coord) (bool, error) { + + return geometry.FeatureContainsCoord(f, c) +} + +func (f *GeoJSONFeature) String() string { + + body, err := json.Marshal(f.body) + + if err != nil { + return "" + } + + return string(body) +} + +func (f *GeoJSONFeature) Bytes() []byte { + + return f.body +} + +func (f *GeoJSONFeature) Id() string { + + possible := []string{ + "id", + "properties.id", + } + + id := utils.StringProperty(f.Bytes(), possible, "") + + if id == "" { + id = f.uid() + } + + return id +} + +func (f *GeoJSONFeature) Name() string { + + possible := []string{ + "properties.name", + } + + name := utils.StringProperty(f.Bytes(), possible, "") + + if name == "" { + name = f.uid() + } + + return name +} + +func (f *GeoJSONFeature) Placetype() string { + + possible := []string{ + "properties.placetype", + } + + pt := utils.StringProperty(f.Bytes(), possible, "") + + if pt == "" { + pt = props_geom.Type(f) + pt = strings.ToLower(pt) + } + + return pt +} + +func (f *GeoJSONFeature) uid() string { + + h, err := utils.GeohashFeature(f) + + if err != nil { + h = "..." + } + + return h +} + +func (f *GeoJSONFeature) BoundingBoxes() (geojson.BoundingBoxes, error) { + return geometry.BoundingBoxesForFeature(f) +} + +func (f *GeoJSONFeature) Polygons() ([]geojson.Polygon, error) { + return geometry.PolygonsForFeature(f) +} + +func (f *GeoJSONFeature) SPR() (spr.StandardPlacesResult, error) { + + bboxes, err := f.BoundingBoxes() + + if err != nil { + return nil, err + } + + mbr := bboxes.MBR() + + lat := mbr.Min.Y + ((mbr.Max.Y - mbr.Min.Y) / 2.0) + lon := mbr.Min.X + ((mbr.Max.X - mbr.Min.X) / 2.0) + + spr := GeoJSONStandardPlacesResult{ + SPRId: f.Id(), + SPRPlacetype: f.Placetype(), + SPRName: f.Name(), + SPRLatitude: lat, + SPRLongitude: lon, + SPRMinLatitude: mbr.Min.Y, + SPRMinLongitude: mbr.Min.X, + SPRMaxLatitude: mbr.Max.Y, + SPRMaxLongitude: mbr.Max.X, + } + + return &spr, nil +} + +func (spr *GeoJSONStandardPlacesResult) Id() string { + return spr.SPRId +} + +func (spr *GeoJSONStandardPlacesResult) ParentId() string { + return "" +} + +func (spr *GeoJSONStandardPlacesResult) Name() string { + return spr.SPRName +} + +func (spr *GeoJSONStandardPlacesResult) Placetype() string { + return spr.SPRPlacetype +} + +func (spr *GeoJSONStandardPlacesResult) Inception() *edtf.EDTFDate { + return nil +} + +func (spr *GeoJSONStandardPlacesResult) Cessation() *edtf.EDTFDate { + return nil +} + +func (spr *GeoJSONStandardPlacesResult) Country() string { + return "XX" +} + +func (spr *GeoJSONStandardPlacesResult) Repo() string { + return "" +} + +func (spr *GeoJSONStandardPlacesResult) Path() string { + return "" +} + +func (spr *GeoJSONStandardPlacesResult) URI() string { + return "" +} + +func (spr *GeoJSONStandardPlacesResult) Latitude() float64 { + return spr.SPRLatitude +} + +func (spr *GeoJSONStandardPlacesResult) Longitude() float64 { + return spr.SPRLongitude +} + +func (spr *GeoJSONStandardPlacesResult) MinLatitude() float64 { + return spr.SPRMinLatitude +} + +func (spr *GeoJSONStandardPlacesResult) MinLongitude() float64 { + return spr.SPRMinLongitude +} + +func (spr *GeoJSONStandardPlacesResult) MaxLatitude() float64 { + return spr.SPRLatitude +} + +func (spr *GeoJSONStandardPlacesResult) MaxLongitude() float64 { + return spr.SPRMaxLongitude +} + +func (spr *GeoJSONStandardPlacesResult) IsCurrent() flags.ExistentialFlag { + return existentialFlag(-1) +} + +func (spr *GeoJSONStandardPlacesResult) IsCeased() flags.ExistentialFlag { + return existentialFlag(-1) +} + +func (spr *GeoJSONStandardPlacesResult) IsDeprecated() flags.ExistentialFlag { + return existentialFlag(-1) +} + +func (spr *GeoJSONStandardPlacesResult) IsSuperseded() flags.ExistentialFlag { + return existentialFlag(-1) +} + +func (spr *GeoJSONStandardPlacesResult) IsSuperseding() flags.ExistentialFlag { + return existentialFlag(-1) +} + +func (spr *GeoJSONStandardPlacesResult) SupersededBy() []int64 { + return []int64{} +} + +func (spr *GeoJSONStandardPlacesResult) Supersedes() []int64 { + return []int64{} +} + +func (spr *GeoJSONStandardPlacesResult) BelongsTo() []int64 { + return []int64{} +} + +func (spr *GeoJSONStandardPlacesResult) LastModified() int64 { + return -1 +} diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/whosonfirst.go b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/whosonfirst.go new file mode 100644 index 00000000..fb676e5c --- /dev/null +++ b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/whosonfirst.go @@ -0,0 +1,454 @@ +package feature + +import ( + "encoding/json" + _ "errors" + "github.com/sfomuseum/go-edtf" + "github.com/sfomuseum/go-edtf/parser" + "github.com/skelterjohn/geom" + "github.com/whosonfirst/go-whosonfirst-flags" + "github.com/whosonfirst/go-whosonfirst-flags/existential" + "github.com/whosonfirst/go-whosonfirst-geojson-v2" + "github.com/whosonfirst/go-whosonfirst-geojson-v2/geometry" + "github.com/whosonfirst/go-whosonfirst-geojson-v2/properties/whosonfirst" + "github.com/whosonfirst/go-whosonfirst-geojson-v2/utils" + "github.com/whosonfirst/go-whosonfirst-placetypes" + "github.com/whosonfirst/go-whosonfirst-spr/v2" + "github.com/whosonfirst/go-whosonfirst-uri" + "github.com/whosonfirst/warning" + "strconv" +) + +type WOFFeature struct { + geojson.Feature + body []byte +} + +type WOFStandardPlacesResult struct { + spr.StandardPlacesResult `json:",omitempty"` + EDTFInception string `json:"edtf:inception"` + EDTFCessation string `json:"edtf:cessation"` + WOFId int64 `json:"wof:id"` + WOFParentId int64 `json:"wof:parent_id"` + WOFName string `json:"wof:name"` + WOFPlacetype string `json:"wof:placetype"` + WOFCountry string `json:"wof:country"` + WOFRepo string `json:"wof:repo"` + WOFPath string `json:"wof:path"` + WOFSupersededBy []int64 `json:"wof:superseded_by"` + WOFSupersedes []int64 `json:"wof:supersedes"` + WOFBelongsTo []int64 `json:"wof:belongsto"` + MZURI string `json:"mz:uri"` + MZLatitude float64 `json:"mz:latitude"` + MZLongitude float64 `json:"mz:longitude"` + MZMinLatitude float64 `json:"mz:min_latitude"` + MZMinLongitude float64 `json:"mz:min_longitude"` + MZMaxLatitude float64 `json:"mz:max_latitude"` + MZMaxLongitude float64 `json:"mz:max_longitude"` + MZIsCurrent int64 `json:"mz:is_current"` + MZIsCeased int64 `json:"mz:is_ceased"` + MZIsDeprecated int64 `json:"mz:is_deprecated"` + MZIsSuperseded int64 `json:"mz:is_superseded"` + MZIsSuperseding int64 `json:"mz:is_superseding"` + WOFLastModified int64 `json:"wof:lastmodified"` +} + +func EnsureWOFFeature(body []byte) error { + + required := []string{ + "properties.wof:id", + "properties.wof:name", + "properties.wof:repo", + "properties.wof:placetype", + // we used to handle these like this but we + // do some jiggling below to account for the + // fact that we might working with an SPR... + // "properties.geom:latitude", + // "properties.geom:longitude", + // "properties.geom:bbox", + } + + err := utils.EnsureProperties(body, required) + + if err != nil { + return err + } + + // strictly speaking we probably want to ensure all if the spr_geom + // properties if we have to test one of them but let's see how this + // works first... (20180223/thisisaaronland) + + required_geom := map[string][]string{ + "properties.geom:latitude": []string{"properties.mz:latitude"}, + "properties.geom:longitude": []string{"properties.mz:latitude"}, + "properties.geom:bbox": []string{"properties.mz:min_latitude", "properties.mz:min_longitude", "properties.mz:max_latitude", "properties.mz:max_longitude"}, + } + + for wof_geom, spr_geom := range required_geom { + + err = utils.EnsureProperties(body, []string{wof_geom}) + + if err == nil { + continue + } + + err = utils.EnsureProperties(body, spr_geom) + + if err != nil { + return err + } + } + + // we may want or need to handle WOF documents with placetypes + // not already defined in core (like for anyone working on datasets + // outside the scope of core...) / there is an open branch of the + // go-whosonfirst-placetypes package for adding custom placetypes + // but it's not at all clear whose vendor-ed (go-wof-pt) package + // will get used so never mind that / we could also add a global flag + // to this package to disable checks but on measure it seems best + // to issue a warning thing that implements the error interface and + // leave the details to individual applications / we are using a + // forked (to the whosonfirst org) version of https://github.com/lunemec/warning + // (20180405/thisisaaronland) + + pt := utils.StringProperty(body, []string{"properties.wof:placetype"}, "") + + if !placetypes.IsValidPlacetype(pt) { + return warning.New("Invalid wof:placetype") + } + + // check wof:repo here? + + return nil +} + +func NewWOFFeature(body []byte) (geojson.Feature, error) { + + var stub interface{} + err := json.Unmarshal(body, &stub) + + if err != nil { + return nil, err + } + + err = EnsureWOFFeature(body) + + if err != nil && !warning.IsWarning(err) { + return nil, err + } + + f := WOFFeature{ + body: body, + } + + // because err might be a warning.Error / see notes above in EnsureWOFFeature + // I don't really love this... (20180405/thisisaaronland) + + return &f, err +} + +func (f *WOFFeature) String() string { + + body, err := json.Marshal(f.body) + + if err != nil { + return "" + } + + return string(body) +} + +func (f *WOFFeature) Bytes() []byte { + return f.body +} + +func (f *WOFFeature) Id() string { + id := whosonfirst.Id(f) + return strconv.FormatInt(id, 10) +} + +func (f *WOFFeature) Name() string { + return whosonfirst.Name(f) +} + +func (f *WOFFeature) Placetype() string { + return whosonfirst.Placetype(f) +} + +func (f *WOFFeature) BoundingBoxes() (geojson.BoundingBoxes, error) { + return geometry.BoundingBoxesForFeature(f) +} + +func (f *WOFFeature) Polygons() ([]geojson.Polygon, error) { + return geometry.PolygonsForFeature(f) +} + +func (f *WOFFeature) ContainsCoord(c geom.Coord) (bool, error) { + return geometry.FeatureContainsCoord(f, c) +} + +func (f *WOFFeature) SPR() (spr.StandardPlacesResult, error) { + + id := whosonfirst.Id(f) + parent_id := whosonfirst.ParentId(f) + name := whosonfirst.Name(f) + placetype := whosonfirst.Placetype(f) + country := whosonfirst.Country(f) + repo := whosonfirst.Repo(f) + + inception := whosonfirst.Inception(f) + cessation := whosonfirst.Cessation(f) + + // See this: We're accounting for all the pre-2019 EDTF spec + // inception but mostly cessation strings by silently swapping + // them out (20210321/straup) + + _, err := parser.ParseString(inception) + + if err != nil { + + if !isDeprecatedEDTF(inception) { + return nil, err + } + + replacement, err := replaceDeprecatedEDTF(inception) + + if err != nil { + return nil, err + } + + inception = replacement + } + + _, err = parser.ParseString(cessation) + + if err != nil { + + if !isDeprecatedEDTF(cessation) { + return nil, err + } + + replacement, err := replaceDeprecatedEDTF(cessation) + + if err != nil { + return nil, err + } + + cessation = replacement + } + + path, err := uri.Id2RelPath(id) + + if err != nil { + return nil, err + } + + uri, err := uri.Id2AbsPath("https://data.whosonfirst.org", id) + + if err != nil { + return nil, err + } + + is_current, err := whosonfirst.IsCurrent(f) + + if err != nil { + return nil, err + } + + is_ceased, err := whosonfirst.IsCeased(f) + + if err != nil { + return nil, err + } + + is_deprecated, err := whosonfirst.IsDeprecated(f) + + if err != nil { + return nil, err + } + + is_superseded, err := whosonfirst.IsSuperseded(f) + + if err != nil { + return nil, err + } + + is_superseding, err := whosonfirst.IsSuperseding(f) + + if err != nil { + return nil, err + } + + centroid, err := whosonfirst.Centroid(f) + + if err != nil { + return nil, err + } + + bboxes, err := f.BoundingBoxes() + + if err != nil { + return nil, err + } + + coord := centroid.Coord() + mbr := bboxes.MBR() + + superseded_by := whosonfirst.SupersededBy(f) + supersedes := whosonfirst.Supersedes(f) + belongsto := whosonfirst.BelongsTo(f) + + lastmod := whosonfirst.LastModified(f) + + spr := WOFStandardPlacesResult{ + WOFId: id, + WOFParentId: parent_id, + WOFPlacetype: placetype, + WOFName: name, + WOFCountry: country, + WOFRepo: repo, + WOFPath: path, + WOFSupersedes: supersedes, + WOFSupersededBy: superseded_by, + WOFBelongsTo: belongsto, + EDTFInception: inception, + EDTFCessation: cessation, + MZURI: uri, + MZLatitude: coord.Y, + MZLongitude: coord.X, + MZMinLatitude: mbr.Min.Y, + MZMinLongitude: mbr.Min.X, + MZMaxLatitude: mbr.Max.Y, + MZMaxLongitude: mbr.Max.X, + MZIsCurrent: is_current.Flag(), + MZIsCeased: is_ceased.Flag(), + MZIsDeprecated: is_deprecated.Flag(), + MZIsSuperseded: is_superseded.Flag(), + MZIsSuperseding: is_superseding.Flag(), + WOFLastModified: lastmod, + } + + return &spr, nil +} + +func (spr *WOFStandardPlacesResult) Id() string { + return strconv.FormatInt(spr.WOFId, 10) +} + +func (spr *WOFStandardPlacesResult) ParentId() string { + return strconv.FormatInt(spr.WOFParentId, 10) +} + +func (spr *WOFStandardPlacesResult) Name() string { + return spr.WOFName +} + +func (spr *WOFStandardPlacesResult) Inception() *edtf.EDTFDate { + return spr.edtfDate(spr.EDTFInception) +} + +func (spr *WOFStandardPlacesResult) Cessation() *edtf.EDTFDate { + return spr.edtfDate(spr.EDTFCessation) +} + +func (spr *WOFStandardPlacesResult) edtfDate(edtf_str string) *edtf.EDTFDate { + + d, err := parser.ParseString(edtf_str) + + if err != nil { + return nil + } + + return d +} + +func (spr *WOFStandardPlacesResult) Placetype() string { + return spr.WOFPlacetype +} + +func (spr *WOFStandardPlacesResult) Country() string { + return spr.WOFCountry +} + +func (spr *WOFStandardPlacesResult) Repo() string { + return spr.WOFRepo +} + +func (spr *WOFStandardPlacesResult) Path() string { + return spr.WOFPath +} + +func (spr *WOFStandardPlacesResult) URI() string { + return spr.MZURI +} + +func (spr *WOFStandardPlacesResult) Latitude() float64 { + return spr.MZLatitude +} + +func (spr *WOFStandardPlacesResult) Longitude() float64 { + return spr.MZLongitude +} + +func (spr *WOFStandardPlacesResult) MinLatitude() float64 { + return spr.MZMinLatitude +} + +func (spr *WOFStandardPlacesResult) MinLongitude() float64 { + return spr.MZMinLongitude +} + +func (spr *WOFStandardPlacesResult) MaxLatitude() float64 { + return spr.MZLatitude +} + +func (spr *WOFStandardPlacesResult) MaxLongitude() float64 { + return spr.MZMaxLongitude +} + +func (spr *WOFStandardPlacesResult) IsCurrent() flags.ExistentialFlag { + return existentialFlag(spr.MZIsCurrent) +} + +func (spr *WOFStandardPlacesResult) IsCeased() flags.ExistentialFlag { + return existentialFlag(spr.MZIsCeased) +} + +func (spr *WOFStandardPlacesResult) IsDeprecated() flags.ExistentialFlag { + return existentialFlag(spr.MZIsDeprecated) +} + +func (spr *WOFStandardPlacesResult) IsSuperseded() flags.ExistentialFlag { + return existentialFlag(spr.MZIsSuperseded) +} + +func (spr *WOFStandardPlacesResult) IsSuperseding() flags.ExistentialFlag { + return existentialFlag(spr.MZIsSuperseding) +} + +func (spr *WOFStandardPlacesResult) SupersededBy() []int64 { + return spr.WOFSupersededBy +} + +func (spr *WOFStandardPlacesResult) Supersedes() []int64 { + return spr.WOFSupersedes +} + +func (spr *WOFStandardPlacesResult) BelongsTo() []int64 { + return spr.WOFBelongsTo +} + +func (spr *WOFStandardPlacesResult) LastModified() int64 { + return spr.WOFLastModified +} + +// we're going to assume that this won't fail since we already go through +// the process of instantiating `flags.ExistentialFlag` thingies in SPR() +// if we need to we'll just cache those instances in the `spr *WOFStandardPlacesResult` +// thingy (and omit them from the JSON output) but today that is unnecessary +// (20170816/thisisaaronland) + +func existentialFlag(i int64) flags.ExistentialFlag { + fl, _ := existential.NewKnownUnknownFlag(i) + return fl +} diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/whosonfirst_alt.go b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/whosonfirst_alt.go new file mode 100644 index 00000000..39ce9229 --- /dev/null +++ b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/feature/whosonfirst_alt.go @@ -0,0 +1,289 @@ +package feature + +import ( + "encoding/json" + "errors" + "fmt" + "github.com/sfomuseum/go-edtf" + "github.com/skelterjohn/geom" + "github.com/whosonfirst/go-whosonfirst-flags" + "github.com/whosonfirst/go-whosonfirst-geojson-v2" + "github.com/whosonfirst/go-whosonfirst-geojson-v2/geometry" + props_wof "github.com/whosonfirst/go-whosonfirst-geojson-v2/properties/whosonfirst" + "github.com/whosonfirst/go-whosonfirst-geojson-v2/utils" + "github.com/whosonfirst/go-whosonfirst-spr/v2" + "github.com/whosonfirst/go-whosonfirst-uri" + "github.com/whosonfirst/warning" + "strconv" + "strings" +) + +type WOFAltFeature struct { + geojson.Feature + body []byte +} + +type WOFAltStandardPlacesResult struct { + spr.StandardPlacesResult `json:",omitempty"` + WOFId string `json:"wof:id"` + WOFName string `json:"wof:name"` + WOFPlacetype string `json:"wof:placetype"` + MZLatitude float64 `json:"mz:latitude"` + MZLongitude float64 `json:"mz:longitude"` + MZMinLatitude float64 `json:"mz:min_latitude"` + MZMinLongitude float64 `json:"mz:min_longitude"` + MZMaxLatitude float64 `json:"mz:max_latitude"` + MZMaxLongitude float64 `json:"mz:max_longitude"` + WOFPath string `json:"wof:path"` + WOFRepo string `json:"wof:repo"` +} + +func EnsureWOFAltFeature(body []byte) error { + + required := []string{ + "properties.wof:id", + "properties.wof:repo", + "properties.src:alt_label", + } + + err := utils.EnsureProperties(body, required) + + if err != nil { + return err + } + + return nil +} + +func NewWOFAltFeature(body []byte) (geojson.Feature, error) { + + var stub interface{} + err := json.Unmarshal(body, &stub) + + if err != nil { + return nil, err + } + + err = EnsureWOFAltFeature(body) + + if err != nil && !warning.IsWarning(err) { + return nil, err + } + + f := WOFAltFeature{ + body: body, + } + + return &f, nil +} + +func (f *WOFAltFeature) ContainsCoord(c geom.Coord) (bool, error) { + + return geometry.FeatureContainsCoord(f, c) +} + +func (f *WOFAltFeature) String() string { + + body, err := json.Marshal(f.body) + + if err != nil { + return "" + } + + return string(body) +} + +func (f *WOFAltFeature) Bytes() []byte { + + return f.body +} + +func (f *WOFAltFeature) Id() string { + + id := props_wof.Id(f) + return strconv.FormatInt(id, 10) +} + +func (f *WOFAltFeature) Name() string { + + id := f.Id() + + src_geom := props_wof.Source(f) + + return fmt.Sprintf("%s alt geometry (%s)", id, src_geom) +} + +func (f *WOFAltFeature) Placetype() string { + return "alt" +} + +func (f *WOFAltFeature) BoundingBoxes() (geojson.BoundingBoxes, error) { + return geometry.BoundingBoxesForFeature(f) +} + +func (f *WOFAltFeature) Polygons() ([]geojson.Polygon, error) { + return geometry.PolygonsForFeature(f) +} + +func (f *WOFAltFeature) SPR() (spr.StandardPlacesResult, error) { + + id := props_wof.Id(f) + alt_label := props_wof.AltLabel(f) + label_parts := strings.Split(alt_label, "-") + + if len(label_parts) == 0 { + return nil, errors.New("Invalid src:alt_label property") + } + + alt_geom := &uri.AltGeom{ + Source: label_parts[0], + } + + if len(label_parts) >= 2 { + alt_geom.Function = label_parts[1] + } + + if len(label_parts) >= 3 { + alt_geom.Extras = label_parts[2:] + } + + uri_args := &uri.URIArgs{ + IsAlternate: true, + AltGeom: alt_geom, + } + + rel_path, err := uri.Id2RelPath(id, uri_args) + + if err != nil { + return nil, err + } + + repo := props_wof.Repo(f) + + bboxes, err := f.BoundingBoxes() + + if err != nil { + return nil, err + } + + mbr := bboxes.MBR() + + lat := mbr.Min.Y + ((mbr.Max.Y - mbr.Min.Y) / 2.0) + lon := mbr.Min.X + ((mbr.Max.X - mbr.Min.X) / 2.0) + + spr := WOFAltStandardPlacesResult{ + WOFId: f.Id(), + WOFPlacetype: f.Placetype(), + WOFName: f.Name(), + MZLatitude: lat, + MZLongitude: lon, + MZMinLatitude: mbr.Min.Y, + MZMinLongitude: mbr.Min.X, + MZMaxLatitude: mbr.Max.Y, + MZMaxLongitude: mbr.Max.X, + WOFPath: rel_path, + WOFRepo: repo, + } + + return &spr, nil +} + +func (spr *WOFAltStandardPlacesResult) Id() string { + return spr.WOFId +} + +func (spr *WOFAltStandardPlacesResult) ParentId() string { + return "-1" +} + +func (spr *WOFAltStandardPlacesResult) Name() string { + return spr.WOFName +} + +func (spr *WOFAltStandardPlacesResult) Placetype() string { + return spr.WOFPlacetype +} + +func (spr *WOFAltStandardPlacesResult) Country() string { + return "XX" +} + +func (spr *WOFAltStandardPlacesResult) Repo() string { + return spr.WOFRepo +} + +func (spr *WOFAltStandardPlacesResult) Path() string { + return spr.WOFPath +} + +func (spr *WOFAltStandardPlacesResult) URI() string { + return "" +} + +func (spr *WOFAltStandardPlacesResult) Latitude() float64 { + return spr.MZLatitude +} + +func (spr *WOFAltStandardPlacesResult) Longitude() float64 { + return spr.MZLongitude +} + +func (spr *WOFAltStandardPlacesResult) MinLatitude() float64 { + return spr.MZMinLatitude +} + +func (spr *WOFAltStandardPlacesResult) MinLongitude() float64 { + return spr.MZMinLongitude +} + +func (spr *WOFAltStandardPlacesResult) MaxLatitude() float64 { + return spr.MZLatitude +} + +func (spr *WOFAltStandardPlacesResult) MaxLongitude() float64 { + return spr.MZMaxLongitude +} + +func (spr *WOFAltStandardPlacesResult) Inception() *edtf.EDTFDate { + return nil +} + +func (spr *WOFAltStandardPlacesResult) Cessation() *edtf.EDTFDate { + return nil +} + +func (spr *WOFAltStandardPlacesResult) IsCurrent() flags.ExistentialFlag { + return existentialFlag(-1) +} + +func (spr *WOFAltStandardPlacesResult) IsCeased() flags.ExistentialFlag { + return existentialFlag(-1) +} + +func (spr *WOFAltStandardPlacesResult) IsDeprecated() flags.ExistentialFlag { + return existentialFlag(-1) +} + +func (spr *WOFAltStandardPlacesResult) IsSuperseded() flags.ExistentialFlag { + return existentialFlag(-1) +} + +func (spr *WOFAltStandardPlacesResult) IsSuperseding() flags.ExistentialFlag { + return existentialFlag(-1) +} + +func (spr *WOFAltStandardPlacesResult) SupersededBy() []int64 { + return []int64{} +} + +func (spr *WOFAltStandardPlacesResult) Supersedes() []int64 { + return []int64{} +} + +func (spr *WOFAltStandardPlacesResult) BelongsTo() []int64 { + return []int64{} +} + +func (spr *WOFAltStandardPlacesResult) LastModified() int64 { + return -1 +} diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/geometry/bbox.go b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/geometry/bbox.go new file mode 100644 index 00000000..5263f674 --- /dev/null +++ b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/geometry/bbox.go @@ -0,0 +1,48 @@ +package geometry + +import ( + "github.com/skelterjohn/geom" + "github.com/whosonfirst/go-whosonfirst-geojson-v2" +) + +type Bboxes struct { + geojson.BoundingBoxes `json:",omitempty"` + BBoxesBounds []*geom.Rect `json:"bounds"` + BBoxesMBR geom.Rect `json:"mbr"` +} + +func (b Bboxes) Bounds() []*geom.Rect { + return b.BBoxesBounds +} + +func (b Bboxes) MBR() geom.Rect { + return b.BBoxesMBR +} + +func BoundingBoxesForFeature(f geojson.Feature) (geojson.BoundingBoxes, error) { + + polys, err := PolygonsForFeature(f) + + if err != nil { + return nil, err + } + + mbr := geom.NilRect() + bounds := make([]*geom.Rect, 0) + + for _, poly := range polys { + + ext := poly.ExteriorRing() + b := ext.Path.Bounds() + + mbr.ExpandToContainRect(*b) + bounds = append(bounds, b) + } + + wb := Bboxes{ + BBoxesBounds: bounds, + BBoxesMBR: mbr, + } + + return wb, nil +} diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/geometry/polygon.go b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/geometry/polygon.go new file mode 100644 index 00000000..9380a212 --- /dev/null +++ b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/geometry/polygon.go @@ -0,0 +1,165 @@ +package geometry + +import ( + "errors" + "fmt" + pm_geojson "github.com/paulmach/go.geojson" + "github.com/skelterjohn/geom" + "github.com/tidwall/gjson" + "github.com/whosonfirst/go-whosonfirst-geojson-v2" + _ "log" + _ "time" +) + +type Polygon struct { + geojson.Polygon `json:",omitempty"` + Exterior geom.Polygon `json:"exterior"` + Interior []geom.Polygon `json:"interior"` +} + +func (p Polygon) ExteriorRing() geom.Polygon { + return p.Exterior +} + +func (p Polygon) InteriorRings() []geom.Polygon { + return p.Interior +} + +func (p Polygon) ContainsCoord(c geom.Coord) bool { + + ext := p.ExteriorRing() + + if !ext.ContainsCoord(c) { + return false + } + + for _, int := range p.InteriorRings() { + + if int.ContainsCoord(c) { + return false + } + } + + return true +} + +func GeometryForFeature(f geojson.Feature) (*pm_geojson.Geometry, error) { + geom_rsp := gjson.GetBytes(f.Bytes(), "geometry") + return pm_geojson.UnmarshalGeometry([]byte(geom_rsp.String())) +} + +func PolygonsForFeature(f geojson.Feature) ([]geojson.Polygon, error) { + + g, err := GeometryForFeature(f) + + if err != nil { + return nil, err + } + + polys := make([]geojson.Polygon, 0) + + switch g.Type { + + case "LineString": + + exterior_ring := newRing(g.LineString) + + polygon := Polygon{ + Exterior: exterior_ring, + } + + polys = []geojson.Polygon{polygon} + + case "Polygon": + + polygon := newPolygon(g.Polygon) + polys = []geojson.Polygon{polygon} + + case "MultiPolygon": + + for _, poly := range g.MultiPolygon { + polygon := newPolygon(poly) + polys = append(polys, polygon) + } + + case "Point": + + lat := g.Point[1] + lon := g.Point[0] + + pt := []float64{ + lon, + lat, + } + + coords := [][]float64{ + pt, pt, + pt, pt, + pt, + } + + exterior_ring := newRing(coords) + + if err != nil { + return nil, err + } + + interior_rings := make([]geom.Polygon, 0) + + polygon := Polygon{ + Exterior: exterior_ring, + Interior: interior_rings, + } + + polys = []geojson.Polygon{polygon} + return polys, nil + + case "MultiPoint": + + exterior_ring := newRing(g.MultiPoint) + + polygon := Polygon{ + Exterior: exterior_ring, + } + + polys = []geojson.Polygon{polygon} + + default: + + msg := fmt.Sprintf("Invalid geometry type '%s'", g.Type) + return nil, errors.New(msg) + } + + return polys, nil +} + +func newRing(coords [][]float64) geom.Polygon { + + poly := geom.Polygon{} + + for _, pt := range coords { + poly.AddVertex(geom.Coord{X: pt[0], Y: pt[1]}) + } + + return poly +} + +func newPolygon(rings [][][]float64) Polygon { + + exterior := newRing(rings[0]) + interior := make([]geom.Polygon, 0) + + if len(rings) > 1 { + + for _, coords := range rings[1:] { + interior = append(interior, newRing(coords)) + } + } + + polygon := Polygon{ + Exterior: exterior, + Interior: interior, + } + + return polygon +} diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/geometry/spatial.go b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/geometry/spatial.go new file mode 100644 index 00000000..487be894 --- /dev/null +++ b/vendor/github.com/whosonfirst/go-whosonfirst-geojson-v2/geometry/spatial.go @@ -0,0 +1,32 @@ +package geometry + +import ( + "github.com/skelterjohn/geom" + "github.com/whosonfirst/go-whosonfirst-geojson-v2" +) + +func FeatureContainsCoord(f geojson.Feature, c geom.Coord) (bool, error) { + + polys, err := PolygonsForFeature(f) + + if err != nil { + return false, err + } + + return PolygonsContainsCoord(polys, c) +} + +func PolygonsContainsCoord(polys []geojson.Polygon, c geom.Coord) (bool, error) { + + contains := false + + for _, p := range polys { + + if p.ContainsCoord(c) { + contains = true + break + } + } + + return contains, nil +} diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-iterate/emitter/featurecollection.go b/vendor/github.com/whosonfirst/go-whosonfirst-iterate/emitter/featurecollection.go index efae9908..d2e2a471 100644 --- a/vendor/github.com/whosonfirst/go-whosonfirst-iterate/emitter/featurecollection.go +++ b/vendor/github.com/whosonfirst/go-whosonfirst-iterate/emitter/featurecollection.go @@ -95,7 +95,7 @@ func (idx *FeatureCollectionEmitter) WalkURI(ctx context.Context, index_cb Emitt } if !ok { - return nil + continue } _, err = fh.Seek(0, 0) diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-spatial/README.md b/vendor/github.com/whosonfirst/go-whosonfirst-spatial/README.md index 84068e0b..c2cd5293 100644 --- a/vendor/github.com/whosonfirst/go-whosonfirst-spatial/README.md +++ b/vendor/github.com/whosonfirst/go-whosonfirst-spatial/README.md @@ -10,6 +10,8 @@ _Once complete this package will supersede the [go-whosonfirst-pip-v2](https://g The following is adapted from [an answer I gave when asked about the differences](https://github.com/whosonfirst/go-whosonfirst-pip-v2/issues/34) between this package and the [go-whosonfirst-pip-v2](https://github.com/whosonfirst/go-whosonfirst-pip-v2) package from which it is derived: +_March 2021: What follows is still true conceptually but some of the specific details have changed and will be updated shortly._ + --- It is an attempt to de-couple the various components that make up `go-whosonfirst-pip-v2` – indexing, storage, querying and serving – in to separate packages in order to allow for more flexibility. @@ -145,21 +147,10 @@ type SpatialDatabase interface { } ``` -### PropertiesReader - -``` -type PropertiesReader interface { - IndexFeature(context.Context, wof_geojson.Feature) error - PropertiesResponseResultsWithStandardPlacesResults(context.Context, spr.StandardPlacesResults, []string) (*spatial.PropertiesResponseResults, error) - Close(context.Context) error -} -``` - ## See also * https://github.com/whosonfirst/go-whosonfirst-spatial-rtree * https://github.com/whosonfirst/go-whosonfirst-spatial-sqlite -* https://github.com/whosonfirst/go-whosonfirst-spatial-http -* https://github.com/whosonfirst/go-whosonfirst-spatial-http-sqlite -* https://github.com/whosonfirst/go-whosonfirst-spatial-grpc -* https://github.com/whosonfirst/go-whosonfirst-geojson-v2 +* https://github.com/whosonfirst/go-whosonfirst-spatial-pip +* https://github.com/whosonfirst/go-whosonfirst-spatial-www +* https://github.com/whosonfirst/go-whosonfirst-spatial-grpc \ No newline at end of file diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-spatial/flags/common.go b/vendor/github.com/whosonfirst/go-whosonfirst-spatial/flags/common.go index 7f641eee..96fb6b54 100644 --- a/vendor/github.com/whosonfirst/go-whosonfirst-spatial/flags/common.go +++ b/vendor/github.com/whosonfirst/go-whosonfirst-spatial/flags/common.go @@ -5,14 +5,25 @@ import ( "fmt" "github.com/sfomuseum/go-flags/flagset" "github.com/sfomuseum/go-flags/lookup" + "github.com/whosonfirst/go-reader" "github.com/whosonfirst/go-whosonfirst-spatial/database" - "github.com/whosonfirst/go-reader" ) func CommonFlags() (*flag.FlagSet, error) { fs := flagset.NewFlagSet("common") + err := AppendCommonFlags(fs) + + if err != nil { + return nil, err + } + + return fs, nil +} + +func AppendCommonFlags(fs *flag.FlagSet) error { + // spatial databases available_databases := database.Schemes() @@ -22,7 +33,7 @@ func CommonFlags() (*flag.FlagSet, error) { available_readers := reader.Schemes() desc_readers := fmt.Sprintf("A valid whosonfirst/go-reader.Reader URI. Available options are: %s", available_readers) - + fs.String(PROPERTIES_READER_URI, "", desc_readers) fs.Bool(IS_WOF, true, "Input data is WOF-flavoured GeoJSON. (Pass a value of '0' or 'false' if you need to index non-WOF documents.") @@ -37,7 +48,7 @@ func CommonFlags() (*flag.FlagSet, error) { fs.Bool(VERBOSE, false, "Be chatty.") - return fs, nil + return nil } func ValidateCommonFlags(fs *flag.FlagSet) error { diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-spatial/go.mod b/vendor/github.com/whosonfirst/go-whosonfirst-spatial/go.mod index 0b0adbe6..e529afec 100644 --- a/vendor/github.com/whosonfirst/go-whosonfirst-spatial/go.mod +++ b/vendor/github.com/whosonfirst/go-whosonfirst-spatial/go.mod @@ -4,15 +4,15 @@ go 1.16 require ( github.com/aaronland/go-roster v0.0.2 - github.com/sfomuseum/go-flags v0.8.1 + github.com/sfomuseum/go-flags v0.8.2 github.com/skelterjohn/geom v0.0.0-20180103142417-96f3e8a219c5 - github.com/tidwall/gjson v1.7.1 - github.com/tidwall/sjson v1.1.5 + github.com/tidwall/gjson v1.7.5 + github.com/tidwall/sjson v1.1.6 github.com/whosonfirst/go-reader v0.5.0 github.com/whosonfirst/go-sanitize v0.1.0 github.com/whosonfirst/go-whosonfirst-flags v0.4.2 - github.com/whosonfirst/go-whosonfirst-geojson-v2 v0.16.1 - github.com/whosonfirst/go-whosonfirst-iterate v1.1.0 + github.com/whosonfirst/go-whosonfirst-geojson-v2 v0.16.3 + github.com/whosonfirst/go-whosonfirst-iterate v1.1.1 github.com/whosonfirst/go-whosonfirst-log v0.1.0 github.com/whosonfirst/go-whosonfirst-placetypes v0.3.0 github.com/whosonfirst/go-whosonfirst-spr/v2 v2.0.0 diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-spatial/go.sum b/vendor/github.com/whosonfirst/go-whosonfirst-spatial/go.sum index 887db333..3f086d6b 100644 --- a/vendor/github.com/whosonfirst/go-whosonfirst-spatial/go.sum +++ b/vendor/github.com/whosonfirst/go-whosonfirst-spatial/go.sum @@ -28,6 +28,8 @@ github.com/sfomuseum/go-flags v0.8.0 h1:gRmrsoWJ/KTNLxitnc+UZBL7nAghi2Vd/Xh45dZT github.com/sfomuseum/go-flags v0.8.0/go.mod h1:ML3DTNbF9xnjExSdS/9FtVLjIUhRU5gm/ehzISv+t2w= github.com/sfomuseum/go-flags v0.8.1 h1:xiytUeZKoVHLf7lvICwUMHrGJxVRmR7C1s/3ozm/oLg= github.com/sfomuseum/go-flags v0.8.1/go.mod h1:ML3DTNbF9xnjExSdS/9FtVLjIUhRU5gm/ehzISv+t2w= +github.com/sfomuseum/go-flags v0.8.2 h1:elSU3KWMo442d1YjXu5Y/bokxvkGV+OrgAHshHZaeIo= +github.com/sfomuseum/go-flags v0.8.2/go.mod h1:ML3DTNbF9xnjExSdS/9FtVLjIUhRU5gm/ehzISv+t2w= github.com/skelterjohn/geom v0.0.0-20180103142417-96f3e8a219c5 h1:qQF/q/+xaKD4CAVz3zfuvpij8U4ihSGIhHfOROI4NFc= github.com/skelterjohn/geom v0.0.0-20180103142417-96f3e8a219c5/go.mod h1:w8cQIijHlvvZM7afYlixPThHAdD+AkRFw3Mb9yQ2Y+I= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -37,24 +39,20 @@ github.com/tidwall/gjson v1.6.8 h1:CTmXMClGYPAmln7652e69B7OLXfTi5ABcPPwjIWUv7w= github.com/tidwall/gjson v1.6.8/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= github.com/tidwall/gjson v1.7.1 h1:hwkZ6V1/EF8FxNhKJrIXQwSscyl2yWCZ1SkOCQYHSHA= github.com/tidwall/gjson v1.7.1/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= +github.com/tidwall/gjson v1.7.4/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= +github.com/tidwall/gjson v1.7.5 h1:zmAN/xmX7OtpAkv4Ovfso60r/BiCi5IErCDYGNJu+uc= +github.com/tidwall/gjson v1.7.5/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU= github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8= github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tidwall/sjson v1.1.5 h1:wsUceI/XDyZk3J1FUvuuYlK62zJv2HO2Pzb8A5EWdUE= -github.com/tidwall/sjson v1.1.5/go.mod h1:VuJzsZnTowhSxWdOgsAnb886i4AjEyTkk7tNtsL7EYE= +github.com/tidwall/sjson v1.1.6 h1:8fDdlahON04OZBlTQCIatW8FstSFJz8oxidj5h0rmSQ= +github.com/tidwall/sjson v1.1.6/go.mod h1:KN3FZ7odvXIHPbJdhNorK/M9lWweVUbXsXXhrJ/kGOA= github.com/whosonfirst/go-ioutil v0.0.1 h1:cCrEYen6NDvHfjzV2q4u/VB21u2kTOwDnUGRlMI8Z9o= github.com/whosonfirst/go-ioutil v0.0.1/go.mod h1:2dS1vWdAIkiHDvDF8fYyjv6k2NISmwaIjJJeEDBEdvg= -github.com/whosonfirst/go-reader v0.2.1 h1:URhO7a2rDZizElGPy7lrWDpV1c4ceInYMGNQPXsQFiM= -github.com/whosonfirst/go-reader v0.2.1/go.mod h1:qUhz3OWefOUX/G1nzCEUzJskDjkF+l9oKPOM3K2fAJI= -github.com/whosonfirst/go-reader v0.3.0 h1:MlNNRzPQMqJKMoU6fueihOxLjtcw1KcfAdTyds+u29s= -github.com/whosonfirst/go-reader v0.3.0/go.mod h1:ffg8ww1158rNNqStFx64EGmDL5m5WZPsoMqR6wohOWE= -github.com/whosonfirst/go-reader v0.4.0 h1:9RQEVL+UYUbIuzj4oxSR9bd/sNIQ53/1jePNhpuYZKo= -github.com/whosonfirst/go-reader v0.4.0/go.mod h1:ffg8ww1158rNNqStFx64EGmDL5m5WZPsoMqR6wohOWE= github.com/whosonfirst/go-reader v0.5.0 h1:nx+ai0F6JXouw+7Dln34dmYglw+3sQ6sG4JZGOJ/sqA= github.com/whosonfirst/go-reader v0.5.0/go.mod h1:4ou/wZUss2CDZp27QK5ySDc8p98GVWvUiqqmwEprjgk= github.com/whosonfirst/go-sanitize v0.1.0 h1:ygSqCnakwdzH/m8UEa15zXGDsoo5/JJeRkgmAjXZrBU= @@ -62,57 +60,30 @@ github.com/whosonfirst/go-sanitize v0.1.0/go.mod h1:p/emgbafMM0p5iVAz2XWwecYPl06 github.com/whosonfirst/go-whosonfirst-cli v0.1.0/go.mod h1:Edy+amD+fMq1QS1yxB3u8maA8I93q/LG7JRNh+fsdfc= 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-flags v0.1.0/go.mod h1:bovMiQphaVhqemXFmNVf9Ts0tqnWtzHRFMUSKX+zTE8= -github.com/whosonfirst/go-whosonfirst-flags v0.2.0 h1:zia/L+rhKSQ5iruITPnwU9lqsd1SavvF+HYRubEARSs= github.com/whosonfirst/go-whosonfirst-flags v0.2.0/go.mod h1:ECd0AJJZIlybmjTGB9z+CPz9pSiMTwxur7fPKmDnoqI= -github.com/whosonfirst/go-whosonfirst-flags v0.3.0 h1:pdmhcVBnykVkgETLfHdw6+Po5rqEt6PWPPqI18bQpDw= -github.com/whosonfirst/go-whosonfirst-flags v0.3.0/go.mod h1:kewFjxBiE00SqjjIanm5DPI81SYvx93wVb3ogwV/PMk= -github.com/whosonfirst/go-whosonfirst-flags v0.4.0 h1:3qEz1v7rALk+TqVstW9DKQOWrMqUIIFInmOiLvsKBZY= -github.com/whosonfirst/go-whosonfirst-flags v0.4.0/go.mod h1:kewFjxBiE00SqjjIanm5DPI81SYvx93wVb3ogwV/PMk= -github.com/whosonfirst/go-whosonfirst-flags v0.4.1 h1:QcbkD29cBxQnZeLpCoeuT+cC3bdMSOcwsxyj3/O3Jxk= -github.com/whosonfirst/go-whosonfirst-flags v0.4.1/go.mod h1:kewFjxBiE00SqjjIanm5DPI81SYvx93wVb3ogwV/PMk= github.com/whosonfirst/go-whosonfirst-flags v0.4.2 h1:HWjy/0MfAQMdCj4M9hi3LAITgK/D+cuDWGHP37mFeZo= github.com/whosonfirst/go-whosonfirst-flags v0.4.2/go.mod h1:kewFjxBiE00SqjjIanm5DPI81SYvx93wVb3ogwV/PMk= -github.com/whosonfirst/go-whosonfirst-geojson-v2 v0.15.1 h1:Kxsd+B6U97YRbIlpBxrZpXNXDYqJYwEBxhgUUzlQky0= -github.com/whosonfirst/go-whosonfirst-geojson-v2 v0.15.1/go.mod h1:zAXmgT1EjBAt5HawVNyr3/N53j5iVqxFVha8VBhkra0= -github.com/whosonfirst/go-whosonfirst-geojson-v2 v0.16.0 h1:o+Q4noTqXYKeDD+dMrf4lb1yFvly5PDAcF4ASKwHwpc= -github.com/whosonfirst/go-whosonfirst-geojson-v2 v0.16.0/go.mod h1:cWVV68R2xgKtmOcAsQmWYsdv8QhIhT4k9DmqRbqrt/4= -github.com/whosonfirst/go-whosonfirst-geojson-v2 v0.16.1 h1:zUJoEVZzmstNybujlUkLXMbJ4ucKIfLS9IgIX0XE/Sk= -github.com/whosonfirst/go-whosonfirst-geojson-v2 v0.16.1/go.mod h1:R3GximAGJWLCITU2eh3I5Vtyze/usjOl5LTGQCDI89Y= +github.com/whosonfirst/go-whosonfirst-geojson-v2 v0.16.3 h1:EaLfTJqWj7q3bVCNil+F9QtVylxiyWNlo09ZEUDtf+E= +github.com/whosonfirst/go-whosonfirst-geojson-v2 v0.16.3/go.mod h1:R3GximAGJWLCITU2eh3I5Vtyze/usjOl5LTGQCDI89Y= github.com/whosonfirst/go-whosonfirst-hash v0.1.0 h1:FpnclPIb+8M1uhSXfl3z8nYcG/3O59vgfkdV+m0hQpA= github.com/whosonfirst/go-whosonfirst-hash v0.1.0/go.mod h1:1ZdCFZTnQt5bwnsj2daB9yHilKOKToVh+Tyj/Z8TbUk= -github.com/whosonfirst/go-whosonfirst-index/v2 v2.0.0 h1:PnPLYvCnBrg7Vvw3ho8tc2lMMRBncHfjVSoGeQ5X5Hw= -github.com/whosonfirst/go-whosonfirst-index/v2 v2.0.0/go.mod h1:BiIcEdIv7W6CZd/sc9m2npVo/rXCVUvWL7dldUb4bu8= -github.com/whosonfirst/go-whosonfirst-iterate v1.0.0 h1:ioIfP81ovXs1wr2vyickbG9o8DUahmcmJyP9Ih1DAOQ= -github.com/whosonfirst/go-whosonfirst-iterate v1.0.0/go.mod h1:nxCcHykhwN5E5ropkHetMsi1Gi/Mh2gooK93i02nXsI= -github.com/whosonfirst/go-whosonfirst-iterate v1.0.1 h1:XTQ6cvfEnNLS5sgx7WLKR9YwkSCuZRh4p6+EqxYjQAU= -github.com/whosonfirst/go-whosonfirst-iterate v1.0.1/go.mod h1:ceLMHQ9s3naZLFcKeUvokP0Sw7/BmwuZJiaQt/mVO0I= -github.com/whosonfirst/go-whosonfirst-iterate v1.1.0 h1:mirgJrwyMS7Qdle3DpHCt9go1AG8lSP+tf0R/nxlmSQ= -github.com/whosonfirst/go-whosonfirst-iterate v1.1.0/go.mod h1:ceLMHQ9s3naZLFcKeUvokP0Sw7/BmwuZJiaQt/mVO0I= +github.com/whosonfirst/go-whosonfirst-iterate v1.1.1 h1:7J8kq86bZgO2uUEJcSW7ciWTaoMC9k5obFQ90lp7ZpQ= +github.com/whosonfirst/go-whosonfirst-iterate v1.1.1/go.mod h1:ceLMHQ9s3naZLFcKeUvokP0Sw7/BmwuZJiaQt/mVO0I= github.com/whosonfirst/go-whosonfirst-log v0.1.0 h1:mWYI5hn16uyeLxBmPsLSvYV4rQKK/cxGVhM+bC2ZoGc= github.com/whosonfirst/go-whosonfirst-log v0.1.0/go.mod h1:pmgBbxZSnjGVy2nsUJBBMcFagxwIKLlmRsW7ClkXmac= -github.com/whosonfirst/go-whosonfirst-placetypes v0.1.0/go.mod h1:Jdmug2QQLbrmg+UcYGz8k575GnrOEg63vZVS46e5fMs= -github.com/whosonfirst/go-whosonfirst-placetypes v0.2.4 h1:hl6BgQ6ozmrCAbw0if0EtGDBn2x7vqgXv6ucWE0lOJ0= github.com/whosonfirst/go-whosonfirst-placetypes v0.2.4/go.mod h1:yl0zZ5tfK80C0kl34pJcPB3mZC5XXR7ybQJ5OJyEcDU= github.com/whosonfirst/go-whosonfirst-placetypes v0.3.0 h1:68kuizK8FXjfEIOKlqWemhs7gyMBIgpLJDbCZF8+8Ok= github.com/whosonfirst/go-whosonfirst-placetypes v0.3.0/go.mod h1:ez0VFkGFbgT2/z2oi3PIuW6FewsZ2+5glyfDD79XEHk= github.com/whosonfirst/go-whosonfirst-sources v0.1.0 h1:JuKLa6KWke22jBfJ1pM9WQHoz1/3pbDv2C+aR+THPPQ= github.com/whosonfirst/go-whosonfirst-sources v0.1.0/go.mod h1:EUMHyGzUmqPPxlMmOp+28BFeoBdxxE0HCKRd67lkqGM= -github.com/whosonfirst/go-whosonfirst-spr v0.1.0 h1:5qE629nCiucF2upy5NjPOEl9cFatsljykYY0l2JKgAk= -github.com/whosonfirst/go-whosonfirst-spr v0.1.0/go.mod h1:R8GtEVz1GVSnwwOjzcoVUd172ZK26Q7hQSLI6SGG7lM= github.com/whosonfirst/go-whosonfirst-spr/v2 v2.0.0 h1:UQ1n/uODS50mckZpXYe5GKm8XwoUUC1jRcNN8oiW2uc= github.com/whosonfirst/go-whosonfirst-spr/v2 v2.0.0/go.mod h1:tveSSFDn8XoiCeAMarSCn769lA6e3Y0/Qi8S19Jz7Gw= github.com/whosonfirst/go-whosonfirst-uri v0.2.0 h1:iODHdyvW+8IXqHZTixZ/9GEZy1dVKGj6dMRg7fn0d2M= github.com/whosonfirst/go-whosonfirst-uri v0.2.0/go.mod h1:8eaDVcc4v+HHHEDaRbApdmhPwM4/JQllw2PktvZcPVs= -github.com/whosonfirst/go-writer v0.3.0 h1:BQfYxKpnRXE7Rda3C7FLlJS/U3wrqlXve69TlATaaoE= -github.com/whosonfirst/go-writer v0.3.0/go.mod h1:kFzhremCFtnkJdmviwJEPLFYKQ5+vq6ocJPxt1bHPFY= -github.com/whosonfirst/go-writer v0.4.0 h1:pwZWJVvmRzdvTwoHKxRO4VY013ltp9NA7nsTTK4X/L8= -github.com/whosonfirst/go-writer v0.4.0/go.mod h1:kFzhremCFtnkJdmviwJEPLFYKQ5+vq6ocJPxt1bHPFY= github.com/whosonfirst/go-writer v0.4.1 h1:pAZ/cwaCM129PfwYy28ggCIRfL98OkrYxNnAxz2dksg= github.com/whosonfirst/go-writer v0.4.1/go.mod h1:kFzhremCFtnkJdmviwJEPLFYKQ5+vq6ocJPxt1bHPFY= 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.0/go.mod h1:cAez7FpC/UEUrbiOXZO15v2JM8eijtFHQlN93AGFy1k= github.com/whosonfirst/warning v0.1.1 h1:h29zL3VNL9VUHztkAAndzblhrDHyik9z47OuUR2Vovw= github.com/whosonfirst/warning v0.1.1/go.mod h1:/unEMzhB9YaMeEwTJpzLN3kM5LiSxdJhKEsf/OQhn6s= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-uri/LICENSE b/vendor/github.com/whosonfirst/go-whosonfirst-uri/LICENSE index 8c0eed17..605a7ad7 100644 --- a/vendor/github.com/whosonfirst/go-whosonfirst-uri/LICENSE +++ b/vendor/github.com/whosonfirst/go-whosonfirst-uri/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016, Mapzen +Copyright (c) 2016, Aaron Straup Cope All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-uri/README.md b/vendor/github.com/whosonfirst/go-whosonfirst-uri/README.md index b15d7ada..b1a5be78 100644 --- a/vendor/github.com/whosonfirst/go-whosonfirst-uri/README.md +++ b/vendor/github.com/whosonfirst/go-whosonfirst-uri/README.md @@ -2,9 +2,9 @@ Go package for working with URIs for Who's On First documents -## Install +## Documentation -All of this package's dependencies are bundled with the code in the `vendor` directory. +[![Go Reference](https://pkg.go.dev/badge/github.com/whosonfirst/go-whosonfirst-uri.svg)](https://pkg.go.dev/github.com/whosonfirst/go-whosonfirst-uri) ## Example diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-uri/doc.go b/vendor/github.com/whosonfirst/go-whosonfirst-uri/doc.go new file mode 100644 index 00000000..22571779 --- /dev/null +++ b/vendor/github.com/whosonfirst/go-whosonfirst-uri/doc.go @@ -0,0 +1,43 @@ +// package uri provides methods for parsing and constructing URIs for Who's On First documents. +// +// Example (simple) +// +// import ( +// "github.com/whosonfirst/go-whosonfirst-uri" +// ) +// +// fname, _ := uri.Id2Fname(101736545) +// rel_path, _ := uri.Id2RelPath(101736545) +// abs_path, _ := uri.Id2AbsPath("/usr/local/data", 101736545) +// +// Produces: +// +// 101736545.geojson +// 101/736/545/101736545.geojson +// /usr/local/data/101/736/545/101736545.geojson +// +// Example (fancy) +// +// import ( +// "github.com/whosonfirst/go-whosonfirst-uri" +// ) +// +// source := "mapzen" +// function := "display" +// extras := []string{ "1024" } +// +// args := uri.NewAlternateURIArgs(source, function, extras...) +// +// fname, _ := uri.Id2Fname(101736545, args) +// rel_path, _ := uri.Id2RelPath(101736545, args) +// abs_path, _ := uri.Id2AbsPath("/usr/local/data", 101736545, args) +// +//Produces: +// +// 101736545-alt-mapzen-display-1024.geojson +// 101/736/545/101736545-alt-mapzen-display-1024.geojson +// /usr/local/data/101/736/545/101736545-alt-mapzen-display-1024.geojson +// +// For detailed description of the rules governing alternate geometries please consult: +// https://github.com/whosonfirst/whosonfirst-cookbook/blob/master/how_to/creating_alt_geometries.md +package uri diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-uri/parse.go b/vendor/github.com/whosonfirst/go-whosonfirst-uri/parse.go index 83457089..baaddfc6 100644 --- a/vendor/github.com/whosonfirst/go-whosonfirst-uri/parse.go +++ b/vendor/github.com/whosonfirst/go-whosonfirst-uri/parse.go @@ -9,12 +9,17 @@ import ( "strings" ) +// URI_REGEXP is the regular expression used to parse Who's On First URIs. +const URI_REGEXP string = `^(\d+)(?:\-alt(?:\-([a-zA-Z0-9_]+(?:\-[a-zA-Z0-9_]+(?:\-[a-zA-Z0-9_\-]+)?)?)))?(?:\.[^\.]+|\/)?$` + +// re_uri is the internal *regexp.Regexp instance used to parse Who's On First URIs. var re_uri *regexp.Regexp func init() { - re_uri = regexp.MustCompile(`^(\d+)(?:\-alt(?:\-([a-zA-Z0-9_]+(?:\-[a-zA-Z0-9_]+(?:\-[a-zA-Z0-9_\-]+)?)?)))?(?:\.[^\.]+|\/)?$`) + re_uri = regexp.MustCompile(URI_REGEXP) } +// ParseURI will parse a Who's On First URI into its unique ID and any optional "alternate" geometry information. func ParseURI(path string) (int64, *URIArgs, error) { abs_path, err := filepath.Abs(path) @@ -75,8 +80,7 @@ func ParseURI(path string) (int64, *URIArgs, error) { return wofid, args, nil } -// - +// ISWOFFile returns a boolean value indicating whether a path is a valid Who's On First URI. func IsWOFFile(path string) (bool, error) { _, _, err := ParseURI(path) @@ -94,6 +98,7 @@ func IsWOFFile(path string) (bool, error) { return true, nil } +// ISAltFile returns a boolean value indicating whether a path is a valid Who's On First URI for an "alternate" geometry. func IsAltFile(path string) (bool, error) { _, uri_args, err := ParseURI(path) @@ -106,6 +111,7 @@ func IsAltFile(path string) (bool, error) { return is_alt, nil } +// AltGeomFromPath parses a path and returns its *AltGeom instance if it is a valid Who's On First "alternate" geometry URI. func AltGeomFromPath(path string) (*AltGeom, error) { _, uri_args, err := ParseURI(path) @@ -121,13 +127,15 @@ func AltGeomFromPath(path string) (*AltGeom, error) { return uri_args.AltGeom, nil } +// IdFromPath parses a path and return its unique Who's On First ID. func IdFromPath(path string) (int64, error) { id, _, err := ParseURI(path) return id, err } -func RepoFromPath(path string) (string, error) { +// RepoFromPath parses a path and if it is a valid whosonfirst-data Who's On First URI returns a GitHub repository name. +func WhosOnFirstDataRepoFromPath(path string) (string, error) { abs_path, err := filepath.Abs(path) diff --git a/vendor/github.com/whosonfirst/go-whosonfirst-uri/uri.go b/vendor/github.com/whosonfirst/go-whosonfirst-uri/uri.go index 382b84a9..93436881 100644 --- a/vendor/github.com/whosonfirst/go-whosonfirst-uri/uri.go +++ b/vendor/github.com/whosonfirst/go-whosonfirst-uri/uri.go @@ -10,18 +10,27 @@ import ( "strings" ) +// URIArgs is a struct indicating whether or not a URI is considered an alternate geometry and specific details if it is. type URIArgs struct { - IsAlternate bool - AltGeom *AltGeom + // Boolean value indicating whether or not a URI is considered an alternate geometry + IsAlternate bool `json:"is_alternate"` + // And *AltGeom struct containing details about an alternate geometry + AltGeom *AltGeom `json:"alternate_geometry"` } +// AltGeom is a struct containing details about an alternate geometry type AltGeom struct { - Source string - Function string - Extras []string - Strict bool + // The source of the alternate geometry. This value is required and SHOULD match a corresponding entry in the whosonfirst/whosonfirst-sources repository. + Source string `json:"source"` + // The labeled function for the alternate geometry. This value MAY be a controlled value relative to `Source`. + Function string `json:"function"` + // A list of optional strings to append to the alternate geometry's URI. + Extras []string `json:"extras,omitempty"` + // A boolean value used to indicate whether the `Source` value has a corresponding entry in the whosonfirst/whosonfirst-sources repository. + Strict bool `json:"strict"` } +// Return the string value for an alternate geometry. func (a *AltGeom) String() (string, error) { source := a.Source @@ -56,6 +65,7 @@ func (a *AltGeom) String() (string, error) { return alt_str, nil } +// Return a `URIArgs` struct whose IsAlternate flag is false. func NewDefaultURIArgs() *URIArgs { alt_geom := &AltGeom{} @@ -68,6 +78,7 @@ func NewDefaultURIArgs() *URIArgs { return &u } +// Return a `URIArgs` struct representing an alternate geometry using the arguments defined in `source`, `function` and `extras`. func NewAlternateURIArgs(source string, function string, extras ...string) *URIArgs { alt_geom := &AltGeom{ @@ -86,6 +97,7 @@ func NewAlternateURIArgs(source string, function string, extras ...string) *URIA // 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. func Id2Fname(id int64, args ...*URIArgs) (string, error) { str_id := strconv.FormatInt(id, 10) @@ -115,6 +127,7 @@ func Id2Fname(id int64, args ...*URIArgs) (string, error) { return fname, nil } +// Id2Path parses a Who's On First ID in to directory tree that would contain that ID. func Id2Path(id int64) (string, error) { parts := []string{} @@ -135,6 +148,7 @@ func Id2Path(id int64) (string, error) { return path, nil } +// Id2RelPath parses a Who's On First ID and one or more URIArgs instances (in practice just one instance) in to a relative path for that ID. This method joins the output of the `Id2Path` and `Id2Fname` methods. func Id2RelPath(id int64, args ...*URIArgs) (string, error) { fname, err := Id2Fname(id, args...) @@ -153,6 +167,7 @@ func Id2RelPath(id int64, args ...*URIArgs) (string, error) { return rel_path, nil } +// Id2AbsPath parses a Who's On First ID and one or more URIArgs instances (in practice just one instance) in to a absolute URL for that ID. This method joins the `root` URL and the output of the `Id2RelPath` method. func Id2AbsPath(root string, id int64, args ...*URIArgs) (string, error) { rel, err := Id2RelPath(id, args...) diff --git a/vendor/github.com/whosonfirst/warning/.gitignore b/vendor/github.com/whosonfirst/warning/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/whosonfirst/warning/LICENSE b/vendor/github.com/whosonfirst/warning/LICENSE new file mode 100644 index 00000000..a5ca1d15 --- /dev/null +++ b/vendor/github.com/whosonfirst/warning/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2018, Lukáš Němec +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/whosonfirst/warning/README.md b/vendor/github.com/whosonfirst/warning/README.md new file mode 100644 index 00000000..c2e3d3a5 --- /dev/null +++ b/vendor/github.com/whosonfirst/warning/README.md @@ -0,0 +1,25 @@ +# warning [![GoDoc](https://godoc.org/github.com/lunemec/warning?status.svg)](http://godoc.org/github.com/lunemec/warning) [![Go Report Card](https://goreportcard.com/badge/github.com/lunemec/warning)](https://goreportcard.com/report/github.com/lunemec/warning) +Package warning provides a simple way to handle errors that should not stop +execution (return err), but rather continue. + +`go get github.com/lunemec/warning` + +Common Go idiom is this: +```go +if err != nil { + return err +} +``` + +But what if you wanted to distinguish between error that ends execution and +error that should just be logged? +This package provides you with just that. + +```go +if err != nil && !warning.IsWarning(err) { + //This is executed only if err is not a warning. + return +} +``` + +It also works well with https://github.com/pkg/errors and https://github.com/hashicorp/go-multierror. diff --git a/vendor/github.com/whosonfirst/warning/go.mod b/vendor/github.com/whosonfirst/warning/go.mod new file mode 100644 index 00000000..2f87fdf7 --- /dev/null +++ b/vendor/github.com/whosonfirst/warning/go.mod @@ -0,0 +1,9 @@ +module github.com/whosonfirst/warning + +go 1.12 + +require ( + github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce // indirect + github.com/hashicorp/go-multierror v0.0.0-20171204182908-b7773ae21874 + github.com/pkg/errors v0.8.0 // indirect +) diff --git a/vendor/github.com/whosonfirst/warning/go.sum b/vendor/github.com/whosonfirst/warning/go.sum new file mode 100644 index 00000000..ff467b60 --- /dev/null +++ b/vendor/github.com/whosonfirst/warning/go.sum @@ -0,0 +1,6 @@ +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce h1:prjrVgOk2Yg6w+PflHoszQNLTUh4kaByUcEWM/9uin4= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v0.0.0-20171204182908-b7773ae21874 h1:em+tTnzgU7N22woTBMcSJAOW7tRHAkK597W+MD/CpK8= +github.com/hashicorp/go-multierror v0.0.0-20171204182908-b7773ae21874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= +github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/vendor/github.com/whosonfirst/warning/warning.go b/vendor/github.com/whosonfirst/warning/warning.go new file mode 100644 index 00000000..da4b9e8d --- /dev/null +++ b/vendor/github.com/whosonfirst/warning/warning.go @@ -0,0 +1,69 @@ +// Package warning provides a simple way to handle errors that should not stop +// execution (return err), but rather continue. +// +// Common Go idiom is this: +// +// if err != nil { +// return err +// } +// +// But what if you wanted to distinguish between error that ends execution and +// error that should just be logged? +// This package provides you with just that. +// +// if err != nil && warning.IsWarning(err) { +// // This is executed only if err is not a warning. +// return +// } +// +// It also works well with https://github.com/pkg/errors and https://github.com/hashicorp/go-multierror. +package warning + +import ( + "fmt" + + "github.com/hashicorp/go-multierror" +) + +// Warning type wraps error interface. This type is used to represent error that +// should not cause stopping of execution, but just be logged and continue. +type Warning struct { + error +} + +// New creates new Warning from a message. +func New(message string) error { + return Warning{fmt.Errorf("%s", message)} +} + +// IsWarning returns true if given error is Warning type. +func IsWarning(err error) bool { + switch v := err.(type) { + case Warning: + return true + case *multierror.Error: + // In case of multierror, we have to iterate over all of wrapped errors + // and return true only if ALL of errors are Warnings. + for _, merr := range v.WrappedErrors() { + if !IsWarning(merr) { + return false + } + } + return true + } + return false +} + +// Wrap wraps any error into Warning. +func Wrap(err error) error { + // Do not wrap nil. + if err == nil { + return nil + } + return Warning{err} +} + +// Cause returns the underlying cause of Warning. +func (w *Warning) Cause() error { + return w.error +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 9f2f3b40..c5ed28ea 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2,6 +2,10 @@ github.com/aaronland/go-json-query # github.com/aaronland/go-roster v0.0.2 github.com/aaronland/go-roster +# github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce +github.com/hashicorp/errwrap +# github.com/hashicorp/go-multierror v0.0.0-20171204182908-b7773ae21874 +github.com/hashicorp/go-multierror # github.com/mattn/go-sqlite3 v2.0.2+incompatible github.com/mattn/go-sqlite3 # github.com/mmcloughlin/geohash v0.10.0 @@ -11,6 +15,8 @@ github.com/natefinch/atomic # github.com/patrickmn/go-cache v2.1.0+incompatible ## explicit github.com/patrickmn/go-cache +# github.com/paulmach/go.geojson v1.4.0 +github.com/paulmach/go.geojson # github.com/sfomuseum/go-edtf v0.2.3 github.com/sfomuseum/go-edtf github.com/sfomuseum/go-edtf/calendar @@ -29,19 +35,19 @@ github.com/sfomuseum/go-flags/multi # github.com/skelterjohn/geom v0.0.0-20180103142417-96f3e8a219c5 ## explicit github.com/skelterjohn/geom -# github.com/tidwall/gjson v1.7.2 +# github.com/tidwall/gjson v1.7.5 github.com/tidwall/gjson # github.com/tidwall/match v1.0.3 github.com/tidwall/match # github.com/tidwall/pretty v1.1.0 github.com/tidwall/pretty -# github.com/tidwall/sjson v1.1.5 +# github.com/tidwall/sjson v1.1.6 github.com/tidwall/sjson # github.com/twpayne/go-geom v1.3.6 github.com/twpayne/go-geom github.com/twpayne/go-geom/encoding/geojson github.com/twpayne/go-geom/encoding/wkt -# github.com/whosonfirst/go-ioutil v0.0.1 +# github.com/whosonfirst/go-ioutil v1.0.0 ## explicit github.com/whosonfirst/go-ioutil # github.com/whosonfirst/go-reader v0.5.0 @@ -63,12 +69,14 @@ github.com/whosonfirst/go-whosonfirst-flags/placetypes # github.com/whosonfirst/go-whosonfirst-geojson-v2 v0.16.3 ## explicit github.com/whosonfirst/go-whosonfirst-geojson-v2 +github.com/whosonfirst/go-whosonfirst-geojson-v2/feature +github.com/whosonfirst/go-whosonfirst-geojson-v2/geometry github.com/whosonfirst/go-whosonfirst-geojson-v2/properties/geometry github.com/whosonfirst/go-whosonfirst-geojson-v2/properties/whosonfirst github.com/whosonfirst/go-whosonfirst-geojson-v2/utils # github.com/whosonfirst/go-whosonfirst-hash v0.1.0 github.com/whosonfirst/go-whosonfirst-hash -# github.com/whosonfirst/go-whosonfirst-iterate v1.1.0 +# github.com/whosonfirst/go-whosonfirst-iterate v1.1.1 github.com/whosonfirst/go-whosonfirst-iterate/emitter github.com/whosonfirst/go-whosonfirst-iterate/filters # github.com/whosonfirst/go-whosonfirst-log v0.1.0 @@ -83,7 +91,7 @@ github.com/whosonfirst/go-whosonfirst-placetypes/placetypes # github.com/whosonfirst/go-whosonfirst-sources v0.1.0 github.com/whosonfirst/go-whosonfirst-sources github.com/whosonfirst/go-whosonfirst-sources/sources -# github.com/whosonfirst/go-whosonfirst-spatial v0.0.55 +# github.com/whosonfirst/go-whosonfirst-spatial v0.0.56 ## explicit github.com/whosonfirst/go-whosonfirst-spatial github.com/whosonfirst/go-whosonfirst-spatial/api @@ -107,10 +115,12 @@ github.com/whosonfirst/go-whosonfirst-sqlite-features/tables # github.com/whosonfirst/go-whosonfirst-sqlite-spr v0.0.6 ## explicit github.com/whosonfirst/go-whosonfirst-sqlite-spr -# github.com/whosonfirst/go-whosonfirst-uri v0.2.0 +# github.com/whosonfirst/go-whosonfirst-uri v1.0.1 ## explicit github.com/whosonfirst/go-whosonfirst-uri # github.com/whosonfirst/go-writer v0.4.1 github.com/whosonfirst/go-writer # github.com/whosonfirst/walk v0.0.1 github.com/whosonfirst/walk +# github.com/whosonfirst/warning v0.1.1 +github.com/whosonfirst/warning