[
  {
    "path": ".github/workflows/tests.yml",
    "content": "on:\n  push:\n    branches:\n    - master\n  pull_request:\nname: Tests\njobs:\n  test:\n    strategy:\n      matrix:\n        go-version: [1.13.x, 1.14.x]\n        platform: [ubuntu-latest, macos-latest, windows-latest]\n    runs-on: ${{ matrix.platform }}\n    steps:\n    - name: Install Go\n      uses: actions/setup-go@v1\n      with:\n        go-version: ${{ matrix.go-version }}\n    - name: Checkout code\n      uses: actions/checkout@v2\n    - name: Test\n      run: |\n        go version\n        go test -race ./...\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Vellum\n\nWe look forward to your contributions, but ask that you first review these guidelines.\n\n### Sign the CLA\n\nAs Vellum is a Couchbase project we require contributors accept the [Couchbase Contributor License Agreement](http://review.couchbase.org/static/individual_agreement.html). To sign this agreement log into the Couchbase [code review tool](http://review.couchbase.org/). The Vellum project does not use this code review tool but it is still used to track acceptance of the contributor license agreements.\n\n### Submitting a Pull Request\n\nAll types of contributions are welcome, but please keep the following in mind:\n\n- If you're planning a large change, you should really discuss it in a github issue first. This helps avoid duplicate effort and spending time on something that may not be merged.\n- Existing tests should continue to pass, new tests for the contribution are nice to have.\n- All code should have gone through `go fmt`\n- All code should pass `go vet`\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License."
  },
  {
    "path": "README.md",
    "content": "# ![vellum](docs/logo.png) vellum\n\n# NOTE: active development of the vellum library has moved to [https://github.com/blevesearch/vellum](https://github.com/blevesearch/vellum)\n\nThis repository will remain as is to support previous Couchbase builds.\n\n[![Tests](https://github.com/couchbase/vellum/workflows/Tests/badge.svg?branch=master&event=push)](https://github.com/couchbase/vellum/actions?query=workflow%3ATests+event%3Apush+branch%3Amaster)\n[![Coverage Status](https://coveralls.io/repos/github/couchbase/vellum/badge.svg?branch=master)](https://coveralls.io/github/couchbase/vellum?branch=master)\n[![GoDoc](https://godoc.org/github.com/couchbase/vellum?status.svg)](https://godoc.org/github.com/couchbase/vellum)\n[![Go Report Card](https://goreportcard.com/badge/github.com/couchbase/vellum)](https://goreportcard.com/report/github.com/couchbase/vellum)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n\nA Go library implementing an FST (finite state transducer) capable of:\n  - mapping between keys ([]byte) and a value (uint64)\n  - enumerating keys in lexicographic order\n\nSome additional goals of this implementation:\n - bounded memory use while building the FST\n - streaming out FST data while building\n - mmap FST runtime to support very large FTSs (optional)\n\n## Usage\n\n### Building an FST\n\nTo build an FST, create a new builder using the `New()` method.  This method takes an `io.Writer` as an argument.  As the FST is being built, data will be streamed to the writer as soon as possible.  With this builder you **MUST** insert keys in lexicographic order.  Inserting keys out of order will result in an error.  After inserting the last key into the builder, you **MUST** call `Close()` on the builder.  This will flush all remaining data to the underlying writer.\n\nIn memory:\n```go\n  var buf bytes.Buffer\n  builder, err := vellum.New(&buf, nil)\n  if err != nil {\n    log.Fatal(err)\n  }\n```\n\nTo disk:\n```go\n  f, err := os.Create(\"/tmp/vellum.fst\")\n  if err != nil {\n    log.Fatal(err)\n  }\n  builder, err := vellum.New(f, nil)\n  if err != nil {\n    log.Fatal(err)\n  }\n```\n\n**MUST** insert keys in lexicographic order:\n```go\nerr = builder.Insert([]byte(\"cat\"), 1)\nif err != nil {\n  log.Fatal(err)\n}\n\nerr = builder.Insert([]byte(\"dog\"), 2)\nif err != nil {\n  log.Fatal(err)\n}\n\nerr = builder.Insert([]byte(\"fish\"), 3)\nif err != nil {\n  log.Fatal(err)\n}\n\nerr = builder.Close()\nif err != nil {\n  log.Fatal(err)\n}\n```\n\n### Using an FST\n\nAfter closing the builder, the data can be used to instantiate an FST.  If the data was written to disk, you can use the `Open()` method to mmap the file.  If the data is already in memory, or you wish to load/mmap the data yourself, you can instantiate the FST with the `Load()` method.\n\nLoad in memory:\n```go\n  fst, err := vellum.Load(buf.Bytes())\n  if err != nil {\n    log.Fatal(err)\n  }\n```\n\nOpen from disk:\n```go\n  fst, err := vellum.Open(\"/tmp/vellum.fst\")\n  if err != nil {\n    log.Fatal(err)\n  }\n```\n\nGet key/value:\n```go\n  val, exists, err = fst.Get([]byte(\"dog\"))\n  if err != nil {\n    log.Fatal(err)\n  }\n  if exists {\n    fmt.Printf(\"contains dog with val: %d\\n\", val)\n  } else {\n    fmt.Printf(\"does not contain dog\")\n  }\n```\n\nIterate key/values:\n```go\n  itr, err := fst.Iterator(startKeyInclusive, endKeyExclusive)\n  for err == nil {\n    key, val := itr.Current()\n    fmt.Printf(\"contains key: %s val: %d\", key, val)\n    err = itr.Next()\n  }\n  if err != nil {\n    log.Fatal(err)\n  }\n```\n\n### How does the FST get built?\n\nA full example of the implementation is beyond the scope of this README, but let's consider a small example where we want to insert 3 key/value pairs.\n\nFirst we insert \"are\" with the value 4.\n\n![step1](docs/demo1.png)\n\nNext, we insert \"ate\" with the value 2.\n\n![step2](docs/demo2.png)\n\nNotice how the values associated with the transitions were adjusted so that by summing them while traversing we still get the expected value.\n\nAt this point, we see that state 5 looks like state 3, and state 4 looks like state 2.  But, we cannot yet combine them because future inserts could change this.\n\nNow, we insert \"see\" with value 3.  Once it has been added, we now know that states 5 and 4 can longer change.  Since they are identical to 3 and 2, we replace them.\n\n![step3](docs/demo3.png)\n\nAgain, we see that states 7 and 8 appear to be identical to 2 and 3.\n\nHaving inserted our last key, we call `Close()` on the builder.\n\n![step4](docs/demo4.png)\n\nNow, states 7 and 8 can safely be replaced with 2 and 3.\n\nFor additional information, see the references at the bottom of this document.\n\n### What does the serialized format look like?\n\nWe've broken out a separate document on the [vellum disk format v1](docs/format.md).\n\n### What if I want to use this on a system that doesn't have mmap?\n\nThe mmap library itself is guarded with system/architecture build tags, but we've also added an additional build tag in vellum.  If you'd like to Open() a file based representation of an FST, but not use mmap, you can build the library with the `nommap` build tag.  NOTE: if you do this, the entire FST will be read into memory.\n\n### Can I use this with Unicode strings?\n\nYes, however this implementation is only aware of the byte representation you choose.  In order to find matches, you must work with some canonical byte representation of the string.  In the future, some encoding-aware traversals may be possible on top of the lower-level byte transitions.\n\n### How did this library come to be?\n\nIn my work on the [Bleve](https://github.com/blevesearch/bleve) project I became aware of the power of the FST for many search-related tasks.  The obvious starting point for such a thing in Go was the [mafsa](https://github.com/smartystreets/mafsa) project.  While working with mafsa I encountered some issues.  First, it did not stream data to disk while building.  Second, it chose to use a rune as the fundamental unit of transition in the FST, but I felt using a byte would be more powerful in the end.  My hope is that higher-level encoding-aware traversals will be possible when necessary.  Finally, as I reported bugs and submitted PRs I learned that the mafsa project was mainly a research project and no longer being maintained.  I wanted to build something that could be used in production.  As the project advanced more and more techniques from the [BurntSushi/fst](https://github.com/BurntSushi/fst) were adapted to our implementation.\n\n### Are there tools to work with vellum files?\n\nUnder the cmd/vellum subdirectory, there's a command-line tool which\nfeatures subcommands that can allow you to create, inspect and query\nvellum files.\n\n### How can I generate a state transition diagram from a vellum file?\n\nThe vellum command-line tool has a \"dot\" subcommand that can emit\ngraphviz dot output data from an input vellum file.  The dot file can\nin turn be converted into an image using graphviz tools.  Example...\n\n    $ vellum dot myFile.vellum > output.dot\n    $ dot -Tpng output.dot -o output.png\n\n## Related Work\n\nMuch credit goes to two existing projects:\n - [mafsa](https://github.com/smartystreets/mafsa)\n - [BurntSushi/fst](https://github.com/BurntSushi/fst)\n\nMost of the original implementation here started with my digging into the internals of mafsa.  As the implementation progressed, I continued to borrow ideas/approaches from the BurntSushi/fst library as well.\n\nFor a great introduction to this topic, please read the blog post [Index 1,600,000,000 Keys with Automata and Rust](http://blog.burntsushi.net/transducers/)\n"
  },
  {
    "path": "automaton.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\n// Automaton represents the general contract of a byte-based finite automaton\ntype Automaton interface {\n\n\t// Start returns the start state\n\tStart() int\n\n\t// IsMatch returns true if and only if the state is a match\n\tIsMatch(int) bool\n\n\t// CanMatch returns true if and only if it is possible to reach a match\n\t// in zero or more steps\n\tCanMatch(int) bool\n\n\t// WillAlwaysMatch returns true if and only if the current state matches\n\t// and will always match no matter what steps are taken\n\tWillAlwaysMatch(int) bool\n\n\t// Accept returns the next state given the input to the specified state\n\tAccept(int, byte) int\n}\n\n// AutomatonContains implements an generic Contains() method which works\n// on any implementation of Automaton\nfunc AutomatonContains(a Automaton, k []byte) bool {\n\ti := 0\n\tcurr := a.Start()\n\tfor a.CanMatch(curr) && i < len(k) {\n\t\tcurr = a.Accept(curr, k[i])\n\t\tif curr == noneAddr {\n\t\t\tbreak\n\t\t}\n\t\ti++\n\t}\n\tif i != len(k) {\n\t\treturn false\n\t}\n\treturn a.IsMatch(curr)\n}\n\n// AlwaysMatch is an Automaton implementation which always matches\ntype AlwaysMatch struct{}\n\n// Start returns the AlwaysMatch start state\nfunc (m *AlwaysMatch) Start() int {\n\treturn 0\n}\n\n// IsMatch always returns true\nfunc (m *AlwaysMatch) IsMatch(int) bool {\n\treturn true\n}\n\n// CanMatch always returns true\nfunc (m *AlwaysMatch) CanMatch(int) bool {\n\treturn true\n}\n\n// WillAlwaysMatch always returns true\nfunc (m *AlwaysMatch) WillAlwaysMatch(int) bool {\n\treturn true\n}\n\n// Accept returns the next AlwaysMatch state\nfunc (m *AlwaysMatch) Accept(int, byte) int {\n\treturn 0\n}\n\n// creating an alwaysMatchAutomaton to avoid unnecessary repeated allocations.\nvar alwaysMatchAutomaton = &AlwaysMatch{}\n"
  },
  {
    "path": "builder.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"bytes\"\n\t\"io\"\n)\n\nvar defaultBuilderOpts = &BuilderOpts{\n\tEncoder:           1,\n\tRegistryTableSize: 10000,\n\tRegistryMRUSize:   2,\n}\n\n// A Builder is used to build a new FST.  When possible data is\n// streamed out to the underlying Writer as soon as possible.\ntype Builder struct {\n\tunfinished *unfinishedNodes\n\tregistry   *registry\n\tlast       []byte\n\tlen        int\n\n\tlastAddr int\n\n\tencoder encoder\n\topts    *BuilderOpts\n\n\tbuilderNodePool *builderNodePool\n}\n\nconst noneAddr = 1\nconst emptyAddr = 0\n\n// NewBuilder returns a new Builder which will stream out the\n// underlying representation to the provided Writer as the set is built.\nfunc newBuilder(w io.Writer, opts *BuilderOpts) (*Builder, error) {\n\tif opts == nil {\n\t\topts = defaultBuilderOpts\n\t}\n\tbuilderNodePool := &builderNodePool{}\n\trv := &Builder{\n\t\tunfinished:      newUnfinishedNodes(builderNodePool),\n\t\tregistry:        newRegistry(builderNodePool, opts.RegistryTableSize, opts.RegistryMRUSize),\n\t\tbuilderNodePool: builderNodePool,\n\t\topts:            opts,\n\t\tlastAddr:        noneAddr,\n\t}\n\n\tvar err error\n\trv.encoder, err = loadEncoder(opts.Encoder, w)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\terr = rv.encoder.start()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn rv, nil\n}\n\nfunc (b *Builder) Reset(w io.Writer) error {\n\tb.unfinished.Reset()\n\tb.registry.Reset()\n\tb.lastAddr = noneAddr\n\tb.encoder.reset(w)\n\tb.last = nil\n\tb.len = 0\n\n\terr := b.encoder.start()\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// Insert the provided value to the set being built.\n// NOTE: values must be inserted in lexicographical order.\nfunc (b *Builder) Insert(key []byte, val uint64) error {\n\t// ensure items are added in lexicographic order\n\tif bytes.Compare(key, b.last) < 0 {\n\t\treturn ErrOutOfOrder\n\t}\n\tif len(key) == 0 {\n\t\tb.len = 1\n\t\tb.unfinished.setRootOutput(val)\n\t\treturn nil\n\t}\n\n\tprefixLen, out := b.unfinished.findCommonPrefixAndSetOutput(key, val)\n\tb.len++\n\terr := b.compileFrom(prefixLen)\n\tif err != nil {\n\t\treturn err\n\t}\n\tb.copyLastKey(key)\n\tb.unfinished.addSuffix(key[prefixLen:], out)\n\n\treturn nil\n}\n\nfunc (b *Builder) copyLastKey(key []byte) {\n\tif b.last == nil {\n\t\tb.last = make([]byte, 0, 64)\n\t} else {\n\t\tb.last = b.last[:0]\n\t}\n\tb.last = append(b.last, key...)\n}\n\n// Close MUST be called after inserting all values.\nfunc (b *Builder) Close() error {\n\terr := b.compileFrom(0)\n\tif err != nil {\n\t\treturn err\n\t}\n\troot := b.unfinished.popRoot()\n\trootAddr, err := b.compile(root)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn b.encoder.finish(b.len, rootAddr)\n}\n\nfunc (b *Builder) compileFrom(iState int) error {\n\taddr := noneAddr\n\tfor iState+1 < len(b.unfinished.stack) {\n\t\tvar node *builderNode\n\t\tif addr == noneAddr {\n\t\t\tnode = b.unfinished.popEmpty()\n\t\t} else {\n\t\t\tnode = b.unfinished.popFreeze(addr)\n\t\t}\n\t\tvar err error\n\t\taddr, err = b.compile(node)\n\t\tif err != nil {\n\t\t\treturn nil\n\t\t}\n\t}\n\tb.unfinished.topLastFreeze(addr)\n\treturn nil\n}\n\nfunc (b *Builder) compile(node *builderNode) (int, error) {\n\tif node.final && len(node.trans) == 0 &&\n\t\tnode.finalOutput == 0 {\n\t\treturn 0, nil\n\t}\n\tfound, addr, entry := b.registry.entry(node)\n\tif found {\n\t\treturn addr, nil\n\t}\n\taddr, err := b.encoder.encodeState(node, b.lastAddr)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tb.lastAddr = addr\n\tentry.addr = addr\n\treturn addr, nil\n}\n\ntype unfinishedNodes struct {\n\tstack []*builderNodeUnfinished\n\n\t// cache allocates a reasonable number of builderNodeUnfinished\n\t// objects up front and tries to keep reusing them\n\t// because the main data structure is a stack, we assume the\n\t// same access pattern, and don't track items separately\n\t// this means calls get() and pushXYZ() must be paired,\n\t// as well as calls put() and popXYZ()\n\tcache []builderNodeUnfinished\n\n\tbuilderNodePool *builderNodePool\n}\n\nfunc (u *unfinishedNodes) Reset() {\n\tu.stack = u.stack[:0]\n\tfor i := 0; i < len(u.cache); i++ {\n\t\tu.cache[i] = builderNodeUnfinished{}\n\t}\n\tu.pushEmpty(false)\n}\n\nfunc newUnfinishedNodes(p *builderNodePool) *unfinishedNodes {\n\trv := &unfinishedNodes{\n\t\tstack:           make([]*builderNodeUnfinished, 0, 64),\n\t\tcache:           make([]builderNodeUnfinished, 64),\n\t\tbuilderNodePool: p,\n\t}\n\trv.pushEmpty(false)\n\treturn rv\n}\n\n// get new builderNodeUnfinished, reusing cache if possible\nfunc (u *unfinishedNodes) get() *builderNodeUnfinished {\n\tif len(u.stack) < len(u.cache) {\n\t\treturn &u.cache[len(u.stack)]\n\t}\n\t// full now allocate a new one\n\treturn &builderNodeUnfinished{}\n}\n\n// return builderNodeUnfinished, clearing it for reuse\nfunc (u *unfinishedNodes) put() {\n\tif len(u.stack) >= len(u.cache) {\n\t\treturn\n\t\t// do nothing, not part of cache\n\t}\n\tu.cache[len(u.stack)] = builderNodeUnfinished{}\n}\n\nfunc (u *unfinishedNodes) findCommonPrefixAndSetOutput(key []byte,\n\tout uint64) (int, uint64) {\n\tvar i int\n\tfor i < len(key) {\n\t\tif i >= len(u.stack) {\n\t\t\tbreak\n\t\t}\n\t\tvar addPrefix uint64\n\t\tif !u.stack[i].hasLastT {\n\t\t\tbreak\n\t\t}\n\t\tif u.stack[i].lastIn == key[i] {\n\t\t\tcommonPre := outputPrefix(u.stack[i].lastOut, out)\n\t\t\taddPrefix = outputSub(u.stack[i].lastOut, commonPre)\n\t\t\tout = outputSub(out, commonPre)\n\t\t\tu.stack[i].lastOut = commonPre\n\t\t\ti++\n\t\t} else {\n\t\t\tbreak\n\t\t}\n\n\t\tif addPrefix != 0 {\n\t\t\tu.stack[i].addOutputPrefix(addPrefix)\n\t\t}\n\t}\n\n\treturn i, out\n}\n\nfunc (u *unfinishedNodes) pushEmpty(final bool) {\n\tnext := u.get()\n\tnext.node = u.builderNodePool.Get()\n\tnext.node.final = final\n\tu.stack = append(u.stack, next)\n}\n\nfunc (u *unfinishedNodes) popRoot() *builderNode {\n\tl := len(u.stack)\n\tvar unfinished *builderNodeUnfinished\n\tu.stack, unfinished = u.stack[:l-1], u.stack[l-1]\n\trv := unfinished.node\n\tu.put()\n\treturn rv\n}\n\nfunc (u *unfinishedNodes) popFreeze(addr int) *builderNode {\n\tl := len(u.stack)\n\tvar unfinished *builderNodeUnfinished\n\tu.stack, unfinished = u.stack[:l-1], u.stack[l-1]\n\tunfinished.lastCompiled(addr)\n\trv := unfinished.node\n\tu.put()\n\treturn rv\n}\n\nfunc (u *unfinishedNodes) popEmpty() *builderNode {\n\tl := len(u.stack)\n\tvar unfinished *builderNodeUnfinished\n\tu.stack, unfinished = u.stack[:l-1], u.stack[l-1]\n\trv := unfinished.node\n\tu.put()\n\treturn rv\n}\n\nfunc (u *unfinishedNodes) setRootOutput(out uint64) {\n\tu.stack[0].node.final = true\n\tu.stack[0].node.finalOutput = out\n}\n\nfunc (u *unfinishedNodes) topLastFreeze(addr int) {\n\tlast := len(u.stack) - 1\n\tu.stack[last].lastCompiled(addr)\n}\n\nfunc (u *unfinishedNodes) addSuffix(bs []byte, out uint64) {\n\tif len(bs) == 0 {\n\t\treturn\n\t}\n\tlast := len(u.stack) - 1\n\tu.stack[last].hasLastT = true\n\tu.stack[last].lastIn = bs[0]\n\tu.stack[last].lastOut = out\n\tfor _, b := range bs[1:] {\n\t\tnext := u.get()\n\t\tnext.node = u.builderNodePool.Get()\n\t\tnext.hasLastT = true\n\t\tnext.lastIn = b\n\t\tnext.lastOut = 0\n\t\tu.stack = append(u.stack, next)\n\t}\n\tu.pushEmpty(true)\n}\n\ntype builderNodeUnfinished struct {\n\tnode     *builderNode\n\tlastOut  uint64\n\tlastIn   byte\n\thasLastT bool\n}\n\nfunc (b *builderNodeUnfinished) lastCompiled(addr int) {\n\tif b.hasLastT {\n\t\ttransIn := b.lastIn\n\t\ttransOut := b.lastOut\n\t\tb.hasLastT = false\n\t\tb.lastOut = 0\n\t\tb.node.trans = append(b.node.trans, transition{\n\t\t\tin:   transIn,\n\t\t\tout:  transOut,\n\t\t\taddr: addr,\n\t\t})\n\t}\n}\n\nfunc (b *builderNodeUnfinished) addOutputPrefix(prefix uint64) {\n\tif b.node.final {\n\t\tb.node.finalOutput = outputCat(prefix, b.node.finalOutput)\n\t}\n\tfor i := range b.node.trans {\n\t\tb.node.trans[i].out = outputCat(prefix, b.node.trans[i].out)\n\t}\n\tif b.hasLastT {\n\t\tb.lastOut = outputCat(prefix, b.lastOut)\n\t}\n}\n\ntype builderNode struct {\n\tfinalOutput uint64\n\ttrans       []transition\n\tfinal       bool\n\n\t// intrusive linked list\n\tnext *builderNode\n}\n\n// reset resets the receiver builderNode to a re-usable state.\nfunc (n *builderNode) reset() {\n\tn.final = false\n\tn.finalOutput = 0\n\tfor i := range n.trans {\n\t\tn.trans[i] = emptyTransition\n\t}\n\tn.trans = n.trans[:0]\n\tn.next = nil\n}\n\nfunc (n *builderNode) equiv(o *builderNode) bool {\n\tif n.final != o.final {\n\t\treturn false\n\t}\n\tif n.finalOutput != o.finalOutput {\n\t\treturn false\n\t}\n\tif len(n.trans) != len(o.trans) {\n\t\treturn false\n\t}\n\tfor i, ntrans := range n.trans {\n\t\totrans := o.trans[i]\n\t\tif ntrans.in != otrans.in {\n\t\t\treturn false\n\t\t}\n\t\tif ntrans.addr != otrans.addr {\n\t\t\treturn false\n\t\t}\n\t\tif ntrans.out != otrans.out {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nvar emptyTransition = transition{}\n\ntype transition struct {\n\tout  uint64\n\taddr int\n\tin   byte\n}\n\nfunc outputPrefix(l, r uint64) uint64 {\n\tif l < r {\n\t\treturn l\n\t}\n\treturn r\n}\n\nfunc outputSub(l, r uint64) uint64 {\n\treturn l - r\n}\n\nfunc outputCat(l, r uint64) uint64 {\n\treturn l + r\n}\n\n// builderNodePool pools builderNodes using a singly linked list.\n//\n// NB: builderNode lifecylce is described by the following interactions -\n// +------------------------+                            +----------------------+\n// |    Unfinished Nodes    |      Transfer once         |        Registry      |\n// |(not frozen builderNode)|-----builderNode is ------->| (frozen builderNode) |\n// +------------------------+      marked frozen         +----------------------+\n//              ^                                                     |\n//              |                                                     |\n//              |                                                   Put()\n//              | Get() on        +-------------------+             when\n//              +-new char--------| builderNode Pool  |<-----------evicted\n//                                +-------------------+\ntype builderNodePool struct {\n\thead *builderNode\n}\n\nfunc (p *builderNodePool) Get() *builderNode {\n\tif p.head == nil {\n\t\treturn &builderNode{}\n\t}\n\thead := p.head\n\tp.head = p.head.next\n\treturn head\n}\n\nfunc (p *builderNodePool) Put(v *builderNode) {\n\tif v == nil {\n\t\treturn\n\t}\n\tv.reset()\n\tv.next = p.head\n\tp.head = v\n}\n"
  },
  {
    "path": "builder_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"bufio\"\n\t\"io/ioutil\"\n\t\"math/rand\"\n\t\"os\"\n\t\"sort\"\n\t\"testing\"\n)\n\nfunc init() {\n\tthousandTestWords, _ = loadWords(\"data/words-1000.txt\")\n}\n\n// this simple test case only has a shared final state\n// it also tests out of order insert\nfunc TestBuilderSimple(t *testing.T) {\n\tb, err := New(ioutil.Discard, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\t// add our first string\n\terr = b.Insert([]byte(\"jul\"), 0)\n\tif err != nil {\n\t\tt.Errorf(\"got error inserting string: %v\", err)\n\t}\n\t// expect len to be 1\n\tif b.len != 1 {\n\t\tt.Errorf(\"expected node count to be 1, got %v\", b.len)\n\t}\n\n\t// try to add a value out of order (not allowed)\n\terr = b.Insert([]byte(\"abc\"), 0)\n\tif err == nil {\n\t\tt.Errorf(\"expected err, got nil\")\n\t}\n\n\t// add a second string\n\terr = b.Insert([]byte(\"mar\"), 0)\n\tif err != nil {\n\t\tt.Errorf(\"got error inserting string: %v\", err)\n\t}\n\t// expect len to grow by 1\n\tif b.len != 2 {\n\t\tt.Errorf(\"expected node count to be 2, got %v\", b.len)\n\t}\n\n\t// now close the builder\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Errorf(\"got error closing set builder: %v\", err)\n\t}\n}\n\nfunc TestBuilderSharedPrefix(t *testing.T) {\n\tb, err := New(ioutil.Discard, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\t// add our first string\n\terr = b.Insert([]byte(\"car\"), 0)\n\tif err != nil {\n\t\tt.Errorf(\"got error inserting string: %v\", err)\n\t}\n\t// expect len to be 1\n\tif b.len != 1 {\n\t\tt.Errorf(\"expected node count to be 1, got %v\", b.len)\n\t}\n\n\t// add a second string\n\terr = b.Insert([]byte(\"cat\"), 0)\n\tif err != nil {\n\t\tt.Errorf(\"got error inserting string: %v\", err)\n\t}\n\t// expect len to be 2\n\tif b.len != 2 {\n\t\tt.Errorf(\"expected node count to be 2, got %v\", b.len)\n\t}\n\n\t// now close the builder\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Errorf(\"got error closing set builder: %v\", err)\n\t}\n}\n\nfunc randomValues(list []string) []uint64 {\n\trv := make([]uint64, len(list))\n\tfor i := range list {\n\t\trv[i] = uint64(rand.Uint64())\n\t}\n\treturn rv\n}\n\nfunc insertStrings(b *Builder, list []string, vals []uint64) error {\n\tfor i, item := range list {\n\t\terr := b.Insert([]byte(item), vals[i])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nvar smallSample = map[string]uint64{\n\t\"mon\":   2,\n\t\"tues\":  3,\n\t\"thurs\": 5,\n\t\"tye\":   99,\n}\n\nfunc insertStringMap(b *Builder, m map[string]uint64) error {\n\t// make list of keys\n\tkeys := make([]string, 0, len(m))\n\tfor k := range m {\n\t\tkeys = append(keys, k)\n\t}\n\t// sort it\n\tsort.Strings(keys)\n\t// insert in sorted order\n\tfor _, k := range keys {\n\t\terr := b.Insert([]byte(k), m[k])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc TestBuilderNodeEquiv(t *testing.T) {\n\ttests := []struct {\n\t\tdesc string\n\t\ta    *builderNode\n\t\tb    *builderNode\n\t\twant bool\n\t}{\n\t\t{\n\t\t\t\"both states final\",\n\t\t\t&builderNode{\n\t\t\t\tfinal: true,\n\t\t\t},\n\t\t\t&builderNode{\n\t\t\t\tfinal: true,\n\t\t\t},\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"both states final, different final val\",\n\t\t\t&builderNode{\n\t\t\t\tfinal:       true,\n\t\t\t\tfinalOutput: 7,\n\t\t\t},\n\t\t\t&builderNode{\n\t\t\t\tfinal:       true,\n\t\t\t\tfinalOutput: 9,\n\t\t\t},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"both states final, same transitions, but different trans val\",\n\t\t\t&builderNode{\n\t\t\t\tfinal: true,\n\t\t\t\ttrans: []transition{\n\t\t\t\t\t{in: 'a', out: 7},\n\t\t\t\t},\n\t\t\t},\n\t\t\t&builderNode{\n\t\t\t\tfinal: true,\n\t\t\t\ttrans: []transition{\n\t\t\t\t\t{in: 'a', out: 9},\n\t\t\t\t},\n\t\t\t},\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.desc, func(t *testing.T) {\n\t\t\tgot := test.a.equiv(test.b)\n\t\t\tif got != test.want {\n\t\t\t\tt.Errorf(\"wanted: %t, got: %t\", test.want, got)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc loadWords(path string) ([]string, error) {\n\tvar rv []string\n\n\tfile, err := os.Open(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tscanner := bufio.NewScanner(file)\n\tfor scanner.Scan() {\n\t\tword := append([]byte(nil), scanner.Bytes()...)\n\t\trv = append(rv, string(word))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tif err = scanner.Err(); err != nil {\n\t\treturn nil, err\n\t}\n\n\terr = file.Close()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn rv, nil\n}\n\nvar thousandTestWords []string\n\nfunc BenchmarkBuilder(b *testing.B) {\n\tdataset := thousandTestWords\n\trandomThousandVals := randomValues(dataset)\n\n\tb.ResetTimer()\n\n\tfor i := 0; i < b.N; i++ {\n\n\t\tbuilder, err := New(ioutil.Discard, nil)\n\t\tif err != nil {\n\t\t\tb.Fatalf(\"error creating builder: %v\", err)\n\t\t}\n\t\terr = insertStrings(builder, dataset, randomThousandVals)\n\t\tif err != nil {\n\t\t\tb.Fatalf(\"error inserting thousand words: %v\", err)\n\t\t}\n\t\terr = builder.Close()\n\t\tif err != nil {\n\t\t\tb.Fatalf(\"error closing builder: %v\", err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/vellum/cmd/dot.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cmd\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\n\t\"github.com/couchbase/vellum\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar dotCmd = &cobra.Command{\n\tUse:   \"dot\",\n\tShort: \"Dot prints the contents of this vellum FST file in the dot format\",\n\tLong:  `Dot prints the contents of this vellum FST file in the dot format.`,\n\tPreRunE: func(cmd *cobra.Command, args []string) error {\n\t\tif len(args) < 1 {\n\t\t\treturn fmt.Errorf(\"path is required\")\n\t\t}\n\t\treturn nil\n\t},\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tfst, err := vellum.Open(args[0])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn dotToWriter(fst, os.Stdout)\n\t},\n}\n\nfunc dotToWriter(fst *vellum.FST, w io.Writer) error {\n\t_, err := fmt.Fprint(w, dotHeader)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = fst.Debug(func(n int, state interface{}) error {\n\t\tif d, ok := state.(dotStringer); ok {\n\t\t\t_, err = fmt.Fprintf(w, \"%s\", d.DotString(n))\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = fmt.Fprint(w, dotFooter)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nconst dotHeader = `\ndigraph automaton {\n    labelloc=\"l\";\n    labeljust=\"l\";\n    rankdir=\"LR\";\n\n`\nconst dotFooter = `}\n`\n\ntype dotStringer interface {\n\tDotString(int) string\n}\n\nfunc init() {\n\tRootCmd.AddCommand(dotCmd)\n}\n"
  },
  {
    "path": "cmd/vellum/cmd/dump.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cmd\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/couchbase/vellum\"\n\t\"github.com/spf13/cobra\"\n)\n\n// dumpCmd represents the dump command\nvar dumpCmd = &cobra.Command{\n\tUse:   \"dump\",\n\tShort: \"Dumps the contents of this vellum FST file\",\n\tLong:  `Dumps the contents of this vellum FST file.`,\n\tPreRunE: func(cmd *cobra.Command, args []string) error {\n\t\tif len(args) < 1 {\n\t\t\treturn fmt.Errorf(\"path is required\")\n\t\t}\n\t\treturn nil\n\t},\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tfst, err := vellum.Open(args[0])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn fst.Debug(debugPrint)\n\t},\n}\n\nfunc debugPrint(n int, state interface{}) error {\n\tfmt.Printf(\"%v\\n\", state)\n\treturn nil\n}\n\nfunc init() {\n\tRootCmd.AddCommand(dumpCmd)\n}\n"
  },
  {
    "path": "cmd/vellum/cmd/fuzzy.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cmd\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/couchbase/vellum\"\n\t\"github.com/couchbase/vellum/levenshtein\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar query string\nvar distance int\n\nvar fuzzyCmd = &cobra.Command{\n\tUse:   \"fuzzy\",\n\tShort: \"Fuzzy runs a fuzzy query over the contents of this vellum FST file\",\n\tLong:  `Fuzzy runs a fuzzy query over the contents of this vellum FST file.`,\n\tPreRunE: func(cmd *cobra.Command, args []string) error {\n\t\tif len(args) < 1 {\n\t\t\treturn fmt.Errorf(\"path is required\")\n\t\t}\n\t\tif len(args) > 1 {\n\t\t\tquery = args[1]\n\t\t}\n\n\t\treturn nil\n\t},\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tfst, err := vellum.Open(args[0])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tlb, err := levenshtein.NewLevenshteinAutomatonBuilder(uint8(distance), false)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tfuzzy, err := lb.BuildDfa(query, uint8(distance))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tvar startKeyB, endKeyB []byte\n\t\tif startKey != \"\" {\n\t\t\tstartKeyB = []byte(startKey)\n\t\t}\n\t\tif endKey != \"\" {\n\t\t\tendKeyB = []byte(endKey)\n\t\t}\n\t\titr, err := fst.Search(fuzzy, startKeyB, endKeyB)\n\t\tfor err == nil {\n\t\t\tkey, val := itr.Current()\n\t\t\tfmt.Printf(\"%s - %d\\n\", key, val)\n\t\t\terr = itr.Next()\n\t\t}\n\n\t\treturn nil\n\t},\n}\n\nfunc init() {\n\tRootCmd.AddCommand(fuzzyCmd)\n\tfuzzyCmd.Flags().StringVar(&startKey, \"start\", \"\", \"start key inclusive\")\n\tfuzzyCmd.Flags().StringVar(&endKey, \"end\", \"\", \"end key inclusive\")\n\tfuzzyCmd.Flags().IntVar(&distance, \"distance\", 1, \"edit distance in Unicode codepoints\")\n}\n"
  },
  {
    "path": "cmd/vellum/cmd/grep.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cmd\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/couchbase/vellum\"\n\t\"github.com/couchbase/vellum/regexp\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar grepCmd = &cobra.Command{\n\tUse: \"grep\",\n\tShort: \"Grep runs regular expression searches over the contents of this \" +\n\t\t\"vellum FST file.\",\n\tLong: `Grep runs regular expression searches over the contents of this ` +\n\t\t`vellum FST file.`,\n\tPreRunE: func(cmd *cobra.Command, args []string) error {\n\t\tif len(args) < 1 {\n\t\t\treturn fmt.Errorf(\"path is required\")\n\t\t}\n\t\tif len(args) > 1 {\n\t\t\tquery = args[1]\n\t\t}\n\n\t\treturn nil\n\t},\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tfst, err := vellum.Open(args[0])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tr, err := regexp.New(query)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tvar startKeyB, endKeyB []byte\n\t\tif startKey != \"\" {\n\t\t\tstartKeyB = []byte(startKey)\n\t\t}\n\t\tif endKey != \"\" {\n\t\t\tendKeyB = []byte(endKey)\n\t\t}\n\t\titr, err := fst.Search(r, startKeyB, endKeyB)\n\t\tfor err == nil {\n\t\t\tkey, val := itr.Current()\n\t\t\tfmt.Printf(\"%s - %d\\n\", key, val)\n\t\t\terr = itr.Next()\n\t\t}\n\n\t\treturn nil\n\t},\n}\n\nfunc init() {\n\tRootCmd.AddCommand(grepCmd)\n\tgrepCmd.Flags().StringVar(&startKey, \"start\", \"\", \"start key inclusive\")\n\tgrepCmd.Flags().StringVar(&endKey, \"end\", \"\", \"end key inclusive\")\n}\n"
  },
  {
    "path": "cmd/vellum/cmd/info.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cmd\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/couchbase/vellum\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar infoCmd = &cobra.Command{\n\tUse:   \"info\",\n\tShort: \"Prints info about this vellum FST file\",\n\tLong:  `Prints info about this vellum FST file.`,\n\tPreRunE: func(cmd *cobra.Command, args []string) error {\n\t\tif len(args) < 1 {\n\t\t\treturn fmt.Errorf(\"path is required\")\n\t\t}\n\t\treturn nil\n\t},\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tfst, err := vellum.Open(args[0])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfmt.Printf(\"version: %d\\n\", fst.Version())\n\t\tfmt.Printf(\"length: %d\\n\", fst.Len())\n\t\treturn nil\n\t},\n}\n\nfunc init() {\n\tRootCmd.AddCommand(infoCmd)\n}\n"
  },
  {
    "path": "cmd/vellum/cmd/map.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cmd\n\nimport (\n\t\"encoding/csv\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"strconv\"\n\n\t\"github.com/couchbase/vellum\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar mapCmd = &cobra.Command{\n\tUse:   \"map\",\n\tShort: \"Map builds a new FST from a CSV file containing key,val pairs\",\n\tLong:  `Map builds a new FST from a CSV file containing key,val pairs.`,\n\tPreRunE: func(cmd *cobra.Command, args []string) error {\n\t\tif len(args) < 1 {\n\t\t\treturn fmt.Errorf(\"source and target paths are required\")\n\t\t}\n\t\tif len(args) < 2 {\n\t\t\treturn fmt.Errorf(\"target path is required\")\n\t\t}\n\t\treturn nil\n\t},\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\n\t\tif !sorted {\n\t\t\treturn fmt.Errorf(\"only sorted input supported at this time\")\n\t\t}\n\n\t\tfile, err := os.Open(args[0])\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tdefer file.Close()\n\n\t\tf, err := os.Create(args[1])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tb, err := vellum.New(f, nil)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treader := csv.NewReader(file)\n\t\treader.FieldsPerRecord = 2\n\n\t\tvar record []string\n\t\trecord, err = reader.Read()\n\t\tfor err == nil {\n\t\t\tvar v uint64\n\t\t\tv, err = strconv.ParseUint(record[1], 10, 64)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\terr = b.Insert([]byte(record[0]), v)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\trecord, err = reader.Read()\n\t\t}\n\t\tif err != io.EOF {\n\t\t\treturn err\n\t\t}\n\n\t\terr = b.Close()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn nil\n\t},\n}\n\nfunc init() {\n\tRootCmd.AddCommand(mapCmd)\n\tmapCmd.Flags().BoolVar(&sorted, \"sorted\", false, \"input already sorted\")\n}\n"
  },
  {
    "path": "cmd/vellum/cmd/range.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cmd\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/couchbase/vellum\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar startKey string\nvar endKey string\n\nvar rangeCmd = &cobra.Command{\n\tUse:   \"range\",\n\tShort: \"Range iterates over the contents of this vellum FST file\",\n\tLong:  `Range iterates over the contents of this vellum FST file.  You can optionally specify start/end keys after the filename.`,\n\tPreRunE: func(cmd *cobra.Command, args []string) error {\n\t\tif len(args) < 1 {\n\t\t\treturn fmt.Errorf(\"path is required\")\n\t\t}\n\t\treturn nil\n\t},\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tfst, err := vellum.Open(args[0])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tvar startKeyB, endKeyB []byte\n\t\tif startKey != \"\" {\n\t\t\tstartKeyB = []byte(startKey)\n\t\t}\n\t\tif endKey != \"\" {\n\t\t\tendKeyB = []byte(endKey)\n\t\t}\n\t\titr, err := fst.Iterator(startKeyB, endKeyB)\n\t\tfor err == nil {\n\t\t\tkey, val := itr.Current()\n\t\t\tfmt.Printf(\"%s - %d\\n\", key, val)\n\t\t\terr = itr.Next()\n\t\t}\n\n\t\treturn nil\n\t},\n}\n\nfunc init() {\n\tRootCmd.AddCommand(rangeCmd)\n\trangeCmd.Flags().StringVar(&startKey, \"start\", \"\", \"start key inclusive\")\n\trangeCmd.Flags().StringVar(&endKey, \"end\", \"\", \"end key inclusive\")\n}\n"
  },
  {
    "path": "cmd/vellum/cmd/root.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cmd\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"github.com/spf13/cobra\"\n)\n\nvar expvarBind string\n\n// RootCmd represents the base command when called without any subcommands\nvar RootCmd = &cobra.Command{\n\tUse:   \"vellum\",\n\tShort: \"A utility to work with vellum FST files\",\n\tLong:  `A utility to work with vellum FST files.`,\n\tPersistentPreRunE: func(cmd *cobra.Command, args []string) error {\n\t\tif expvarBind != \"\" {\n\t\t\tgo http.ListenAndServe(expvarBind, nil)\n\t\t}\n\t\treturn nil\n\t},\n}\n\n// Execute adds all child commands to the root command sets flags appropriately.\n// This is called by main.main(). It only needs to happen once to the rootCmd.\nfunc Execute() {\n\tif err := RootCmd.Execute(); err != nil {\n\t\tfmt.Println(err)\n\t\tos.Exit(-1)\n\t}\n}\n\nfunc init() {\n\tRootCmd.PersistentFlags().StringVar(&expvarBind, \"expvar\", \"\", \"bind address for expvar, default none\")\n}\n"
  },
  {
    "path": "cmd/vellum/cmd/set.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cmd\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\t\"github.com/couchbase/vellum\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar sorted bool\n\nvar setCmd = &cobra.Command{\n\tUse:   \"set\",\n\tShort: \"Set builds a new FST from a file containing new-line separated values\",\n\tLong:  `Set builds a new FST from a file containing new-line separated values.`,\n\tPreRunE: func(cmd *cobra.Command, args []string) error {\n\t\tif len(args) < 1 {\n\t\t\treturn fmt.Errorf(\"source and target paths are required\")\n\t\t}\n\t\tif len(args) < 2 {\n\t\t\treturn fmt.Errorf(\"target path is required\")\n\t\t}\n\t\treturn nil\n\t},\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\n\t\tif !sorted {\n\t\t\treturn fmt.Errorf(\"only sorted input supported at this time\")\n\t\t}\n\n\t\tfile, err := os.Open(args[0])\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tdefer file.Close()\n\n\t\tf, err := os.Create(args[1])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tb, err := vellum.New(f, nil)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tscanner := bufio.NewScanner(file)\n\t\tfor scanner.Scan() {\n\t\t\tword := append([]byte(nil), scanner.Bytes()...)\n\t\t\terr = b.Insert(word, 0)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\tif err = scanner.Err(); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\n\t\terr = b.Close()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn nil\n\t},\n}\n\nfunc init() {\n\tRootCmd.AddCommand(setCmd)\n\tsetCmd.Flags().BoolVar(&sorted, \"sorted\", false, \"input already sorted\")\n}\n"
  },
  {
    "path": "cmd/vellum/cmd/svg.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cmd\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"os/exec\"\n\n\t\"github.com/couchbase/vellum\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar svgCmd = &cobra.Command{\n\tUse:   \"svg\",\n\tShort: \"SVG prints the contents of this vellum FST file in the SVG format\",\n\tLong:  `SVG prints the contents of this vellum FST file in the SVG format.`,\n\tPreRunE: func(cmd *cobra.Command, args []string) error {\n\t\tif len(args) < 1 {\n\t\t\treturn fmt.Errorf(\"path is required\")\n\t\t}\n\t\treturn nil\n\t},\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tfst, err := vellum.Open(args[0])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn svgToWriter(fst, os.Stdout)\n\t},\n}\n\nfunc svgToWriter(fst *vellum.FST, w io.Writer) error {\n\tpr, pw := io.Pipe()\n\tgo func() {\n\t\tdefer func() {\n\t\t\t_ = pw.Close()\n\t\t}()\n\t\t_ = dotToWriter(fst, pw)\n\t}()\n\tcmd := exec.Command(\"dot\", \"-Tsvg\")\n\tcmd.Stdin = pr\n\tcmd.Stdout = w\n\tcmd.Stderr = ioutil.Discard\n\terr := cmd.Run()\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc init() {\n\tRootCmd.AddCommand(svgCmd)\n}\n"
  },
  {
    "path": "cmd/vellum/main.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage main\n\nimport (\n\t_ \"expvar\"\n\n\t\"github.com/couchbase/vellum/cmd/vellum/cmd\"\n)\n\nfunc main() {\n\tcmd.Execute()\n}\n"
  },
  {
    "path": "common.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nconst maxCommon = 1<<6 - 1\n\nfunc encodeCommon(in byte) byte {\n\tval := byte((int(commonInputs[in]) + 1) % 256)\n\tif val > maxCommon {\n\t\treturn 0\n\t}\n\treturn val\n}\n\nfunc decodeCommon(in byte) byte {\n\treturn commonInputsInv[in-1]\n}\n\nvar commonInputs = []byte{\n\t84,  // '\\x00'\n\t85,  // '\\x01'\n\t86,  // '\\x02'\n\t87,  // '\\x03'\n\t88,  // '\\x04'\n\t89,  // '\\x05'\n\t90,  // '\\x06'\n\t91,  // '\\x07'\n\t92,  // '\\x08'\n\t93,  // '\\t'\n\t94,  // '\\n'\n\t95,  // '\\x0b'\n\t96,  // '\\x0c'\n\t97,  // '\\r'\n\t98,  // '\\x0e'\n\t99,  // '\\x0f'\n\t100, // '\\x10'\n\t101, // '\\x11'\n\t102, // '\\x12'\n\t103, // '\\x13'\n\t104, // '\\x14'\n\t105, // '\\x15'\n\t106, // '\\x16'\n\t107, // '\\x17'\n\t108, // '\\x18'\n\t109, // '\\x19'\n\t110, // '\\x1a'\n\t111, // '\\x1b'\n\t112, // '\\x1c'\n\t113, // '\\x1d'\n\t114, // '\\x1e'\n\t115, // '\\x1f'\n\t116, // ' '\n\t80,  // '!'\n\t117, // '\"'\n\t118, // '#'\n\t79,  // '$'\n\t39,  // '%'\n\t30,  // '&'\n\t81,  // \"'\"\n\t75,  // '('\n\t74,  // ')'\n\t82,  // '*'\n\t57,  // '+'\n\t66,  // ','\n\t16,  // '-'\n\t12,  // '.'\n\t2,   // '/'\n\t19,  // '0'\n\t20,  // '1'\n\t21,  // '2'\n\t27,  // '3'\n\t32,  // '4'\n\t29,  // '5'\n\t35,  // '6'\n\t36,  // '7'\n\t37,  // '8'\n\t34,  // '9'\n\t24,  // ':'\n\t73,  // ';'\n\t119, // '<'\n\t23,  // '='\n\t120, // '>'\n\t40,  // '?'\n\t83,  // '@'\n\t44,  // 'A'\n\t48,  // 'B'\n\t42,  // 'C'\n\t43,  // 'D'\n\t49,  // 'E'\n\t46,  // 'F'\n\t62,  // 'G'\n\t61,  // 'H'\n\t47,  // 'I'\n\t69,  // 'J'\n\t68,  // 'K'\n\t58,  // 'L'\n\t56,  // 'M'\n\t55,  // 'N'\n\t59,  // 'O'\n\t51,  // 'P'\n\t72,  // 'Q'\n\t54,  // 'R'\n\t45,  // 'S'\n\t52,  // 'T'\n\t64,  // 'U'\n\t65,  // 'V'\n\t63,  // 'W'\n\t71,  // 'X'\n\t67,  // 'Y'\n\t70,  // 'Z'\n\t77,  // '['\n\t121, // '\\\\'\n\t78,  // ']'\n\t122, // '^'\n\t31,  // '_'\n\t123, // '`'\n\t4,   // 'a'\n\t25,  // 'b'\n\t9,   // 'c'\n\t17,  // 'd'\n\t1,   // 'e'\n\t26,  // 'f'\n\t22,  // 'g'\n\t13,  // 'h'\n\t7,   // 'i'\n\t50,  // 'j'\n\t38,  // 'k'\n\t14,  // 'l'\n\t15,  // 'm'\n\t10,  // 'n'\n\t3,   // 'o'\n\t8,   // 'p'\n\t60,  // 'q'\n\t6,   // 'r'\n\t5,   // 's'\n\t0,   // 't'\n\t18,  // 'u'\n\t33,  // 'v'\n\t11,  // 'w'\n\t41,  // 'x'\n\t28,  // 'y'\n\t53,  // 'z'\n\t124, // '{'\n\t125, // '|'\n\t126, // '}'\n\t76,  // '~'\n\t127, // '\\x7f'\n\t128, // '\\x80'\n\t129, // '\\x81'\n\t130, // '\\x82'\n\t131, // '\\x83'\n\t132, // '\\x84'\n\t133, // '\\x85'\n\t134, // '\\x86'\n\t135, // '\\x87'\n\t136, // '\\x88'\n\t137, // '\\x89'\n\t138, // '\\x8a'\n\t139, // '\\x8b'\n\t140, // '\\x8c'\n\t141, // '\\x8d'\n\t142, // '\\x8e'\n\t143, // '\\x8f'\n\t144, // '\\x90'\n\t145, // '\\x91'\n\t146, // '\\x92'\n\t147, // '\\x93'\n\t148, // '\\x94'\n\t149, // '\\x95'\n\t150, // '\\x96'\n\t151, // '\\x97'\n\t152, // '\\x98'\n\t153, // '\\x99'\n\t154, // '\\x9a'\n\t155, // '\\x9b'\n\t156, // '\\x9c'\n\t157, // '\\x9d'\n\t158, // '\\x9e'\n\t159, // '\\x9f'\n\t160, // '\\xa0'\n\t161, // '¡'\n\t162, // '¢'\n\t163, // '£'\n\t164, // '¤'\n\t165, // '¥'\n\t166, // '¦'\n\t167, // '§'\n\t168, // '¨'\n\t169, // '©'\n\t170, // 'ª'\n\t171, // '«'\n\t172, // '¬'\n\t173, // '\\xad'\n\t174, // '®'\n\t175, // '¯'\n\t176, // '°'\n\t177, // '±'\n\t178, // '²'\n\t179, // '³'\n\t180, // '´'\n\t181, // 'µ'\n\t182, // '¶'\n\t183, // '·'\n\t184, // '¸'\n\t185, // '¹'\n\t186, // 'º'\n\t187, // '»'\n\t188, // '¼'\n\t189, // '½'\n\t190, // '¾'\n\t191, // '¿'\n\t192, // 'À'\n\t193, // 'Á'\n\t194, // 'Â'\n\t195, // 'Ã'\n\t196, // 'Ä'\n\t197, // 'Å'\n\t198, // 'Æ'\n\t199, // 'Ç'\n\t200, // 'È'\n\t201, // 'É'\n\t202, // 'Ê'\n\t203, // 'Ë'\n\t204, // 'Ì'\n\t205, // 'Í'\n\t206, // 'Î'\n\t207, // 'Ï'\n\t208, // 'Ð'\n\t209, // 'Ñ'\n\t210, // 'Ò'\n\t211, // 'Ó'\n\t212, // 'Ô'\n\t213, // 'Õ'\n\t214, // 'Ö'\n\t215, // '×'\n\t216, // 'Ø'\n\t217, // 'Ù'\n\t218, // 'Ú'\n\t219, // 'Û'\n\t220, // 'Ü'\n\t221, // 'Ý'\n\t222, // 'Þ'\n\t223, // 'ß'\n\t224, // 'à'\n\t225, // 'á'\n\t226, // 'â'\n\t227, // 'ã'\n\t228, // 'ä'\n\t229, // 'å'\n\t230, // 'æ'\n\t231, // 'ç'\n\t232, // 'è'\n\t233, // 'é'\n\t234, // 'ê'\n\t235, // 'ë'\n\t236, // 'ì'\n\t237, // 'í'\n\t238, // 'î'\n\t239, // 'ï'\n\t240, // 'ð'\n\t241, // 'ñ'\n\t242, // 'ò'\n\t243, // 'ó'\n\t244, // 'ô'\n\t245, // 'õ'\n\t246, // 'ö'\n\t247, // '÷'\n\t248, // 'ø'\n\t249, // 'ù'\n\t250, // 'ú'\n\t251, // 'û'\n\t252, // 'ü'\n\t253, // 'ý'\n\t254, // 'þ'\n\t255, // 'ÿ'\n}\n\nvar commonInputsInv = []byte{\n\t't',\n\t'e',\n\t'/',\n\t'o',\n\t'a',\n\t's',\n\t'r',\n\t'i',\n\t'p',\n\t'c',\n\t'n',\n\t'w',\n\t'.',\n\t'h',\n\t'l',\n\t'm',\n\t'-',\n\t'd',\n\t'u',\n\t'0',\n\t'1',\n\t'2',\n\t'g',\n\t'=',\n\t':',\n\t'b',\n\t'f',\n\t'3',\n\t'y',\n\t'5',\n\t'&',\n\t'_',\n\t'4',\n\t'v',\n\t'9',\n\t'6',\n\t'7',\n\t'8',\n\t'k',\n\t'%',\n\t'?',\n\t'x',\n\t'C',\n\t'D',\n\t'A',\n\t'S',\n\t'F',\n\t'I',\n\t'B',\n\t'E',\n\t'j',\n\t'P',\n\t'T',\n\t'z',\n\t'R',\n\t'N',\n\t'M',\n\t'+',\n\t'L',\n\t'O',\n\t'q',\n\t'H',\n\t'G',\n\t'W',\n\t'U',\n\t'V',\n\t',',\n\t'Y',\n\t'K',\n\t'J',\n\t'Z',\n\t'X',\n\t'Q',\n\t';',\n\t')',\n\t'(',\n\t'~',\n\t'[',\n\t']',\n\t'$',\n\t'!',\n\t'\\'',\n\t'*',\n\t'@',\n\t'\\x00',\n\t'\\x01',\n\t'\\x02',\n\t'\\x03',\n\t'\\x04',\n\t'\\x05',\n\t'\\x06',\n\t'\\x07',\n\t'\\x08',\n\t'\\t',\n\t'\\n',\n\t'\\x0b',\n\t'\\x0c',\n\t'\\r',\n\t'\\x0e',\n\t'\\x0f',\n\t'\\x10',\n\t'\\x11',\n\t'\\x12',\n\t'\\x13',\n\t'\\x14',\n\t'\\x15',\n\t'\\x16',\n\t'\\x17',\n\t'\\x18',\n\t'\\x19',\n\t'\\x1a',\n\t'\\x1b',\n\t'\\x1c',\n\t'\\x1d',\n\t'\\x1e',\n\t'\\x1f',\n\t' ',\n\t'\"',\n\t'#',\n\t'<',\n\t'>',\n\t'\\\\',\n\t'^',\n\t'`',\n\t'{',\n\t'|',\n\t'}',\n\t'\\x7f',\n\t'\\x80',\n\t'\\x81',\n\t'\\x82',\n\t'\\x83',\n\t'\\x84',\n\t'\\x85',\n\t'\\x86',\n\t'\\x87',\n\t'\\x88',\n\t'\\x89',\n\t'\\x8a',\n\t'\\x8b',\n\t'\\x8c',\n\t'\\x8d',\n\t'\\x8e',\n\t'\\x8f',\n\t'\\x90',\n\t'\\x91',\n\t'\\x92',\n\t'\\x93',\n\t'\\x94',\n\t'\\x95',\n\t'\\x96',\n\t'\\x97',\n\t'\\x98',\n\t'\\x99',\n\t'\\x9a',\n\t'\\x9b',\n\t'\\x9c',\n\t'\\x9d',\n\t'\\x9e',\n\t'\\x9f',\n\t'\\xa0',\n\t'\\xa1',\n\t'\\xa2',\n\t'\\xa3',\n\t'\\xa4',\n\t'\\xa5',\n\t'\\xa6',\n\t'\\xa7',\n\t'\\xa8',\n\t'\\xa9',\n\t'\\xaa',\n\t'\\xab',\n\t'\\xac',\n\t'\\xad',\n\t'\\xae',\n\t'\\xaf',\n\t'\\xb0',\n\t'\\xb1',\n\t'\\xb2',\n\t'\\xb3',\n\t'\\xb4',\n\t'\\xb5',\n\t'\\xb6',\n\t'\\xb7',\n\t'\\xb8',\n\t'\\xb9',\n\t'\\xba',\n\t'\\xbb',\n\t'\\xbc',\n\t'\\xbd',\n\t'\\xbe',\n\t'\\xbf',\n\t'\\xc0',\n\t'\\xc1',\n\t'\\xc2',\n\t'\\xc3',\n\t'\\xc4',\n\t'\\xc5',\n\t'\\xc6',\n\t'\\xc7',\n\t'\\xc8',\n\t'\\xc9',\n\t'\\xca',\n\t'\\xcb',\n\t'\\xcc',\n\t'\\xcd',\n\t'\\xce',\n\t'\\xcf',\n\t'\\xd0',\n\t'\\xd1',\n\t'\\xd2',\n\t'\\xd3',\n\t'\\xd4',\n\t'\\xd5',\n\t'\\xd6',\n\t'\\xd7',\n\t'\\xd8',\n\t'\\xd9',\n\t'\\xda',\n\t'\\xdb',\n\t'\\xdc',\n\t'\\xdd',\n\t'\\xde',\n\t'\\xdf',\n\t'\\xe0',\n\t'\\xe1',\n\t'\\xe2',\n\t'\\xe3',\n\t'\\xe4',\n\t'\\xe5',\n\t'\\xe6',\n\t'\\xe7',\n\t'\\xe8',\n\t'\\xe9',\n\t'\\xea',\n\t'\\xeb',\n\t'\\xec',\n\t'\\xed',\n\t'\\xee',\n\t'\\xef',\n\t'\\xf0',\n\t'\\xf1',\n\t'\\xf2',\n\t'\\xf3',\n\t'\\xf4',\n\t'\\xf5',\n\t'\\xf6',\n\t'\\xf7',\n\t'\\xf8',\n\t'\\xf9',\n\t'\\xfa',\n\t'\\xfb',\n\t'\\xfc',\n\t'\\xfd',\n\t'\\xfe',\n\t'\\xff',\n}\n"
  },
  {
    "path": "common_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport \"testing\"\n\nfunc TestCommonInputs(t *testing.T) {\n\n\t// first ensure items that can be encoded round trip properly\n\tfor i := 0; i < 256; i++ {\n\t\troundTrip(t, byte(i))\n\t}\n\n\t// G maps to 62, +1 is 63, which is highest 6-bit value we can encode\n\tenc := encodeCommon('G')\n\tif enc != 63 {\n\t\tt.Errorf(\"expected G to encode to 63, got %d\", enc)\n\t}\n\n\t// W encodes to 63, +1 is 64, which is too big to fit\n\tenc = encodeCommon('W')\n\tif enc != 0 {\n\t\tt.Errorf(\"expected W to encode to 0, got %d\", enc)\n\t}\n}\n\nfunc roundTrip(t *testing.T, b byte) {\n\tenc := encodeCommon(b)\n\tif enc > 0 {\n\t\tdec := decodeCommon(enc)\n\t\tif dec != b {\n\t\t\tt.Errorf(\"error round trip common input: %d\", b)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "data/words-1000.txt",
    "content": "American\nCongress\nDemocrat\nI\nMr\nMrs\nPM\nRepublican\nTV\na\nability\nable\nabout\nabove\naccept\naccording\naccount\nacross\nact\naction\nactivity\nactually\nadd\naddress\nadministration\nadmit\nadult\naffect\nafter\nagain\nagainst\nage\nagency\nagent\nago\nagree\nagreement\nahead\nair\nall\nallow\nalmost\nalone\nalong\nalready\nalso\nalthough\nalways\namong\namount\nanalysis\nand\nanimal\nanother\nanswer\nany\nanyone\nanything\nappear\napply\napproach\narea\nargue\narm\naround\narrive\nart\narticle\nartist\nas\nask\nassume\nat\nattack\nattention\nattorney\naudience\nauthor\nauthority\navailable\navoid\naway\nbaby\nback\nbad\nbag\nball\nbank\nbar\nbase\nbe\nbeat\nbeautiful\nbecause\nbecome\nbed\nbefore\nbegin\nbehavior\nbehind\nbelieve\nbenefit\nbest\nbetter\nbetween\nbeyond\nbig\nbill\nbillion\nbit\nblack\nblood\nblue\nboard\nbody\nbook\nborn\nboth\nbox\nboy\nbreak\nbring\nbrother\nbudget\nbuild\nbuilding\nbusiness\nbut\nbuy\nby\ncall\ncamera\ncampaign\ncan\ncancer\ncandidate\ncapital\ncar\ncard\ncare\ncareer\ncarry\ncase\ncatch\ncause\ncell\ncenter\ncentral\ncentury\ncertain\ncertainly\nchair\nchallenge\nchance\nchange\ncharacter\ncharge\ncheck\nchild\nchoice\nchoose\nchurch\ncitizen\ncity\ncivil\nclaim\nclass\nclear\nclearly\nclose\ncoach\ncold\ncollection\ncollege\ncolor\ncome\ncommercial\ncommon\ncommunity\ncompany\ncompare\ncomputer\nconcern\ncondition\nconference\nconsider\nconsumer\ncontain\ncontinue\ncontrol\ncost\ncould\ncountry\ncouple\ncourse\ncourt\ncover\ncreate\ncrime\ncultural\nculture\ncup\ncurrent\ncustomer\ncut\ndark\ndata\ndaughter\nday\ndead\ndeal\ndeath\ndebate\ndecade\ndecide\ndecision\ndeep\ndefense\ndegree\ndemocratic\ndescribe\ndesign\ndespite\ndetail\ndetermine\ndevelop\ndevelopment\ndie\ndifference\ndifferent\ndifficult\ndinner\ndirection\ndirector\ndiscover\ndiscuss\ndiscussion\ndisease\ndo\ndoctor\ndog\ndoor\ndown\ndraw\ndream\ndrive\ndrop\ndrug\nduring\neach\nearly\neast\neasy\neat\neconomic\neconomy\nedge\neducation\neffect\neffort\neight\neither\nelection\nelse\nemployee\nend\nenergy\nenjoy\nenough\nenter\nentire\nenvironment\nenvironmental\nespecially\nestablish\neven\nevening\nevent\never\nevery\neverybody\neveryone\neverything\nevidence\nexactly\nexample\nexecutive\nexist\nexpect\nexperience\nexpert\nexplain\neye\nface\nfact\nfactor\nfail\nfall\nfamily\nfar\nfast\nfather\nfear\nfederal\nfeel\nfeeling\nfew\nfield\nfight\nfigure\nfill\nfilm\nfinal\nfinally\nfinancial\nfind\nfine\nfinger\nfinish\nfire\nfirm\nfirst\nfish\nfive\nfloor\nfly\nfocus\nfollow\nfood\nfoot\nfor\nforce\nforeign\nforget\nform\nformer\nforward\nfour\nfree\nfriend\nfrom\nfront\nfull\nfund\nfuture\ngame\ngarden\ngas\ngeneral\ngeneration\nget\ngirl\ngive\nglass\ngo\ngoal\ngood\ngovernment\ngreat\ngreen\nground\ngroup\ngrow\ngrowth\nguess\ngun\nguy\nhair\nhalf\nhand\nhang\nhappen\nhappy\nhard\nhave\nhe\nhead\nhealth\nhear\nheart\nheat\nheavy\nhelp\nher\nhere\nherself\nhigh\nhim\nhimself\nhis\nhistory\nhit\nhold\nhome\nhope\nhospital\nhot\nhotel\nhour\nhouse\nhow\nhowever\nhuge\nhuman\nhundred\nhusband\nidea\nidentify\nif\nimage\nimagine\nimpact\nimportant\nimprove\nin\ninclude\nincluding\nincrease\nindeed\nindicate\nindividual\nindustry\ninformation\ninside\ninstead\ninstitution\ninterest\ninteresting\ninternational\ninterview\ninto\ninvestment\ninvolve\nissue\nit\nitem\nits\nitself\njob\njoin\njust\nkeep\nkey\nkid\nkill\nkind\nkitchen\nknow\nknowledge\nland\nlanguage\nlarge\nlast\nlate\nlater\nlaugh\nlaw\nlawyer\nlay\nlead\nleader\nlearn\nleast\nleave\nleft\nleg\nlegal\nless\nlet\nletter\nlevel\nlie\nlife\nlight\nlike\nlikely\nline\nlist\nlisten\nlittle\nlive\nlocal\nlong\nlook\nlose\nloss\nlot\nlove\nlow\nmachine\nmagazine\nmain\nmaintain\nmajor\nmajority\nmake\nman\nmanage\nmanagement\nmanager\nmany\nmarket\nmarriage\nmaterial\nmatter\nmay\nmaybe\nme\nmean\nmeasure\nmedia\nmedical\nmeet\nmeeting\nmember\nmemory\nmention\nmessage\nmethod\nmiddle\nmight\nmilitary\nmillion\nmind\nminute\nmiss\nmission\nmodel\nmodern\nmoment\nmoney\nmonth\nmore\nmorning\nmost\nmother\nmouth\nmove\nmovement\nmovie\nmuch\nmusic\nmust\nmy\nmyself\nn't\nname\nnation\nnational\nnatural\nnature\nnear\nnearly\nnecessary\nneed\nnetwork\nnever\nnew\nnews\nnewspaper\nnext\nnice\nnight\nno\nnone\nnor\nnorth\nnot\nnote\nnothing\nnotice\nnow\nnumber\noccur\nof\noff\noffer\noffice\nofficer\nofficial\noften\noh\noil\nok\nold\non\nonce\none\nonly\nonto\nopen\noperation\nopportunity\noption\nor\norder\norganization\nother\nothers\nour\nout\noutside\nover\nown\nowner\npage\npain\npainting\npaper\nparent\npart\nparticipant\nparticular\nparticularly\npartner\nparty\npass\npast\npatient\npattern\npay\npeace\npeople\nper\nperform\nperformance\nperhaps\nperiod\nperson\npersonal\nphone\nphysical\npick\npicture\npiece\nplace\nplan\nplant\nplay\nplayer\npoint\npolice\npolicy\npolitical\npolitics\npoor\npopular\npopulation\nposition\npositive\npossible\npower\npractice\nprepare\npresent\npresident\npressure\npretty\nprevent\nprice\nprivate\nprobably\nproblem\nprocess\nproduce\nproduct\nproduction\nprofessional\nprofessor\nprogram\nproject\nproperty\nprotect\nprove\nprovide\npublic\npull\npurpose\npush\nput\nquality\nquestion\nquickly\nquite\nrace\nradio\nraise\nrange\nrate\nrather\nreach\nread\nready\nreal\nreality\nrealize\nreally\nreason\nreceive\nrecent\nrecently\nrecognize\nrecord\nred\nreduce\nreflect\nregion\nrelate\nrelationship\nreligious\nremain\nremember\nremove\nreport\nrepresent\nrequire\nresearch\nresource\nrespond\nresponse\nresponsibility\nrest\nresult\nreturn\nreveal\nrich\nright\nrise\nrisk\nroad\nrock\nrole\nroom\nrule\nrun\nsafe\nsame\nsave\nsay\nscene\nschool\nscience\nscientist\nscore\nsea\nseason\nseat\nsecond\nsection\nsecurity\nsee\nseek\nseem\nsell\nsend\nsenior\nsense\nseries\nserious\nserve\nservice\nset\nseven\nseveral\nsex\nsexual\nshake\nshare\nshe\nshoot\nshort\nshot\nshould\nshoulder\nshow\nside\nsign\nsignificant\nsimilar\nsimple\nsimply\nsince\nsing\nsingle\nsister\nsit\nsite\nsituation\nsix\nsize\nskill\nskin\nsmall\nsmile\nso\nsocial\nsociety\nsoldier\nsome\nsomebody\nsomeone\nsomething\nsometimes\nson\nsong\nsoon\nsort\nsound\nsource\nsouth\nsouthern\nspace\nspeak\nspecial\nspecific\nspeech\nspend\nsport\nspring\nstaff\nstage\nstand\nstandard\nstar\nstart\nstate\nstatement\nstation\nstay\nstep\nstill\nstock\nstop\nstore\nstory\nstrategy\nstreet\nstrong\nstructure\nstudent\nstudy\nstuff\nstyle\nsubject\nsuccess\nsuccessful\nsuch\nsuddenly\nsuffer\nsuggest\nsummer\nsupport\nsure\nsurface\nsystem\ntable\ntake\ntalk\ntask\ntax\nteach\nteacher\nteam\ntechnology\ntelevision\ntell\nten\ntend\nterm\ntest\nthan\nthank\nthat\nthe\ntheir\nthem\nthemselves\nthen\ntheory\nthere\nthese\nthey\nthing\nthink\nthird\nthis\nthose\nthough\nthought\nthousand\nthreat\nthree\nthrough\nthroughout\nthrow\nthus\ntime\nto\ntoday\ntogether\ntonight\ntoo\ntop\ntotal\ntough\ntoward\ntown\ntrade\ntraditional\ntraining\ntravel\ntreat\ntreatment\ntree\ntrial\ntrip\ntrouble\ntrue\ntruth\ntry\nturn\ntwo\ntype\nunder\nunderstand\nunit\nuntil\nup\nupon\nus\nuse\nusually\nvalue\nvarious\nvery\nvictim\nview\nviolence\nvisit\nvoice\nvote\nwait\nwalk\nwall\nwant\nwar\nwatch\nwater\nway\nwe\nweapon\nwear\nweek\nweight\nwell\nwest\nwestern\nwhat\nwhatever\nwhen\nwhere\nwhether\nwhich\nwhile\nwhite\nwho\nwhole\nwhom\nwhose\nwhy\nwide\nwife\nwill\nwin\nwind\nwindow\nwish\nwith\nwithin\nwithout\nwoman\nwonder\nword\nwork\nworker\nworld\nworry\nwould\nwrite\nwriter\nwrong\nyard\nyeah\nyear\nyes\nyet\nyou\nyoung\nyour\nyourself\n"
  },
  {
    "path": "decoder_v1.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"strconv\"\n)\n\nfunc init() {\n\tregisterDecoder(versionV1, func(data []byte) decoder {\n\t\treturn newDecoderV1(data)\n\t})\n}\n\ntype decoderV1 struct {\n\tdata []byte\n}\n\nfunc newDecoderV1(data []byte) *decoderV1 {\n\treturn &decoderV1{\n\t\tdata: data,\n\t}\n}\n\nfunc (d *decoderV1) getRoot() int {\n\tif len(d.data) < footerSizeV1 {\n\t\treturn noneAddr\n\t}\n\tfooter := d.data[len(d.data)-footerSizeV1:]\n\troot := binary.LittleEndian.Uint64(footer[8:])\n\treturn int(root)\n}\n\nfunc (d *decoderV1) getLen() int {\n\tif len(d.data) < footerSizeV1 {\n\t\treturn 0\n\t}\n\tfooter := d.data[len(d.data)-footerSizeV1:]\n\tdlen := binary.LittleEndian.Uint64(footer)\n\treturn int(dlen)\n}\n\nfunc (d *decoderV1) stateAt(addr int, prealloc fstState) (fstState, error) {\n\tstate, ok := prealloc.(*fstStateV1)\n\tif ok && state != nil {\n\t\t*state = fstStateV1{} // clear the struct\n\t} else {\n\t\tstate = &fstStateV1{}\n\t}\n\terr := state.at(d.data, addr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn state, nil\n}\n\ntype fstStateV1 struct {\n\tdata     []byte\n\ttop      int\n\tbottom   int\n\tnumTrans int\n\n\t// single trans only\n\tsingleTransChar byte\n\tsingleTransNext bool\n\tsingleTransAddr uint64\n\tsingleTransOut  uint64\n\n\t// shared\n\ttransSize int\n\toutSize   int\n\n\t// multiple trans only\n\tfinal       bool\n\ttransTop    int\n\ttransBottom int\n\tdestTop     int\n\tdestBottom  int\n\toutTop      int\n\toutBottom   int\n\toutFinal    int\n}\n\nfunc (f *fstStateV1) isEncodedSingle() bool {\n\tif f.data[f.top]>>7 > 0 {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (f *fstStateV1) at(data []byte, addr int) error {\n\tf.data = data\n\tif addr == emptyAddr {\n\t\treturn f.atZero()\n\t} else if addr == noneAddr {\n\t\treturn f.atNone()\n\t}\n\tif addr > len(data) || addr < 16 {\n\t\treturn fmt.Errorf(\"invalid address %d/%d\", addr, len(data))\n\t}\n\tf.top = addr\n\tf.bottom = addr\n\tif f.isEncodedSingle() {\n\t\treturn f.atSingle(data, addr)\n\t}\n\treturn f.atMulti(data, addr)\n}\n\nfunc (f *fstStateV1) atZero() error {\n\tf.top = 0\n\tf.bottom = 1\n\tf.numTrans = 0\n\tf.final = true\n\tf.outFinal = 0\n\treturn nil\n}\n\nfunc (f *fstStateV1) atNone() error {\n\tf.top = 0\n\tf.bottom = 1\n\tf.numTrans = 0\n\tf.final = false\n\tf.outFinal = 0\n\treturn nil\n}\n\nfunc (f *fstStateV1) atSingle(data []byte, addr int) error {\n\t// handle single transition case\n\tf.numTrans = 1\n\tf.singleTransNext = data[f.top]&transitionNext > 0\n\tf.singleTransChar = data[f.top] & maxCommon\n\tif f.singleTransChar == 0 {\n\t\tf.bottom-- // extra byte for uncommon\n\t\tf.singleTransChar = data[f.bottom]\n\t} else {\n\t\tf.singleTransChar = decodeCommon(f.singleTransChar)\n\t}\n\tif f.singleTransNext {\n\t\t// now we know the bottom, can compute next addr\n\t\tf.singleTransAddr = uint64(f.bottom - 1)\n\t\tf.singleTransOut = 0\n\t} else {\n\t\tf.bottom-- // extra byte with pack sizes\n\t\tf.transSize, f.outSize = decodePackSize(data[f.bottom])\n\t\tf.bottom -= f.transSize // exactly one trans\n\t\tf.singleTransAddr = readPackedUint(data[f.bottom : f.bottom+f.transSize])\n\t\tif f.outSize > 0 {\n\t\t\tf.bottom -= f.outSize // exactly one out (could be length 0 though)\n\t\t\tf.singleTransOut = readPackedUint(data[f.bottom : f.bottom+f.outSize])\n\t\t} else {\n\t\t\tf.singleTransOut = 0\n\t\t}\n\t\t// need to wait till we know bottom\n\t\tif f.singleTransAddr != 0 {\n\t\t\tf.singleTransAddr = uint64(f.bottom) - f.singleTransAddr\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (f *fstStateV1) atMulti(data []byte, addr int) error {\n\t// handle multiple transitions case\n\tf.final = data[f.top]&stateFinal > 0\n\tf.numTrans = int(data[f.top] & maxNumTrans)\n\tif f.numTrans == 0 {\n\t\tf.bottom-- // extra byte for number of trans\n\t\tf.numTrans = int(data[f.bottom])\n\t\tif f.numTrans == 1 {\n\t\t\t// can't really be 1 here, this is special case that means 256\n\t\t\tf.numTrans = 256\n\t\t}\n\t}\n\tf.bottom-- // extra byte with pack sizes\n\tf.transSize, f.outSize = decodePackSize(data[f.bottom])\n\n\tf.transTop = f.bottom\n\tf.bottom -= f.numTrans // one byte for each transition\n\tf.transBottom = f.bottom\n\n\tf.destTop = f.bottom\n\tf.bottom -= f.numTrans * f.transSize\n\tf.destBottom = f.bottom\n\n\tif f.outSize > 0 {\n\t\tf.outTop = f.bottom\n\t\tf.bottom -= f.numTrans * f.outSize\n\t\tf.outBottom = f.bottom\n\t\tif f.final {\n\t\t\tf.bottom -= f.outSize\n\t\t\tf.outFinal = f.bottom\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (f *fstStateV1) Address() int {\n\treturn f.top\n}\n\nfunc (f *fstStateV1) Final() bool {\n\treturn f.final\n}\n\nfunc (f *fstStateV1) FinalOutput() uint64 {\n\tif f.final && f.outSize > 0 {\n\t\treturn readPackedUint(f.data[f.outFinal : f.outFinal+f.outSize])\n\t}\n\treturn 0\n}\n\nfunc (f *fstStateV1) NumTransitions() int {\n\treturn f.numTrans\n}\n\nfunc (f *fstStateV1) TransitionAt(i int) byte {\n\tif f.isEncodedSingle() {\n\t\treturn f.singleTransChar\n\t}\n\ttransitionKeys := f.data[f.transBottom:f.transTop]\n\treturn transitionKeys[f.numTrans-i-1]\n}\n\nfunc (f *fstStateV1) TransitionFor(b byte) (int, int, uint64) {\n\tif f.isEncodedSingle() {\n\t\tif f.singleTransChar == b {\n\t\t\treturn 0, int(f.singleTransAddr), f.singleTransOut\n\t\t}\n\t\treturn -1, noneAddr, 0\n\t}\n\ttransitionKeys := f.data[f.transBottom:f.transTop]\n\tpos := bytes.IndexByte(transitionKeys, b)\n\tif pos < 0 {\n\t\treturn -1, noneAddr, 0\n\t}\n\ttransDests := f.data[f.destBottom:f.destTop]\n\tdest := int(readPackedUint(transDests[pos*f.transSize : pos*f.transSize+f.transSize]))\n\tif dest > 0 {\n\t\t// convert delta\n\t\tdest = f.bottom - dest\n\t}\n\ttransVals := f.data[f.outBottom:f.outTop]\n\tvar out uint64\n\tif f.outSize > 0 {\n\t\tout = readPackedUint(transVals[pos*f.outSize : pos*f.outSize+f.outSize])\n\t}\n\treturn f.numTrans - pos - 1, dest, out\n}\n\nfunc (f *fstStateV1) String() string {\n\trv := \"\"\n\trv += fmt.Sprintf(\"State: %d (%#x)\", f.top, f.top)\n\tif f.final {\n\t\trv += \" final\"\n\t\tfout := f.FinalOutput()\n\t\tif fout != 0 {\n\t\t\trv += fmt.Sprintf(\" (%d)\", fout)\n\t\t}\n\t}\n\trv += \"\\n\"\n\trv += fmt.Sprintf(\"Data: % x\\n\", f.data[f.bottom:f.top+1])\n\n\tfor i := 0; i < f.numTrans; i++ {\n\t\ttransChar := f.TransitionAt(i)\n\t\t_, transDest, transOut := f.TransitionFor(transChar)\n\t\trv += fmt.Sprintf(\" - %d (%#x) '%s' ---> %d (%#x)  with output: %d\", transChar, transChar, string(transChar), transDest, transDest, transOut)\n\t\trv += \"\\n\"\n\t}\n\tif f.numTrans == 0 {\n\t\trv += \"\\n\"\n\t}\n\treturn rv\n}\n\nfunc (f *fstStateV1) DotString(num int) string {\n\trv := \"\"\n\tlabel := fmt.Sprintf(\"%d\", num)\n\tfinal := \"\"\n\tif f.final {\n\t\tfinal = \",peripheries=2\"\n\t}\n\trv += fmt.Sprintf(\"    %d [label=\\\"%s\\\"%s];\\n\", f.top, label, final)\n\n\tfor i := 0; i < f.numTrans; i++ {\n\t\ttransChar := f.TransitionAt(i)\n\t\t_, transDest, transOut := f.TransitionFor(transChar)\n\t\tout := \"\"\n\t\tif transOut != 0 {\n\t\t\tout = fmt.Sprintf(\"/%d\", transOut)\n\t\t}\n\t\trv += fmt.Sprintf(\"    %d -> %d [label=\\\"%s%s\\\"];\\n\", f.top, transDest, escapeInput(transChar), out)\n\t}\n\n\treturn rv\n}\n\nfunc escapeInput(b byte) string {\n\tx := strconv.AppendQuoteRune(nil, rune(b))\n\treturn string(x[1:(len(x) - 1)])\n}\n"
  },
  {
    "path": "decoder_v1_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestDecoderVersionError(t *testing.T) {\n\t_, err := loadDecoder(629, nil)\n\tif err == nil {\n\t\tt.Errorf(\"expected error loading decoder version 629, got nil\")\n\t}\n}\n\nfunc TestShortHeader(t *testing.T) {\n\theader := make([]byte, 15)\n\t_, _, err := decodeHeader(header)\n\tif err == nil {\n\t\tt.Errorf(\"expected error decoding short header, got nil\")\n\t}\n}\n\nfunc TestDecoderRootLen(t *testing.T) {\n\td := newDecoderV1([]byte{1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0})\n\tif d.getLen() != 1 {\n\t\tt.Fatalf(\"expected parsed footer length 1, got %d\", d.getLen())\n\t}\n\tif d.getRoot() != 2 {\n\t\tt.Fatalf(\"expected parsed footer length 2, got %d\", d.getLen())\n\t}\n}\n\nfunc TestDecoderStateAt(t *testing.T) {\n\ttests := []struct {\n\t\tdesc string\n\t\tdata []byte\n\t\twant *fstStateV1\n\t}{\n\t\t{\n\t\t\t\"one trans, trans next, common char\",\n\t\t\t[]byte{\n\t\t\t\t// header\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t\t// test node data\n\t\t\t\toneTransition | transitionNext | encodeCommon('a'),\n\t\t\t\t// footer\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t},\n\t\t\t&fstStateV1{\n\t\t\t\tnumTrans:        1,\n\t\t\t\ttop:             16,\n\t\t\t\tbottom:          16,\n\t\t\t\tsingleTransChar: 'a',\n\t\t\t\tsingleTransNext: true,\n\t\t\t\tsingleTransAddr: 15,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"one trans, trans next, uncommon char\",\n\t\t\t[]byte{\n\t\t\t\t// header\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t\t// test node data\n\t\t\t\t0xff,\n\t\t\t\toneTransition | transitionNext,\n\t\t\t\t// footer\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t},\n\t\t\t&fstStateV1{\n\t\t\t\tnumTrans:        1,\n\t\t\t\ttop:             17,\n\t\t\t\tbottom:          16,\n\t\t\t\tsingleTransChar: 0xff,\n\t\t\t\tsingleTransNext: true,\n\t\t\t\tsingleTransAddr: 15,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"one trans, trans not next, common char\",\n\t\t\t[]byte{\n\t\t\t\t// header\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t\t// test node data\n\t\t\t\t4,        // delta address packed\n\t\t\t\t1<<4 | 0, // pack sizes\n\t\t\t\toneTransition | encodeCommon('a'),\n\t\t\t\t// footer\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t},\n\t\t\t&fstStateV1{\n\t\t\t\tnumTrans:        1,\n\t\t\t\ttop:             18,\n\t\t\t\tbottom:          16,\n\t\t\t\tsingleTransChar: 'a',\n\t\t\t\tsingleTransNext: false,\n\t\t\t\tsingleTransAddr: 12,\n\t\t\t\ttransSize:       1,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"one trans, trans not next, uncommon char\",\n\t\t\t[]byte{\n\t\t\t\t// header\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t\t// test node data\n\t\t\t\t4,        // delta address packed\n\t\t\t\t1<<4 | 0, // pack sizes\n\t\t\t\t0xff,\n\t\t\t\toneTransition,\n\t\t\t\t// footer\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t},\n\t\t\t&fstStateV1{\n\t\t\t\tnumTrans:        1,\n\t\t\t\ttop:             19,\n\t\t\t\tbottom:          16,\n\t\t\t\tsingleTransChar: 0xff,\n\t\t\t\tsingleTransNext: false,\n\t\t\t\tsingleTransAddr: 12,\n\t\t\t\ttransSize:       1,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"one trans, trans not next, common char, with value\",\n\t\t\t[]byte{\n\t\t\t\t// header\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t\t// test node data\n\t\t\t\t27,       // trans value\n\t\t\t\t4,        // delta address packed\n\t\t\t\t1<<4 | 1, // pack sizes\n\t\t\t\toneTransition | encodeCommon('a'),\n\t\t\t\t// footer\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t},\n\t\t\t&fstStateV1{\n\t\t\t\tnumTrans:        1,\n\t\t\t\ttop:             19,\n\t\t\t\tbottom:          16,\n\t\t\t\tsingleTransChar: 'a',\n\t\t\t\tsingleTransNext: false,\n\t\t\t\tsingleTransAddr: 12,\n\t\t\t\tsingleTransOut:  27,\n\t\t\t\ttransSize:       1,\n\t\t\t\toutSize:         1,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"one trans, trans not next, uncommon char, with value\",\n\t\t\t[]byte{\n\t\t\t\t// header\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t\t// test node data\n\t\t\t\t39,       // trans val\n\t\t\t\t4,        // delta address packed\n\t\t\t\t1<<4 | 1, // pack sizes\n\t\t\t\t0xff,\n\t\t\t\toneTransition,\n\t\t\t\t// footer\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t},\n\t\t\t&fstStateV1{\n\t\t\t\tnumTrans:        1,\n\t\t\t\ttop:             20,\n\t\t\t\tbottom:          16,\n\t\t\t\tsingleTransChar: 0xff,\n\t\t\t\tsingleTransNext: false,\n\t\t\t\tsingleTransAddr: 12,\n\t\t\t\tsingleTransOut:  39,\n\t\t\t\ttransSize:       1,\n\t\t\t\toutSize:         1,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"many trans, not final, no values\",\n\t\t\t[]byte{\n\t\t\t\t// header\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t\t// test node data\n\t\t\t\t2, // delta addresses packed\n\t\t\t\t3,\n\t\t\t\t4,\n\t\t\t\t'c', // encoded keys reversed\n\t\t\t\t'b',\n\t\t\t\t'a',\n\t\t\t\t1<<4 | 0, // pack sizes\n\t\t\t\tencodeNumTrans(3),\n\t\t\t\t// footer\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t},\n\t\t\t&fstStateV1{\n\t\t\t\tnumTrans:    3,\n\t\t\t\ttop:         23,\n\t\t\t\tbottom:      16,\n\t\t\t\ttransSize:   1,\n\t\t\t\tdestBottom:  16,\n\t\t\t\tdestTop:     19,\n\t\t\t\ttransBottom: 19,\n\t\t\t\ttransTop:    22,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"many trans, not final, with values\",\n\t\t\t[]byte{\n\t\t\t\t// header\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t\t// test node data\n\t\t\t\t7, // values reversed\n\t\t\t\t0,\n\t\t\t\t3,\n\t\t\t\t2, // delta addresses reversed\n\t\t\t\t3,\n\t\t\t\t4,\n\t\t\t\t'c', // encoded keys reversed\n\t\t\t\t'b',\n\t\t\t\t'a',\n\t\t\t\t1<<4 | 1, // pack sizes\n\t\t\t\tencodeNumTrans(3),\n\t\t\t\t// footer\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t},\n\t\t\t&fstStateV1{\n\t\t\t\tnumTrans:    3,\n\t\t\t\ttop:         26,\n\t\t\t\tbottom:      16,\n\t\t\t\ttransSize:   1,\n\t\t\t\toutSize:     1,\n\t\t\t\toutBottom:   16,\n\t\t\t\toutTop:      19,\n\t\t\t\tdestBottom:  19,\n\t\t\t\tdestTop:     22,\n\t\t\t\ttransBottom: 22,\n\t\t\t\ttransTop:    25,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"many trans, final, with values\",\n\t\t\t[]byte{\n\t\t\t\t// header\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t\t// test node data\n\t\t\t\t9, // node final val\n\t\t\t\t7, // values reversed\n\t\t\t\t0,\n\t\t\t\t3,\n\t\t\t\t2, // delta addresses reversed\n\t\t\t\t3,\n\t\t\t\t4,\n\t\t\t\t'c', // encoded keys reversed\n\t\t\t\t'b',\n\t\t\t\t'a',\n\t\t\t\t1<<4 | 1, // pack sizes\n\t\t\t\tstateFinal | encodeNumTrans(3),\n\t\t\t\t// footer\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t},\n\t\t\t&fstStateV1{\n\t\t\t\tfinal:       true,\n\t\t\t\tnumTrans:    3,\n\t\t\t\ttop:         27,\n\t\t\t\tbottom:      16,\n\t\t\t\ttransSize:   1,\n\t\t\t\toutSize:     1,\n\t\t\t\toutBottom:   17,\n\t\t\t\toutTop:      20,\n\t\t\t\tdestBottom:  20,\n\t\t\t\tdestTop:     23,\n\t\t\t\ttransBottom: 23,\n\t\t\t\ttransTop:    26,\n\t\t\t\toutFinal:    16,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"max trans, \",\n\t\t\t[]byte{\n\t\t\t\t// header\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t\t// test node data\n\t\t\t\t// delta addresses packed\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,\n\t\t\t\t// encoded keys reversed\n\t\t\t\t0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,\n\t\t\t\t0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,\n\t\t\t\t0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,\n\t\t\t\t0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,\n\t\t\t\t0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,\n\t\t\t\t0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,\n\t\t\t\t0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,\n\t\t\t\t0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,\n\t\t\t\t0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,\n\t\t\t\t0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,\n\t\t\t\t0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,\n\t\t\t\t0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,\n\t\t\t\t0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,\n\t\t\t\t0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,\n\t\t\t\t0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,\n\t\t\t\t0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,\n\t\t\t\t1<<4 | 0, // pack sizes\n\t\t\t\t1,        // actual trans 1 == 256\n\t\t\t\t0,        // zero trans (wont fit)\n\t\t\t\t// footer\n\t\t\t\t1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,\n\t\t\t},\n\t\t\t&fstStateV1{\n\t\t\t\tnumTrans:    256,\n\t\t\t\ttop:         530,\n\t\t\t\tbottom:      16,\n\t\t\t\ttransSize:   1,\n\t\t\t\tdestBottom:  16,\n\t\t\t\tdestTop:     272,\n\t\t\t\ttransBottom: 272,\n\t\t\t\ttransTop:    528,\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.desc, func(t *testing.T) {\n\t\t\td := newDecoderV1(test.data)\n\t\t\ttest.want.data = test.data\n\t\t\tgot, err := d.stateAt(len(test.data)-17, nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif !reflect.DeepEqual(got, test.want) {\n\t\t\t\tt.Errorf(\"wanted: %+v, got: %+v\", test.want, got)\n\t\t\t}\n\t\t\taddr := got.Address()\n\t\t\tif addr != test.want.top {\n\t\t\t\tt.Errorf(\"expected address to match: %d - %d\", addr, test.want.top)\n\t\t\t}\n\t\t\tfin := got.Final()\n\t\t\tif fin != test.want.final {\n\t\t\t\tt.Errorf(\"expected final to match: %t - %t\", fin, test.want.final)\n\t\t\t}\n\t\t\tntrans := got.NumTransitions()\n\t\t\tif ntrans != test.want.numTrans {\n\t\t\t\tt.Errorf(\"expected num trans to match: %d - %d\", ntrans, test.want.numTrans)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestFSTStateFinalOutput(t *testing.T) {\n\ttests := []struct {\n\t\tdesc string\n\t\tin   *fstStateV1\n\t\twant uint64\n\t}{\n\t\t{\n\t\t\t\"final output for final state\",\n\t\t\t&fstStateV1{\n\t\t\t\tdata:     []byte{7},\n\t\t\t\tnumTrans: 2,\n\t\t\t\tfinal:    true,\n\t\t\t\toutSize:  1,\n\t\t\t\toutFinal: 0,\n\t\t\t},\n\t\t\t7,\n\t\t},\n\t\t{\n\t\t\t\"final output for non-final state\",\n\t\t\t&fstStateV1{\n\t\t\t\tdata:     []byte{7},\n\t\t\t\tnumTrans: 2,\n\t\t\t\tfinal:    false,\n\t\t\t\toutSize:  1,\n\t\t\t},\n\t\t\t0,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.desc, func(t *testing.T) {\n\t\t\tgot := test.in.FinalOutput()\n\t\t\tif got != test.want {\n\t\t\t\tt.Errorf(\"wanted: %d, got: %d\", test.want, got)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestDecodeStateZero(t *testing.T) {\n\tvar state fstStateV1\n\terr := state.at(nil, 0)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif state.numTrans != 0 {\n\t\tt.Errorf(\"expected 0 states, got %d\", state.numTrans)\n\t}\n\tif !state.final {\n\t\tt.Errorf(\"expected state final, got %t\", state.final)\n\t}\n}\n\nfunc TestDecodeAtInvalid(t *testing.T) {\n\tvar state fstStateV1\n\terr := state.at(nil, 15)\n\tif err == nil {\n\t\tt.Errorf(\"expected error invalid address, got nil\")\n\t}\n}\n\nfunc TestFSTStateTransitionAt(t *testing.T) {\n\tstate := fstStateV1{\n\t\tdata:            []byte{oneTransition | encodeCommon('a')},\n\t\tnumTrans:        1,\n\t\tsingleTransChar: 'a',\n\t}\n\tgot := state.TransitionAt(0)\n\tif got != state.singleTransChar {\n\t\tt.Errorf(\"expected %s got %s\", string(state.singleTransChar), string(got))\n\t}\n\n\tstate = fstStateV1{\n\t\tdata:        []byte{'b', 'a'},\n\t\tnumTrans:    2,\n\t\ttransBottom: 0,\n\t\ttransTop:    2,\n\t}\n\tgot = state.TransitionAt(0)\n\tif got != 'a' {\n\t\tt.Errorf(\"expected %s got %s\", string('a'), string(got))\n\t}\n\n}\n"
  },
  {
    "path": "docs/format.md",
    "content": "# vellum file format v1\n\nThe v1 file format for vellum has been designed by trying to understand the file format used by [BurntSushi/fst](https://github.com/BurntSushi/fst) library.  It should be binary compatible, but no attempt has been made to verify this.\n\n## Overview\n\nThe file has 3 sections:\n - header\n - edge/transition data\n - footer\n\n### Header\n\nThe header is 16 bytes in total.\n - 8 bytes version, uint64 little-endian\n - 8 bytes type, uint64 little-endian (currently always 0, no meaning assigned)\n\nA side-effect of this header is that when computing transition target addresses at runtime, any address < 16 is invalid.\n\n### State/Transition Data\n\nA state is encoded with the following sections, HOWEVER, many sections are optional and omitted for various combinations of settings.  In the order they occur:\n\n- node final output value (packed integer of the computed output size for this node)\n- n transition output values (packed integers, of the computed output size for this node, in REVERSE transition order)\n- n transition addresses (delta encoded, relative the lowest byte of this node, packed at the computed transition address size for this node, in REVERSE transition order)\n- n transition bytes (1 byte for each transition, in REVERSE transition order)\n- pack sizes, 1 byte, high 4 bits transition address size, low 4 bits output size\n- number of transitions, 1 byte (ONLY if it didn't fit in the top byte), value of 1 in this byte means 256 (1 would have fit into the top byte)\n- single transition byte, 1 byte (ONLY if it didn't fit in the top byte)\n- top byte, encodes various flags, and uses remaining bits depending on those flags, broken out separate below\n\n#### State Top Byte\n\n - high bit\n  - 1 means, this edge has just 1 transition\n  - 0 means, this edge has multiple transitions\n\n##### 1 transition States\n\n - second bit flags jump to previous\n  - 1 means this transition target is the immediately preceding state\n  - 0 means there will transition address in the rest of the data\n\n - remaining 6 bits attempt to encode the transition byte\n  - Obviously this requires 8 bits, but we map the most frequently used bytes into the lowest 6 bits (see common.go). If the byte we need to encode doesn't fit, we encode 0, and read it fully in the following byte. This allows the most common bytes in a single transition edge to fit into just a single byte.\n\n##### Multiple Transition States\n\n - second bit flags final states\n  - 1 means this is a final state\n  - 0 means this is not a final state\n\n - remaining 6 bits attempt to encode the number of transitions\n  - Obviously, this can require 8 bits, be we assume that many states have fewer transition, and will fit. If the number won't fit, we encode 0 here, and read it fully in the following byte. Because we could 256 transitions, that full byte still isn't enough, so we reuse the value 1 to mean 256. The value of 1 would never naturally occur in this position, since 1 transition would have fit into the top byte (NOTE: single transition states that are final are encoded as multi-transition states, but the value of 1 would fit in the top 6 bytes).\n\n### Single Transition Jump To Previous\n\nThe flag marking that a single transition state should jump to the previous state works because we encode all of the node data backwards (ie, we start processing state date with the last byte).  Since, at runtime, we can always compute the lowest byte of the state we're in, we can trivially compute the start address of the previous node, just by subtracting one.  This allows saving another set of bytes in many cases which would have otherwise been needed to encode that address.\n\n### Delta Addresses\n\nAll transition target addresses are delta encoded, relative to the lowest byte in the current state.\n\n### Packed Integer Encoding\n\nFor both the output values and transition target addresses, we choose a fixed size number of bytes that will work for encoding all the appropriate values in this state.  Because this length will be recorded (in the pack sizes section), we don't need to use varint encoding, we can instead simply use the minimum number of bytes required.  So, 8-bit values take just 1 byte, etc.  This has the advantage that small values take less space, but the sizes are still fixed, so we can easily navigate without excessive computation.\n\n\n### Footer\n\nThe footer is 16 bytes in total.\n- 8 bytes number of keys, uint64 little-endian\n- 8 bytes root address (absolute, not delta encoded like other addresses in file), uint64 little-endian\n\n## Encoding Streaming\n\nStates are written out to the underlying writer as soon as possible.  This allows us to get an early start on I/O while still building the FST, reducing the overall time to build, and it also allows us to reduce the memory consumed during the build process.\n\nBecause of this, the root node will always be the last node written in the file.\n"
  },
  {
    "path": "encoder_v1.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"io\"\n)\n\nconst versionV1 = 1\nconst oneTransition = 1 << 7\nconst transitionNext = 1 << 6\nconst stateFinal = 1 << 6\nconst footerSizeV1 = 16\n\nfunc init() {\n\tregisterEncoder(versionV1, func(w io.Writer) encoder {\n\t\treturn newEncoderV1(w)\n\t})\n}\n\ntype encoderV1 struct {\n\tbw *writer\n}\n\nfunc newEncoderV1(w io.Writer) *encoderV1 {\n\treturn &encoderV1{\n\t\tbw: newWriter(w),\n\t}\n}\n\nfunc (e *encoderV1) reset(w io.Writer) {\n\te.bw.Reset(w)\n}\n\nfunc (e *encoderV1) start() error {\n\theader := make([]byte, headerSize)\n\tbinary.LittleEndian.PutUint64(header, versionV1)\n\tbinary.LittleEndian.PutUint64(header[8:], uint64(0)) // type\n\tn, err := e.bw.Write(header)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif n != headerSize {\n\t\treturn fmt.Errorf(\"short write of header %d/%d\", n, headerSize)\n\t}\n\treturn nil\n}\n\nfunc (e *encoderV1) encodeState(s *builderNode, lastAddr int) (int, error) {\n\tif len(s.trans) == 0 && s.final && s.finalOutput == 0 {\n\t\treturn 0, nil\n\t} else if len(s.trans) != 1 || s.final {\n\t\treturn e.encodeStateMany(s)\n\t} else if !s.final && s.trans[0].out == 0 && s.trans[0].addr == lastAddr {\n\t\treturn e.encodeStateOneFinish(s, transitionNext)\n\t}\n\treturn e.encodeStateOne(s)\n}\n\nfunc (e *encoderV1) encodeStateOne(s *builderNode) (int, error) {\n\tstart := uint64(e.bw.counter)\n\toutPackSize := 0\n\tif s.trans[0].out != 0 {\n\t\toutPackSize = packedSize(s.trans[0].out)\n\t\terr := e.bw.WritePackedUintIn(s.trans[0].out, outPackSize)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t}\n\tdelta := deltaAddr(start, uint64(s.trans[0].addr))\n\ttransPackSize := packedSize(delta)\n\terr := e.bw.WritePackedUintIn(delta, transPackSize)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tpackSize := encodePackSize(transPackSize, outPackSize)\n\terr = e.bw.WriteByte(packSize)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\treturn e.encodeStateOneFinish(s, 0)\n}\n\nfunc (e *encoderV1) encodeStateOneFinish(s *builderNode, next byte) (int, error) {\n\tenc := encodeCommon(s.trans[0].in)\n\n\t// not a common input\n\tif enc == 0 {\n\t\terr := e.bw.WriteByte(s.trans[0].in)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t}\n\terr := e.bw.WriteByte(oneTransition | next | enc)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\treturn e.bw.counter - 1, nil\n}\n\nfunc (e *encoderV1) encodeStateMany(s *builderNode) (int, error) {\n\tstart := uint64(e.bw.counter)\n\ttransPackSize := 0\n\toutPackSize := packedSize(s.finalOutput)\n\tanyOutputs := s.finalOutput != 0\n\tfor i := range s.trans {\n\t\tdelta := deltaAddr(start, uint64(s.trans[i].addr))\n\t\ttsize := packedSize(delta)\n\t\tif tsize > transPackSize {\n\t\t\ttransPackSize = tsize\n\t\t}\n\t\tosize := packedSize(s.trans[i].out)\n\t\tif osize > outPackSize {\n\t\t\toutPackSize = osize\n\t\t}\n\t\tanyOutputs = anyOutputs || s.trans[i].out != 0\n\t}\n\tif !anyOutputs {\n\t\toutPackSize = 0\n\t}\n\n\tif anyOutputs {\n\t\t// output final value\n\t\tif s.final {\n\t\t\terr := e.bw.WritePackedUintIn(s.finalOutput, outPackSize)\n\t\t\tif err != nil {\n\t\t\t\treturn 0, err\n\t\t\t}\n\t\t}\n\t\t// output transition values (in reverse)\n\t\tfor j := len(s.trans) - 1; j >= 0; j-- {\n\t\t\terr := e.bw.WritePackedUintIn(s.trans[j].out, outPackSize)\n\t\t\tif err != nil {\n\t\t\t\treturn 0, err\n\t\t\t}\n\t\t}\n\t}\n\n\t// output transition dests (in reverse)\n\tfor j := len(s.trans) - 1; j >= 0; j-- {\n\t\tdelta := deltaAddr(start, uint64(s.trans[j].addr))\n\t\terr := e.bw.WritePackedUintIn(delta, transPackSize)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t}\n\n\t// output transition keys (in reverse)\n\tfor j := len(s.trans) - 1; j >= 0; j-- {\n\t\terr := e.bw.WriteByte(s.trans[j].in)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t}\n\n\tpackSize := encodePackSize(transPackSize, outPackSize)\n\terr := e.bw.WriteByte(packSize)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tnumTrans := encodeNumTrans(len(s.trans))\n\n\t// if number of transitions wont fit in edge header byte\n\t// write out separately\n\tif numTrans == 0 {\n\t\tif len(s.trans) == 256 {\n\t\t\t// this wouldn't fit in single byte, but reuse value 1\n\t\t\t// which would have always fit in the edge header instead\n\t\t\terr = e.bw.WriteByte(1)\n\t\t\tif err != nil {\n\t\t\t\treturn 0, err\n\t\t\t}\n\t\t} else {\n\t\t\terr = e.bw.WriteByte(byte(len(s.trans)))\n\t\t\tif err != nil {\n\t\t\t\treturn 0, err\n\t\t\t}\n\t\t}\n\t}\n\n\t// finally write edge header\n\tif s.final {\n\t\tnumTrans |= stateFinal\n\t}\n\terr = e.bw.WriteByte(numTrans)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\treturn e.bw.counter - 1, nil\n}\n\nfunc (e *encoderV1) finish(count, rootAddr int) error {\n\tfooter := make([]byte, footerSizeV1)\n\tbinary.LittleEndian.PutUint64(footer, uint64(count))        // root addr\n\tbinary.LittleEndian.PutUint64(footer[8:], uint64(rootAddr)) // root addr\n\tn, err := e.bw.Write(footer)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif n != footerSizeV1 {\n\t\treturn fmt.Errorf(\"short write of footer %d/%d\", n, footerSizeV1)\n\t}\n\terr = e.bw.Flush()\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "encoder_v1_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"bytes\"\n\t\"reflect\"\n\t\"testing\"\n)\n\n// FIXME add tests for longjmp (wider delta address)\n// FIXME add tests for wider values\n// FIXME add tests for mixed value sizes in same edge (fixed size, but padded)\n// FIXME add test for final state (must include final val even if 0)\n\nfunc TestEncoderVersionError(t *testing.T) {\n\t_, err := loadEncoder(629, nil)\n\tif err == nil {\n\t\tt.Errorf(\"expected error loading encoder version 629, got nil\")\n\t}\n}\n\nfunc TestEncoderStart(t *testing.T) {\n\n\tvar headerV1 = []byte{\n\t\t1, 0, 0, 0, 0, 0, 0, 0,\n\t\t0, 0, 0, 0, 0, 0, 0, 0,\n\t}\n\n\tvar buf bytes.Buffer\n\te := newEncoderV1(&buf)\n\terr := e.start()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// manually flush\n\terr = e.bw.Flush()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := buf.Bytes()\n\tif !reflect.DeepEqual(got, headerV1) {\n\t\tt.Errorf(\"expected header: %v, got %v\", headerV1, got)\n\t}\n}\n\nfunc TestEncoderStateOneNextWithCommonInput(t *testing.T) {\n\n\tcurr := &builderNode{\n\t\ttrans: []transition{\n\t\t\t{\n\t\t\t\tin:   'a',\n\t\t\t\taddr: 27,\n\t\t\t},\n\t\t},\n\t}\n\n\tvar buf bytes.Buffer\n\te := newEncoderV1(&buf)\n\n\t// now encode the curr state\n\t_, err := e.encodeState(curr, 27)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// manually flush\n\terr = e.bw.Flush()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// now look at the bytes produced\n\tvar want = []byte{\n\t\toneTransition | transitionNext | encodeCommon('a'),\n\t}\n\tgot := buf.Bytes()\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"expected bytes: %v, got %v\", want, got)\n\t}\n}\n\nfunc TestEncoderStateOneNextWithUncommonInput(t *testing.T) {\n\n\tcurr := &builderNode{\n\t\ttrans: []transition{\n\t\t\t{\n\t\t\t\tin:   0xff,\n\t\t\t\taddr: 27,\n\t\t\t},\n\t\t},\n\t}\n\n\tvar buf bytes.Buffer\n\te := newEncoderV1(&buf)\n\n\t// now encode the curr state\n\t_, err := e.encodeState(curr, 27)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// manually flush\n\terr = e.bw.Flush()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// now look at the bytes produced\n\tvar want = []byte{\n\t\t0xff,\n\t\toneTransition | transitionNext,\n\t}\n\tgot := buf.Bytes()\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"expected bytes: %v, got %v\", want, got)\n\t}\n}\n\nfunc TestEncoderStateOneNotNextWithCommonInputNoValue(t *testing.T) {\n\n\tcurr := &builderNode{\n\t\ttrans: []transition{\n\t\t\t{\n\t\t\t\tin:   'a',\n\t\t\t\taddr: 32,\n\t\t\t},\n\t\t},\n\t}\n\n\tvar buf bytes.Buffer\n\te := newEncoderV1(&buf)\n\n\t// pretend we're at a position in the file\n\te.bw.counter = 64\n\n\t// now encode the curr state\n\t_, err := e.encodeState(curr, 64)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// manually flush\n\terr = e.bw.Flush()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// now look at the bytes produced\n\tvar want = []byte{\n\t\t32,       // delta address packed\n\t\t1<<4 | 0, // pack sizes\n\t\toneTransition | encodeCommon('a'),\n\t}\n\tgot := buf.Bytes()\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"expected bytes: %v, got %v\", want, got)\n\t}\n}\n\nfunc TestEncoderStateOneNotNextWithUncommonInputNoValue(t *testing.T) {\n\n\tcurr := &builderNode{\n\t\ttrans: []transition{\n\t\t\t{\n\t\t\t\tin:   0xff,\n\t\t\t\taddr: 32,\n\t\t\t},\n\t\t},\n\t}\n\n\tvar buf bytes.Buffer\n\te := newEncoderV1(&buf)\n\n\t// pretend we're at a position in the file\n\te.bw.counter = 64\n\n\t// now encode the curr state\n\t_, err := e.encodeState(curr, 64)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// manually flush\n\terr = e.bw.Flush()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// now look at the bytes produced\n\tvar want = []byte{\n\t\t32,       // delta address packed\n\t\t1<<4 | 0, // pack sizes\n\t\t0xff,\n\t\toneTransition,\n\t}\n\tgot := buf.Bytes()\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"expected bytes: %v, got %v\", want, got)\n\t}\n}\n\nfunc TestEncoderStateOneNotNextWithCommonInputWithValue(t *testing.T) {\n\n\tcurr := &builderNode{\n\t\ttrans: []transition{\n\t\t\t{\n\t\t\t\tin:   'a',\n\t\t\t\taddr: 32,\n\t\t\t\tout:  27,\n\t\t\t},\n\t\t},\n\t}\n\n\tvar buf bytes.Buffer\n\te := newEncoderV1(&buf)\n\n\t// pretend we're at a position in the file\n\te.bw.counter = 64\n\n\t// now encode the curr state\n\t_, err := e.encodeState(curr, 64)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// manually flush\n\terr = e.bw.Flush()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// now look at the bytes produced\n\tvar want = []byte{\n\t\t27,       // trans value\n\t\t32,       // delta address packed\n\t\t1<<4 | 1, // pack sizes\n\t\toneTransition | encodeCommon('a'),\n\t}\n\tgot := buf.Bytes()\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"expected bytes: %v, got %v\", want, got)\n\t}\n}\n\nfunc TestEncoderStateOneNotNextWithUncommonInputWithValue(t *testing.T) {\n\n\tcurr := &builderNode{\n\t\ttrans: []transition{\n\t\t\t{\n\t\t\t\tin:   0xff,\n\t\t\t\taddr: 32,\n\t\t\t\tout:  39,\n\t\t\t},\n\t\t},\n\t}\n\n\tvar buf bytes.Buffer\n\te := newEncoderV1(&buf)\n\n\t// pretend we're at a position in the file\n\te.bw.counter = 64\n\n\t// now encode the curr state\n\t_, err := e.encodeState(curr, 64)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// manually flush\n\terr = e.bw.Flush()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// now look at the bytes produced\n\tvar want = []byte{\n\t\t39,       // trans val\n\t\t32,       // delta address packed\n\t\t1<<4 | 1, // pack sizes\n\t\t0xff,\n\t\toneTransition,\n\t}\n\tgot := buf.Bytes()\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"expected bytes: %v, got %v\", want, got)\n\t}\n}\n\nfunc TestEncoderStateManyWithNoValues(t *testing.T) {\n\n\tcurr := &builderNode{\n\t\ttrans: []transition{\n\t\t\t{\n\t\t\t\tin:   'a',\n\t\t\t\taddr: 32,\n\t\t\t},\n\t\t\t{\n\t\t\t\tin:   'b',\n\t\t\t\taddr: 45,\n\t\t\t},\n\t\t\t{\n\t\t\t\tin:   'c',\n\t\t\t\taddr: 52,\n\t\t\t},\n\t\t},\n\t}\n\n\tvar buf bytes.Buffer\n\te := newEncoderV1(&buf)\n\n\t// pretend we're at a position in the file\n\te.bw.counter = 64\n\n\t// now encode the curr state\n\t_, err := e.encodeState(curr, 64)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// manually flush\n\terr = e.bw.Flush()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// now look at the bytes produced\n\tvar want = []byte{\n\t\t12, // delta addresses packed\n\t\t19,\n\t\t32,\n\t\t'c', // encoded keys reversed\n\t\t'b',\n\t\t'a',\n\t\t1<<4 | 0, // pack sizes\n\t\tencodeNumTrans(3),\n\t}\n\tgot := buf.Bytes()\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"expected bytes: %v, got %v\", want, got)\n\t}\n}\n\nfunc TestEncoderStateManyWithValues(t *testing.T) {\n\n\tcurr := &builderNode{\n\t\ttrans: []transition{\n\t\t\t{\n\t\t\t\tin:   'a',\n\t\t\t\taddr: 32,\n\t\t\t\tout:  3,\n\t\t\t},\n\t\t\t{\n\t\t\t\tin:   'b',\n\t\t\t\taddr: 45,\n\t\t\t\tout:  0,\n\t\t\t},\n\t\t\t{\n\t\t\t\tin:   'c',\n\t\t\t\taddr: 52,\n\t\t\t\tout:  7,\n\t\t\t},\n\t\t},\n\t}\n\n\tvar buf bytes.Buffer\n\te := newEncoderV1(&buf)\n\n\t// pretend we're at a position in the file\n\te.bw.counter = 64\n\n\t// now encode the curr state\n\t_, err := e.encodeState(curr, 64)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// manually flush\n\terr = e.bw.Flush()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// now look at the bytes produced\n\tvar want = []byte{\n\t\t7, // values reversed\n\t\t0,\n\t\t3,\n\t\t12, // delta addresses reversed\n\t\t19,\n\t\t32,\n\t\t'c', // encoded keys reversed\n\t\t'b',\n\t\t'a',\n\t\t1<<4 | 1, // pack sizes\n\t\tencodeNumTrans(3),\n\t}\n\tgot := buf.Bytes()\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"expected bytes: %v, got %v\", want, got)\n\t}\n}\n\nfunc TestEncoderStateMaxTransitions(t *testing.T) {\n\ttestEncoderStateNTransitions(t, 256)\n}\n\nfunc TestEncoderStateMoreTransitionsThanFitInHeader(t *testing.T) {\n\ttestEncoderStateNTransitions(t, 1<<6)\n}\n\nfunc testEncoderStateNTransitions(t *testing.T, n int) {\n\n\tcurr := &builderNode{\n\t\ttrans: make([]transition, n),\n\t}\n\tfor i := 0; i < n; i++ {\n\t\tcurr.trans[i] = transition{\n\t\t\tin:   byte(i),\n\t\t\taddr: 32,\n\t\t}\n\t}\n\n\tvar buf bytes.Buffer\n\te := newEncoderV1(&buf)\n\n\t// pretend we're at a position in the file\n\te.bw.counter = 64\n\n\t// now encode the curr state\n\t_, err := e.encodeState(curr, 64)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// manually flush\n\terr = e.bw.Flush()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// now look at the bytes produced\n\tvar want []byte\n\t// append 256 delta addresses\n\tfor i := 0; i < n; i++ {\n\t\twant = append(want, 32)\n\t}\n\t// append transition keys (reversed)\n\tfor i := n - 1; i >= 0; i-- {\n\t\twant = append(want, byte(i))\n\t}\n\t// append pack sizes\n\twant = append(want, 1<<4|0)\n\n\tif n > 1<<6-1 {\n\t\t// append separate byte of pack sizes\n\t\tif n == 256 { // 256 is specially encoded as 1\n\t\t\twant = append(want, 1)\n\t\t} else {\n\t\t\twant = append(want, byte(n))\n\t\t}\n\n\t}\n\t// append header byte, which is all 0 in this case\n\twant = append(want, 0)\n\tgot := buf.Bytes()\n\tif !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"expected bytes: %v, got %v\", want, got)\n\t}\n}\n"
  },
  {
    "path": "encoding.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"io\"\n)\n\nconst headerSize = 16\n\ntype encoderConstructor func(w io.Writer) encoder\ntype decoderConstructor func([]byte) decoder\n\nvar encoders = map[int]encoderConstructor{}\nvar decoders = map[int]decoderConstructor{}\n\ntype encoder interface {\n\tstart() error\n\tencodeState(s *builderNode, addr int) (int, error)\n\tfinish(count, rootAddr int) error\n\treset(w io.Writer)\n}\n\nfunc loadEncoder(ver int, w io.Writer) (encoder, error) {\n\tif cons, ok := encoders[ver]; ok {\n\t\treturn cons(w), nil\n\t}\n\treturn nil, fmt.Errorf(\"no encoder for version %d registered\", ver)\n}\n\nfunc registerEncoder(ver int, cons encoderConstructor) {\n\tencoders[ver] = cons\n}\n\ntype decoder interface {\n\tgetRoot() int\n\tgetLen() int\n\tstateAt(addr int, prealloc fstState) (fstState, error)\n}\n\nfunc loadDecoder(ver int, data []byte) (decoder, error) {\n\tif cons, ok := decoders[ver]; ok {\n\t\treturn cons(data), nil\n\t}\n\treturn nil, fmt.Errorf(\"no decoder for version %d registered\", ver)\n}\n\nfunc registerDecoder(ver int, cons decoderConstructor) {\n\tdecoders[ver] = cons\n}\n\nfunc decodeHeader(header []byte) (ver int, typ int, err error) {\n\tif len(header) < headerSize {\n\t\terr = fmt.Errorf(\"invalid header < 16 bytes\")\n\t\treturn\n\t}\n\tver = int(binary.LittleEndian.Uint64(header[0:8]))\n\ttyp = int(binary.LittleEndian.Uint64(header[8:16]))\n\treturn\n}\n\n// fstState represents a state inside the FTS runtime\n// It is the main contract between the FST impl and the decoder\n// The FST impl should work only with this interface, while only the decoder\n// impl knows the physical representation.\ntype fstState interface {\n\tAddress() int\n\tFinal() bool\n\tFinalOutput() uint64\n\tNumTransitions() int\n\tTransitionFor(b byte) (int, int, uint64)\n\tTransitionAt(i int) byte\n}\n"
  },
  {
    "path": "example_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/couchbase/vellum\"\n)\n\nfunc Example() {\n\n\tvar buf bytes.Buffer\n\tbuilder, err := vellum.New(&buf, nil)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\terr = builder.Insert([]byte(\"cat\"), 1)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\terr = builder.Insert([]byte(\"dog\"), 2)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\terr = builder.Insert([]byte(\"fish\"), 3)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\terr = builder.Close()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfst, err := vellum.Load(buf.Bytes())\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tval, exists, err := fst.Get([]byte(\"cat\"))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif exists {\n\t\tfmt.Println(val)\n\t}\n\n\tval, exists, err = fst.Get([]byte(\"dog\"))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif exists {\n\t\tfmt.Println(val)\n\t}\n\n\tval, exists, err = fst.Get([]byte(\"fish\"))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif exists {\n\t\tfmt.Println(val)\n\t}\n\n\t// Output: 1\n\t// 2\n\t// 3\n}\n"
  },
  {
    "path": "fst.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"io\"\n\n\t\"github.com/willf/bitset\"\n)\n\n// FST is an in-memory representation of a finite state transducer,\n// capable of returning the uint64 value associated with\n// each []byte key stored, as well as enumerating all of the keys\n// in order.\ntype FST struct {\n\tf       io.Closer\n\tver     int\n\tlen     int\n\ttyp     int\n\tdata    []byte\n\tdecoder decoder\n}\n\nfunc new(data []byte, f io.Closer) (rv *FST, err error) {\n\trv = &FST{\n\t\tdata: data,\n\t\tf:    f,\n\t}\n\n\trv.ver, rv.typ, err = decodeHeader(data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\trv.decoder, err = loadDecoder(rv.ver, rv.data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\trv.len = rv.decoder.getLen()\n\n\treturn rv, nil\n}\n\n// Contains returns true if this FST contains the specified key.\nfunc (f *FST) Contains(val []byte) (bool, error) {\n\t_, exists, err := f.Get(val)\n\treturn exists, err\n}\n\n// Get returns the value associated with the key.  NOTE: a value of zero\n// does not imply the key does not exist, you must consult the second\n// return value as well.\nfunc (f *FST) Get(input []byte) (uint64, bool, error) {\n\treturn f.get(input, nil)\n}\n\nfunc (f *FST) get(input []byte, prealloc fstState) (uint64, bool, error) {\n\tvar total uint64\n\tcurr := f.decoder.getRoot()\n\tstate, err := f.decoder.stateAt(curr, prealloc)\n\tif err != nil {\n\t\treturn 0, false, err\n\t}\n\tfor _, c := range input {\n\t\t_, curr, output := state.TransitionFor(c)\n\t\tif curr == noneAddr {\n\t\t\treturn 0, false, nil\n\t\t}\n\n\t\tstate, err = f.decoder.stateAt(curr, state)\n\t\tif err != nil {\n\t\t\treturn 0, false, err\n\t\t}\n\n\t\ttotal += output\n\t}\n\n\tif state.Final() {\n\t\ttotal += state.FinalOutput()\n\t\treturn total, true, nil\n\t}\n\treturn 0, false, nil\n}\n\n// Version returns the encoding version used by this FST instance.\nfunc (f *FST) Version() int {\n\treturn f.ver\n}\n\n// Len returns the number of entries in this FST instance.\nfunc (f *FST) Len() int {\n\treturn f.len\n}\n\n// Type returns the type of this FST instance.\nfunc (f *FST) Type() int {\n\treturn f.typ\n}\n\n// Close will unmap any mmap'd data (if managed by vellum) and it will close\n// the backing file (if managed by vellum).  You MUST call Close() for any\n// FST instance that is created.\nfunc (f *FST) Close() error {\n\tif f.f != nil {\n\t\terr := f.f.Close()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tf.data = nil\n\tf.decoder = nil\n\treturn nil\n}\n\n// Start returns the start state of this Automaton\nfunc (f *FST) Start() int {\n\treturn f.decoder.getRoot()\n}\n\n// IsMatch returns if this state is a matching state in this Automaton\nfunc (f *FST) IsMatch(addr int) bool {\n\tmatch, _ := f.IsMatchWithVal(addr)\n\treturn match\n}\n\n// CanMatch returns if this state can ever transition to a matching state\n// in this Automaton\nfunc (f *FST) CanMatch(addr int) bool {\n\tif addr == noneAddr {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// WillAlwaysMatch returns if from this state the Automaton will always\n// be in a matching state\nfunc (f *FST) WillAlwaysMatch(int) bool {\n\treturn false\n}\n\n// Accept returns the next state for this Automaton on input of byte b\nfunc (f *FST) Accept(addr int, b byte) int {\n\tnext, _ := f.AcceptWithVal(addr, b)\n\treturn next\n}\n\n// IsMatchWithVal returns if this state is a matching state in this Automaton\n// and also returns the final output value for this state\nfunc (f *FST) IsMatchWithVal(addr int) (bool, uint64) {\n\ts, err := f.decoder.stateAt(addr, nil)\n\tif err != nil {\n\t\treturn false, 0\n\t}\n\treturn s.Final(), s.FinalOutput()\n}\n\n// AcceptWithVal returns the next state for this Automaton on input of byte b\n// and also returns the output value for the transition\nfunc (f *FST) AcceptWithVal(addr int, b byte) (int, uint64) {\n\ts, err := f.decoder.stateAt(addr, nil)\n\tif err != nil {\n\t\treturn noneAddr, 0\n\t}\n\t_, next, output := s.TransitionFor(b)\n\treturn next, output\n}\n\n// Iterator returns a new Iterator capable of enumerating the key/value pairs\n// between the provided startKeyInclusive and endKeyExclusive.\nfunc (f *FST) Iterator(startKeyInclusive, endKeyExclusive []byte) (*FSTIterator, error) {\n\treturn newIterator(f, startKeyInclusive, endKeyExclusive, nil)\n}\n\n// Search returns a new Iterator capable of enumerating the key/value pairs\n// between the provided startKeyInclusive and endKeyExclusive that also\n// satisfy the provided automaton.\nfunc (f *FST) Search(aut Automaton, startKeyInclusive, endKeyExclusive []byte) (*FSTIterator, error) {\n\treturn newIterator(f, startKeyInclusive, endKeyExclusive, aut)\n}\n\n// Debug is only intended for debug purposes, it simply asks the underlying\n// decoder visit each state, and pass it to the provided callback.\nfunc (f *FST) Debug(callback func(int, interface{}) error) error {\n\n\taddr := f.decoder.getRoot()\n\tset := bitset.New(uint(addr))\n\tstack := addrStack{addr}\n\n\tstateNumber := 0\n\tstack, addr = stack[:len(stack)-1], stack[len(stack)-1]\n\tfor addr != noneAddr {\n\t\tif set.Test(uint(addr)) {\n\t\t\tstack, addr = stack.Pop()\n\t\t\tcontinue\n\t\t}\n\t\tset.Set(uint(addr))\n\t\tstate, err := f.decoder.stateAt(addr, nil)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\terr = callback(stateNumber, state)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor i := 0; i < state.NumTransitions(); i++ {\n\t\t\ttchar := state.TransitionAt(i)\n\t\t\t_, dest, _ := state.TransitionFor(tchar)\n\t\t\tstack = append(stack, dest)\n\t\t}\n\t\tstateNumber++\n\t\tstack, addr = stack.Pop()\n\t}\n\n\treturn nil\n}\n\ntype addrStack []int\n\nfunc (a addrStack) Pop() (addrStack, int) {\n\tl := len(a)\n\tif l < 1 {\n\t\treturn a, noneAddr\n\t}\n\treturn a[:l-1], a[l-1]\n}\n\n// Reader() returns a Reader instance that a single thread may use to\n// retrieve data from the FST\nfunc (f *FST) Reader() (*Reader, error) {\n\treturn &Reader{f: f}, nil\n}\n\nfunc (f *FST) GetMinKey() ([]byte, error) {\n\tvar rv []byte\n\n\tcurr := f.decoder.getRoot()\n\tstate, err := f.decoder.stateAt(curr, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfor !state.Final() {\n\t\tnextTrans := state.TransitionAt(0)\n\t\t_, curr, _ = state.TransitionFor(nextTrans)\n\t\tstate, err = f.decoder.stateAt(curr, state)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\trv = append(rv, nextTrans)\n\t}\n\n\treturn rv, nil\n}\n\nfunc (f *FST) GetMaxKey() ([]byte, error) {\n\tvar rv []byte\n\n\tcurr := f.decoder.getRoot()\n\tstate, err := f.decoder.stateAt(curr, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfor state.NumTransitions() > 0 {\n\t\tnextTrans := state.TransitionAt(state.NumTransitions() - 1)\n\t\t_, curr, _ = state.TransitionFor(nextTrans)\n\t\tstate, err = f.decoder.stateAt(curr, state)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\trv = append(rv, nextTrans)\n\t}\n\n\treturn rv, nil\n}\n\n// A Reader is meant for a single threaded use\ntype Reader struct {\n\tf        *FST\n\tprealloc fstStateV1\n}\n\nfunc (r *Reader) Get(input []byte) (uint64, bool, error) {\n\treturn r.f.get(input, &r.prealloc)\n}\n"
  },
  {
    "path": "fst_iterator.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"bytes\"\n)\n\n// Iterator represents a means of visiting key/value pairs in order.\ntype Iterator interface {\n\n\t// Current() returns the key/value pair currently pointed to.\n\t// The []byte of the key is ONLY guaranteed to be valid until\n\t// another call to Next/Seek/Close.  If you need it beyond that\n\t// point you MUST make a copy.\n\tCurrent() ([]byte, uint64)\n\n\t// Next() advances the iterator to the next key/value pair.\n\t// If no more key/value pairs exist, ErrIteratorDone is returned.\n\tNext() error\n\n\t// Seek() advances the iterator the specified key, or the next key\n\t// if it does not exist.\n\t// If no keys exist after that point, ErrIteratorDone is returned.\n\tSeek(key []byte) error\n\n\t// Reset resets the Iterator' internal state to allow for iterator\n\t// reuse (e.g. pooling).\n\tReset(f *FST, startKeyInclusive, endKeyExclusive []byte, aut Automaton) error\n\n\t// Close() frees any resources held by this iterator.\n\tClose() error\n}\n\n// FSTIterator is a structure for iterating key/value pairs in this FST in\n// lexicographic order.  Iterators should be constructed with the FSTIterator\n// method on the parent FST structure.\ntype FSTIterator struct {\n\tf   *FST\n\taut Automaton\n\n\tstartKeyInclusive []byte\n\tendKeyExclusive   []byte\n\n\tstatesStack    []fstState\n\tkeysStack      []byte\n\tkeysPosStack   []int\n\tvalsStack      []uint64\n\tautStatesStack []int\n\n\tnextStart []byte\n}\n\nfunc newIterator(f *FST, startKeyInclusive, endKeyExclusive []byte,\n\taut Automaton) (*FSTIterator, error) {\n\n\trv := &FSTIterator{}\n\terr := rv.Reset(f, startKeyInclusive, endKeyExclusive, aut)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn rv, nil\n}\n\n// Reset resets the Iterator' internal state to allow for iterator\n// reuse (e.g. pooling).\nfunc (i *FSTIterator) Reset(f *FST,\n\tstartKeyInclusive, endKeyExclusive []byte, aut Automaton) error {\n\tif aut == nil {\n\t\taut = alwaysMatchAutomaton\n\t}\n\n\ti.f = f\n\ti.startKeyInclusive = startKeyInclusive\n\ti.endKeyExclusive = endKeyExclusive\n\ti.aut = aut\n\n\treturn i.pointTo(startKeyInclusive)\n}\n\n// pointTo attempts to point us to the specified location\nfunc (i *FSTIterator) pointTo(key []byte) error {\n\t// tried to seek before start\n\tif bytes.Compare(key, i.startKeyInclusive) < 0 {\n\t\tkey = i.startKeyInclusive\n\t}\n\n\t// tried to see past end\n\tif i.endKeyExclusive != nil &&\n\t\tbytes.Compare(key, i.endKeyExclusive) > 0 {\n\t\tkey = i.endKeyExclusive\n\t}\n\n\t// reset any state, pointTo always starts over\n\ti.statesStack = i.statesStack[:0]\n\ti.keysStack = i.keysStack[:0]\n\ti.keysPosStack = i.keysPosStack[:0]\n\ti.valsStack = i.valsStack[:0]\n\ti.autStatesStack = i.autStatesStack[:0]\n\n\troot, err := i.f.decoder.stateAt(i.f.decoder.getRoot(), nil)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tautStart := i.aut.Start()\n\n\tmaxQ := -1\n\t// root is always part of the path\n\ti.statesStack = append(i.statesStack, root)\n\ti.autStatesStack = append(i.autStatesStack, autStart)\n\tfor j := 0; j < len(key); j++ {\n\t\tkeyJ := key[j]\n\t\tcurr := i.statesStack[len(i.statesStack)-1]\n\t\tautCurr := i.autStatesStack[len(i.autStatesStack)-1]\n\n\t\tpos, nextAddr, nextVal := curr.TransitionFor(keyJ)\n\t\tif nextAddr == noneAddr {\n\t\t\t// needed transition doesn't exist\n\t\t\t// find last trans before the one we needed\n\t\t\tfor q := curr.NumTransitions() - 1; q >= 0; q-- {\n\t\t\t\tif curr.TransitionAt(q) < keyJ {\n\t\t\t\t\tmaxQ = q\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t\tautNext := i.aut.Accept(autCurr, keyJ)\n\n\t\tnext, err := i.f.decoder.stateAt(nextAddr, nil)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\ti.statesStack = append(i.statesStack, next)\n\t\ti.keysStack = append(i.keysStack, keyJ)\n\t\ti.keysPosStack = append(i.keysPosStack, pos)\n\t\ti.valsStack = append(i.valsStack, nextVal)\n\t\ti.autStatesStack = append(i.autStatesStack, autNext)\n\t\tcontinue\n\t}\n\n\tif !i.statesStack[len(i.statesStack)-1].Final() ||\n\t\t!i.aut.IsMatch(i.autStatesStack[len(i.autStatesStack)-1]) ||\n\t\tbytes.Compare(i.keysStack, key) < 0 {\n\t\treturn i.next(maxQ)\n\t}\n\n\treturn nil\n}\n\n// Current returns the key and value currently pointed to by the iterator.\n// If the iterator is not pointing at a valid value (because Iterator/Next/Seek)\n// returned an error previously, it may return nil,0.\nfunc (i *FSTIterator) Current() ([]byte, uint64) {\n\tcurr := i.statesStack[len(i.statesStack)-1]\n\tif curr.Final() {\n\t\tvar total uint64\n\t\tfor _, v := range i.valsStack {\n\t\t\ttotal += v\n\t\t}\n\t\ttotal += curr.FinalOutput()\n\t\treturn i.keysStack, total\n\t}\n\treturn nil, 0\n}\n\n// Next advances this iterator to the next key/value pair.  If there is none\n// or the advancement goes beyond the configured endKeyExclusive, then\n// ErrIteratorDone is returned.\nfunc (i *FSTIterator) Next() error {\n\treturn i.next(-1)\n}\n\nfunc (i *FSTIterator) next(lastOffset int) error {\n\t// remember where we started with keysStack in this next() call\n\ti.nextStart = append(i.nextStart[:0], i.keysStack...)\n\n\tnextOffset := lastOffset + 1\n\tallowCompare := false\n\nOUTER:\n\tfor true {\n\t\tcurr := i.statesStack[len(i.statesStack)-1]\n\t\tautCurr := i.autStatesStack[len(i.autStatesStack)-1]\n\n\t\tif curr.Final() && i.aut.IsMatch(autCurr) && allowCompare {\n\t\t\t// check to see if new keystack might have gone too far\n\t\t\tif i.endKeyExclusive != nil &&\n\t\t\t\tbytes.Compare(i.keysStack, i.endKeyExclusive) >= 0 {\n\t\t\t\treturn ErrIteratorDone\n\t\t\t}\n\n\t\t\tcmp := bytes.Compare(i.keysStack, i.nextStart)\n\t\t\tif cmp > 0 {\n\t\t\t\t// in final state greater than start key\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\n\t\tnumTrans := curr.NumTransitions()\n\n\tINNER:\n\t\tfor nextOffset < numTrans {\n\t\t\tt := curr.TransitionAt(nextOffset)\n\n\t\t\tautNext := i.aut.Accept(autCurr, t)\n\t\t\tif !i.aut.CanMatch(autNext) {\n\t\t\t\t// TODO: potential optimization to skip nextOffset\n\t\t\t\t// forwards more directly to something that the\n\t\t\t\t// automaton likes rather than a linear scan?\n\t\t\t\tnextOffset += 1\n\t\t\t\tcontinue INNER\n\t\t\t}\n\n\t\t\tpos, nextAddr, v := curr.TransitionFor(t)\n\n\t\t\t// the next slot in the statesStack might have an\n\t\t\t// fstState instance that we can reuse\n\t\t\tvar nextPrealloc fstState\n\t\t\tif len(i.statesStack) < cap(i.statesStack) {\n\t\t\t\tnextPrealloc = i.statesStack[0:cap(i.statesStack)][len(i.statesStack)]\n\t\t\t}\n\n\t\t\t// push onto stack\n\t\t\tnext, err := i.f.decoder.stateAt(nextAddr, nextPrealloc)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\ti.statesStack = append(i.statesStack, next)\n\t\t\ti.keysStack = append(i.keysStack, t)\n\t\t\ti.keysPosStack = append(i.keysPosStack, pos)\n\t\t\ti.valsStack = append(i.valsStack, v)\n\t\t\ti.autStatesStack = append(i.autStatesStack, autNext)\n\n\t\t\tnextOffset = 0\n\t\t\tallowCompare = true\n\n\t\t\tcontinue OUTER\n\t\t}\n\n\t\t// no more transitions, so need to backtrack and stack pop\n\t\tif len(i.statesStack) <= 1 {\n\t\t\t// stack len is 1 (root), can't go back further, we're done\n\t\t\tbreak\n\t\t}\n\n\t\t// if the top of the stack represents a linear chain of states\n\t\t// (i.e., a suffix of nodes linked by single transitions),\n\t\t// then optimize by popping the suffix in one shot without\n\t\t// going back all the way to the OUTER loop\n\t\tvar popNum int\n\t\tfor j := len(i.statesStack) - 1; j > 0; j-- {\n\t\t\tif j == 1 || i.statesStack[j].NumTransitions() != 1 {\n\t\t\t\tpopNum = len(i.statesStack) - 1 - j\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif popNum < 1 { // always pop at least 1 entry from the stacks\n\t\t\tpopNum = 1\n\t\t}\n\n\t\tnextOffset = i.keysPosStack[len(i.keysPosStack)-popNum] + 1\n\t\tallowCompare = false\n\n\t\ti.statesStack = i.statesStack[:len(i.statesStack)-popNum]\n\t\ti.keysStack = i.keysStack[:len(i.keysStack)-popNum]\n\t\ti.keysPosStack = i.keysPosStack[:len(i.keysPosStack)-popNum]\n\t\ti.valsStack = i.valsStack[:len(i.valsStack)-popNum]\n\t\ti.autStatesStack = i.autStatesStack[:len(i.autStatesStack)-popNum]\n\t}\n\n\treturn ErrIteratorDone\n}\n\n// Seek advances this iterator to the specified key/value pair.  If this key\n// is not in the FST, Current() will return the next largest key.  If this\n// seek operation would go past the last key, or outside the configured\n// startKeyInclusive/endKeyExclusive then ErrIteratorDone is returned.\nfunc (i *FSTIterator) Seek(key []byte) error {\n\treturn i.pointTo(key)\n}\n\n// Close will free any resources held by this iterator.\nfunc (i *FSTIterator) Close() error {\n\t// at the moment we don't do anything,\n\t// but wanted this for API completeness\n\treturn nil\n}\n"
  },
  {
    "path": "fst_iterator_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"bytes\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/couchbase/vellum/levenshtein\"\n\t\"github.com/couchbase/vellum/regexp\"\n)\n\nfunc TestIterator(t *testing.T) {\n\tvar buf bytes.Buffer\n\tb, err := New(&buf, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = insertStringMap(b, smallSample)\n\tif err != nil {\n\t\tt.Fatalf(\"error building: %v\", err)\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tfst, err := Load(buf.Bytes())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\n\tgot := map[string]uint64{}\n\titr, err := fst.Iterator(nil, nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(smallSample, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", smallSample, got)\n\t}\n}\n\nfunc TestIteratorReset(t *testing.T) {\n\tvar buf bytes.Buffer\n\tb, err := New(&buf, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = insertStringMap(b, smallSample)\n\tif err != nil {\n\t\tt.Fatalf(\"error building: %v\", err)\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tfst, err := Load(buf.Bytes())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\n\titr, err := fst.Iterator(nil, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating an iterator: %v\", err)\n\t}\n\n\tbuf.Reset()\n\tb, err = New(&buf, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\tsmallSample2 := map[string]uint64{\n\t\t\"bold\": 25,\n\t\t\"last\": 1,\n\t\t\"next\": 500,\n\t\t\"tank\": 0,\n\t}\n\terr = insertStringMap(b, smallSample2)\n\tif err != nil {\n\t\tt.Fatalf(\"error building: %v\", err)\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tfst, err = Load(buf.Bytes())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\n\tgot := map[string]uint64{}\n\terr = itr.Reset(fst, nil, nil, nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(smallSample2, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", smallSample2, got)\n\t}\n\n}\n\nfunc TestIteratorStartKey(t *testing.T) {\n\tvar buf bytes.Buffer\n\tb, err := New(&buf, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = insertStringMap(b, smallSample)\n\tif err != nil {\n\t\tt.Fatalf(\"error building: %v\", err)\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tfst, err := Load(buf.Bytes())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\n\t// with start key < \"mon\", we should still get it\n\tgot := map[string]uint64{}\n\titr, err := fst.Iterator([]byte(\"a\"), nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(smallSample, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", smallSample, got)\n\t}\n\n\t// with start key = \"mon\", we should still get it\n\tgot = map[string]uint64{}\n\titr, err = fst.Iterator([]byte(\"mon\"), nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(smallSample, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", smallSample, got)\n\t}\n\n\t// with start key > \"mon\", we don't expect to get it\n\texpect := map[string]uint64{\n\t\t\"tues\":  smallSample[\"tues\"],\n\t\t\"thurs\": smallSample[\"thurs\"],\n\t\t\"tye\":   smallSample[\"tye\"],\n\t}\n\tgot = map[string]uint64{}\n\titr, err = fst.Iterator([]byte(\"mona\"), nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(expect, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", expect, got)\n\t}\n\n\t// with start key > \"mon\", we don't expect to get it\n\texpect = map[string]uint64{\n\t\t\"tues\":  smallSample[\"tues\"],\n\t\t\"thurs\": smallSample[\"thurs\"],\n\t\t\"tye\":   smallSample[\"tye\"],\n\t}\n\tgot = map[string]uint64{}\n\titr, err = fst.Iterator([]byte(\"my\"), nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(expect, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", expect, got)\n\t}\n}\n\nfunc TestIteratorEndKey(t *testing.T) {\n\tvar buf bytes.Buffer\n\tb, err := New(&buf, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = insertStringMap(b, smallSample)\n\tif err != nil {\n\t\tt.Fatalf(\"error building: %v\", err)\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tfst, err := Load(buf.Bytes())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\n\t// with end key > \"tye\", we should still get it\n\tgot := map[string]uint64{}\n\titr, err := fst.Iterator(nil, []byte(\"zeus\"))\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(smallSample, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", smallSample, got)\n\t}\n\n\t// with end key = \"tye\", we should NOT get it (end key exclusive)\n\texpect := map[string]uint64{\n\t\t\"mon\":   smallSample[\"mon\"],\n\t\t\"tues\":  smallSample[\"tues\"],\n\t\t\"thurs\": smallSample[\"thurs\"],\n\t}\n\tgot = map[string]uint64{}\n\titr, err = fst.Iterator(nil, []byte(\"tye\"))\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(expect, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", expect, got)\n\t}\n\n\t// with start key < \"tye\", we don't expect to get it\n\tgot = map[string]uint64{}\n\titr, err = fst.Iterator(nil, []byte(\"tv\"))\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(expect, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", expect, got)\n\t}\n}\n\nfunc TestIteratorSeek(t *testing.T) {\n\tvar buf bytes.Buffer\n\tb, err := New(&buf, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = insertStringMap(b, smallSample)\n\tif err != nil {\n\t\tt.Fatalf(\"error building: %v\", err)\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tfst, err := Load(buf.Bytes())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\n\t// seek past thurs (exactly to tues)\n\texpect := map[string]uint64{\n\t\t\"mon\":  smallSample[\"mon\"],\n\t\t\"tues\": smallSample[\"tues\"],\n\t\t\"tye\":  smallSample[\"tye\"],\n\t}\n\tgot := map[string]uint64{}\n\titr, err := fst.Iterator(nil, nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\n\t\tif string(key) == \"mon\" {\n\t\t\terr = itr.Seek([]byte(\"tue\"))\n\t\t} else {\n\t\t\terr = itr.Next()\n\t\t}\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(expect, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", expect, got)\n\t}\n\n\t// similar but seek to something after thurs before tues\n\tgot = map[string]uint64{}\n\titr, err = fst.Iterator(nil, nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\n\t\tif string(key) == \"mon\" {\n\t\t\terr = itr.Seek([]byte(\"thv\"))\n\t\t} else {\n\t\t\terr = itr.Next()\n\t\t}\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(expect, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", expect, got)\n\t}\n\n\t// similar but seek to thurs+suffix\n\tgot = map[string]uint64{}\n\titr, err = fst.Iterator(nil, nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\n\t\tif string(key) == \"mon\" {\n\t\t\terr = itr.Seek([]byte(\"thursday\"))\n\t\t} else {\n\t\t\terr = itr.Next()\n\t\t}\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(expect, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", expect, got)\n\t}\n\n\t// seek past last key (still inside iterator boundaries)\n\texpect = map[string]uint64{\n\t\t\"mon\": smallSample[\"mon\"],\n\t}\n\tgot = map[string]uint64{}\n\titr, err = fst.Iterator(nil, nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\n\t\tif string(key) == \"mon\" {\n\t\t\terr = itr.Seek([]byte(\"zzz\"))\n\t\t} else {\n\t\t\terr = itr.Next()\n\t\t}\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(expect, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", expect, got)\n\t}\n}\n\nfunc TestIteratorSeekOutsideBoundaries(t *testing.T) {\n\tvar buf bytes.Buffer\n\tb, err := New(&buf, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = insertStringMap(b, smallSample)\n\tif err != nil {\n\t\tt.Fatalf(\"error building: %v\", err)\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tfst, err := Load(buf.Bytes())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\n\t// first test with boundaries should just see thurs/tues\n\texpect := map[string]uint64{\n\t\t\"thurs\": smallSample[\"thurs\"],\n\t\t\"tues\":  smallSample[\"tues\"],\n\t}\n\tgot := map[string]uint64{}\n\titr, err := fst.Iterator([]byte(\"th\"), []byte(\"tuesd\"))\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(expect, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", expect, got)\n\t}\n\n\t// this time try to seek before the start,\n\t// still shouldn't see mon\n\tgot = map[string]uint64{}\n\titr, err = fst.Iterator([]byte(\"th\"), []byte(\"tuesd\"))\n\tif err != nil {\n\t\tt.Fatalf(\"error before seeking: %v\", err)\n\t}\n\terr = itr.Seek([]byte(\"cat\"))\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(expect, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", expect, got)\n\t}\n\n\t// this time try to seek past the end\n\t// should see nothing\n\n\titr, err = fst.Iterator([]byte(\"th\"), []byte(\"tuesd\"))\n\tif err != nil {\n\t\tt.Fatalf(\"error before seeking: %v\", err)\n\t}\n\terr = itr.Seek([]byte(\"ty\"))\n\tif err != ErrIteratorDone {\n\t\tt.Fatalf(\"expected ErrIteratorDone, got %v\", err)\n\t}\n}\n\nvar key []byte\nvar val uint64\n\nfunc BenchmarkFSTIteratorAllInMem(b *testing.B) {\n\t// first build the FST once\n\tdataset := thousandTestWords\n\trandomThousandVals := randomValues(dataset)\n\tvar buf bytes.Buffer\n\tbuilder, err := New(&buf, nil)\n\tif err != nil {\n\t\tb.Fatalf(\"error creating builder: %v\", err)\n\t}\n\terr = insertStrings(builder, dataset, randomThousandVals)\n\tif err != nil {\n\t\tb.Fatalf(\"error inserting thousand words: %v\", err)\n\t}\n\terr = builder.Close()\n\tif err != nil {\n\t\tb.Fatalf(\"error closing builder: %v\", err)\n\t}\n\n\tb.ResetTimer()\n\n\tfor i := 0; i < b.N; i++ {\n\n\t\tfst, err := Load(buf.Bytes())\n\t\tif err != nil {\n\t\t\tb.Fatalf(\"error loading FST: %v\", err)\n\t\t}\n\n\t\titr, err := fst.Iterator(nil, nil)\n\t\tfor err == nil {\n\t\t\tkey, val = itr.Current()\n\t\t\terr = itr.Next()\n\t\t}\n\t\tif err != ErrIteratorDone {\n\t\t\tb.Fatalf(\"iterator error: %v\", err)\n\t\t}\n\n\t\terr = fst.Close()\n\t\tif err != nil {\n\t\t\tb.Fatalf(\"error closing FST: %v\", err)\n\t\t}\n\n\t}\n}\n\nfunc TestFuzzySearch(t *testing.T) {\n\tvar buf bytes.Buffer\n\tb, err := New(&buf, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = insertStringMap(b, smallSample)\n\tif err != nil {\n\t\tt.Fatalf(\"error building: %v\", err)\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tfst, err := Load(buf.Bytes())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\n\tlb, err := levenshtein.NewLevenshteinAutomatonBuilder(uint8(1), false)\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\n\tfuzzy, err := lb.BuildDfa(\"tue\", 1)\n\tif err != nil {\n\t\tt.Fatalf(\"error building levenshtein automaton: %v\", err)\n\t}\n\n\twant := map[string]uint64{\n\t\t\"tues\": 3,\n\t\t\"tye\":  99,\n\t}\n\tgot := map[string]uint64{}\n\titr, err := fst.Search(fuzzy, nil, nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(want, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", want, got)\n\t}\n}\n\nfunc TestRegexpSearch(t *testing.T) {\n\tvar buf bytes.Buffer\n\tb, err := New(&buf, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = insertStringMap(b, smallSample)\n\tif err != nil {\n\t\tt.Fatalf(\"error building: %v\", err)\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tfst, err := Load(buf.Bytes())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\n\tr, err := regexp.New(`t.*s`)\n\tif err != nil {\n\t\tt.Fatalf(\"error building regexp automaton: %v\", err)\n\t}\n\n\twant := map[string]uint64{\n\t\t\"thurs\": 5,\n\t\t\"tues\":  3,\n\t}\n\n\tgot := map[string]uint64{}\n\titr, err := fst.Search(r, nil, nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(want, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", want, got)\n\t}\n\n\tgot = map[string]uint64{}\n\titr, err = fst.Search(r, []byte(\"t\"), nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(want, got) {\n\t\tt.Errorf(\"with start key t, expected %v, got: %v\", want, got)\n\t}\n\n\tgot = map[string]uint64{}\n\titr, err = fst.Search(r, nil, []byte(\"u\"))\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(want, got) {\n\t\tt.Errorf(\"with end key u, expected %v, got: %v\", want, got)\n\t}\n\n\tgot = map[string]uint64{}\n\titr, err = fst.Search(r, []byte(\"t\"), []byte(\"u\"))\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(want, got) {\n\t\tt.Errorf(\"with start key t, end key u, expected %v, got: %v\", want, got)\n\t}\n}\n\nfunc TestIssue32(t *testing.T) {\n\tvar buf bytes.Buffer\n\tb, err := New(&buf, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\terr = b.Insert(bytes.Repeat([]byte{'a'}, 1000000), 0)\n\tif err != nil {\n\t\tt.Fatalf(\"error inserting large key: %v\", err)\n\t}\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\tfst, err := Load(buf.Bytes())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\titr, err := fst.Iterator(nil, nil)\n\tfor err == nil {\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/couchbase/vellum\n\ngo 1.12\n\nrequire (\n\tgithub.com/blevesearch/mmap-go v1.0.2\n\tgithub.com/spf13/cobra v0.0.5\n\tgithub.com/willf/bitset v1.1.10\n\tgolang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a // indirect\n)\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=\ngithub.com/blevesearch/mmap-go v1.0.2 h1:JtMHb+FgQCTTYIhtMvimw15dJwu1Y5lrZDMOFXVWPk0=\ngithub.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+7LMvAB5IbSA=\ngithub.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=\ngithub.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=\ngithub.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=\ngithub.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=\ngithub.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=\ngithub.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=\ngithub.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=\ngithub.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=\ngithub.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=\ngithub.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=\ngithub.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=\ngithub.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=\ngithub.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=\ngithub.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=\ngithub.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=\ngithub.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=\ngithub.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=\ngithub.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=\ngithub.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=\ngithub.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc=\ngithub.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=\ngithub.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=\ngolang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=\ngolang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\n"
  },
  {
    "path": "levenshtein/LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n"
  },
  {
    "path": "levenshtein/README.md",
    "content": "# levenshtein\nlevenshtein automaton \n\nThis package makes it fast and simple to build a finite determinic automaton that computes the levenshtein distance from a given string.\n\n# Sample usage:\n\n```\n// build a re-usable builder\nlb := NewLevenshteinAutomatonBuilder(2, false)\n\norigTerm := \"couchbasefts\"\ndfa := lb.BuildDfa(\"couchbases\", 2)\ned := dfa.eval([]byte(origTerm))\nif ed.distance() != 2 {\n\tlog.Errorf(\"expected distance 2, actual: %d\", ed.distance())\n}\n\n```\n\nThis implementation is inspired by [blog post](https://fulmicoton.com/posts/levenshtein/) and is intended to be\na port of original rust implementation: https://github.com/tantivy-search/levenshtein-automata\n\n\nMicro Benchmark Results against the current vellum/levenshtein is as below.\n\n```\nBenchmarkNewEditDistance1-8       \t   30000\t     52684 ns/op\t   89985 B/op\t     295 allocs/op\nBenchmarkOlderEditDistance1-8     \t   10000\t    132931 ns/op\t  588892 B/op\t     363 allocs/op\n\nBenchmarkNewEditDistance2-8       \t   10000\t    199127 ns/op\t  377532 B/op\t    1019 allocs/op\nBenchmarkOlderEditDistance2-8     \t    2000\t    988109 ns/op\t 4236609 B/op\t    1898 allocs/op\n```\n"
  },
  {
    "path": "levenshtein/alphabet.go",
    "content": "//  Copyright (c) 2018 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage levenshtein\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\t\"unicode/utf8\"\n)\n\ntype FullCharacteristicVector []uint32\n\nfunc (fcv FullCharacteristicVector) shiftAndMask(offset, mask uint32) uint32 {\n\tbucketID := offset / 32\n\talign := offset - bucketID*32\n\tif align == 0 {\n\t\treturn fcv[bucketID] & mask\n\t}\n\tleft := fcv[bucketID] >> align\n\tright := fcv[bucketID+1] << (32 - align)\n\treturn (left | right) & mask\n}\n\ntype tuple struct {\n\tchar rune\n\tfcv  FullCharacteristicVector\n}\n\ntype sortRunes []rune\n\nfunc (s sortRunes) Less(i, j int) bool {\n\treturn s[i] < s[j]\n}\n\nfunc (s sortRunes) Swap(i, j int) {\n\ts[i], s[j] = s[j], s[i]\n}\n\nfunc (s sortRunes) Len() int {\n\treturn len(s)\n}\n\nfunc sortRune(r []rune) []rune {\n\tsort.Sort(sortRunes(r))\n\treturn r\n}\n\ntype Alphabet struct {\n\tcharset []tuple\n\tindex   uint32\n}\n\nfunc (a *Alphabet) resetNext() {\n\ta.index = 0\n}\n\nfunc (a *Alphabet) next() (rune, FullCharacteristicVector, error) {\n\tif int(a.index) >= len(a.charset) {\n\t\treturn 0, nil, fmt.Errorf(\"eof\")\n\t}\n\n\trv := a.charset[a.index]\n\ta.index++\n\treturn rv.char, rv.fcv, nil\n}\n\nfunc dedupe(in string) string {\n\tlookUp := make(map[rune]struct{}, len(in))\n\tvar rv string\n\tfor len(in) > 0 {\n\t\tr, size := utf8.DecodeRuneInString(in)\n\t\tin = in[size:]\n\t\tif _, ok := lookUp[r]; !ok {\n\t\t\trv += string(r)\n\t\t\tlookUp[r] = struct{}{}\n\t\t}\n\t}\n\treturn rv\n}\n\nfunc queryChars(qChars string) Alphabet {\n\tchars := dedupe(qChars)\n\tinChars := sortRune([]rune(chars))\n\tcharsets := make([]tuple, 0, len(inChars))\n\n\tfor _, c := range inChars {\n\t\ttempChars := qChars\n\t\tvar bits []uint32\n\t\tfor len(tempChars) > 0 {\n\t\t\tvar chunk string\n\t\t\tif len(tempChars) > 32 {\n\t\t\t\tchunk = tempChars[0:32]\n\t\t\t\ttempChars = tempChars[32:]\n\t\t\t} else {\n\t\t\t\tchunk = tempChars\n\t\t\t\ttempChars = tempChars[:0]\n\t\t\t}\n\n\t\t\tchunkBits := uint32(0)\n\t\t\tbit := uint32(1)\n\t\t\tfor _, chr := range chunk {\n\t\t\t\tif chr == c {\n\t\t\t\t\tchunkBits |= bit\n\t\t\t\t}\n\t\t\t\tbit <<= 1\n\t\t\t}\n\t\t\tbits = append(bits, chunkBits)\n\t\t}\n\t\tbits = append(bits, 0)\n\t\tcharsets = append(charsets, tuple{char: c, fcv: FullCharacteristicVector(bits)})\n\t}\n\treturn Alphabet{charset: charsets}\n}\n"
  },
  {
    "path": "levenshtein/alphabet_test.go",
    "content": "//  Copyright (c) 2018 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage levenshtein\n\nimport \"testing\"\n\nfunc TestAlphabet(t *testing.T) {\n\tchars := \"happy\"\n\talphabet := queryChars(chars)\n\n\tc, chi, _ := alphabet.next()\n\tif c != 'a' {\n\t\tt.Errorf(\"expecting 'a', got: %v\", c)\n\t}\n\n\tif chi[0] != 2 {\n\t\tt.Errorf(\"expecting 2, got: %v\", chi[0])\n\t}\n\n\tc, chi, _ = alphabet.next()\n\tif c != 'h' {\n\t\tt.Errorf(\"expecting 'h', got: %v\", c)\n\t}\n\n\tif chi[0] != 1 {\n\t\tt.Errorf(\"expecting 1, got: %v\", chi[0])\n\t}\n\n\tc, chi, _ = alphabet.next()\n\tif c != 'p' {\n\t\tt.Errorf(\"expecting 'p', got: %v\", c)\n\t}\n\n\tif chi[0] != 12 {\n\t\tt.Errorf(\"expecting 12, got: %v\", chi[0])\n\t}\n\n\tc, chi, _ = alphabet.next()\n\tif c != 'y' {\n\t\tt.Errorf(\"expecting 'y', got: %v\", c)\n\t}\n\n\tif chi[0] != 16 {\n\t\tt.Errorf(\"expecting 16, got: %v\", chi[0])\n\t}\n}\n\nfunc TestFullCharacteristic(t *testing.T) {\n\tfcv := FullCharacteristicVector([]uint32{2, 0})\n\tif fcv.shiftAndMask(1, 1) != 1 {\n\t\tt.Errorf(\"expected 1, got: %v\", fcv.shiftAndMask(1, 1))\n\t}\n\n\tfcv = FullCharacteristicVector([]uint32{1<<5 + 1<<10, 0})\n\tif fcv.shiftAndMask(3, 63) != 4 {\n\t\tt.Errorf(\"expected 4, got: %v\", fcv.shiftAndMask(3, 63))\n\t}\n}\n\nfunc TestLongCharacteristic(t *testing.T) {\n\tqChars := \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcabewa\"\n\talphabet := queryChars(qChars)\n\n\tc, chi, _ := alphabet.next()\n\tif c != 'a' {\n\t\tt.Errorf(\"expecting 'a', got: %v\", c)\n\t}\n\tif chi.shiftAndMask(0, 7) != 7 {\n\t\tt.Errorf(\"expecting 7 , got: %v\", chi.shiftAndMask(0, 7))\n\t}\n\n\tif chi.shiftAndMask(28, 7) != 3 {\n\t\tt.Errorf(\"expecting 3 , got: %v\", chi.shiftAndMask(28, 7))\n\t}\n\n\tif chi.shiftAndMask(28, 127) != 1+2+16 {\n\t\tt.Errorf(\"expecting 19 , got: %v\", chi.shiftAndMask(28, 127))\n\t}\n\n\tif chi.shiftAndMask(28, 4095) != 1+2+16+256 {\n\t\tt.Errorf(\"expecting 275 , got: %v\", chi.shiftAndMask(28, 4095))\n\t}\n\n\tc, chi, _ = alphabet.next()\n\tif c != 'b' {\n\t\tt.Errorf(\"expecting 'b', got: %v\", c)\n\t}\n\tif chi.shiftAndMask(0, 7) != 0 {\n\t\tt.Errorf(\"expecting 0 , got: %v\", chi.shiftAndMask(0, 7))\n\t}\n\n\tif chi.shiftAndMask(28, 15) != 4 {\n\t\tt.Errorf(\"expecting 4 , got: %v\", chi.shiftAndMask(28, 15))\n\t}\n\n\tif chi.shiftAndMask(28, 63) != 4+32 {\n\t\tt.Errorf(\"expecting 36 , got: %v\", chi.shiftAndMask(28, 63))\n\t}\n\n}\n"
  },
  {
    "path": "levenshtein/benchmark_test.go",
    "content": "//  Copyright (c) 2018 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage levenshtein\n\nimport (\n\t\"testing\"\n)\n\nfunc BenchmarkNewEvalEditDistance1(b *testing.B) {\n\tlb, _ := NewLevenshteinAutomatonBuilder(1, true)\n\n\tquery := \"coucibase\"\n\tfor i := 0; i < b.N; i++ {\n\t\tdfa, _ := lb.BuildDfa(\"couchbase\", 1)\n\t\ted := dfa.eval([]byte(query))\n\t\tif ed.distance() != 1 {\n\t\t\tb.Errorf(\"expected distance 1, actual: %d\", ed.distance())\n\t\t}\n\n\t}\n}\n\nfunc BenchmarkNewEvalEditDistance2(b *testing.B) {\n\tlb, _ := NewLevenshteinAutomatonBuilder(2, false)\n\n\tquery := \"couchbasefts\"\n\tfor i := 0; i < b.N; i++ {\n\t\tdfa, _ := lb.BuildDfa(\"couchbases\", 2)\n\t\ted := dfa.eval([]byte(query))\n\t\tif ed.distance() != 2 {\n\t\t\tb.Errorf(\"expected distance 2, actual: %d\", ed.distance())\n\t\t}\n\t}\n}\n\nfunc BenchmarkNewEditDistance1(b *testing.B) {\n\tlb, _ := NewLevenshteinAutomatonBuilder(1, true)\n\n\tquery := \"coucibase\"\n\tfor i := 0; i < b.N; i++ {\n\t\tdfa, _ := lb.BuildDfa(\"couchbase\", 1)\n\n\t\tstate := dfa.initialState()\n\t\tfor _, b := range []byte(query) {\n\t\t\tstate = dfa.transition(state, b)\n\t\t}\n\n\t\tif !dfa.IsMatch(state) {\n\t\t\tb.Errorf(\"expected isMatch %t, got %t\", true, !dfa.IsMatch(state))\n\t\t}\n\n\t}\n}\n\nfunc BenchmarkNewEditDistance2(b *testing.B) {\n\tlb, _ := NewLevenshteinAutomatonBuilder(2, false)\n\n\tquery := \"couchbasefts\"\n\tfor i := 0; i < b.N; i++ {\n\t\tdfa, _ := lb.BuildDfa(\"couchbases\", 2)\n\n\t\tstate := dfa.initialState()\n\t\tfor _, b := range []byte(query) {\n\t\t\tstate = dfa.transition(state, b)\n\t\t}\n\n\t\tif !dfa.IsMatch(state) {\n\t\t\tb.Errorf(\"expected isMatch %t, got %t\", true, !dfa.IsMatch(state))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "levenshtein/dfa.go",
    "content": "//  Copyright (c) 2018 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage levenshtein\n\nimport (\n\t\"fmt\"\n\t\"math\"\n)\n\nconst SinkState = uint32(0)\n\ntype DFA struct {\n\ttransitions [][256]uint32\n\tdistances   []Distance\n\tinitState   int\n\ted          uint8\n}\n\n/// Returns the initial state\nfunc (d *DFA) initialState() int {\n\treturn d.initState\n}\n\n/// Returns the Levenshtein distance associated to the\n/// current state.\nfunc (d *DFA) distance(stateId int) Distance {\n\treturn d.distances[stateId]\n}\n\n/// Returns the number of states in the `DFA`.\nfunc (d *DFA) numStates() int {\n\treturn len(d.transitions)\n}\n\n/// Returns the destination state reached after consuming a given byte.\nfunc (d *DFA) transition(fromState int, b uint8) int {\n\treturn int(d.transitions[fromState][b])\n}\n\nfunc (d *DFA) eval(bytes []uint8) Distance {\n\tstate := d.initialState()\n\n\tfor _, b := range bytes {\n\t\tstate = d.transition(state, b)\n\t}\n\n\treturn d.distance(state)\n}\n\nfunc (d *DFA) Start() int {\n\treturn int(d.initialState())\n}\n\nfunc (d *DFA) IsMatch(state int) bool {\n\tif _, ok := d.distance(state).(Exact); ok {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (d *DFA) CanMatch(state int) bool {\n\treturn state > 0 && state < d.numStates()\n}\n\nfunc (d *DFA) Accept(state int, b byte) int {\n\treturn int(d.transition(state, b))\n}\n\n// WillAlwaysMatch returns if the specified state will always end in a\n// matching state.\nfunc (d *DFA) WillAlwaysMatch(state int) bool {\n\treturn false\n}\n\nfunc fill(dest []uint32, val uint32) {\n\tfor i := range dest {\n\t\tdest[i] = val\n\t}\n}\n\nfunc fillTransitions(dest *[256]uint32, val uint32) {\n\tfor i := range dest {\n\t\tdest[i] = val\n\t}\n}\n\ntype Utf8DFAStateBuilder struct {\n\tdfaBuilder       *Utf8DFABuilder\n\tstateID          uint32\n\tdefaultSuccessor []uint32\n}\n\nfunc (sb *Utf8DFAStateBuilder) addTransitionID(fromStateID uint32, b uint8,\n\ttoStateID uint32) {\n\tsb.dfaBuilder.transitions[fromStateID][b] = toStateID\n}\n\nfunc (sb *Utf8DFAStateBuilder) addTransition(in rune, toStateID uint32) {\n\tfromStateID := sb.stateID\n\tchars := []byte(string(in))\n\tlastByte := chars[len(chars)-1]\n\n\tfor i, ch := range chars[:len(chars)-1] {\n\t\tremNumBytes := len(chars) - i - 1\n\t\tdefaultSuccessor := sb.defaultSuccessor[remNumBytes]\n\t\tintermediateStateID := sb.dfaBuilder.transitions[fromStateID][ch]\n\n\t\tif intermediateStateID == defaultSuccessor {\n\t\t\tintermediateStateID = sb.dfaBuilder.allocate()\n\t\t\tfillTransitions(&sb.dfaBuilder.transitions[intermediateStateID],\n\t\t\t\tsb.defaultSuccessor[remNumBytes-1])\n\t\t}\n\n\t\tsb.addTransitionID(fromStateID, ch, intermediateStateID)\n\t\tfromStateID = intermediateStateID\n\t}\n\n\ttoStateIDDecoded := sb.dfaBuilder.getOrAllocate(original(toStateID))\n\tsb.addTransitionID(fromStateID, lastByte, toStateIDDecoded)\n}\n\ntype Utf8StateId uint32\n\nfunc original(stateId uint32) Utf8StateId {\n\treturn predecessor(stateId, 0)\n}\n\nfunc predecessor(stateId uint32, numSteps uint8) Utf8StateId {\n\treturn Utf8StateId(stateId*4 + uint32(numSteps))\n}\n\n// Utf8DFABuilder makes it possible to define a DFA\n// that takes unicode character, and build a `DFA`\n// that operates on utf-8 encoded\ntype Utf8DFABuilder struct {\n\tindex        []uint32\n\tdistances    []Distance\n\ttransitions  [][256]uint32\n\tinitialState uint32\n\tnumStates    uint32\n\tmaxNumStates uint32\n}\n\nfunc withMaxStates(maxStates uint32) *Utf8DFABuilder {\n\trv := &Utf8DFABuilder{\n\t\tindex:        make([]uint32, maxStates*2+100),\n\t\tdistances:    make([]Distance, 0, maxStates),\n\t\ttransitions:  make([][256]uint32, 0, maxStates),\n\t\tmaxNumStates: maxStates,\n\t}\n\n\tfor i := range rv.index {\n\t\trv.index[i] = math.MaxUint32\n\t}\n\n\treturn rv\n}\n\nfunc (dfab *Utf8DFABuilder) allocate() uint32 {\n\tnewState := dfab.numStates\n\tdfab.numStates++\n\n\tdfab.distances = append(dfab.distances, Atleast{d: 255})\n\tdfab.transitions = append(dfab.transitions, [256]uint32{})\n\n\treturn newState\n}\n\nfunc (dfab *Utf8DFABuilder) getOrAllocate(state Utf8StateId) uint32 {\n\tif int(state) >= cap(dfab.index) {\n\t\tcloneIndex := make([]uint32, int(state)*2)\n\t\tcopy(cloneIndex, dfab.index)\n\t\tdfab.index = cloneIndex\n\t}\n\tif dfab.index[state] != math.MaxUint32 {\n\t\treturn dfab.index[state]\n\t}\n\n\tnstate := dfab.allocate()\n\tdfab.index[state] = nstate\n\n\treturn nstate\n}\n\nfunc (dfab *Utf8DFABuilder) setInitialState(iState uint32) {\n\tdecodedID := dfab.getOrAllocate(original(iState))\n\tdfab.initialState = decodedID\n}\n\nfunc (dfab *Utf8DFABuilder) build(ed uint8) *DFA {\n\treturn &DFA{\n\t\ttransitions: dfab.transitions,\n\t\tdistances:   dfab.distances,\n\t\tinitState:   int(dfab.initialState),\n\t\ted:          ed,\n\t}\n}\n\nfunc (dfab *Utf8DFABuilder) addState(state, default_suc_orig uint32,\n\tdistance Distance) (*Utf8DFAStateBuilder, error) {\n\tif state > dfab.maxNumStates {\n\t\treturn nil, fmt.Errorf(\"State id is larger than maxNumStates\")\n\t}\n\n\tstateID := dfab.getOrAllocate(original(state))\n\tdfab.distances[stateID] = distance\n\n\tdefaultSuccID := dfab.getOrAllocate(original(default_suc_orig))\n\t// creates a chain of states of predecessors of `default_suc_orig`.\n\t// Accepting k-bytes (whatever the bytes are) from `predecessor_states[k-1]`\n\t// leads to the `default_suc_orig` state.\n\tpredecessorStates := []uint32{defaultSuccID,\n\t\tdefaultSuccID,\n\t\tdefaultSuccID,\n\t\tdefaultSuccID}\n\n\tfor numBytes := uint8(1); numBytes < 4; numBytes++ {\n\t\tpredecessorState := predecessor(default_suc_orig, numBytes)\n\t\tpredecessorStateID := dfab.getOrAllocate(predecessorState)\n\t\tpredecessorStates[numBytes] = predecessorStateID\n\t\tsucc := predecessorStates[numBytes-1]\n\t\tfillTransitions(&dfab.transitions[predecessorStateID], succ)\n\t}\n\n\t// 1-byte encoded chars.\n\tfill(dfab.transitions[stateID][0:192], predecessorStates[0])\n\t// 2-bytes encoded chars.\n\tfill(dfab.transitions[stateID][192:224], predecessorStates[1])\n\t// 3-bytes encoded chars.\n\tfill(dfab.transitions[stateID][224:240], predecessorStates[2])\n\t// 4-bytes encoded chars.\n\tfill(dfab.transitions[stateID][240:256], predecessorStates[3])\n\n\treturn &Utf8DFAStateBuilder{\n\t\tdfaBuilder:       dfab,\n\t\tstateID:          stateID,\n\t\tdefaultSuccessor: predecessorStates}, nil\n}\n"
  },
  {
    "path": "levenshtein/dfa_test.go",
    "content": "//  Copyright (c) 2018 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage levenshtein\n\nimport (\n\t\"testing\"\n)\n\nfunc TestLevenshtein2(t *testing.T) {\n\tdfaBuilder := withMaxStates(2)\n\tdfaBuilder.addState(0, 1, Exact{d: 1})\n\tdfaBuilder.addState(1, 0, Exact{d: 0})\n\tdfaBuilder.setInitialState(1)\n\t_ = dfaBuilder.build(1)\n}\n"
  },
  {
    "path": "levenshtein/levenshtein.go",
    "content": "//  Copyright (c) 2018 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage levenshtein\n\nimport \"fmt\"\n\n// StateLimit is the maximum number of states allowed\nconst StateLimit = 10000\n\n// ErrTooManyStates is returned if you attempt to build a Levenshtein\n// automaton which requires too many states.\nvar ErrTooManyStates = fmt.Errorf(\"dfa contains more than %d states\",\n\tStateLimit)\n\n// LevenshteinAutomatonBuilder wraps a precomputed\n// datastructure that allows to produce small (but not minimal) DFA.\ntype LevenshteinAutomatonBuilder struct {\n\tpDfa *ParametricDFA\n}\n\n// NewLevenshteinAutomatonBuilder creates a\n// reusable, threadsafe Levenshtein automaton builder.\n// `maxDistance` - maximum distance considered by the automaton.\n// `transposition` - assign a distance of 1 for transposition\n//\n// Building this automaton builder is computationally intensive.\n// While it takes only a few milliseconds for `d=2`, it grows\n// exponentially with `d`. It is only reasonable to `d <= 5`.\nfunc NewLevenshteinAutomatonBuilder(maxDistance uint8,\n\ttransposition bool) (*LevenshteinAutomatonBuilder, error) {\n\tlnfa := newLevenshtein(maxDistance, transposition)\n\n\tpdfa, err := fromNfa(lnfa)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &LevenshteinAutomatonBuilder{pDfa: pdfa}, nil\n}\n\n// BuildDfa builds the levenshtein automaton for serving\n// queries with a given edit distance.\nfunc (lab *LevenshteinAutomatonBuilder) BuildDfa(query string,\n\tfuzziness uint8) (*DFA, error) {\n\treturn lab.pDfa.buildDfa(query, fuzziness, false)\n}\n\n// MaxDistance returns the MaxEdit distance supported by the\n// LevenshteinAutomatonBuilder builder.\nfunc (lab *LevenshteinAutomatonBuilder) MaxDistance() uint8 {\n\treturn lab.pDfa.maxDistance\n}\n"
  },
  {
    "path": "levenshtein/levenshtein_nfa.go",
    "content": "//  Copyright (c) 2018 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage levenshtein\n\nimport (\n\t\"math\"\n\t\"sort\"\n)\n\n/// Levenshtein Distance computed by a Levenshtein Automaton.\n///\n/// Levenshtein automata can only compute the exact Levenshtein distance\n/// up to a given `max_distance`.\n///\n/// Over this distance, the automaton will invariably\n/// return `Distance::AtLeast(max_distance + 1)`.\ntype Distance interface {\n\tdistance() uint8\n}\n\ntype Exact struct {\n\td uint8\n}\n\nfunc (e Exact) distance() uint8 {\n\treturn e.d\n}\n\ntype Atleast struct {\n\td uint8\n}\n\nfunc (a Atleast) distance() uint8 {\n\treturn a.d\n}\n\nfunc characteristicVector(query []rune, c rune) uint64 {\n\tchi := uint64(0)\n\tfor i := 0; i < len(query); i++ {\n\t\tif query[i] == c {\n\t\t\tchi |= 1 << uint64(i)\n\t\t}\n\t}\n\treturn chi\n}\n\ntype NFAState struct {\n\tOffset      uint32\n\tDistance    uint8\n\tInTranspose bool\n}\n\ntype NFAStates []NFAState\n\nfunc (ns NFAStates) Len() int {\n\treturn len(ns)\n}\n\nfunc (ns NFAStates) Less(i, j int) bool {\n\tif ns[i].Offset != ns[j].Offset {\n\t\treturn ns[i].Offset < ns[j].Offset\n\t}\n\n\tif ns[i].Distance != ns[j].Distance {\n\t\treturn ns[i].Distance < ns[j].Distance\n\t}\n\n\treturn !ns[i].InTranspose && ns[j].InTranspose\n}\n\nfunc (ns NFAStates) Swap(i, j int) {\n\tns[i], ns[j] = ns[j], ns[i]\n}\n\nfunc (ns *NFAState) imply(other NFAState) bool {\n\ttransposeImply := ns.InTranspose\n\tif !other.InTranspose {\n\t\ttransposeImply = !other.InTranspose\n\t}\n\n\tdeltaOffset := ns.Offset - other.Offset\n\tif ns.Offset < other.Offset {\n\t\tdeltaOffset = other.Offset - ns.Offset\n\t}\n\n\tif transposeImply {\n\t\treturn uint32(other.Distance) >= (uint32(ns.Distance) + deltaOffset)\n\t}\n\n\treturn uint32(other.Distance) > (uint32(ns.Distance) + deltaOffset)\n}\n\ntype MultiState struct {\n\tstates []NFAState\n}\n\nfunc (ms *MultiState) States() []NFAState {\n\treturn ms.states\n}\n\nfunc (ms *MultiState) Clear() {\n\tms.states = ms.states[:0]\n}\n\nfunc newMultiState() *MultiState {\n\treturn &MultiState{states: make([]NFAState, 0)}\n}\n\nfunc (ms *MultiState) normalize() uint32 {\n\tminOffset := uint32(math.MaxUint32)\n\n\tfor _, s := range ms.states {\n\t\tif s.Offset < minOffset {\n\t\t\tminOffset = s.Offset\n\t\t}\n\t}\n\tif minOffset == uint32(math.MaxUint32) {\n\t\tminOffset = 0\n\t}\n\n\tfor i := 0; i < len(ms.states); i++ {\n\t\tms.states[i].Offset -= minOffset\n\t}\n\n\tsort.Sort(NFAStates(ms.states))\n\n\treturn minOffset\n}\n\nfunc (ms *MultiState) addStates(nState NFAState) {\n\n\tfor _, s := range ms.states {\n\t\tif s.imply(nState) {\n\t\t\treturn\n\t\t}\n\t}\n\n\ti := 0\n\tfor i < len(ms.states) {\n\t\tif nState.imply(ms.states[i]) {\n\t\t\tms.states = append(ms.states[:i], ms.states[i+1:]...)\n\t\t} else {\n\t\t\ti++\n\t\t}\n\t}\n\tms.states = append(ms.states, nState)\n\n}\n\nfunc extractBit(bitset uint64, pos uint8) bool {\n\tshift := bitset >> pos\n\tbit := shift & 1\n\treturn bit == uint64(1)\n}\n\nfunc dist(left, right uint32) uint32 {\n\tif left > right {\n\t\treturn left - right\n\t}\n\treturn right - left\n}\n\ntype LevenshteinNFA struct {\n\tmDistance uint8\n\tdamerau   bool\n}\n\nfunc newLevenshtein(maxD uint8, transposition bool) *LevenshteinNFA {\n\treturn &LevenshteinNFA{mDistance: maxD,\n\t\tdamerau: transposition,\n\t}\n}\n\nfunc (la *LevenshteinNFA) maxDistance() uint8 {\n\treturn la.mDistance\n}\n\nfunc (la *LevenshteinNFA) msDiameter() uint8 {\n\treturn 2*la.mDistance + 1\n}\n\nfunc (la *LevenshteinNFA) initialStates() *MultiState {\n\tms := MultiState{}\n\tnfaState := NFAState{}\n\tms.addStates(nfaState)\n\treturn &ms\n}\n\nfunc (la *LevenshteinNFA) multistateDistance(ms *MultiState,\n\tqueryLen uint32) Distance {\n\tminDistance := Atleast{d: la.mDistance + 1}\n\tfor _, s := range ms.states {\n\t\tt := s.Distance + uint8(dist(queryLen, s.Offset))\n\t\tif t <= uint8(la.mDistance) {\n\t\t\tif minDistance.distance() > t {\n\t\t\t\tminDistance.d = t\n\t\t\t}\n\t\t}\n\t}\n\n\tif minDistance.distance() == la.mDistance+1 {\n\t\treturn Atleast{d: la.mDistance + 1}\n\t}\n\n\treturn minDistance\n}\n\nfunc (la *LevenshteinNFA) simpleTransition(state NFAState,\n\tsymbol uint64, ms *MultiState) {\n\n\tif state.Distance < la.mDistance {\n\t\t// insertion\n\t\tms.addStates(NFAState{Offset: state.Offset,\n\t\t\tDistance:    state.Distance + 1,\n\t\t\tInTranspose: false})\n\n\t\t// substitution\n\t\tms.addStates(NFAState{Offset: state.Offset + 1,\n\t\t\tDistance:    state.Distance + 1,\n\t\t\tInTranspose: false})\n\n\t\tn := la.mDistance + 1 - state.Distance\n\t\tfor d := uint8(1); d < n; d++ {\n\t\t\tif extractBit(symbol, d) {\n\t\t\t\t//  for d > 0, as many deletion and character match\n\t\t\t\tms.addStates(NFAState{Offset: state.Offset + 1 + uint32(d),\n\t\t\t\t\tDistance:    state.Distance + d,\n\t\t\t\t\tInTranspose: false})\n\t\t\t}\n\t\t}\n\n\t\tif la.damerau && extractBit(symbol, 1) {\n\t\t\tms.addStates(NFAState{\n\t\t\t\tOffset:      state.Offset,\n\t\t\t\tDistance:    state.Distance + 1,\n\t\t\t\tInTranspose: true})\n\t\t}\n\n\t}\n\n\tif extractBit(symbol, 0) {\n\t\tms.addStates(NFAState{Offset: state.Offset + 1,\n\t\t\tDistance:    state.Distance,\n\t\t\tInTranspose: false})\n\t}\n\n\tif state.InTranspose && extractBit(symbol, 0) {\n\t\tms.addStates(NFAState{Offset: state.Offset + 2,\n\t\t\tDistance:    state.Distance,\n\t\t\tInTranspose: false})\n\t}\n\n}\n\nfunc (la *LevenshteinNFA) transition(cState *MultiState,\n\tdState *MultiState, scv uint64) {\n\tdState.Clear()\n\tmask := (uint64(1) << la.msDiameter()) - uint64(1)\n\n\tfor _, state := range cState.states {\n\t\tcv := (scv >> state.Offset) & mask\n\t\tla.simpleTransition(state, cv, dState)\n\t}\n\n\tsort.Sort(NFAStates(dState.states))\n}\n\nfunc (la *LevenshteinNFA) computeDistance(query, other []rune) Distance {\n\tcState := la.initialStates()\n\tnState := newMultiState()\n\n\tfor _, i := range other {\n\t\tnState.Clear()\n\t\tchi := characteristicVector(query, i)\n\t\tla.transition(cState, nState, chi)\n\t\tcState, nState = nState, cState\n\t}\n\n\treturn la.multistateDistance(cState, uint32(len(query)))\n}\n"
  },
  {
    "path": "levenshtein/levenshtein_test.go",
    "content": "//  Copyright (c) 2018 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage levenshtein\n\nimport (\n\t\"testing\"\n)\n\nfunc TestLevenshtein(t *testing.T) {\n\n\thash := make(map[uint8]LevenshteinAutomatonBuilder, 4)\n\tfor i := 0; i < 3; i++ {\n\t\tlb, err := NewLevenshteinAutomatonBuilder(uint8(i), false)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"NewLevenshteinAutomatonBuilder(%d, false) failed, err: %v\", i, err)\n\t\t}\n\t\thash[uint8(i)] = *lb\n\t}\n\n\ttests := []struct {\n\t\tdesc     string\n\t\tquery    string\n\t\tdistance uint8\n\t\tseq      []byte\n\t\tisMatch  bool\n\t\tcanMatch bool\n\t}{\n\t\t{\n\t\t\tdesc:     \"cat/0 - c a t\",\n\t\t\tquery:    \"cat\",\n\t\t\tdistance: 0,\n\t\t\tseq:      []byte{'c', 'a', 't'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cat/1 - c a\",\n\t\t\tquery:    \"cat\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'c', 'a'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cat/1 - c a t s\",\n\t\t\tquery:    \"cat\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'c', 'a', 't', 's'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cat/0 - c a\",\n\t\t\tquery:    \"cat\",\n\t\t\tdistance: 0,\n\t\t\tseq:      []byte{'c', 'a'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cat/0 - c a t s\",\n\t\t\tquery:    \"cat\",\n\t\t\tdistance: 0,\n\t\t\tseq:      []byte{'c', 'a', 't', 's'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cate/1 - cate\",\n\t\t\tquery:    \"cate\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'c', 'a', 't', 'e'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cater/1 - cate\",\n\t\t\tquery:    \"cater\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'c', 'a', 't', 'e'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cater/1 - ctr\",\n\t\t\tquery:    \"cater\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'c', 't', 'r'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"catered/2 - cater\",\n\t\t\tquery:    \"catered\",\n\t\t\tdistance: 2,\n\t\t\tseq:      []byte{'c', 'a', 't', 'e', 'r'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t// this section contains cases where the sequence\n\t\t// of bytes encountered contains utf-8 encoded\n\t\t// multi-byte characters, which should count as 1\n\t\t// for the purposes of the levenshtein edit distance\n\t\t{\n\t\t\tdesc:     \"cat/0 - c 0xc3 0xa1 t (cát)\",\n\t\t\tquery:    \"cat\",\n\t\t\tdistance: 0,\n\t\t\tseq:      []byte{'c', 0xc3, 0xa1, 't'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cat/1 - c 0xc3 0xa1 t (cát)\",\n\t\t\tquery:    \"cat\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'c', 0xc3, 0xa1, 't'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cat/1 - c 0xc3 0xa1 t (cáts)\",\n\t\t\tquery:    \"cat\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'c', 0xc3, 0xa1, 't', 's'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cat/1 - 0xc3 0xa1 (á)\",\n\t\t\tquery:    \"cat\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{0xc3, 0xa1},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cat/1 - c 0xc3 0xa1 t (ácat)\",\n\t\t\tquery:    \"cat\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{0xc3, 0xa1, 'c', 'a', 't'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t// this section has utf-8 encoded multi-byte characters\n\t\t// in the query, which should still just count as 1\n\t\t// for the purposes of the levenshtein edit distance\n\t\t{\n\t\t\tdesc:     \"cát/0 - c a t (cat)\",\n\t\t\tquery:    \"cát\",\n\t\t\tdistance: 0,\n\t\t\tseq:      []byte{'c', 'a', 't'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cát/1 - c 0xc3 0xa1 (cá)\",\n\t\t\tquery:    \"cát\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'c', 0xc3, 0xa1},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cát/1 - c 0xc3 0xa1 s (cás)\",\n\t\t\tquery:    \"cát\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'c', 0xc3, 0xa1, 's'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cát/1 - c 0xc3 0xa1 t a (cáta)\",\n\t\t\tquery:    \"cát\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'c', 0xc3, 0xa1, 't', 'a'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cát/1 - d 0xc3 0xa1 (dát)\",\n\t\t\tquery:    \"cát\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'d', 0xc3, 0xa1, 't'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cát/1 - c a t (cat)\",\n\t\t\tquery:    \"cát\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'c', 'a', 't'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\n\t\t{\n\t\t\tdesc:     \"cát/1 - c a t (cats)\",\n\t\t\tquery:    \"cát\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'c', 'a', 't', 's'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cát/1 - 0xc3, 0xa (á)\",\n\t\t\tquery:    \"cát\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{0xc3, 0xa1},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tdesc:     \"cát/1 - a c 0xc3 0xa1 t (acát)\",\n\t\t\tquery:    \"cát\",\n\t\t\tdistance: 1,\n\t\t\tseq:      []byte{'a', 'c', 0xc3, 0xa1, 't'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.desc, func(t *testing.T) {\n\t\t\tl, err := hash[uint8(test.distance)].pDfa.buildDfa(test.query, test.distance, false)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"buildDfa(%s, %d, false) failed, err: %v\", test.query,\n\t\t\t\t\ttest.distance, err)\n\t\t\t}\n\n\t\t\ts := l.Start()\n\t\t\tfor _, b := range test.seq {\n\t\t\t\ts = l.Accept(s, b)\n\t\t\t\tif uint32(s) == SinkState {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tisMatch := l.IsMatch(s)\n\t\t\tif isMatch != test.isMatch {\n\t\t\t\tt.Errorf(\"expected isMatch %t, got %t\", test.isMatch, isMatch)\n\t\t\t}\n\n\t\t\tcanMatch := l.CanMatch(s)\n\t\t\tif canMatch != test.canMatch {\n\t\t\t\tt.Errorf(\"expectec canMatch %t, got %t\", test.canMatch, canMatch)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc makeDistance(d uint8, md uint8) Distance {\n\tif d > md {\n\t\treturn Atleast{d: md + 1}\n\t}\n\treturn Exact{d: d}\n}\n\nfunc testLevenshteinNfaUtil(left, right string, ed uint8, t *testing.T) {\n\tfor _, d := range []uint8{0, 1, 2, 3} {\n\t\texpectedDistance := makeDistance(ed, uint8(d))\n\t\tlev := newLevenshtein(d, false)\n\t\ttestSymmetric(lev, left, right, expectedDistance, t)\n\t}\n}\n\nfunc testSymmetric(lev *LevenshteinNFA, left, right string, expected Distance, t *testing.T) {\n\tlevd := lev.computeDistance([]rune(left), []rune(right))\n\tif levd.distance() != expected.distance() {\n\t\tt.Errorf(\"expected distance: %d, actual: %d\", expected.distance(), levd.distance())\n\t}\n\n\tlevd = lev.computeDistance([]rune(right), []rune(left))\n\tif levd.distance() != expected.distance() {\n\t\tt.Errorf(\"expected distance: %d, actual: %d\", expected.distance(), levd.distance())\n\t}\n}\nfunc TestLevenshteinNfa(t *testing.T) {\n\ttestLevenshteinNfaUtil(\"abc\", \"abc\", 0, t)\n\ttestLevenshteinNfaUtil(\"abc\", \"abcd\", 1, t)\n\ttestLevenshteinNfaUtil(\"aab\", \"ab\", 1, t)\n}\n\n/*func TestDeadState(t *testing.T) {\n\tnfa := newLevenshtein(2, false)\n\tpdfa := fromNfa(nfa)\n\tdfa := pdfa.buildDfa(\"abcdefghijklmnop\", 0, false)\n\tstate := dfa.initialState()\n\tr := []rune(\"X\")\n\tstate = dfa.transition(state, uint8(r[0]))\n\tif state != 0 {\n\t\tt.Errorf(\"expected state: 0, actual: %d\", state)\n\t}\n\tstate = dfa.transition(state, uint8(r[0]))\n\tif state != 0 {\n\t\tt.Errorf(\"expected state: 0, actual: %d\", state)\n\t}\n\tstate = dfa.transition(state, uint8(r[0]))\n\tif state != 0 {\n\t\tt.Errorf(\"expected state: 0, actual: %d\", state)\n\t}\n}*/\n\nfunc TestLevenshteinParametricDfa(t *testing.T) {\n\tlev := newLevenshtein(1, true)\n\tpDfa, err := fromNfa(lev)\n\tif err != nil {\n\t\tt.Errorf(\"fromNfa err: %v\", err)\n\t}\n\n\ttestStr := \"abc\"\n\tdfa, err := pDfa.buildDfa(testStr, 1, false)\n\tif err != nil {\n\t\tt.Errorf(\"buildDfa(%s, 1, false) failed, err: %v\", testStr, err)\n\t}\n\n\trd := dfa.eval([]byte(\"abc\"))\n\tif rd.distance() != 0 {\n\t\tt.Errorf(\"expected distance 0, actual: %d\", rd.distance())\n\t}\n\n\trd = dfa.eval([]byte(\"ab\"))\n\tif rd.distance() != 1 {\n\t\tt.Errorf(\"expected distance 1, actual: %d\", rd.distance())\n\t}\n\n\trd = dfa.eval([]byte(\"ac\"))\n\tif rd.distance() != 1 {\n\t\tt.Errorf(\"expected distance 1, actual: %d\", rd.distance())\n\t}\n\n\trd = dfa.eval([]byte(\"a\"))\n\tif rd.distance() != 2 {\n\t\tt.Errorf(\"expected distance 2, actual: %d\", rd.distance())\n\t}\n\n\trd = dfa.eval([]byte(\"abcd\"))\n\tif rd.distance() != 1 {\n\t\tt.Errorf(\"expected distance 1, actual: %d\", rd.distance())\n\t}\n\n\trd = dfa.eval([]byte(\"abdd\"))\n\tif rd.distance() != 2 {\n\t\tt.Errorf(\"expected distance 2, actual: %d\", rd.distance())\n\t}\n\n\ttestStr = \"abcdefghijlmnopqrstuvwxyz\" +\n\t\t\"abcdefghijlmnopqrstuvwxyz\" +\n\t\t\"abcdefghijlmnopqrstuvwxyz\" +\n\t\t\"abcdefghijlmnopqrstuvwxyz\"\n\n\tdfa, err = pDfa.buildDfa(testStr, 1, false)\n\tif err != nil {\n\t\tt.Errorf(\"buildDfa(%s, 1, false) failed, err: %v\", testStr, err)\n\t}\n\n\tsample1 := \"abcdefghijlmnopqrstuvwxyz\" +\n\t\t\"abcdefghijlnopqrstuvwxyz\" +\n\t\t\"abcdefghijlmnopqrstuvwxyz\" +\n\t\t\"abcdefghijlmnopqrstuvwxyz\"\n\trd = dfa.eval([]byte(sample1))\n\tif rd.distance() != 1 {\n\t\tt.Errorf(\"expected distance 1, actual: %d\", rd.distance())\n\t}\n\n\tsample2 := \"abcdefghijlmnopqrstuvwxyz\" +\n\t\t\"abcdefghijlnopqrstuvwxyz\" +\n\t\t\"abcdefghijlmnopqrstuvwxyz\" +\n\t\t\"abcdefghijlmnoprqstuvwxyz\"\n\trd = dfa.eval([]byte(sample2))\n\tif rd.distance() != 2 {\n\t\tt.Errorf(\"expected distance 2, actual: %d\", rd.distance())\n\t}\n}\n\nfunc TestDamerau(t *testing.T) {\n\tnfa := newLevenshtein(2, true)\n\ttestSymmetric(nfa, \"abc\", \"abc\", Exact{d: 0}, t)\n\ttestSymmetric(nfa, \"abc\", \"abcd\", Exact{d: 1}, t)\n\ttestSymmetric(nfa, \"abcdef\", \"abddef\", Exact{d: 1}, t)\n\ttestSymmetric(nfa, \"abcdef\", \"abdcef\", Exact{d: 1}, t)\n}\n\nfunc TestLevenshteinDfa(t *testing.T) {\n\tnfa := newLevenshtein(2, false)\n\tpDfa, err := fromNfa(nfa)\n\tif err != nil {\n\t\tt.Errorf(\"fromNfa failed, err: %v\", err)\n\t}\n\n\tdfa, err := pDfa.buildDfa(\"abcabcaaabc\", 2, false)\n\tif err != nil {\n\t\tt.Errorf(\"buildDfa(abcabcaaabc, 1, false) failed, err: %v\", err)\n\t}\n\n\tif dfa.numStates() != 273 {\n\t\tt.Errorf(\"expected number of states: 273, actual: %d\", dfa.numStates())\n\t}\n}\n\nfunc TestUtf8Simple(t *testing.T) {\n\tnfa := newLevenshtein(1, false)\n\tpDfa, err := fromNfa(nfa)\n\tif err != nil {\n\t\tt.Errorf(\"fromNfa failed, err: %v\", err)\n\t}\n\n\tdfa, err := pDfa.buildDfa(\"あ\", 1, false)\n\tif err != nil {\n\t\tt.Errorf(\"buildDfa(あ, 1, false) failed, err: %v\", err)\n\t}\n\n\ted := dfa.eval([]byte(\"あ\"))\n\tif ed.distance() != 0 {\n\t\tt.Errorf(\"expected distance 0, actual: %d\", ed.distance())\n\t}\n}\n\nfunc TestSimple(t *testing.T) {\n\tquery := \"abcdef\"\n\tnfa := newLevenshtein(2, false)\n\tpDfa, err := fromNfa(nfa)\n\tif err != nil {\n\t\tt.Errorf(\"fromNfa failed, err: %v\", err)\n\t}\n\n\tdfa, err := pDfa.buildDfa(query, 1, false)\n\tif err != nil {\n\t\tt.Errorf(\"buildDfa(%s, 1, false) failed, err: %v\", query, err)\n\t}\n\n\ted := dfa.eval([]byte(query))\n\tif ed.distance() != 0 {\n\t\tt.Errorf(\"expected distance 0, actual: %d\", ed.distance())\n\t}\n\n\ted = dfa.eval([]byte(\"abcdf\"))\n\tif ed.distance() != 1 {\n\t\tt.Errorf(\"expected distance 1, actual: %d\", ed.distance())\n\t}\n\ted = dfa.eval([]byte(\"abcdgf\"))\n\tif ed.distance() != 1 {\n\t\tt.Errorf(\"expected distance 1, actual: %d\", ed.distance())\n\t}\n\ted = dfa.eval([]byte(\"abccdef\"))\n\tif ed.distance() != 1 {\n\t\tt.Errorf(\"expected distance 1, actual: %d\", ed.distance())\n\t}\n}\n\nfunc TestJapanese(t *testing.T) {\n\tquery := \"寿司は焦げられない\"\n\tnfa := newLevenshtein(2, false)\n\tpDfa, err := fromNfa(nfa)\n\tif err != nil {\n\t\tt.Errorf(\"fromNfa failed, err: %v\", err)\n\t}\n\n\tdfa, err := pDfa.buildDfa(query, 2, false)\n\tif err != nil {\n\t\tt.Errorf(\"buildDfa(%s, 2, false) failed, err: %v\", query, err)\n\t}\n\n\ted := dfa.eval([]byte(query))\n\tif ed.distance() != 0 {\n\t\tt.Errorf(\"expected distance 0, actual: %d\", ed.distance())\n\t}\n\n\ted = dfa.eval([]byte(\"寿司は焦げられな\"))\n\tif ed.distance() != 1 {\n\t\tt.Errorf(\"expected distance 1, actual: %d\", ed.distance())\n\t}\n\n\ted = dfa.eval([]byte(\"寿司は焦げられなI\"))\n\tif ed.distance() != 1 {\n\t\tt.Errorf(\"expected distance 1, actual: %d\", ed.distance())\n\t}\n\n\ted = dfa.eval([]byte(\"寿司は焦られなI\"))\n\tif ed.distance() != 2 {\n\t\tt.Errorf(\"expected distance 2, actual: %d\", ed.distance())\n\t}\n}\n\nfunc TestJapaneseEnglish(t *testing.T) {\n\tquery := \"寿a\"\n\tnfa := newLevenshtein(1, false)\n\tpDfa, err := fromNfa(nfa)\n\tif err != nil {\n\t\tt.Errorf(\"fromNfa failed, err: %v\", err)\n\t}\n\n\tdfa, err := pDfa.buildDfa(query, 1, false)\n\tif err != nil {\n\t\tt.Errorf(\"buildDfa(%s, 1, false) failed, err: %v\", query, err)\n\t}\n\n\ted := dfa.eval([]byte(query))\n\tif ed.distance() != 0 {\n\t\tt.Errorf(\"expected distance 0, actual: %d\", ed.distance())\n\t}\n\n\ted = dfa.eval([]byte(\"a\"))\n\tif ed.distance() != 1 {\n\t\tt.Errorf(\"expected distance 0, actual: %d\", ed.distance())\n\t}\n}\n\nfunc TestTooManyStatesError(t *testing.T) {\n\tnfa := newLevenshtein(3, true)\n\tpDfa, err := fromNfa(nfa)\n\tif err != nil {\n\t\tt.Errorf(\"fromNfa failed, err: %v\", err)\n\t}\n\n\t// query of length 139 characters won't generate 10K states as against\n\t// the current levenshtein limit of query length 50.\n\tlengthQuery := \"1234567890123456789012345678901234567890123456789\" + // 50 chars\n\t\t\"1234567890123456789012345678901234567890123456789\" + // 50 chars\n\t\t\"1234567890123456789012345678901234567890\" // 40 chars (total 140)\n\n\t_, err = pDfa.buildDfa(lengthQuery, 1, false)\n\tif err != ErrTooManyStates {\n\t\tt.Errorf(\"buildDfa(%s, 1, false) expected to fail with err: %v\",\n\t\t\tlengthQuery, ErrTooManyStates)\n\t}\n}\n"
  },
  {
    "path": "levenshtein/parametric_dfa.go",
    "content": "//  Copyright (c) 2018 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage levenshtein\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math\"\n)\n\ntype ParametricState struct {\n\tshapeID uint32\n\toffset  uint32\n}\n\nfunc newParametricState() ParametricState {\n\treturn ParametricState{}\n}\n\nfunc (ps *ParametricState) isDeadEnd() bool {\n\treturn ps.shapeID == 0\n}\n\ntype Transition struct {\n\tdestShapeID uint32\n\tdeltaOffset uint32\n}\n\nfunc (t *Transition) apply(state ParametricState) ParametricState {\n\tps := ParametricState{\n\t\tshapeID: t.destShapeID}\n\t// don't need any offset if we are in the dead state,\n\t// this ensures we have only one dead state.\n\tif t.destShapeID != 0 {\n\t\tps.offset = state.offset + t.deltaOffset\n\t}\n\n\treturn ps\n}\n\ntype ParametricStateIndex struct {\n\tstateIndex []uint32\n\tstateQueue []ParametricState\n\tnumOffsets uint32\n}\n\nfunc newParametricStateIndex(queryLen,\n\tnumParamState uint32) ParametricStateIndex {\n\tnumOffsets := queryLen + 1\n\tif numParamState == 0 {\n\t\tnumParamState = numOffsets\n\t}\n\tmaxNumStates := numParamState * numOffsets\n\tpsi := ParametricStateIndex{\n\t\tstateIndex: make([]uint32, maxNumStates),\n\t\tstateQueue: make([]ParametricState, 0, 150),\n\t\tnumOffsets: numOffsets,\n\t}\n\n\tfor i := uint32(0); i < maxNumStates; i++ {\n\t\tpsi.stateIndex[i] = math.MaxUint32\n\t}\n\treturn psi\n}\n\nfunc (psi *ParametricStateIndex) numStates() int {\n\treturn len(psi.stateQueue)\n}\n\nfunc (psi *ParametricStateIndex) maxNumStates() int {\n\treturn len(psi.stateIndex)\n}\n\nfunc (psi *ParametricStateIndex) get(stateID uint32) ParametricState {\n\treturn psi.stateQueue[stateID]\n}\n\nfunc (psi *ParametricStateIndex) getOrAllocate(ps ParametricState) uint32 {\n\tbucket := ps.shapeID*psi.numOffsets + ps.offset\n\tif bucket < uint32(len(psi.stateIndex)) &&\n\t\tpsi.stateIndex[bucket] != math.MaxUint32 {\n\t\treturn psi.stateIndex[bucket]\n\t}\n\tnState := uint32(len(psi.stateQueue))\n\tpsi.stateQueue = append(psi.stateQueue, ps)\n\n\tpsi.stateIndex[bucket] = nState\n\treturn nState\n}\n\ntype ParametricDFA struct {\n\tdistance         []uint8\n\ttransitions      []Transition\n\tmaxDistance      uint8\n\ttransitionStride uint32\n\tdiameter         uint32\n}\n\nfunc (pdfa *ParametricDFA) initialState() ParametricState {\n\treturn ParametricState{shapeID: 1}\n}\n\n// Returns true iff whatever characters come afterward,\n// we will never reach a shorter distance\nfunc (pdfa *ParametricDFA) isPrefixSink(state ParametricState, queryLen uint32) bool {\n\tif state.isDeadEnd() {\n\t\treturn true\n\t}\n\n\tremOffset := queryLen - state.offset\n\tif remOffset < pdfa.diameter {\n\t\tstateDistances := pdfa.distance[pdfa.diameter*state.shapeID:]\n\t\tprefixDistance := stateDistances[remOffset]\n\t\tif prefixDistance > pdfa.maxDistance {\n\t\t\treturn false\n\t\t}\n\n\t\tfor _, d := range stateDistances {\n\t\t\tif d < prefixDistance {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (pdfa *ParametricDFA) numStates() int {\n\treturn len(pdfa.transitions) / int(pdfa.transitionStride)\n}\n\nfunc min(x, y uint32) uint32 {\n\tif x < y {\n\t\treturn x\n\t}\n\treturn y\n}\n\nfunc (pdfa *ParametricDFA) transition(state ParametricState,\n\tchi uint32) Transition {\n\treturn pdfa.transitions[pdfa.transitionStride*state.shapeID+chi]\n}\n\nfunc (pdfa *ParametricDFA) getDistance(state ParametricState,\n\tqLen uint32) Distance {\n\tremainingOffset := qLen - state.offset\n\tif state.isDeadEnd() || remainingOffset >= pdfa.diameter {\n\t\treturn Atleast{d: pdfa.maxDistance + 1}\n\t}\n\tdist := pdfa.distance[int(pdfa.diameter*state.shapeID)+int(remainingOffset)]\n\tif dist > pdfa.maxDistance {\n\t\treturn Atleast{d: dist}\n\t}\n\treturn Exact{d: dist}\n}\n\nfunc (pdfa *ParametricDFA) computeDistance(left, right string) Distance {\n\tstate := pdfa.initialState()\n\tleftChars := []rune(left)\n\tfor _, chr := range []rune(right) {\n\t\tstart := state.offset\n\t\tstop := min(start+pdfa.diameter, uint32(len(leftChars)))\n\t\tchi := characteristicVector(leftChars[start:stop], chr)\n\t\ttransition := pdfa.transition(state, uint32(chi))\n\t\tstate = transition.apply(state)\n\t\tif state.isDeadEnd() {\n\t\t\treturn Atleast{d: pdfa.maxDistance + 1}\n\t\t}\n\t}\n\treturn pdfa.getDistance(state, uint32(len(left)))\n}\n\nfunc (pdfa *ParametricDFA) buildDfa(query string, distance uint8,\n\tprefix bool) (*DFA, error) {\n\tqLen := uint32(len([]rune(query)))\n\talphabet := queryChars(query)\n\n\tpsi := newParametricStateIndex(qLen, uint32(pdfa.numStates()))\n\tmaxNumStates := psi.maxNumStates()\n\tdeadEndStateID := psi.getOrAllocate(newParametricState())\n\tif deadEndStateID != 0 {\n\t\treturn nil, fmt.Errorf(\"Invalid dead end state\")\n\t}\n\n\tinitialStateID := psi.getOrAllocate(pdfa.initialState())\n\tdfaBuilder := withMaxStates(uint32(maxNumStates))\n\tmask := uint32((1 << pdfa.diameter) - 1)\n\n\tvar stateID int\n\tfor stateID = 0; stateID < StateLimit; stateID++ {\n\t\tif stateID == psi.numStates() {\n\t\t\tbreak\n\t\t}\n\t\tstate := psi.get(uint32(stateID))\n\t\tif prefix && pdfa.isPrefixSink(state, qLen) {\n\t\t\tdistance := pdfa.getDistance(state, qLen)\n\t\t\tdfaBuilder.addState(uint32(stateID), uint32(stateID), distance)\n\t\t} else {\n\t\t\ttransition := pdfa.transition(state, 0)\n\t\t\tdefSuccessor := transition.apply(state)\n\t\t\tdefSuccessorID := psi.getOrAllocate(defSuccessor)\n\t\t\tdistance := pdfa.getDistance(state, qLen)\n\t\t\tstateBuilder, err := dfaBuilder.addState(uint32(stateID), defSuccessorID, distance)\n\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"parametric_dfa: buildDfa, err: %v\", err)\n\t\t\t}\n\n\t\t\talphabet.resetNext()\n\t\t\tchr, cv, err := alphabet.next()\n\t\t\tfor err == nil {\n\t\t\t\tchi := cv.shiftAndMask(state.offset, mask)\n\n\t\t\t\ttransition := pdfa.transition(state, chi)\n\n\t\t\t\tdestState := transition.apply(state)\n\n\t\t\t\tdestStateID := psi.getOrAllocate(destState)\n\n\t\t\t\tstateBuilder.addTransition(chr, destStateID)\n\n\t\t\t\tchr, cv, err = alphabet.next()\n\t\t\t}\n\t\t}\n\t}\n\n\tif stateID == StateLimit {\n\t\treturn nil, ErrTooManyStates\n\t}\n\n\tdfaBuilder.setInitialState(initialStateID)\n\treturn dfaBuilder.build(distance), nil\n}\n\nfunc fromNfa(nfa *LevenshteinNFA) (*ParametricDFA, error) {\n\tlookUp := newHash()\n\tlookUp.getOrAllocate(*newMultiState())\n\tinitialState := nfa.initialStates()\n\tlookUp.getOrAllocate(*initialState)\n\n\tmaxDistance := nfa.maxDistance()\n\tmsDiameter := nfa.msDiameter()\n\n\tnumChi := 1 << msDiameter\n\tchiValues := make([]uint64, numChi)\n\tfor i := 0; i < numChi; i++ {\n\t\tchiValues[i] = uint64(i)\n\t}\n\n\ttransitions := make([]Transition, 0, numChi*int(msDiameter))\n\tvar stateID int\n\tfor stateID = 0; stateID < StateLimit; stateID++ {\n\t\tif stateID == len(lookUp.items) {\n\t\t\tbreak\n\t\t}\n\n\t\tfor _, chi := range chiValues {\n\t\t\tdestMs := newMultiState()\n\n\t\t\tms := lookUp.getFromID(stateID)\n\n\t\t\tnfa.transition(ms, destMs, chi)\n\n\t\t\ttranslation := destMs.normalize()\n\n\t\t\tdestID := lookUp.getOrAllocate(*destMs)\n\n\t\t\ttransitions = append(transitions, Transition{\n\t\t\t\tdestShapeID: uint32(destID),\n\t\t\t\tdeltaOffset: translation,\n\t\t\t})\n\t\t}\n\t}\n\n\tif stateID == StateLimit {\n\t\treturn nil, ErrTooManyStates\n\t}\n\n\tns := len(lookUp.items)\n\tdiameter := int(msDiameter)\n\n\tdistances := make([]uint8, 0, diameter*ns)\n\tfor stateID := 0; stateID < ns; stateID++ {\n\t\tms := lookUp.getFromID(stateID)\n\t\tfor offset := 0; offset < diameter; offset++ {\n\t\t\tdist := nfa.multistateDistance(ms, uint32(offset))\n\t\t\tdistances = append(distances, dist.distance())\n\t\t}\n\t}\n\n\treturn &ParametricDFA{\n\t\tdiameter:         uint32(msDiameter),\n\t\ttransitions:      transitions,\n\t\tmaxDistance:      maxDistance,\n\t\ttransitionStride: uint32(numChi),\n\t\tdistance:         distances,\n\t}, nil\n}\n\ntype hash struct {\n\tindex map[[16]byte]int\n\titems []MultiState\n}\n\nfunc newHash() *hash {\n\treturn &hash{\n\t\tindex: make(map[[16]byte]int, 100),\n\t\titems: make([]MultiState, 0, 100),\n\t}\n}\n\nfunc (h *hash) getOrAllocate(m MultiState) int {\n\tsize := len(h.items)\n\tvar exists bool\n\tvar pos int\n\tmd5 := getHash(&m)\n\tif pos, exists = h.index[md5]; !exists {\n\t\th.index[md5] = size\n\t\tpos = size\n\t\th.items = append(h.items, m)\n\t}\n\treturn pos\n}\n\nfunc (h *hash) getFromID(id int) *MultiState {\n\treturn &h.items[id]\n}\n\nfunc getHash(ms *MultiState) [16]byte {\n\tmsBytes := []byte{}\n\tfor _, state := range ms.states {\n\t\tjsonBytes, _ := json.Marshal(&state)\n\t\tmsBytes = append(msBytes, jsonBytes...)\n\t}\n\treturn md5.Sum(msBytes)\n}\n"
  },
  {
    "path": "merge_iterator.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"bytes\"\n)\n\n// MergeFunc is used to choose the new value for a key when merging a slice\n// of iterators, and the same key is observed with multiple values.\n// Values presented to the MergeFunc will be in the same order as the\n// original slice creating the MergeIterator.  This allows some MergeFunc\n// implementations to prioritize one iterator over another.\ntype MergeFunc func([]uint64) uint64\n\n// MergeIterator implements the Iterator interface by traversing a slice\n// of iterators and merging the contents of them.  If the same key exists\n// in mulitipe underlying iterators, a user-provided MergeFunc will be\n// invoked to choose the new value.\ntype MergeIterator struct {\n\titrs   []Iterator\n\tf      MergeFunc\n\tcurrKs [][]byte\n\tcurrVs []uint64\n\n\tlowK    []byte\n\tlowV    uint64\n\tlowIdxs []int\n\n\tmergeV []uint64\n}\n\n// NewMergeIterator creates a new MergeIterator over the provided slice of\n// Iterators and with the specified MergeFunc to resolve duplicate keys.\nfunc NewMergeIterator(itrs []Iterator, f MergeFunc) (*MergeIterator, error) {\n\trv := &MergeIterator{\n\t\titrs:    itrs,\n\t\tf:       f,\n\t\tcurrKs:  make([][]byte, len(itrs)),\n\t\tcurrVs:  make([]uint64, len(itrs)),\n\t\tlowIdxs: make([]int, 0, len(itrs)),\n\t\tmergeV:  make([]uint64, 0, len(itrs)),\n\t}\n\trv.init()\n\tif rv.lowK == nil {\n\t\treturn rv, ErrIteratorDone\n\t}\n\treturn rv, nil\n}\n\nfunc (m *MergeIterator) init() {\n\tfor i, itr := range m.itrs {\n\t\tm.currKs[i], m.currVs[i] = itr.Current()\n\t}\n\tm.updateMatches()\n}\n\nfunc (m *MergeIterator) updateMatches() {\n\tif len(m.itrs) < 1 {\n\t\treturn\n\t}\n\tm.lowK = m.currKs[0]\n\tm.lowIdxs = m.lowIdxs[:0]\n\tm.lowIdxs = append(m.lowIdxs, 0)\n\tfor i := 1; i < len(m.itrs); i++ {\n\t\tif m.currKs[i] == nil {\n\t\t\tcontinue\n\t\t}\n\t\tcmp := bytes.Compare(m.currKs[i], m.lowK)\n\t\tif m.lowK == nil || cmp < 0 {\n\t\t\t// reached a new low\n\t\t\tm.lowK = m.currKs[i]\n\t\t\tm.lowIdxs = m.lowIdxs[:0]\n\t\t\tm.lowIdxs = append(m.lowIdxs, i)\n\t\t} else if cmp == 0 {\n\t\t\tm.lowIdxs = append(m.lowIdxs, i)\n\t\t}\n\t}\n\tif len(m.lowIdxs) > 1 {\n\t\t// merge multiple values\n\t\tm.mergeV = m.mergeV[:0]\n\t\tfor _, vi := range m.lowIdxs {\n\t\t\tm.mergeV = append(m.mergeV, m.currVs[vi])\n\t\t}\n\t\tm.lowV = m.f(m.mergeV)\n\t} else if len(m.lowIdxs) == 1 {\n\t\tm.lowV = m.currVs[m.lowIdxs[0]]\n\t}\n}\n\n// Current returns the key and value currently pointed to by this iterator.\n// If the iterator is not pointing at a valid value (because Iterator/Next/Seek)\n// returned an error previously, it may return nil,0.\nfunc (m *MergeIterator) Current() ([]byte, uint64) {\n\treturn m.lowK, m.lowV\n}\n\n// Next advances this iterator to the next key/value pair.  If there is none,\n// then ErrIteratorDone is returned.\nfunc (m *MergeIterator) Next() error {\n\t// move all the current low iterators to next\n\tfor _, vi := range m.lowIdxs {\n\t\terr := m.itrs[vi].Next()\n\t\tif err != nil && err != ErrIteratorDone {\n\t\t\treturn err\n\t\t}\n\t\tm.currKs[vi], m.currVs[vi] = m.itrs[vi].Current()\n\t}\n\tm.updateMatches()\n\tif m.lowK == nil {\n\t\treturn ErrIteratorDone\n\t}\n\treturn nil\n}\n\n// Seek advances this iterator to the specified key/value pair.  If this key\n// is not in the FST, Current() will return the next largest key.  If this\n// seek operation would go past the last key, then ErrIteratorDone is returned.\nfunc (m *MergeIterator) Seek(key []byte) error {\n\tfor i := range m.itrs {\n\t\terr := m.itrs[i].Seek(key)\n\t\tif err != nil && err != ErrIteratorDone {\n\t\t\treturn err\n\t\t}\n\t}\n\tm.updateMatches()\n\tif m.lowK == nil {\n\t\treturn ErrIteratorDone\n\t}\n\treturn nil\n}\n\n// Close will attempt to close all the underlying Iterators.  If any errors\n// are encountered, the first will be returned.\nfunc (m *MergeIterator) Close() error {\n\tvar rv error\n\tfor i := range m.itrs {\n\t\t// close all iterators, return first error if any\n\t\terr := m.itrs[i].Close()\n\t\tif rv == nil {\n\t\t\trv = err\n\t\t}\n\t}\n\treturn rv\n}\n\n// MergeMin chooses the minimum value\nfunc MergeMin(vals []uint64) uint64 {\n\trv := vals[0]\n\tfor _, v := range vals[1:] {\n\t\tif v < rv {\n\t\t\trv = v\n\t\t}\n\t}\n\treturn rv\n}\n\n// MergeMax chooses the maximum value\nfunc MergeMax(vals []uint64) uint64 {\n\trv := vals[0]\n\tfor _, v := range vals[1:] {\n\t\tif v > rv {\n\t\t\trv = v\n\t\t}\n\t}\n\treturn rv\n}\n\n// MergeSum sums the values\nfunc MergeSum(vals []uint64) uint64 {\n\trv := vals[0]\n\tfor _, v := range vals[1:] {\n\t\trv += v\n\t}\n\treturn rv\n}\n"
  },
  {
    "path": "merge_iterator_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"reflect\"\n\t\"sort\"\n\t\"testing\"\n)\n\nfunc TestMergeIterator(t *testing.T) {\n\n\ttests := []struct {\n\t\tdesc  string\n\t\tin    []map[string]uint64\n\t\tmerge MergeFunc\n\t\twant  map[string]uint64\n\t}{\n\t\t{\n\t\t\tdesc: \"two non-empty iterators with no duplicate keys\",\n\t\t\tin: []map[string]uint64{\n\t\t\t\t{\n\t\t\t\t\t\"a\": 1,\n\t\t\t\t\t\"c\": 3,\n\t\t\t\t\t\"e\": 5,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"b\": 2,\n\t\t\t\t\t\"d\": 4,\n\t\t\t\t\t\"f\": 6,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmerge: func(mvs []uint64) uint64 {\n\t\t\t\treturn mvs[0]\n\t\t\t},\n\t\t\twant: map[string]uint64{\n\t\t\t\t\"a\": 1,\n\t\t\t\t\"c\": 3,\n\t\t\t\t\"e\": 5,\n\t\t\t\t\"b\": 2,\n\t\t\t\t\"d\": 4,\n\t\t\t\t\"f\": 6,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc: \"two non-empty iterators with duplicate keys summed\",\n\t\t\tin: []map[string]uint64{\n\t\t\t\t{\n\t\t\t\t\t\"a\": 1,\n\t\t\t\t\t\"c\": 3,\n\t\t\t\t\t\"e\": 5,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"a\": 2,\n\t\t\t\t\t\"c\": 4,\n\t\t\t\t\t\"e\": 6,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmerge: func(mvs []uint64) uint64 {\n\t\t\t\tvar rv uint64\n\t\t\t\tfor _, mv := range mvs {\n\t\t\t\t\trv += mv\n\t\t\t\t}\n\t\t\t\treturn rv\n\t\t\t},\n\t\t\twant: map[string]uint64{\n\t\t\t\t\"a\": 3,\n\t\t\t\t\"c\": 7,\n\t\t\t\t\"e\": 11,\n\t\t\t},\n\t\t},\n\n\t\t{\n\t\t\tdesc: \"non-working example\",\n\t\t\tin: []map[string]uint64{\n\t\t\t\t{\n\t\t\t\t\t\"mon\":   2,\n\t\t\t\t\t\"tues\":  3,\n\t\t\t\t\t\"thurs\": 5,\n\t\t\t\t\t\"tye\":   99,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"bold\": 25,\n\t\t\t\t\t\"last\": 1,\n\t\t\t\t\t\"next\": 500,\n\t\t\t\t\t\"tank\": 0,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmerge: func(mvs []uint64) uint64 {\n\t\t\t\treturn mvs[0]\n\t\t\t},\n\t\t\twant: map[string]uint64{\n\t\t\t\t\"mon\":   2,\n\t\t\t\t\"tues\":  3,\n\t\t\t\t\"thurs\": 5,\n\t\t\t\t\"tye\":   99,\n\t\t\t\t\"bold\":  25,\n\t\t\t\t\"last\":  1,\n\t\t\t\t\"next\":  500,\n\t\t\t\t\"tank\":  0,\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.desc, func(t *testing.T) {\n\t\t\tvar itrs []Iterator\n\t\t\tfor i := range test.in {\n\t\t\t\titr, err := newTestIterator(test.in[i])\n\t\t\t\tif err != nil && err != ErrIteratorDone {\n\t\t\t\t\tt.Fatalf(\"error creating iterator: %v\", err)\n\t\t\t\t}\n\t\t\t\tif err == nil {\n\t\t\t\t\titrs = append(itrs, itr)\n\t\t\t\t}\n\t\t\t}\n\t\t\tmi, err := NewMergeIterator(itrs, test.merge)\n\t\t\tif err != nil && err != ErrIteratorDone {\n\t\t\t\tt.Fatalf(\"error creating iterator: %v\", err)\n\t\t\t}\n\t\t\tgot := make(map[string]uint64)\n\t\t\tfor err == nil {\n\t\t\t\tcurrk, currv := mi.Current()\n\t\t\t\terr = mi.Next()\n\t\t\t\tgot[string(currk)] = currv\n\t\t\t}\n\t\t\tif err != nil && err != ErrIteratorDone {\n\t\t\t\tt.Fatalf(\"error iterating: %v\", err)\n\t\t\t}\n\n\t\t\tif !reflect.DeepEqual(got, test.want) {\n\t\t\t\tt.Errorf(\"expected %v, got %v\", test.want, got)\n\t\t\t}\n\t\t})\n\t}\n}\n\ntype testIterator struct {\n\tvals map[int]uint64\n\tkeys []string\n\tcurr int\n}\n\nfunc newTestIterator(in map[string]uint64) (*testIterator, error) {\n\trv := &testIterator{\n\t\tvals: make(map[int]uint64, len(in)),\n\t}\n\tfor k := range in {\n\t\trv.keys = append(rv.keys, k)\n\t}\n\tsort.Strings(rv.keys)\n\tfor i, k := range rv.keys {\n\t\trv.vals[i] = in[k]\n\t}\n\treturn rv, nil\n}\n\nfunc (m *testIterator) Current() ([]byte, uint64) {\n\tif m.curr >= len(m.keys) {\n\t\treturn nil, 0\n\t}\n\treturn []byte(m.keys[m.curr]), m.vals[m.curr]\n}\n\nfunc (m *testIterator) Next() error {\n\tm.curr++\n\tif m.curr >= len(m.keys) {\n\t\treturn ErrIteratorDone\n\t}\n\treturn nil\n}\n\nfunc (m *testIterator) Seek(key []byte) error {\n\tm.curr = sort.SearchStrings(m.keys, string(key))\n\tif m.curr >= len(m.keys) {\n\t\treturn ErrIteratorDone\n\t}\n\treturn nil\n}\n\nfunc (m *testIterator) Reset(f *FST, startKeyInclusive, endKeyExclusive []byte, aut Automaton) error {\n\treturn nil\n}\n\nfunc (m *testIterator) Close() error {\n\treturn nil\n}\n\nfunc (m *testIterator) Exists(key []byte) (bool, error) {\n\treturn false, nil\n}\n\nfunc TestMergeFunc(t *testing.T) {\n\ttests := []struct {\n\t\tdesc  string\n\t\tin    []uint64\n\t\tmerge MergeFunc\n\t\twant  uint64\n\t}{\n\t\t{\n\t\t\tdesc:  \"min\",\n\t\t\tin:    []uint64{5, 99, 1},\n\t\t\tmerge: MergeMin,\n\t\t\twant:  1,\n\t\t},\n\t\t{\n\t\t\tdesc:  \"max\",\n\t\t\tin:    []uint64{5, 99, 1},\n\t\t\tmerge: MergeMax,\n\t\t\twant:  99,\n\t\t},\n\t\t{\n\t\t\tdesc:  \"sum\",\n\t\t\tin:    []uint64{5, 99, 1},\n\t\t\tmerge: MergeSum,\n\t\t\twant:  105,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.desc, func(t *testing.T) {\n\t\t\tgot := test.merge(test.in)\n\t\t\tif test.want != got {\n\t\t\t\tt.Errorf(\"expected %d, got %d\", test.want, got)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestEmptyMergeIterator(t *testing.T) {\n\tmi, err := NewMergeIterator([]Iterator{}, MergeMin)\n\tif err != ErrIteratorDone {\n\t\tt.Fatalf(\"expected iterator done, got %v\", err)\n\t}\n\n\t// should get valid merge iterator anyway\n\tif mi == nil {\n\t\tt.Fatalf(\"expected non-nil merge iterator\")\n\t}\n\n\t// current returns nil, 0 per interface spec\n\tck, cv := mi.Current()\n\tif ck != nil {\n\t\tt.Errorf(\"expected current to return nil key, got %v\", ck)\n\t}\n\tif cv != 0 {\n\t\tt.Errorf(\"expected current to return 0 val, got %d\", cv)\n\t}\n\n\t// calling Next/Seek continues to return ErrIteratorDone\n\terr = mi.Next()\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"expected iterator done, got %v\", err)\n\t}\n\terr = mi.Seek([]byte(\"anywhere\"))\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"expected iterator done, got %v\", err)\n\t}\n\n\terr = mi.Close()\n\tif err != nil {\n\t\tt.Errorf(\"error closing %v\", err)\n\t}\n\n}\n"
  },
  {
    "path": "pack.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nfunc deltaAddr(base, trans uint64) uint64 {\n\t// transition dest of 0 is special case\n\tif trans == 0 {\n\t\treturn 0\n\t}\n\treturn base - trans\n}\n\nconst packOutMask = 1<<4 - 1\n\nfunc encodePackSize(transSize, outSize int) byte {\n\tvar rv byte\n\trv = byte(transSize << 4)\n\trv |= byte(outSize)\n\treturn rv\n}\n\nfunc decodePackSize(pack byte) (transSize int, packSize int) {\n\ttransSize = int(pack >> 4)\n\tpackSize = int(pack & packOutMask)\n\treturn\n}\n\nconst maxNumTrans = 1<<6 - 1\n\nfunc encodeNumTrans(n int) byte {\n\tif n <= maxNumTrans {\n\t\treturn byte(n)\n\t}\n\treturn 0\n}\n\nfunc readPackedUint(data []byte) (rv uint64) {\n\tfor i := range data {\n\t\tshifted := uint64(data[i]) << uint(i*8)\n\t\trv |= shifted\n\t}\n\treturn\n}\n"
  },
  {
    "path": "pack_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\nfunc TestEncodeDecodePackSize(t *testing.T) {\n\n\tfor i := 0; i <= 8; i++ {\n\t\tfor j := 0; j <= 8; j++ {\n\t\t\tgot := encodePackSize(i, j)\n\t\t\tgoti, gotj := decodePackSize(got)\n\t\t\tif goti != i || gotj != j {\n\t\t\t\tt.Errorf(\"failed to round trip %d,%d packed as %b to %d,%d\", i, j, got, goti, gotj)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestEncodeNumTrans(t *testing.T) {\n\ttests := []struct {\n\t\tinput int\n\t\twant  byte\n\t}{\n\t\t{0, 0},\n\t\t{5, 5},\n\t\t{1<<6 - 1, 1<<6 - 1},\n\t\t{1 << 6, 0},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(fmt.Sprintf(\"input %d\", test.input), func(t *testing.T) {\n\t\t\tgot := encodeNumTrans(test.input)\n\t\t\tif got != test.want {\n\t\t\t\tt.Errorf(\"wanted: %d, got: %d\", test.want, got)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "regexp/compile.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage regexp\n\nimport (\n\t\"regexp/syntax\"\n\t\"unicode\"\n\n\tunicode_utf8 \"unicode/utf8\"\n\n\t\"github.com/couchbase/vellum/utf8\"\n)\n\ntype compiler struct {\n\tsizeLimit uint\n\tinsts     prog\n\tinstsPool []inst\n\n\tsequences  utf8.Sequences\n\trangeStack utf8.RangeStack\n\tstartBytes []byte\n\tendBytes   []byte\n}\n\nfunc newCompiler(sizeLimit uint) *compiler {\n\treturn &compiler{\n\t\tsizeLimit:  sizeLimit,\n\t\tstartBytes: make([]byte, unicode_utf8.UTFMax),\n\t\tendBytes:   make([]byte, unicode_utf8.UTFMax),\n\t}\n}\n\nfunc (c *compiler) compile(ast *syntax.Regexp) (prog, error) {\n\terr := c.c(ast)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tinst := c.allocInst()\n\tinst.op = OpMatch\n\tc.insts = append(c.insts, inst)\n\treturn c.insts, nil\n}\n\nfunc (c *compiler) c(ast *syntax.Regexp) (err error) {\n\tif ast.Flags&syntax.NonGreedy > 1 {\n\t\treturn ErrNoLazy\n\t}\n\n\tswitch ast.Op {\n\tcase syntax.OpEndLine, syntax.OpBeginLine,\n\t\tsyntax.OpBeginText, syntax.OpEndText:\n\t\treturn ErrNoEmpty\n\tcase syntax.OpWordBoundary, syntax.OpNoWordBoundary:\n\t\treturn ErrNoWordBoundary\n\tcase syntax.OpEmptyMatch:\n\t\treturn nil\n\tcase syntax.OpLiteral:\n\t\tfor _, r := range ast.Rune {\n\t\t\tif ast.Flags&syntax.FoldCase > 0 {\n\t\t\t\tnext := syntax.Regexp{\n\t\t\t\t\tOp:    syntax.OpCharClass,\n\t\t\t\t\tFlags: ast.Flags & syntax.FoldCase,\n\t\t\t\t\tRune0: [2]rune{r, r},\n\t\t\t\t}\n\t\t\t\tnext.Rune = next.Rune0[0:2]\n\t\t\t\t// try to find more folded runes\n\t\t\t\tfor r1 := unicode.SimpleFold(r); r1 != r; r1 = unicode.SimpleFold(r1) {\n\t\t\t\t\tnext.Rune = append(next.Rune, r1, r1)\n\t\t\t\t}\n\t\t\t\terr = c.c(&next)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tc.sequences, c.rangeStack, err = utf8.NewSequencesPrealloc(\n\t\t\t\t\tr, r, c.sequences, c.rangeStack, c.startBytes, c.endBytes)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tfor _, seq := range c.sequences {\n\t\t\t\t\tc.compileUtf8Ranges(seq)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tcase syntax.OpAnyChar:\n\t\tnext := syntax.Regexp{\n\t\t\tOp:    syntax.OpCharClass,\n\t\t\tFlags: ast.Flags & syntax.FoldCase,\n\t\t\tRune0: [2]rune{0, unicode.MaxRune},\n\t\t}\n\t\tnext.Rune = next.Rune0[:2]\n\t\treturn c.c(&next)\n\tcase syntax.OpAnyCharNotNL:\n\t\tnext := syntax.Regexp{\n\t\t\tOp:    syntax.OpCharClass,\n\t\t\tFlags: ast.Flags & syntax.FoldCase,\n\t\t\tRune:  []rune{0, 0x09, 0x0B, unicode.MaxRune},\n\t\t}\n\t\treturn c.c(&next)\n\tcase syntax.OpCharClass:\n\t\treturn c.compileClass(ast)\n\tcase syntax.OpCapture:\n\t\treturn c.c(ast.Sub[0])\n\tcase syntax.OpConcat:\n\t\tfor _, sub := range ast.Sub {\n\t\t\terr := c.c(sub)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\tcase syntax.OpAlternate:\n\t\tif len(ast.Sub) == 0 {\n\t\t\treturn nil\n\t\t}\n\t\tjmpsToEnd := make([]uint, 0, len(ast.Sub)-1)\n\t\t// does not handle last entry\n\t\tfor i := 0; i < len(ast.Sub)-1; i++ {\n\t\t\tsub := ast.Sub[i]\n\t\t\tsplit := c.emptySplit()\n\t\t\tj1 := c.top()\n\t\t\terr := c.c(sub)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tjmpsToEnd = append(jmpsToEnd, c.emptyJump())\n\t\t\tj2 := c.top()\n\t\t\tc.setSplit(split, j1, j2)\n\t\t}\n\t\t// handle last entry\n\t\terr := c.c(ast.Sub[len(ast.Sub)-1])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tend := uint(len(c.insts))\n\t\tfor _, jmpToEnd := range jmpsToEnd {\n\t\t\tc.setJump(jmpToEnd, end)\n\t\t}\n\tcase syntax.OpQuest:\n\t\tsplit := c.emptySplit()\n\t\tj1 := c.top()\n\t\terr := c.c(ast.Sub[0])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tj2 := c.top()\n\t\tc.setSplit(split, j1, j2)\n\n\tcase syntax.OpStar:\n\t\tj1 := c.top()\n\t\tsplit := c.emptySplit()\n\t\tj2 := c.top()\n\t\terr := c.c(ast.Sub[0])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tjmp := c.emptyJump()\n\t\tj3 := uint(len(c.insts))\n\n\t\tc.setJump(jmp, j1)\n\t\tc.setSplit(split, j2, j3)\n\n\tcase syntax.OpPlus:\n\t\tj1 := c.top()\n\t\terr := c.c(ast.Sub[0])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tsplit := c.emptySplit()\n\t\tj2 := c.top()\n\t\tc.setSplit(split, j1, j2)\n\n\tcase syntax.OpRepeat:\n\t\tif ast.Max == -1 {\n\t\t\tfor i := 0; i < ast.Min; i++ {\n\t\t\t\terr := c.c(ast.Sub[0])\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t\tnext := syntax.Regexp{\n\t\t\t\tOp:    syntax.OpStar,\n\t\t\t\tFlags: ast.Flags,\n\t\t\t\tSub:   ast.Sub,\n\t\t\t\tSub0:  ast.Sub0,\n\t\t\t\tRune:  ast.Rune,\n\t\t\t\tRune0: ast.Rune0,\n\t\t\t}\n\t\t\treturn c.c(&next)\n\t\t}\n\t\tfor i := 0; i < ast.Min; i++ {\n\t\t\terr := c.c(ast.Sub[0])\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tsplits := make([]uint, 0, ast.Max-ast.Min)\n\t\tstarts := make([]uint, 0, ast.Max-ast.Min)\n\t\tfor i := ast.Min; i < ast.Max; i++ {\n\t\t\tsplits = append(splits, c.emptySplit())\n\t\t\tstarts = append(starts, uint(len(c.insts)))\n\t\t\terr := c.c(ast.Sub[0])\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tend := uint(len(c.insts))\n\t\tfor i := 0; i < len(splits); i++ {\n\t\t\tc.setSplit(splits[i], starts[i], end)\n\t\t}\n\n\t}\n\n\treturn c.checkSize()\n}\n\nfunc (c *compiler) checkSize() error {\n\tif uint(len(c.insts)*instSize) > c.sizeLimit {\n\t\treturn ErrCompiledTooBig\n\t}\n\treturn nil\n}\n\nfunc (c *compiler) compileClass(ast *syntax.Regexp) error {\n\tif len(ast.Rune) == 0 {\n\t\treturn nil\n\t}\n\tjmps := make([]uint, 0, len(ast.Rune)-2)\n\t// does not do last pair\n\tfor i := 0; i < len(ast.Rune)-2; i += 2 {\n\t\trstart := ast.Rune[i]\n\t\trend := ast.Rune[i+1]\n\n\t\tsplit := c.emptySplit()\n\t\tj1 := c.top()\n\t\terr := c.compileClassRange(rstart, rend)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tjmps = append(jmps, c.emptyJump())\n\t\tj2 := c.top()\n\t\tc.setSplit(split, j1, j2)\n\t}\n\t// handle last pair\n\trstart := ast.Rune[len(ast.Rune)-2]\n\trend := ast.Rune[len(ast.Rune)-1]\n\terr := c.compileClassRange(rstart, rend)\n\tif err != nil {\n\t\treturn err\n\t}\n\tend := c.top()\n\tfor _, jmp := range jmps {\n\t\tc.setJump(jmp, end)\n\t}\n\treturn nil\n}\n\nfunc (c *compiler) compileClassRange(startR, endR rune) (err error) {\n\tc.sequences, c.rangeStack, err = utf8.NewSequencesPrealloc(\n\t\tstartR, endR, c.sequences, c.rangeStack, c.startBytes, c.endBytes)\n\tif err != nil {\n\t\treturn err\n\t}\n\tjmps := make([]uint, 0, len(c.sequences)-1)\n\t// does not do last entry\n\tfor i := 0; i < len(c.sequences)-1; i++ {\n\t\tseq := c.sequences[i]\n\t\tsplit := c.emptySplit()\n\t\tj1 := c.top()\n\t\tc.compileUtf8Ranges(seq)\n\t\tjmps = append(jmps, c.emptyJump())\n\t\tj2 := c.top()\n\t\tc.setSplit(split, j1, j2)\n\t}\n\t// handle last entry\n\tc.compileUtf8Ranges(c.sequences[len(c.sequences)-1])\n\tend := c.top()\n\tfor _, jmp := range jmps {\n\t\tc.setJump(jmp, end)\n\t}\n\n\treturn nil\n}\n\nfunc (c *compiler) compileUtf8Ranges(seq utf8.Sequence) {\n\tfor _, r := range seq {\n\t\tinst := c.allocInst()\n\t\tinst.op = OpRange\n\t\tinst.rangeStart = r.Start\n\t\tinst.rangeEnd = r.End\n\t\tc.insts = append(c.insts, inst)\n\t}\n}\n\nfunc (c *compiler) emptySplit() uint {\n\tinst := c.allocInst()\n\tinst.op = OpSplit\n\tc.insts = append(c.insts, inst)\n\treturn c.top() - 1\n}\n\nfunc (c *compiler) emptyJump() uint {\n\tinst := c.allocInst()\n\tinst.op = OpJmp\n\tc.insts = append(c.insts, inst)\n\treturn c.top() - 1\n}\n\nfunc (c *compiler) setSplit(i, pc1, pc2 uint) {\n\tsplit := c.insts[i]\n\tsplit.splitA = pc1\n\tsplit.splitB = pc2\n}\n\nfunc (c *compiler) setJump(i, pc uint) {\n\tjmp := c.insts[i]\n\tjmp.to = pc\n}\n\nfunc (c *compiler) top() uint {\n\treturn uint(len(c.insts))\n}\n\nfunc (c *compiler) allocInst() *inst {\n\tif len(c.instsPool) <= 0 {\n\t\tc.instsPool = make([]inst, 16)\n\t}\n\tinst := &c.instsPool[0]\n\tc.instsPool = c.instsPool[1:]\n\treturn inst\n}\n"
  },
  {
    "path": "regexp/compile_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage regexp\n\nimport (\n\t\"reflect\"\n\t\"regexp/syntax\"\n\t\"testing\"\n)\n\nfunc TestCompiler(t *testing.T) {\n\n\ttests := []struct {\n\t\tquery     string\n\t\twantInsts prog\n\t\twantErr   error\n\t}{\n\t\t{\n\t\t\tquery: \"\",\n\t\t\twantInsts: []*inst{\n\t\t\t\t{op: OpMatch},\n\t\t\t},\n\t\t\twantErr: nil,\n\t\t},\n\t\t{\n\t\t\tquery:   \"^\",\n\t\t\twantErr: ErrNoEmpty,\n\t\t},\n\t\t{\n\t\t\tquery:   `\\b`,\n\t\t\twantErr: ErrNoWordBoundary,\n\t\t},\n\t\t{\n\t\t\tquery:   `.*?`,\n\t\t\twantErr: ErrNoLazy,\n\t\t},\n\t\t{\n\t\t\tquery: `a`,\n\t\t\twantInsts: []*inst{\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpMatch},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tquery: `[a-c]`,\n\t\t\twantInsts: []*inst{\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'c'},\n\t\t\t\t{op: OpMatch},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tquery: `(a)`,\n\t\t\twantInsts: []*inst{\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpMatch},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tquery: `a?`,\n\t\t\twantInsts: []*inst{\n\t\t\t\t{op: OpSplit, splitA: 1, splitB: 2},\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpMatch},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tquery: `a*`,\n\t\t\twantInsts: []*inst{\n\t\t\t\t{op: OpSplit, splitA: 1, splitB: 3},\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpJmp, to: 0},\n\t\t\t\t{op: OpMatch},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tquery: `a+`,\n\t\t\twantInsts: []*inst{\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpSplit, splitA: 0, splitB: 2},\n\t\t\t\t{op: OpMatch},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tquery: `a{2,4}`,\n\t\t\twantInsts: []*inst{\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpSplit, splitA: 3, splitB: 6},\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpSplit, splitA: 5, splitB: 6},\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpMatch},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tquery: `a{3,}`,\n\t\t\twantInsts: []*inst{\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpSplit, splitA: 4, splitB: 6},\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpJmp, to: 3},\n\t\t\t\t{op: OpMatch},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tquery: `a+|b+`,\n\t\t\twantInsts: []*inst{\n\t\t\t\t{op: OpSplit, splitA: 1, splitB: 4},\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpSplit, splitA: 1, splitB: 3},\n\t\t\t\t{op: OpJmp, to: 6},\n\t\t\t\t{op: OpRange, rangeStart: 'b', rangeEnd: 'b'},\n\t\t\t\t{op: OpSplit, splitA: 4, splitB: 6},\n\t\t\t\t{op: OpMatch},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tquery: `a+b+`,\n\t\t\twantInsts: []*inst{\n\t\t\t\t{op: OpRange, rangeStart: 'a', rangeEnd: 'a'},\n\t\t\t\t{op: OpSplit, splitA: 0, splitB: 2},\n\t\t\t\t{op: OpRange, rangeStart: 'b', rangeEnd: 'b'},\n\t\t\t\t{op: OpSplit, splitA: 2, splitB: 4},\n\t\t\t\t{op: OpMatch},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tquery: `.`,\n\t\t\twantInsts: []*inst{\n\t\t\t\t{op: OpSplit, splitA: 1, splitB: 3},\n\t\t\t\t{op: OpRange, rangeStart: 0, rangeEnd: 0x09},\n\t\t\t\t{op: OpJmp, to: 46}, // match ascii, less than 0x0a\n\t\t\t\t{op: OpSplit, splitA: 4, splitB: 6},\n\t\t\t\t{op: OpRange, rangeStart: 0x0b, rangeEnd: 0x7f},\n\t\t\t\t{op: OpJmp, to: 46}, // match rest ascii\n\t\t\t\t{op: OpSplit, splitA: 7, splitB: 10},\n\t\t\t\t{op: OpRange, rangeStart: 0xc2, rangeEnd: 0xdf},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpJmp, to: 46}, // match\n\t\t\t\t{op: OpSplit, splitA: 11, splitB: 15},\n\t\t\t\t{op: OpRange, rangeStart: 0xe0, rangeEnd: 0xe0},\n\t\t\t\t{op: OpRange, rangeStart: 0xa0, rangeEnd: 0xbf},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpJmp, to: 46}, // match\n\t\t\t\t{op: OpSplit, splitA: 16, splitB: 20},\n\t\t\t\t{op: OpRange, rangeStart: 0xe1, rangeEnd: 0xec},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpJmp, to: 46}, // match\n\t\t\t\t{op: OpSplit, splitA: 21, splitB: 25},\n\t\t\t\t{op: OpRange, rangeStart: 0xed, rangeEnd: 0xed},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0x9f},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpJmp, to: 46}, // match\n\t\t\t\t{op: OpSplit, splitA: 26, splitB: 30},\n\t\t\t\t{op: OpRange, rangeStart: 0xee, rangeEnd: 0xef},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpJmp, to: 46}, // match\n\t\t\t\t{op: OpSplit, splitA: 31, splitB: 36},\n\t\t\t\t{op: OpRange, rangeStart: 0xf0, rangeEnd: 0xf0},\n\t\t\t\t{op: OpRange, rangeStart: 0x90, rangeEnd: 0xbf},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpJmp, to: 46}, // match\n\t\t\t\t{op: OpSplit, splitA: 37, splitB: 42},\n\t\t\t\t{op: OpRange, rangeStart: 0xf1, rangeEnd: 0xf3},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpJmp, to: 46}, // match\n\t\t\t\t{op: OpRange, rangeStart: 0xf4, rangeEnd: 0xf4},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0x8f},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpRange, rangeStart: 0x80, rangeEnd: 0xbf},\n\t\t\t\t{op: OpMatch},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.query, func(t *testing.T) {\n\t\t\tp, err := syntax.Parse(test.query, syntax.Perl)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"error parsing regexp: %v\", err)\n\t\t\t}\n\t\t\tc := newCompiler(10000)\n\t\t\tgotInsts, gotErr := c.compile(p)\n\t\t\tif !reflect.DeepEqual(test.wantErr, gotErr) {\n\t\t\t\tt.Errorf(\"expected error: %v, got error: %v\", test.wantErr, gotErr)\n\t\t\t}\n\t\t\tif !reflect.DeepEqual(test.wantInsts, gotInsts) {\n\t\t\t\tt.Errorf(\"expected insts: %v, got insts:%v\", test.wantInsts, gotInsts)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "regexp/dfa.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage regexp\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n)\n\n// StateLimit is the maximum number of states allowed\nconst StateLimit = 10000\n\n// ErrTooManyStates is returned if you attempt to build a Levenshtein\n// automaton which requires too many states.\nvar ErrTooManyStates = fmt.Errorf(\"dfa contains more than %d states\",\n\tStateLimit)\n\ntype dfaBuilder struct {\n\tdfa    *dfa\n\tcache  map[string]int\n\tkeyBuf []byte\n}\n\nfunc newDfaBuilder(insts prog) *dfaBuilder {\n\td := &dfaBuilder{\n\t\tdfa: &dfa{\n\t\t\tinsts:  insts,\n\t\t\tstates: make([]state, 0, 16),\n\t\t},\n\t\tcache: make(map[string]int, 1024),\n\t}\n\t// add 0 state that is invalid\n\td.dfa.states = append(d.dfa.states, state{\n\t\tnext:  make([]int, 256),\n\t\tmatch: false,\n\t})\n\treturn d\n}\n\nfunc (d *dfaBuilder) build() (*dfa, error) {\n\tcur := newSparseSet(uint(len(d.dfa.insts)))\n\tnext := newSparseSet(uint(len(d.dfa.insts)))\n\n\td.dfa.add(cur, 0)\n\tns, instsReuse := d.cachedState(cur, nil)\n\tstates := intStack{ns}\n\tseen := make(map[int]struct{})\n\tvar s int\n\tstates, s = states.Pop()\n\tfor s != 0 {\n\t\tfor b := 0; b < 256; b++ {\n\t\t\tvar ns int\n\t\t\tns, instsReuse = d.runState(cur, next, s, byte(b), instsReuse)\n\t\t\tif ns != 0 {\n\t\t\t\tif _, ok := seen[ns]; !ok {\n\t\t\t\t\tseen[ns] = struct{}{}\n\t\t\t\t\tstates = states.Push(ns)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(d.dfa.states) > StateLimit {\n\t\t\t\treturn nil, ErrTooManyStates\n\t\t\t}\n\t\t}\n\t\tstates, s = states.Pop()\n\t}\n\treturn d.dfa, nil\n}\n\nfunc (d *dfaBuilder) runState(cur, next *sparseSet, state int, b byte, instsReuse []uint) (\n\tint, []uint) {\n\tcur.Clear()\n\tfor _, ip := range d.dfa.states[state].insts {\n\t\tcur.Add(ip)\n\t}\n\td.dfa.run(cur, next, b)\n\tvar nextState int\n\tnextState, instsReuse = d.cachedState(next, instsReuse)\n\td.dfa.states[state].next[b] = nextState\n\treturn nextState, instsReuse\n}\n\nfunc instsKey(insts []uint, buf []byte) []byte {\n\tif cap(buf) < 8*len(insts) {\n\t\tbuf = make([]byte, 8*len(insts))\n\t} else {\n\t\tbuf = buf[0 : 8*len(insts)]\n\t}\n\tfor i, inst := range insts {\n\t\tbinary.LittleEndian.PutUint64(buf[i*8:], uint64(inst))\n\t}\n\treturn buf\n}\n\nfunc (d *dfaBuilder) cachedState(set *sparseSet,\n\tinstsReuse []uint) (int, []uint) {\n\tinsts := instsReuse[:0]\n\tif cap(insts) == 0 {\n\t\tinsts = make([]uint, 0, set.Len())\n\t}\n\tvar isMatch bool\n\tfor i := uint(0); i < uint(set.Len()); i++ {\n\t\tip := set.Get(i)\n\t\tswitch d.dfa.insts[ip].op {\n\t\tcase OpRange:\n\t\t\tinsts = append(insts, ip)\n\t\tcase OpMatch:\n\t\t\tisMatch = true\n\t\t\tinsts = append(insts, ip)\n\t\t}\n\t}\n\tif len(insts) == 0 {\n\t\treturn 0, insts\n\t}\n\td.keyBuf = instsKey(insts, d.keyBuf)\n\tv, ok := d.cache[string(d.keyBuf)]\n\tif ok {\n\t\treturn v, insts\n\t}\n\td.dfa.states = append(d.dfa.states, state{\n\t\tinsts: insts,\n\t\tnext:  make([]int, 256),\n\t\tmatch: isMatch,\n\t})\n\tnewV := len(d.dfa.states) - 1\n\td.cache[string(d.keyBuf)] = newV\n\treturn newV, nil\n}\n\ntype dfa struct {\n\tinsts  prog\n\tstates []state\n}\n\nfunc (d *dfa) add(set *sparseSet, ip uint) {\n\tif set.Contains(ip) {\n\t\treturn\n\t}\n\tset.Add(ip)\n\tswitch d.insts[ip].op {\n\tcase OpJmp:\n\t\td.add(set, d.insts[ip].to)\n\tcase OpSplit:\n\t\td.add(set, d.insts[ip].splitA)\n\t\td.add(set, d.insts[ip].splitB)\n\t}\n}\n\nfunc (d *dfa) run(from, to *sparseSet, b byte) bool {\n\tto.Clear()\n\tvar isMatch bool\n\tfor i := uint(0); i < uint(from.Len()); i++ {\n\t\tip := from.Get(i)\n\t\tswitch d.insts[ip].op {\n\t\tcase OpMatch:\n\t\t\tisMatch = true\n\t\tcase OpRange:\n\t\t\tif d.insts[ip].rangeStart <= b &&\n\t\t\t\tb <= d.insts[ip].rangeEnd {\n\t\t\t\td.add(to, ip+1)\n\t\t\t}\n\t\t}\n\t}\n\treturn isMatch\n}\n\ntype state struct {\n\tinsts []uint\n\tnext  []int\n\tmatch bool\n}\n\ntype intStack []int\n\nfunc (s intStack) Push(v int) intStack {\n\treturn append(s, v)\n}\n\nfunc (s intStack) Pop() (intStack, int) {\n\tl := len(s)\n\tif l < 1 {\n\t\treturn s, 0\n\t}\n\treturn s[:l-1], s[l-1]\n}\n"
  },
  {
    "path": "regexp/inst.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage regexp\n\nimport \"fmt\"\n\n// instOp represents a instruction operation\ntype instOp int\n\n// the enumeration of operations\nconst (\n\tOpMatch instOp = iota\n\tOpJmp\n\tOpSplit\n\tOpRange\n)\n\n// instSize is the approximate size of the an inst struct in bytes\nconst instSize = 40\n\ntype inst struct {\n\top         instOp\n\tto         uint\n\tsplitA     uint\n\tsplitB     uint\n\trangeStart byte\n\trangeEnd   byte\n}\n\nfunc (i *inst) String() string {\n\tswitch i.op {\n\tcase OpJmp:\n\t\treturn fmt.Sprintf(\"JMP: %d\", i.to)\n\tcase OpSplit:\n\t\treturn fmt.Sprintf(\"SPLIT: %d - %d\", i.splitA, i.splitB)\n\tcase OpRange:\n\t\treturn fmt.Sprintf(\"RANGE: %x - %x\", i.rangeStart, i.rangeEnd)\n\t}\n\treturn \"MATCH\"\n}\n\ntype prog []*inst\n\nfunc (p prog) String() string {\n\trv := \"\\n\"\n\tfor i, pi := range p {\n\t\trv += fmt.Sprintf(\"%d %v\\n\", i, pi)\n\t}\n\treturn rv\n}\n"
  },
  {
    "path": "regexp/regexp.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage regexp\n\nimport (\n\t\"fmt\"\n\t\"regexp/syntax\"\n)\n\n// ErrNoEmpty returned when \"zero width assertions\" are used\nvar ErrNoEmpty = fmt.Errorf(\"zero width assertions not allowed\")\n\n// ErrNoWordBoundary returned when word boundaries are used\nvar ErrNoWordBoundary = fmt.Errorf(\"word boundaries are not allowed\")\n\n// ErrNoBytes returned when byte literals are used\nvar ErrNoBytes = fmt.Errorf(\"byte literals are not allowed\")\n\n// ErrNoLazy returned when lazy quantifiers are used\nvar ErrNoLazy = fmt.Errorf(\"lazy quantifiers are not allowed\")\n\n// ErrCompiledTooBig returned when regular expression parses into\n// too many instructions\nvar ErrCompiledTooBig = fmt.Errorf(\"too many instructions\")\n\nvar DefaultLimit = uint(10 * (1 << 20))\n\n// Regexp implements the vellum.Automaton interface for matcing a user\n// specified regular expression.\ntype Regexp struct {\n\torig string\n\tdfa  *dfa\n}\n\n// NewRegexp creates a new Regular Expression automaton with the specified\n// expression.  By default it is limited to approximately 10MB for the\n// compiled finite state automaton.  If this size is exceeded,\n// ErrCompiledTooBig will be returned.\nfunc New(expr string) (*Regexp, error) {\n\treturn NewWithLimit(expr, DefaultLimit)\n}\n\n// NewRegexpWithLimit creates a new Regular Expression automaton with\n// the specified expression.  The size of the compiled finite state\n// automaton exceeds the user specified size,  ErrCompiledTooBig will be\n// returned.\nfunc NewWithLimit(expr string, size uint) (*Regexp, error) {\n\tparsed, err := syntax.Parse(expr, syntax.Perl)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn NewParsedWithLimit(expr, parsed, size)\n}\n\nfunc NewParsedWithLimit(expr string, parsed *syntax.Regexp, size uint) (*Regexp, error) {\n\tcompiler := newCompiler(size)\n\tinsts, err := compiler.compile(parsed)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdfaBuilder := newDfaBuilder(insts)\n\tdfa, err := dfaBuilder.build()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &Regexp{\n\t\torig: expr,\n\t\tdfa:  dfa,\n\t}, nil\n}\n\n// Start returns the start state of this automaton.\nfunc (r *Regexp) Start() int {\n\treturn 1\n}\n\n// IsMatch returns if the specified state is a matching state.\nfunc (r *Regexp) IsMatch(s int) bool {\n\tif s < len(r.dfa.states) {\n\t\treturn r.dfa.states[s].match\n\t}\n\treturn false\n}\n\n// CanMatch returns if the specified state can ever transition to a matching\n// state.\nfunc (r *Regexp) CanMatch(s int) bool {\n\tif s < len(r.dfa.states) && s > 0 {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// WillAlwaysMatch returns if the specified state will always end in a\n// matching state.\nfunc (r *Regexp) WillAlwaysMatch(int) bool {\n\treturn false\n}\n\n// Accept returns the new state, resulting from the transition byte b\n// when currently in the state s.\nfunc (r *Regexp) Accept(s int, b byte) int {\n\tif s < len(r.dfa.states) {\n\t\treturn r.dfa.states[s].next[b]\n\t}\n\treturn 0\n}\n"
  },
  {
    "path": "regexp/regexp_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage regexp\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\nfunc TestRegexp(t *testing.T) {\n\ttests := []struct {\n\t\tquery    string\n\t\tseq      []byte\n\t\tisMatch  bool\n\t\tcanMatch bool\n\t}{\n\t\t{\n\t\t\tquery:    ``,\n\t\t\tseq:      []byte{},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t// test simple literal\n\t\t{\n\t\t\tquery:    `a`,\n\t\t\tseq:      []byte{'a'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `a`,\n\t\t\tseq:      []byte{},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `a`,\n\t\t\tseq:      []byte{'a', 'b'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t// test actual pattern\n\t\t{\n\t\t\tquery:    `wat.r`,\n\t\t\tseq:      []byte{'x'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t{\n\t\t\tquery:    `wat.r`,\n\t\t\tseq:      []byte{'w', 'a', 't'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `wat.r`,\n\t\t\tseq:      []byte{'w', 'a', 't', 'e'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `wat.r`,\n\t\t\tseq:      []byte{'w', 'a', 't', 'e', 'r'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `wat.r`,\n\t\t\tseq:      []byte{'w', 'a', 't', 'e', 'r', 's'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t// test alternation\n\t\t{\n\t\t\tquery:    `a+|b+`,\n\t\t\tseq:      []byte{},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `a+|b+`,\n\t\t\tseq:      []byte{'a'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `a+|b+`,\n\t\t\tseq:      []byte{'b'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `a+|b+`,\n\t\t\tseq:      []byte{'a', 'a'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `a+|b+`,\n\t\t\tseq:      []byte{'b', 'b'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `a+|b+`,\n\t\t\tseq:      []byte{'a', 'b'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t{\n\t\t\tquery:    `a+|b+`,\n\t\t\tseq:      []byte{'b', 'a'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t// test others\n\t\t{\n\t\t\tquery:    `[a-z]?[1-9]*`,\n\t\t\tseq:      []byte{},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `[a-z]?[1-9]*`,\n\t\t\tseq:      []byte{'a'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `[a-z]?[1-9]*`,\n\t\t\tseq:      []byte{'a', '1'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `[a-z]?[1-9]*`,\n\t\t\tseq:      []byte{'a', '1', '2'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `[a-z]?[1-9]*`,\n\t\t\tseq:      []byte{'a', '1', '2', 'z'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t{\n\t\t\tquery:    `[a-z]?[1-9]*`,\n\t\t\tseq:      []byte{'a', 'b'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t// basic case insensitive match literals\n\t\t{\n\t\t\tquery:    `(?i)mArTy`,\n\t\t\tseq:      []byte{'m', 'a', 'r', 't', 'y'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `(?i)marty`,\n\t\t\tseq:      []byte{'m', 'A', 'r', 'T', 'y'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t// case insensitive character class\n\t\t{\n\t\t\tquery:    `(?i)[d-f]*`,\n\t\t\tseq:      []byte{'D', 'e', 'e', 'F'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t// case insensitive, with case sensitive pattern in the middle\n\t\t{\n\t\t\tquery:    `(?i)[d-f]*(?-i:m)wow`,\n\t\t\tseq:      []byte{'D', 'e', 'e', 'F', 'm', 'W', 'o', 'W'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t// (?i)caseless(?-i)cased\n\t\t{\n\t\t\tquery:    `(?i)[d-f]*(?-i)wOw`,\n\t\t\tseq:      []byte{'D', 'e', 'e', 'F', 'w', 'O', 'w'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t// from: https://docs.rs/crate/regex-syntax/0.2.4/source/src/lib.rs\n\t\t// `(?i)[^x]` really should match any character sans `x` and `X`, but if `[^x]` is negated\n\t\t// before being case folded, you'll end up matching any character.\n\t\t{\n\t\t\tquery:    `(?i)[^x]`,\n\t\t\tseq:      []byte{'a'},\n\t\t\tisMatch:  true,\n\t\t\tcanMatch: true,\n\t\t},\n\t\t{\n\t\t\tquery:    `(?i)[^x]`,\n\t\t\tseq:      []byte{'x'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t\t{\n\t\t\tquery:    `(?i)[^x]`,\n\t\t\tseq:      []byte{'X'},\n\t\t\tisMatch:  false,\n\t\t\tcanMatch: false,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(fmt.Sprintf(\"%s - %v\", test.query, test.seq), func(t *testing.T) {\n\t\t\tr, err := New(test.query)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\ts := r.Start()\n\t\t\tfor _, b := range test.seq {\n\t\t\t\ts = r.Accept(s, b)\n\t\t\t}\n\n\t\t\tisMatch := r.IsMatch(s)\n\t\t\tif isMatch != test.isMatch {\n\t\t\t\tt.Errorf(\"expected isMatch %t, got %t\", test.isMatch, isMatch)\n\t\t\t}\n\n\t\t\tcanMatch := r.CanMatch(s)\n\t\t\tif canMatch != test.canMatch {\n\t\t\t\tt.Errorf(\"expectec canMatch %t, got %t\", test.canMatch, canMatch)\n\t\t\t}\n\t\t})\n\t}\n\n}\n\nfunc BenchmarkNewWildcard(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\tNew(\"my.*h\")\n\t}\n}\n"
  },
  {
    "path": "regexp/sparse.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage regexp\n\ntype sparseSet struct {\n\tdense  []uint\n\tsparse []uint\n\tsize   uint\n}\n\nfunc newSparseSet(size uint) *sparseSet {\n\treturn &sparseSet{\n\t\tdense:  make([]uint, size),\n\t\tsparse: make([]uint, size),\n\t\tsize:   0,\n\t}\n}\n\nfunc (s *sparseSet) Len() int {\n\treturn int(s.size)\n}\n\nfunc (s *sparseSet) Add(ip uint) uint {\n\ti := s.size\n\ts.dense[i] = ip\n\ts.sparse[ip] = i\n\ts.size++\n\treturn i\n}\n\nfunc (s *sparseSet) Get(i uint) uint {\n\treturn s.dense[i]\n}\n\nfunc (s *sparseSet) Contains(ip uint) bool {\n\ti := s.sparse[ip]\n\treturn i < s.size && s.dense[i] == ip\n}\n\nfunc (s *sparseSet) Clear() {\n\ts.size = 0\n}\n"
  },
  {
    "path": "regexp/sparse_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage regexp\n\nimport \"testing\"\n\nfunc TestSparse(t *testing.T) {\n\n\ts := newSparseSet(10)\n\tif s.Contains(0) {\n\t\tt.Errorf(\"expected not to contain 0\")\n\t}\n\n\ts.Add(3)\n\tif !s.Contains(3) {\n\t\tt.Errorf(\"expected to contains 3, did not\")\n\t}\n\n\tif s.Len() != 1 {\n\t\tt.Errorf(\"expected len 1, got %d\", s.Len())\n\t}\n\n\tif s.Get(0) != 3 {\n\t\tt.Errorf(\"expected 10, got %d\", s.Get(0))\n\t}\n\n\ts.Clear()\n\n\tif s.Len() != 0 {\n\t\tt.Errorf(\"expected len 0, got %d\", s.Len())\n\t}\n}\n"
  },
  {
    "path": "registry.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\ntype registryCell struct {\n\taddr int\n\tnode *builderNode\n}\n\ntype registry struct {\n\tbuilderNodePool *builderNodePool\n\ttable           []registryCell\n\ttableSize       uint\n\tmruSize         uint\n}\n\nfunc newRegistry(p *builderNodePool, tableSize, mruSize int) *registry {\n\tnsize := tableSize * mruSize\n\trv := &registry{\n\t\tbuilderNodePool: p,\n\t\ttable:           make([]registryCell, nsize),\n\t\ttableSize:       uint(tableSize),\n\t\tmruSize:         uint(mruSize),\n\t}\n\treturn rv\n}\n\nfunc (r *registry) Reset() {\n\tvar empty registryCell\n\tfor i := range r.table {\n\t\tr.builderNodePool.Put(r.table[i].node)\n\t\tr.table[i] = empty\n\t}\n}\n\nfunc (r *registry) entry(node *builderNode) (bool, int, *registryCell) {\n\tif len(r.table) == 0 {\n\t\treturn false, 0, nil\n\t}\n\tbucket := r.hash(node)\n\tstart := r.mruSize * uint(bucket)\n\tend := start + r.mruSize\n\trc := registryCache(r.table[start:end])\n\treturn rc.entry(node, r.builderNodePool)\n}\n\nconst fnvPrime = 1099511628211\n\nfunc (r *registry) hash(b *builderNode) int {\n\tvar final uint64\n\tif b.final {\n\t\tfinal = 1\n\t}\n\n\tvar h uint64 = 14695981039346656037\n\th = (h ^ final) * fnvPrime\n\th = (h ^ b.finalOutput) * fnvPrime\n\tfor _, t := range b.trans {\n\t\th = (h ^ uint64(t.in)) * fnvPrime\n\t\th = (h ^ t.out) * fnvPrime\n\t\th = (h ^ uint64(t.addr)) * fnvPrime\n\t}\n\treturn int(h % uint64(r.tableSize))\n}\n\ntype registryCache []registryCell\n\nfunc (r registryCache) entry(node *builderNode, pool *builderNodePool) (bool, int, *registryCell) {\n\tif len(r) == 1 {\n\t\tif r[0].node != nil && r[0].node.equiv(node) {\n\t\t\treturn true, r[0].addr, nil\n\t\t}\n\t\tpool.Put(r[0].node)\n\t\tr[0].node = node\n\t\treturn false, 0, &r[0]\n\t}\n\tfor i := range r {\n\t\tif r[i].node != nil && r[i].node.equiv(node) {\n\t\t\taddr := r[i].addr\n\t\t\tr.promote(i)\n\t\t\treturn true, addr, nil\n\t\t}\n\t}\n\t// no match\n\tlast := len(r) - 1\n\tpool.Put(r[last].node)\n\tr[last].node = node // discard LRU\n\tr.promote(last)\n\treturn false, 0, &r[0]\n\n}\n\nfunc (r registryCache) promote(i int) {\n\tfor i > 0 {\n\t\tr.swap(i-1, i)\n\t\ti--\n\t}\n}\n\nfunc (r registryCache) swap(i, j int) {\n\tr[i], r[j] = r[j], r[i]\n}\n"
  },
  {
    "path": "registry_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport \"testing\"\n\n// FIXME add tests for MRU\n\nfunc TestRegistry(t *testing.T) {\n\tp := &builderNodePool{}\n\tr := newRegistry(p, 10, 1)\n\n\tn1 := &builderNode{\n\t\ttrans: []transition{\n\t\t\t{\n\t\t\t\tin:   'a',\n\t\t\t\taddr: 1,\n\t\t\t},\n\t\t\t{\n\t\t\t\tin:   'b',\n\t\t\t\taddr: 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tin:   'c',\n\t\t\t\taddr: 3,\n\t\t\t},\n\t\t},\n\t}\n\n\t// first look, doesn't exist\n\tfound, _, cell := r.entry(n1)\n\tif found {\n\t\tt.Errorf(\"expected empty registry to not have equivalent\")\n\t}\n\n\tcell.addr = 276\n\n\t// second look, does\n\tvar nowAddr int\n\tfound, nowAddr, _ = r.entry(n1)\n\tif !found {\n\t\tt.Errorf(\"expected to find equivalent after registering it\")\n\t}\n\tif nowAddr != 276 {\n\t\tt.Errorf(\"expected to get addr 276, got %d\", nowAddr)\n\t}\n}\n"
  },
  {
    "path": "transducer.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\n// Transducer represents the general contract of a byte-based finite transducer\ntype Transducer interface {\n\n\t// all transducers are also automatons\n\tAutomaton\n\n\t// IsMatchWithValue returns true if and only if the state is a match\n\t// additionally it returns a states final value (if any)\n\tIsMatchWithVal(int) (bool, uint64)\n\n\t// Accept returns the next state given the input to the specified state\n\t// additionally it returns the value associated with the transition\n\tAcceptWithVal(int, byte) (int, uint64)\n}\n\n// TransducerGet implements an generic Get() method which works\n// on any implementation of Transducer\n// The caller MUST check the boolean return value for a match.\n// Zero is a valid value regardless of match status,\n// and if it is NOT a match, the value collected so far is returned.\nfunc TransducerGet(t Transducer, k []byte) (bool, uint64) {\n\tvar total uint64\n\ti := 0\n\tcurr := t.Start()\n\tfor t.CanMatch(curr) && i < len(k) {\n\t\tvar transVal uint64\n\t\tcurr, transVal = t.AcceptWithVal(curr, k[i])\n\t\tif curr == noneAddr {\n\t\t\tbreak\n\t\t}\n\t\ttotal += transVal\n\t\ti++\n\t}\n\tif i != len(k) {\n\t\treturn false, total\n\t}\n\tmatch, finalVal := t.IsMatchWithVal(curr)\n\treturn match, total + finalVal\n}\n"
  },
  {
    "path": "utf8/utf8.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage utf8\n\nimport (\n\t\"fmt\"\n\t\"unicode/utf8\"\n)\n\n// Sequences is a collection of Sequence\ntype Sequences []Sequence\n\n// NewSequences constructs a collection of Sequence which describe the\n// byte ranges covered between the start and end runes.\nfunc NewSequences(start, end rune) (Sequences, error) {\n\trv, _, err := NewSequencesPrealloc(start, end, nil, nil, nil, nil)\n\treturn rv, err\n}\n\nfunc NewSequencesPrealloc(start, end rune,\n\tpreallocSequences Sequences,\n\tpreallocRangeStack RangeStack,\n\tpreallocStartBytes, preallocEndBytes []byte) (Sequences, RangeStack, error) {\n\trv := preallocSequences[:0]\n\n\tstartBytes := preallocStartBytes\n\tif cap(startBytes) < utf8.UTFMax {\n\t\tstartBytes = make([]byte, utf8.UTFMax)\n\t}\n\tstartBytes = startBytes[:utf8.UTFMax]\n\n\tendBytes := preallocEndBytes\n\tif cap(endBytes) < utf8.UTFMax {\n\t\tendBytes = make([]byte, utf8.UTFMax)\n\t}\n\tendBytes = endBytes[:utf8.UTFMax]\n\n\trangeStack := preallocRangeStack[:0]\n\trangeStack = rangeStack.Push(scalarRange{start, end})\n\n\trangeStack, r := rangeStack.Pop()\nTOP:\n\tfor r != nilScalarRange {\n\tINNER:\n\t\tfor {\n\t\t\tr1, r2 := r.split()\n\t\t\tif r1 != nilScalarRange {\n\t\t\t\trangeStack = rangeStack.Push(scalarRange{r2.start, r2.end})\n\t\t\t\tr.start = r1.start\n\t\t\t\tr.end = r1.end\n\t\t\t\tcontinue INNER\n\t\t\t}\n\t\t\tif !r.valid() {\n\t\t\t\trangeStack, r = rangeStack.Pop()\n\t\t\t\tcontinue TOP\n\t\t\t}\n\t\t\tfor i := 1; i < utf8.UTFMax; i++ {\n\t\t\t\tmax := maxScalarValue(i)\n\t\t\t\tif r.start <= max && max < r.end {\n\t\t\t\t\trangeStack = rangeStack.Push(scalarRange{max + 1, r.end})\n\t\t\t\t\tr.end = max\n\t\t\t\t\tcontinue INNER\n\t\t\t\t}\n\t\t\t}\n\t\t\tasciiRange := r.ascii()\n\t\t\tif asciiRange != nilRange {\n\t\t\t\trv = append(rv, Sequence{\n\t\t\t\t\tasciiRange,\n\t\t\t\t})\n\t\t\t\trangeStack, r = rangeStack.Pop()\n\t\t\t\tcontinue TOP\n\t\t\t}\n\t\t\tfor i := uint(1); i < utf8.UTFMax; i++ {\n\t\t\t\tm := rune((1 << (6 * i)) - 1)\n\t\t\t\tif (r.start & ^m) != (r.end & ^m) {\n\t\t\t\t\tif (r.start & m) != 0 {\n\t\t\t\t\t\trangeStack = rangeStack.Push(scalarRange{(r.start | m) + 1, r.end})\n\t\t\t\t\t\tr.end = r.start | m\n\t\t\t\t\t\tcontinue INNER\n\t\t\t\t\t}\n\t\t\t\t\tif (r.end & m) != m {\n\t\t\t\t\t\trangeStack = rangeStack.Push(scalarRange{r.end & ^m, r.end})\n\t\t\t\t\t\tr.end = (r.end & ^m) - 1\n\t\t\t\t\t\tcontinue INNER\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tn, m := r.encode(startBytes, endBytes)\n\t\t\tseq, err := SequenceFromEncodedRange(startBytes[0:n], endBytes[0:m])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\trv = append(rv, seq)\n\t\t\trangeStack, r = rangeStack.Pop()\n\t\t\tcontinue TOP\n\t\t}\n\t}\n\n\treturn rv, rangeStack, nil\n}\n\n// Sequence is a collection of Range\ntype Sequence []Range\n\n// SequenceFromEncodedRange creates sequence from the encoded bytes\nfunc SequenceFromEncodedRange(start, end []byte) (Sequence, error) {\n\tif len(start) != len(end) {\n\t\treturn nil, fmt.Errorf(\"byte slices must be the same length\")\n\t}\n\tswitch len(start) {\n\tcase 2:\n\t\treturn Sequence{\n\t\t\tRange{start[0], end[0]},\n\t\t\tRange{start[1], end[1]},\n\t\t}, nil\n\tcase 3:\n\t\treturn Sequence{\n\t\t\tRange{start[0], end[0]},\n\t\t\tRange{start[1], end[1]},\n\t\t\tRange{start[2], end[2]},\n\t\t}, nil\n\tcase 4:\n\t\treturn Sequence{\n\t\t\tRange{start[0], end[0]},\n\t\t\tRange{start[1], end[1]},\n\t\t\tRange{start[2], end[2]},\n\t\t\tRange{start[3], end[3]},\n\t\t}, nil\n\t}\n\n\treturn nil, fmt.Errorf(\"invalid encoded byte length\")\n}\n\n// Matches checks to see if the provided byte slice matches the Sequence\nfunc (u Sequence) Matches(bytes []byte) bool {\n\tif len(bytes) < len(u) {\n\t\treturn false\n\t}\n\tfor i := 0; i < len(u); i++ {\n\t\tif !u[i].matches(bytes[i]) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc (u Sequence) String() string {\n\tswitch len(u) {\n\tcase 1:\n\t\treturn fmt.Sprintf(\"%v\", u[0])\n\tcase 2:\n\t\treturn fmt.Sprintf(\"%v%v\", u[0], u[1])\n\tcase 3:\n\t\treturn fmt.Sprintf(\"%v%v%v\", u[0], u[1], u[2])\n\tcase 4:\n\t\treturn fmt.Sprintf(\"%v%v%v%v\", u[0], u[1], u[2], u[3])\n\tdefault:\n\t\treturn fmt.Sprintf(\"invalid utf8 sequence\")\n\t}\n}\n\n// Range describes a single range of byte values\ntype Range struct {\n\tStart byte\n\tEnd   byte\n}\n\nvar nilRange = Range{0xff, 0}\n\nfunc (u Range) matches(b byte) bool {\n\tif u.Start <= b && b <= u.End {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (u Range) String() string {\n\tif u.Start == u.End {\n\t\treturn fmt.Sprintf(\"[%X]\", u.Start)\n\t}\n\treturn fmt.Sprintf(\"[%X-%X]\", u.Start, u.End)\n}\n\ntype scalarRange struct {\n\tstart rune\n\tend   rune\n}\n\nvar nilScalarRange = scalarRange{0xffff, 0}\n\nfunc (s *scalarRange) String() string {\n\treturn fmt.Sprintf(\"ScalarRange(%d,%d)\", s.start, s.end)\n}\n\n// split this scalar range if it overlaps with a surrogate codepoint\nfunc (s *scalarRange) split() (scalarRange, scalarRange) {\n\tif s.start < 0xe000 && s.end > 0xd7ff {\n\t\treturn scalarRange{\n\t\t\t\tstart: s.start,\n\t\t\t\tend:   0xd7ff,\n\t\t\t},\n\t\t\tscalarRange{\n\t\t\t\tstart: 0xe000,\n\t\t\t\tend:   s.end,\n\t\t\t}\n\t}\n\treturn nilScalarRange, nilScalarRange\n}\n\nfunc (s *scalarRange) valid() bool {\n\treturn s.start <= s.end\n}\n\nfunc (s *scalarRange) ascii() Range {\n\tif s.valid() && s.end <= 0x7f {\n\t\treturn Range{\n\t\t\tStart: byte(s.start),\n\t\t\tEnd:   byte(s.end),\n\t\t}\n\t}\n\treturn nilRange\n}\n\n// start and end MUST have capacity for utf8.UTFMax bytes\nfunc (s *scalarRange) encode(start, end []byte) (int, int) {\n\tn := utf8.EncodeRune(start, s.start)\n\tm := utf8.EncodeRune(end, s.end)\n\treturn n, m\n}\n\ntype RangeStack []scalarRange\n\nfunc (s RangeStack) Push(v scalarRange) RangeStack {\n\treturn append(s, v)\n}\n\nfunc (s RangeStack) Pop() (RangeStack, scalarRange) {\n\tl := len(s)\n\tif l < 1 {\n\t\treturn s, nilScalarRange\n\t}\n\treturn s[:l-1], s[l-1]\n}\n\nfunc maxScalarValue(nbytes int) rune {\n\tswitch nbytes {\n\tcase 1:\n\t\treturn 0x007f\n\tcase 2:\n\t\treturn 0x07FF\n\tcase 3:\n\t\treturn 0xFFFF\n\tdefault:\n\t\treturn 0x10FFFF\n\t}\n}\n"
  },
  {
    "path": "utf8/utf8_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage utf8\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"testing\"\n\t\"unicode/utf8\"\n)\n\nfunc TestUtf8Sequences(t *testing.T) {\n\n\twant := Sequences{\n\t\tSequence{\n\t\t\tRange{0x0, 0x7f},\n\t\t},\n\t\tSequence{\n\t\t\tRange{0xc2, 0xdf},\n\t\t\tRange{0x80, 0xbf},\n\t\t},\n\t\tSequence{\n\t\t\tRange{0xe0, 0xe0},\n\t\t\tRange{0xa0, 0xbf},\n\t\t\tRange{0x80, 0xbf},\n\t\t},\n\t\tSequence{\n\t\t\tRange{0xe1, 0xec},\n\t\t\tRange{0x80, 0xbf},\n\t\t\tRange{0x80, 0xbf},\n\t\t},\n\t\tSequence{\n\t\t\tRange{0xed, 0xed},\n\t\t\tRange{0x80, 0x9f},\n\t\t\tRange{0x80, 0xbf},\n\t\t},\n\t\tSequence{\n\t\t\tRange{0xee, 0xef},\n\t\t\tRange{0x80, 0xbf},\n\t\t\tRange{0x80, 0xbf},\n\t\t},\n\t}\n\n\tgot, err := NewSequences(0, 0xffff)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !reflect.DeepEqual(want, got) {\n\t\tt.Errorf(\"wanted: %v, got %v\", want, got)\n\t}\n}\n\nfunc TestCodepointsNoSurrogates(t *testing.T) {\n\tneverAcceptsSurrogateCodepoints(0x0, 0xFFFF)\n\tneverAcceptsSurrogateCodepoints(0x0, 0x10FFFF)\n\tneverAcceptsSurrogateCodepoints(0x0, 0x10FFFE)\n\tneverAcceptsSurrogateCodepoints(0x80, 0x10FFFF)\n\tneverAcceptsSurrogateCodepoints(0xD7FF, 0xE000)\n}\n\nfunc neverAcceptsSurrogateCodepoints(start, end rune) error {\n\tvar buf = make([]byte, utf8.UTFMax)\n\tsequences, err := NewSequences(start, end)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor i := start; i < end; i++ {\n\t\tn := utf8.EncodeRune(buf, i)\n\t\tfor _, seq := range sequences {\n\t\t\tif seq.Matches(buf[:n]) {\n\t\t\t\treturn fmt.Errorf(\"utf8 seq: %v matches surrogate %d\", seq, i)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "vellum.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n/*\nPackage vellum is a library for building, serializing and executing an FST (finite\nstate transducer).\n\nThere are two distinct phases, building an FST and using it.\n\nWhen building an FST, you insert keys ([]byte) and their associated value\n(uint64). Insert operations MUST be done in lexicographic order.  While\nbuilding the FST, data is streamed to an underlying Writer. At the conclusion\nof building, you MUST call Close() on the builder.\n\nAfter completion of the build phase, you can either Open() the FST if you\nserialized it to disk.  Alternatively, if you already have the bytes in\nmemory, you can use Load().  By default, Open() will use mmap to avoid loading\nthe entire file into memory.\n\nOnce the FST is ready, you can use the Contains() method to see if a keys is\nin the FST.  You can use the Get() method to see if a key is in the FST and\nretrieve it's associated value.  And, you can use the Iterator method to\nenumerate key/value pairs within a specified range.\n\n*/\npackage vellum\n\nimport (\n\t\"errors\"\n\t\"io\"\n)\n\n// ErrOutOfOrder is returned when values are not inserted in\n// lexicographic order.\nvar ErrOutOfOrder = errors.New(\"values not inserted in lexicographic order\")\n\n// ErrIteratorDone is returned by Iterator/Next/Seek methods when the\n// Current() value pointed to by the iterator is greater than the last\n// key in this FST, or outside the configured startKeyInclusive/endKeyExclusive\n// range of the Iterator.\nvar ErrIteratorDone = errors.New(\"iterator-done\")\n\n// BuilderOpts is a structure to let advanced users customize the behavior\n// of the builder and some aspects of the generated FST.\ntype BuilderOpts struct {\n\tEncoder           int\n\tRegistryTableSize int\n\tRegistryMRUSize   int\n}\n\n// New returns a new Builder which will stream out the\n// underlying representation to the provided Writer as the set is built.\nfunc New(w io.Writer, opts *BuilderOpts) (*Builder, error) {\n\treturn newBuilder(w, opts)\n}\n\n// Open loads the FST stored in the provided path\nfunc Open(path string) (*FST, error) {\n\treturn open(path)\n}\n\n// Load will return the FST represented by the provided byte slice.\nfunc Load(data []byte) (*FST, error) {\n\treturn new(data, nil)\n}\n\n// Merge will iterate through the provided Iterators, merge duplicate keys\n// with the provided MergeFunc, and build a new FST to the provided Writer.\nfunc Merge(w io.Writer, opts *BuilderOpts, itrs []Iterator, f MergeFunc) error {\n\tbuilder, err := New(w, opts)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\titr, err := NewMergeIterator(itrs, f)\n\tfor err == nil {\n\t\tk, v := itr.Current()\n\t\terr = builder.Insert(k, v)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\terr = itr.Next()\n\t}\n\n\tif err != nil && err != ErrIteratorDone {\n\t\treturn err\n\t}\n\n\terr = itr.Close()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = builder.Close()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "vellum_mmap.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// +build !nommap\n\npackage vellum\n\nimport (\n\t\"os\"\n\n\tmmap \"github.com/blevesearch/mmap-go\"\n)\n\ntype mmapWrapper struct {\n\tf  *os.File\n\tmm mmap.MMap\n}\n\nfunc (m *mmapWrapper) Close() (err error) {\n\tif m.mm != nil {\n\t\terr = m.mm.Unmap()\n\t}\n\t// try to close file even if unmap failed\n\tif m.f != nil {\n\t\terr2 := m.f.Close()\n\t\tif err == nil {\n\t\t\t// try to return first error\n\t\t\terr = err2\n\t\t}\n\t}\n\treturn\n}\n\nfunc open(path string) (*FST, error) {\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tmm, err := mmap.Map(f, mmap.RDONLY, 0)\n\tif err != nil {\n\t\t// mmap failed, try to close the file\n\t\t_ = f.Close()\n\t\treturn nil, err\n\t}\n\treturn new(mm, &mmapWrapper{\n\t\tf:  f,\n\t\tmm: mm,\n\t})\n}\n"
  },
  {
    "path": "vellum_nommap.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// +build nommap\n\npackage vellum\n\nimport \"io/ioutil\"\n\nfunc open(path string) (*FST, error) {\n\tdata, err := ioutil.ReadFile(string)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn new(data, nil)\n}\n"
  },
  {
    "path": "vellum_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"bytes\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestRoundTripSimple(t *testing.T) {\n\tf, err := ioutil.TempFile(\"\", \"vellum\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\terr = f.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\terr = os.Remove(f.Name())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tb, err := New(f, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = insertStringMap(b, smallSample)\n\tif err != nil {\n\t\tt.Fatalf(\"error building: %v\", err)\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tfst, err := Open(f.Name())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\tdefer func() {\n\t\terr = fst.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\t// first check all the expected values\n\tgot := map[string]uint64{}\n\titr, err := fst.Iterator(nil, nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(smallSample, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", smallSample, got)\n\t}\n\n\t// some additional tests for items that should not exist\n\tif ok, _ := fst.Contains([]byte(\"mo\")); ok {\n\t\tt.Errorf(\"expected to not contain mo, but did\")\n\t}\n\n\tif ok, _ := fst.Contains([]byte(\"monr\")); ok {\n\t\tt.Errorf(\"expected to not contain monr, but did\")\n\t}\n\n\tif ok, _ := fst.Contains([]byte(\"thur\")); ok {\n\t\tt.Errorf(\"expected to not contain thur, but did\")\n\t}\n\n\tif ok, _ := fst.Contains([]byte(\"thurp\")); ok {\n\t\tt.Errorf(\"expected to not contain thurp, but did\")\n\t}\n\n\tif ok, _ := fst.Contains([]byte(\"tue\")); ok {\n\t\tt.Errorf(\"expected to not contain tue, but did\")\n\t}\n\n\tif ok, _ := fst.Contains([]byte(\"tuesd\")); ok {\n\t\tt.Errorf(\"expected to not contain tuesd, but did\")\n\t}\n\n\t// a few more misc non-existent values to increase coverage\n\tif ok, _ := fst.Contains([]byte(\"x\")); ok {\n\t\tt.Errorf(\"expected to not contain x, but did\")\n\t}\n\n\t// now try accessing it through the Automaton interface\n\texists := AutomatonContains(fst, []byte(\"mon\"))\n\tif !exists {\n\t\tt.Errorf(\"expected key 'mon' to exist, doesn't\")\n\t}\n\n\texists = AutomatonContains(fst, []byte(\"mons\"))\n\tif exists {\n\t\tt.Errorf(\"expected key 'mo' to not exist, does\")\n\t}\n\n\t// now try accessing it through the Transducer interface\n\tvar val uint64\n\texists, val = TransducerGet(fst, []byte(\"mon\"))\n\tif !exists {\n\t\tt.Errorf(\"expected key 'mon' to exist, doesn't\")\n\t}\n\tif val != 2 {\n\t\tt.Errorf(\"expected val 2, got %d\", val)\n\t}\n\n\t// now try accessing it through the Transducer interface\n\t// for key that doesn't exist\n\texists, _ = TransducerGet(fst, []byte(\"mons\"))\n\tif exists {\n\t\tt.Errorf(\"expected key 'mo' to not exist, does\")\n\t}\n\n\tminKey, _ := fst.GetMinKey()\n\tif string(minKey) != \"mon\" {\n\t\tt.Errorf(\"expected minKey 'mon', got %v\", string(minKey))\n\t}\n\n\tmaxKey, _ := fst.GetMaxKey()\n\tif string(maxKey) != \"tye\" {\n\t\tt.Errorf(\"expected maxKey 'tye', got %v\", string(maxKey))\n\t}\n}\n\nfunc TestRoundTripThousand(t *testing.T) {\n\tdataset := thousandTestWords\n\trandomThousandVals := randomValues(dataset)\n\n\tf, err := ioutil.TempFile(\"\", \"vellum\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\terr = f.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\terr = os.Remove(f.Name())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tb, err := New(f, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = insertStrings(b, dataset, randomThousandVals)\n\tif err != nil {\n\t\tt.Fatalf(\"error inserting thousand words: %v\", err)\n\t}\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing builder: %v\", err)\n\t}\n\n\tfst, err := Open(f.Name())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\tdefer func() {\n\t\terr = fst.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\t// first check all the expected values\n\tgot := map[string]uint64{}\n\titr, err := fst.Iterator(nil, nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\n\tfor i := 0; i < len(dataset); i++ {\n\t\tfoundVal, ok := got[dataset[i]]\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected to find key, but didn't: %s\", dataset[i])\n\t\t}\n\n\t\tif foundVal != randomThousandVals[i] {\n\t\t\tt.Fatalf(\"expected value %d for key %s, but got %d\", randomThousandVals[i], dataset[i], foundVal)\n\t\t}\n\n\t\t// now remove it\n\t\tdelete(got, dataset[i])\n\t}\n\n\tif len(got) != 0 {\n\t\tt.Fatalf(\"expected got map to be empty after checking, still has %v\", got)\n\t}\n}\n\nfunc TestRoundTripEmpty(t *testing.T) {\n\tf, err := ioutil.TempFile(\"\", \"vellum\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\terr = f.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\terr = os.Remove(f.Name())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tb, err := New(f, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tfst, err := Open(f.Name())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\tdefer func() {\n\t\terr = fst.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tif fst.Len() != 0 {\n\t\tt.Fatalf(\"expected length 0, got %d\", fst.Len())\n\t}\n\n\t// first check all the expected values\n\tgot := map[string]uint64{}\n\titr, err := fst.Iterator(nil, nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif len(got) > 0 {\n\t\tt.Errorf(\"expected not to see anything, got %v\", got)\n\t}\n}\n\nfunc TestRoundTripEmptyString(t *testing.T) {\n\tf, err := ioutil.TempFile(\"\", \"vellum\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\terr = f.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\terr = os.Remove(f.Name())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tb, err := New(f, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = b.Insert([]byte(\"\"), 1)\n\tif err != nil {\n\t\tt.Fatalf(\"error inserting empty string\")\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tfst, err := Open(f.Name())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\tdefer func() {\n\t\terr = fst.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tif fst.Len() != 1 {\n\t\tt.Fatalf(\"expected length 1, got %d\", fst.Len())\n\t}\n\n\t// first check all the expected values\n\twant := map[string]uint64{\n\t\t\"\": 1,\n\t}\n\tgot := map[string]uint64{}\n\titr, err := fst.Iterator(nil, nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(want, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", want, got)\n\t}\n}\n\nfunc TestRoundTripEmptyStringAndOthers(t *testing.T) {\n\tf, err := ioutil.TempFile(\"\", \"vellum\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\terr = f.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\terr = os.Remove(f.Name())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tb, err := New(f, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = b.Insert([]byte(\"\"), 0)\n\tif err != nil {\n\t\tt.Fatalf(\"error inserting empty string\")\n\t}\n\terr = b.Insert([]byte(\"a\"), 0)\n\tif err != nil {\n\t\tt.Fatalf(\"error inserting empty string\")\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tfst, err := Open(f.Name())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\tdefer func() {\n\t\terr = fst.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tif fst.Len() != 2 {\n\t\tt.Fatalf(\"expected length 2, got %d\", fst.Len())\n\t}\n\n\t// first check all the expected values\n\twant := map[string]uint64{\n\t\t\"\":  0,\n\t\t\"a\": 0,\n\t}\n\tgot := map[string]uint64{}\n\titr, err := fst.Iterator(nil, nil)\n\tfor err == nil {\n\t\tkey, val := itr.Current()\n\t\tgot[string(key)] = val\n\t\terr = itr.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(want, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", want, got)\n\t}\n}\n\nfunc TestMerge(t *testing.T) {\n\n\t// first create a file with the smallSample data\n\tf, err := ioutil.TempFile(\"\", \"vellum1\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\terr = f.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\terr = os.Remove(f.Name())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tb, err := New(f, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = insertStringMap(b, smallSample)\n\tif err != nil {\n\t\tt.Fatalf(\"error building: %v\", err)\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\tsmallSample2 := map[string]uint64{\n\t\t\"bold\": 25,\n\t\t\"last\": 1,\n\t\t\"next\": 500,\n\t\t\"tank\": 0,\n\t}\n\n\t// next create a file with the smallSample2 data\n\tf2, err := ioutil.TempFile(\"\", \"vellum1\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\terr = f2.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\terr = os.Remove(f2.Name())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tb, err = New(f2, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error creating builder: %v\", err)\n\t}\n\n\terr = insertStringMap(b, smallSample2)\n\tif err != nil {\n\t\tt.Fatalf(\"error building: %v\", err)\n\t}\n\n\terr = b.Close()\n\tif err != nil {\n\t\tt.Fatalf(\"error closing: %v\", err)\n\t}\n\n\t// now open them both up\n\tfst, err := Open(f.Name())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\tdefer func() {\n\t\terr = fst.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\tfst2, err := Open(f2.Name())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\tdefer func() {\n\t\terr = fst2.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\t// create full range iterators on both\n\titr, err := fst.Iterator(nil, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error opening iterator: %v\", err)\n\t}\n\titr2, err := fst2.Iterator(nil, nil)\n\tif err != nil {\n\t\tt.Fatalf(\"error opening iterator: %v\", err)\n\t}\n\n\tf3, err := ioutil.TempFile(\"\", \"vellum1\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\terr = f3.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\terr = os.Remove(f3.Name())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\terr = Merge(f3, nil, []Iterator{itr, itr2}, MergeSum)\n\tif err != nil {\n\t\tt.Fatalf(\"error merging iterators: %v\", err)\n\t}\n\n\t// now check it\n\tfstc, err := Open(f3.Name())\n\tif err != nil {\n\t\tt.Fatalf(\"error loading set: %v\", err)\n\t}\n\tdefer func() {\n\t\terr = fstc.Close()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\tif fstc.Len() != 8 {\n\t\tt.Fatalf(\"expected length 8, got %d\", fst.Len())\n\t}\n\n\t// now check all the expected values\n\twant := map[string]uint64{\n\t\t\"mon\":   2,\n\t\t\"tues\":  3,\n\t\t\"thurs\": 5,\n\t\t\"tye\":   99,\n\t\t\"bold\":  25,\n\t\t\"last\":  1,\n\t\t\"next\":  500,\n\t\t\"tank\":  0,\n\t}\n\tgot := map[string]uint64{}\n\titrc, err := fstc.Iterator(nil, nil)\n\tfor err == nil {\n\t\tkey, val := itrc.Current()\n\t\tgot[string(key)] = val\n\t\terr = itrc.Next()\n\t}\n\tif err != ErrIteratorDone {\n\t\tt.Errorf(\"iterator error: %v\", err)\n\t}\n\tif !reflect.DeepEqual(want, got) {\n\t\tt.Errorf(\"expected %v, got: %v\", want, got)\n\t}\n}\n\nfunc BenchmarkKey4000K(b *testing.B) {\n\tbenchmarkBigKey(b, 4000000)\n}\n\nfunc BenchmarkKey1000K(b *testing.B) {\n\tbenchmarkBigKey(b, 1000000)\n}\n\nfunc BenchmarkKey100K(b *testing.B) {\n\tbenchmarkBigKey(b, 100000)\n}\n\nfunc BenchmarkKey10K(b *testing.B) {\n\tbenchmarkBigKey(b, 10000)\n}\n\nfunc BenchmarkKey1K(b *testing.B) {\n\tbenchmarkBigKey(b, 1000)\n}\n\nfunc benchmarkBigKey(b *testing.B, n int) {\n\tbig := bytes.Repeat([]byte(\"a\"), n)\n\n\tb.ResetTimer()\n\n\tfor i := 0; i < b.N; i++ {\n\t\tb, err := New(ioutil.Discard, nil)\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\n\t\terr = b.Insert(big, 0)\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\n\t\terr = b.Close()\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc TestMaxWithSubstring(t *testing.T) {\n\tvar buf bytes.Buffer\n\tbuilder, err := New(&buf, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\terr = builder.Insert([]byte(\"1\"), 1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\terr = builder.Insert([]byte(\"11\"), 1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\terr = builder.Insert([]byte(\"9\"), 9)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\terr = builder.Insert([]byte(\"99\"), 99)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\terr = builder.Close()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfst, err := Load(buf.Bytes())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tmink, err := fst.GetMinKey()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif string(mink) != \"1\" {\n\t\tt.Fatalf(\"expected max key 1, got %s\", string(mink))\n\t}\n\n\tmaxk, err := fst.GetMaxKey()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif string(maxk) != \"99\" {\n\t\tt.Fatalf(\"expected max key 99, got %s\", string(maxk))\n\t}\n}\n"
  },
  {
    "path": "vendor/github.com/edsrzf/mmap-go/LICENSE",
    "content": "Copyright (c) 2011, Evan Shaw <edsrzf@gmail.com>\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the copyright holder nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n"
  },
  {
    "path": "vendor/github.com/edsrzf/mmap-go/mmap.go",
    "content": "// Copyright 2011 Evan Shaw. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file defines the common package interface and contains a little bit of\n// factored out logic.\n\n// Package mmap allows mapping files into memory. It tries to provide a simple, reasonably portable interface,\n// but doesn't go out of its way to abstract away every little platform detail.\n// This specifically means:\n//\t* forked processes may or may not inherit mappings\n//\t* a file's timestamp may or may not be updated by writes through mappings\n//\t* specifying a size larger than the file's actual size can increase the file's size\n//\t* If the mapped file is being modified by another process while your program's running, don't expect consistent results between platforms\npackage mmap\n\nimport (\n\t\"errors\"\n\t\"os\"\n\t\"reflect\"\n\t\"unsafe\"\n)\n\nconst (\n\t// RDONLY maps the memory read-only.\n\t// Attempts to write to the MMap object will result in undefined behavior.\n\tRDONLY = 0\n\t// RDWR maps the memory as read-write. Writes to the MMap object will update the\n\t// underlying file.\n\tRDWR = 1 << iota\n\t// COPY maps the memory as copy-on-write. Writes to the MMap object will affect\n\t// memory, but the underlying file will remain unchanged.\n\tCOPY\n\t// If EXEC is set, the mapped memory is marked as executable.\n\tEXEC\n)\n\nconst (\n\t// If the ANON flag is set, the mapped memory will not be backed by a file.\n\tANON = 1 << iota\n)\n\n// MMap represents a file mapped into memory.\ntype MMap []byte\n\n// Map maps an entire file into memory.\n// If ANON is set in flags, f is ignored.\nfunc Map(f *os.File, prot, flags int) (MMap, error) {\n\treturn MapRegion(f, -1, prot, flags, 0)\n}\n\n// MapRegion maps part of a file into memory.\n// The offset parameter must be a multiple of the system's page size.\n// If length < 0, the entire file will be mapped.\n// If ANON is set in flags, f is ignored.\nfunc MapRegion(f *os.File, length int, prot, flags int, offset int64) (MMap, error) {\n\tvar fd uintptr\n\tif flags&ANON == 0 {\n\t\tfd = uintptr(f.Fd())\n\t\tif length < 0 {\n\t\t\tfi, err := f.Stat()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tlength = int(fi.Size())\n\t\t}\n\t} else {\n\t\tif length <= 0 {\n\t\t\treturn nil, errors.New(\"anonymous mapping requires non-zero length\")\n\t\t}\n\t\tfd = ^uintptr(0)\n\t}\n\treturn mmap(length, uintptr(prot), uintptr(flags), fd, offset)\n}\n\nfunc (m *MMap) header() *reflect.SliceHeader {\n\treturn (*reflect.SliceHeader)(unsafe.Pointer(m))\n}\n\n// Lock keeps the mapped region in physical memory, ensuring that it will not be\n// swapped out.\nfunc (m MMap) Lock() error {\n\tdh := m.header()\n\treturn lock(dh.Data, uintptr(dh.Len))\n}\n\n// Unlock reverses the effect of Lock, allowing the mapped region to potentially\n// be swapped out.\n// If m is already unlocked, aan error will result.\nfunc (m MMap) Unlock() error {\n\tdh := m.header()\n\treturn unlock(dh.Data, uintptr(dh.Len))\n}\n\n// Flush synchronizes the mapping's contents to the file's contents on disk.\nfunc (m MMap) Flush() error {\n\tdh := m.header()\n\treturn flush(dh.Data, uintptr(dh.Len))\n}\n\n// Unmap deletes the memory mapped region, flushes any remaining changes, and sets\n// m to nil.\n// Trying to read or write any remaining references to m after Unmap is called will\n// result in undefined behavior.\n// Unmap should only be called on the slice value that was originally returned from\n// a call to Map. Calling Unmap on a derived slice may cause errors.\nfunc (m *MMap) Unmap() error {\n\tdh := m.header()\n\terr := unmap(dh.Data, uintptr(dh.Len))\n\t*m = nil\n\treturn err\n}\n"
  },
  {
    "path": "vendor/github.com/edsrzf/mmap-go/mmap_unix.go",
    "content": "// Copyright 2011 Evan Shaw. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build darwin dragonfly freebsd linux openbsd solaris netbsd\n\npackage mmap\n\nimport (\n\t\"syscall\"\n)\n\nfunc mmap(len int, inprot, inflags, fd uintptr, off int64) ([]byte, error) {\n\tflags := syscall.MAP_SHARED\n\tprot := syscall.PROT_READ\n\tswitch {\n\tcase inprot&COPY != 0:\n\t\tprot |= syscall.PROT_WRITE\n\t\tflags = syscall.MAP_PRIVATE\n\tcase inprot&RDWR != 0:\n\t\tprot |= syscall.PROT_WRITE\n\t}\n\tif inprot&EXEC != 0 {\n\t\tprot |= syscall.PROT_EXEC\n\t}\n\tif inflags&ANON != 0 {\n\t\tflags |= syscall.MAP_ANON\n\t}\n\n\tb, err := syscall.Mmap(int(fd), off, len, prot, flags)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\nfunc flush(addr, len uintptr) error {\n\t_, _, errno := syscall.Syscall(_SYS_MSYNC, addr, len, _MS_SYNC)\n\tif errno != 0 {\n\t\treturn syscall.Errno(errno)\n\t}\n\treturn nil\n}\n\nfunc lock(addr, len uintptr) error {\n\t_, _, errno := syscall.Syscall(syscall.SYS_MLOCK, addr, len, 0)\n\tif errno != 0 {\n\t\treturn syscall.Errno(errno)\n\t}\n\treturn nil\n}\n\nfunc unlock(addr, len uintptr) error {\n\t_, _, errno := syscall.Syscall(syscall.SYS_MUNLOCK, addr, len, 0)\n\tif errno != 0 {\n\t\treturn syscall.Errno(errno)\n\t}\n\treturn nil\n}\n\nfunc unmap(addr, len uintptr) error {\n\t_, _, errno := syscall.Syscall(syscall.SYS_MUNMAP, addr, len, 0)\n\tif errno != 0 {\n\t\treturn syscall.Errno(errno)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/edsrzf/mmap-go/mmap_windows.go",
    "content": "// Copyright 2011 Evan Shaw. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mmap\n\nimport (\n\t\"errors\"\n\t\"os\"\n\t\"sync\"\n\t\"syscall\"\n)\n\n// mmap on Windows is a two-step process.\n// First, we call CreateFileMapping to get a handle.\n// Then, we call MapviewToFile to get an actual pointer into memory.\n// Because we want to emulate a POSIX-style mmap, we don't want to expose\n// the handle -- only the pointer. We also want to return only a byte slice,\n// not a struct, so it's convenient to manipulate.\n\n// We keep this map so that we can get back the original handle from the memory address.\nvar handleLock sync.Mutex\nvar handleMap = map[uintptr]syscall.Handle{}\n\nfunc mmap(len int, prot, flags, hfile uintptr, off int64) ([]byte, error) {\n\tflProtect := uint32(syscall.PAGE_READONLY)\n\tdwDesiredAccess := uint32(syscall.FILE_MAP_READ)\n\tswitch {\n\tcase prot&COPY != 0:\n\t\tflProtect = syscall.PAGE_WRITECOPY\n\t\tdwDesiredAccess = syscall.FILE_MAP_COPY\n\tcase prot&RDWR != 0:\n\t\tflProtect = syscall.PAGE_READWRITE\n\t\tdwDesiredAccess = syscall.FILE_MAP_WRITE\n\t}\n\tif prot&EXEC != 0 {\n\t\tflProtect <<= 4\n\t\tdwDesiredAccess |= syscall.FILE_MAP_EXECUTE\n\t}\n\n\t// The maximum size is the area of the file, starting from 0,\n\t// that we wish to allow to be mappable. It is the sum of\n\t// the length the user requested, plus the offset where that length\n\t// is starting from. This does not map the data into memory.\n\tmaxSizeHigh := uint32((off + int64(len)) >> 32)\n\tmaxSizeLow := uint32((off + int64(len)) & 0xFFFFFFFF)\n\t// TODO: Do we need to set some security attributes? It might help portability.\n\th, errno := syscall.CreateFileMapping(syscall.Handle(hfile), nil, flProtect, maxSizeHigh, maxSizeLow, nil)\n\tif h == 0 {\n\t\treturn nil, os.NewSyscallError(\"CreateFileMapping\", errno)\n\t}\n\n\t// Actually map a view of the data into memory. The view's size\n\t// is the length the user requested.\n\tfileOffsetHigh := uint32(off >> 32)\n\tfileOffsetLow := uint32(off & 0xFFFFFFFF)\n\taddr, errno := syscall.MapViewOfFile(h, dwDesiredAccess, fileOffsetHigh, fileOffsetLow, uintptr(len))\n\tif addr == 0 {\n\t\treturn nil, os.NewSyscallError(\"MapViewOfFile\", errno)\n\t}\n\thandleLock.Lock()\n\thandleMap[addr] = h\n\thandleLock.Unlock()\n\n\tm := MMap{}\n\tdh := m.header()\n\tdh.Data = addr\n\tdh.Len = len\n\tdh.Cap = dh.Len\n\n\treturn m, nil\n}\n\nfunc flush(addr, len uintptr) error {\n\terrno := syscall.FlushViewOfFile(addr, len)\n\tif errno != nil {\n\t\treturn os.NewSyscallError(\"FlushViewOfFile\", errno)\n\t}\n\n\thandleLock.Lock()\n\tdefer handleLock.Unlock()\n\thandle, ok := handleMap[addr]\n\tif !ok {\n\t\t// should be impossible; we would've errored above\n\t\treturn errors.New(\"unknown base address\")\n\t}\n\n\terrno = syscall.FlushFileBuffers(handle)\n\treturn os.NewSyscallError(\"FlushFileBuffers\", errno)\n}\n\nfunc lock(addr, len uintptr) error {\n\terrno := syscall.VirtualLock(addr, len)\n\treturn os.NewSyscallError(\"VirtualLock\", errno)\n}\n\nfunc unlock(addr, len uintptr) error {\n\terrno := syscall.VirtualUnlock(addr, len)\n\treturn os.NewSyscallError(\"VirtualUnlock\", errno)\n}\n\nfunc unmap(addr, len uintptr) error {\n\tflush(addr, len)\n\t// Lock the UnmapViewOfFile along with the handleMap deletion.\n\t// As soon as we unmap the view, the OS is free to give the\n\t// same addr to another new map. We don't want another goroutine\n\t// to insert and remove the same addr into handleMap while\n\t// we're trying to remove our old addr/handle pair.\n\thandleLock.Lock()\n\tdefer handleLock.Unlock()\n\terr := syscall.UnmapViewOfFile(addr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\thandle, ok := handleMap[addr]\n\tif !ok {\n\t\t// should be impossible; we would've errored above\n\t\treturn errors.New(\"unknown base address\")\n\t}\n\tdelete(handleMap, addr)\n\n\te := syscall.CloseHandle(syscall.Handle(handle))\n\treturn os.NewSyscallError(\"CloseHandle\", e)\n}\n"
  },
  {
    "path": "vendor/github.com/edsrzf/mmap-go/msync_netbsd.go",
    "content": "// Copyright 2011 Evan Shaw. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mmap\n\nconst _SYS_MSYNC = 277\nconst _MS_SYNC = 0x04\n"
  },
  {
    "path": "vendor/github.com/edsrzf/mmap-go/msync_unix.go",
    "content": "// Copyright 2011 Evan Shaw. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build darwin dragonfly freebsd linux openbsd solaris\n\npackage mmap\n\nimport (\n\t\"syscall\"\n)\n\nconst _SYS_MSYNC = syscall.SYS_MSYNC\nconst _MS_SYNC = syscall.MS_SYNC\n"
  },
  {
    "path": "vendor/github.com/inconshreveable/mousetrap/LICENSE",
    "content": "Copyright 2014 Alan Shreve\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "vendor/github.com/inconshreveable/mousetrap/trap_others.go",
    "content": "// +build !windows\n\npackage mousetrap\n\n// StartedByExplorer returns true if the program was invoked by the user\n// double-clicking on the executable from explorer.exe\n//\n// It is conservative and returns false if any of the internal calls fail.\n// It does not guarantee that the program was run from a terminal. It only can tell you\n// whether it was launched from explorer.exe\n//\n// On non-Windows platforms, it always returns false.\nfunc StartedByExplorer() bool {\n\treturn false\n}\n"
  },
  {
    "path": "vendor/github.com/inconshreveable/mousetrap/trap_windows.go",
    "content": "// +build windows\n// +build !go1.4\n\npackage mousetrap\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"syscall\"\n\t\"unsafe\"\n)\n\nconst (\n\t// defined by the Win32 API\n\tth32cs_snapprocess uintptr = 0x2\n)\n\nvar (\n\tkernel                   = syscall.MustLoadDLL(\"kernel32.dll\")\n\tCreateToolhelp32Snapshot = kernel.MustFindProc(\"CreateToolhelp32Snapshot\")\n\tProcess32First           = kernel.MustFindProc(\"Process32FirstW\")\n\tProcess32Next            = kernel.MustFindProc(\"Process32NextW\")\n)\n\n// ProcessEntry32 structure defined by the Win32 API\ntype processEntry32 struct {\n\tdwSize              uint32\n\tcntUsage            uint32\n\tth32ProcessID       uint32\n\tth32DefaultHeapID   int\n\tth32ModuleID        uint32\n\tcntThreads          uint32\n\tth32ParentProcessID uint32\n\tpcPriClassBase      int32\n\tdwFlags             uint32\n\tszExeFile           [syscall.MAX_PATH]uint16\n}\n\nfunc getProcessEntry(pid int) (pe *processEntry32, err error) {\n\tsnapshot, _, e1 := CreateToolhelp32Snapshot.Call(th32cs_snapprocess, uintptr(0))\n\tif snapshot == uintptr(syscall.InvalidHandle) {\n\t\terr = fmt.Errorf(\"CreateToolhelp32Snapshot: %v\", e1)\n\t\treturn\n\t}\n\tdefer syscall.CloseHandle(syscall.Handle(snapshot))\n\n\tvar processEntry processEntry32\n\tprocessEntry.dwSize = uint32(unsafe.Sizeof(processEntry))\n\tok, _, e1 := Process32First.Call(snapshot, uintptr(unsafe.Pointer(&processEntry)))\n\tif ok == 0 {\n\t\terr = fmt.Errorf(\"Process32First: %v\", e1)\n\t\treturn\n\t}\n\n\tfor {\n\t\tif processEntry.th32ProcessID == uint32(pid) {\n\t\t\tpe = &processEntry\n\t\t\treturn\n\t\t}\n\n\t\tok, _, e1 = Process32Next.Call(snapshot, uintptr(unsafe.Pointer(&processEntry)))\n\t\tif ok == 0 {\n\t\t\terr = fmt.Errorf(\"Process32Next: %v\", e1)\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc getppid() (pid int, err error) {\n\tpe, err := getProcessEntry(os.Getpid())\n\tif err != nil {\n\t\treturn\n\t}\n\n\tpid = int(pe.th32ParentProcessID)\n\treturn\n}\n\n// StartedByExplorer returns true if the program was invoked by the user double-clicking\n// on the executable from explorer.exe\n//\n// It is conservative and returns false if any of the internal calls fail.\n// It does not guarantee that the program was run from a terminal. It only can tell you\n// whether it was launched from explorer.exe\nfunc StartedByExplorer() bool {\n\tppid, err := getppid()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\tpe, err := getProcessEntry(ppid)\n\tif err != nil {\n\t\treturn false\n\t}\n\n\tname := syscall.UTF16ToString(pe.szExeFile[:])\n\treturn name == \"explorer.exe\"\n}\n"
  },
  {
    "path": "vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go",
    "content": "// +build windows\n// +build go1.4\n\npackage mousetrap\n\nimport (\n\t\"os\"\n\t\"syscall\"\n\t\"unsafe\"\n)\n\nfunc getProcessEntry(pid int) (*syscall.ProcessEntry32, error) {\n\tsnapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer syscall.CloseHandle(snapshot)\n\tvar procEntry syscall.ProcessEntry32\n\tprocEntry.Size = uint32(unsafe.Sizeof(procEntry))\n\tif err = syscall.Process32First(snapshot, &procEntry); err != nil {\n\t\treturn nil, err\n\t}\n\tfor {\n\t\tif procEntry.ProcessID == uint32(pid) {\n\t\t\treturn &procEntry, nil\n\t\t}\n\t\terr = syscall.Process32Next(snapshot, &procEntry)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n}\n\n// StartedByExplorer returns true if the program was invoked by the user double-clicking\n// on the executable from explorer.exe\n//\n// It is conservative and returns false if any of the internal calls fail.\n// It does not guarantee that the program was run from a terminal. It only can tell you\n// whether it was launched from explorer.exe\nfunc StartedByExplorer() bool {\n\tpe, err := getProcessEntry(os.Getppid())\n\tif err != nil {\n\t\treturn false\n\t}\n\treturn \"explorer.exe\" == syscall.UTF16ToString(pe.ExeFile[:])\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/cobra/LICENSE.txt",
    "content": "                                Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n"
  },
  {
    "path": "vendor/github.com/spf13/cobra/bash_completions.go",
    "content": "package cobra\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/spf13/pflag\"\n)\n\n// Annotations for Bash completion.\nconst (\n\tBashCompFilenameExt     = \"cobra_annotation_bash_completion_filename_extensions\"\n\tBashCompCustom          = \"cobra_annotation_bash_completion_custom\"\n\tBashCompOneRequiredFlag = \"cobra_annotation_bash_completion_one_required_flag\"\n\tBashCompSubdirsInDir    = \"cobra_annotation_bash_completion_subdirs_in_dir\"\n)\n\nfunc preamble(out io.Writer, name string) error {\n\t_, err := fmt.Fprintf(out, \"# bash completion for %-36s -*- shell-script -*-\\n\", name)\n\tif err != nil {\n\t\treturn err\n\t}\n\tpreamStr := `\n__debug()\n{\n    if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then\n        echo \"$*\" >> \"${BASH_COMP_DEBUG_FILE}\"\n    fi\n}\n\n# Homebrew on Macs have version 1.3 of bash-completion which doesn't include\n# _init_completion. This is a very minimal version of that function.\n__my_init_completion()\n{\n    COMPREPLY=()\n    _get_comp_words_by_ref \"$@\" cur prev words cword\n}\n\n__index_of_word()\n{\n    local w word=$1\n    shift\n    index=0\n    for w in \"$@\"; do\n        [[ $w = \"$word\" ]] && return\n        index=$((index+1))\n    done\n    index=-1\n}\n\n__contains_word()\n{\n    local w word=$1; shift\n    for w in \"$@\"; do\n        [[ $w = \"$word\" ]] && return\n    done\n    return 1\n}\n\n__handle_reply()\n{\n    __debug \"${FUNCNAME[0]}\"\n    case $cur in\n        -*)\n            if [[ $(type -t compopt) = \"builtin\" ]]; then\n                compopt -o nospace\n            fi\n            local allflags\n            if [ ${#must_have_one_flag[@]} -ne 0 ]; then\n                allflags=(\"${must_have_one_flag[@]}\")\n            else\n                allflags=(\"${flags[*]} ${two_word_flags[*]}\")\n            fi\n            COMPREPLY=( $(compgen -W \"${allflags[*]}\" -- \"$cur\") )\n            if [[ $(type -t compopt) = \"builtin\" ]]; then\n                [[ \"${COMPREPLY[0]}\" == *= ]] || compopt +o nospace\n            fi\n\n            # complete after --flag=abc\n            if [[ $cur == *=* ]]; then\n                if [[ $(type -t compopt) = \"builtin\" ]]; then\n                    compopt +o nospace\n                fi\n\n                local index flag\n                flag=\"${cur%%=*}\"\n                __index_of_word \"${flag}\" \"${flags_with_completion[@]}\"\n                if [[ ${index} -ge 0 ]]; then\n                    COMPREPLY=()\n                    PREFIX=\"\"\n                    cur=\"${cur#*=}\"\n                    ${flags_completion[${index}]}\n                    if [ -n \"${ZSH_VERSION}\" ]; then\n                        # zfs completion needs --flag= prefix\n                        eval \"COMPREPLY=( \\\"\\${COMPREPLY[@]/#/${flag}=}\\\" )\"\n                    fi\n                fi\n            fi\n            return 0;\n            ;;\n    esac\n\n    # check if we are handling a flag with special work handling\n    local index\n    __index_of_word \"${prev}\" \"${flags_with_completion[@]}\"\n    if [[ ${index} -ge 0 ]]; then\n        ${flags_completion[${index}]}\n        return\n    fi\n\n    # we are parsing a flag and don't have a special handler, no completion\n    if [[ ${cur} != \"${words[cword]}\" ]]; then\n        return\n    fi\n\n    local completions\n    completions=(\"${commands[@]}\")\n    if [[ ${#must_have_one_noun[@]} -ne 0 ]]; then\n        completions=(\"${must_have_one_noun[@]}\")\n    fi\n    if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then\n        completions+=(\"${must_have_one_flag[@]}\")\n    fi\n    COMPREPLY=( $(compgen -W \"${completions[*]}\" -- \"$cur\") )\n\n    if [[ ${#COMPREPLY[@]} -eq 0 && ${#noun_aliases[@]} -gt 0 && ${#must_have_one_noun[@]} -ne 0 ]]; then\n        COMPREPLY=( $(compgen -W \"${noun_aliases[*]}\" -- \"$cur\") )\n    fi\n\n    if [[ ${#COMPREPLY[@]} -eq 0 ]]; then\n        declare -F __custom_func >/dev/null && __custom_func\n    fi\n\n    __ltrim_colon_completions \"$cur\"\n}\n\n# The arguments should be in the form \"ext1|ext2|extn\"\n__handle_filename_extension_flag()\n{\n    local ext=\"$1\"\n    _filedir \"@(${ext})\"\n}\n\n__handle_subdirs_in_dir_flag()\n{\n    local dir=\"$1\"\n    pushd \"${dir}\" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1\n}\n\n__handle_flag()\n{\n    __debug \"${FUNCNAME[0]}: c is $c words[c] is ${words[c]}\"\n\n    # if a command required a flag, and we found it, unset must_have_one_flag()\n    local flagname=${words[c]}\n    local flagvalue\n    # if the word contained an =\n    if [[ ${words[c]} == *\"=\"* ]]; then\n        flagvalue=${flagname#*=} # take in as flagvalue after the =\n        flagname=${flagname%%=*} # strip everything after the =\n        flagname=\"${flagname}=\" # but put the = back\n    fi\n    __debug \"${FUNCNAME[0]}: looking for ${flagname}\"\n    if __contains_word \"${flagname}\" \"${must_have_one_flag[@]}\"; then\n        must_have_one_flag=()\n    fi\n\n    # if you set a flag which only applies to this command, don't show subcommands\n    if __contains_word \"${flagname}\" \"${local_nonpersistent_flags[@]}\"; then\n      commands=()\n    fi\n\n    # keep flag value with flagname as flaghash\n    if [ -n \"${flagvalue}\" ] ; then\n        flaghash[${flagname}]=${flagvalue}\n    elif [ -n \"${words[ $((c+1)) ]}\" ] ; then\n        flaghash[${flagname}]=${words[ $((c+1)) ]}\n    else\n        flaghash[${flagname}]=\"true\" # pad \"true\" for bool flag\n    fi\n\n    # skip the argument to a two word flag\n    if __contains_word \"${words[c]}\" \"${two_word_flags[@]}\"; then\n        c=$((c+1))\n        # if we are looking for a flags value, don't show commands\n        if [[ $c -eq $cword ]]; then\n            commands=()\n        fi\n    fi\n\n    c=$((c+1))\n\n}\n\n__handle_noun()\n{\n    __debug \"${FUNCNAME[0]}: c is $c words[c] is ${words[c]}\"\n\n    if __contains_word \"${words[c]}\" \"${must_have_one_noun[@]}\"; then\n        must_have_one_noun=()\n    elif __contains_word \"${words[c]}\" \"${noun_aliases[@]}\"; then\n        must_have_one_noun=()\n    fi\n\n    nouns+=(\"${words[c]}\")\n    c=$((c+1))\n}\n\n__handle_command()\n{\n    __debug \"${FUNCNAME[0]}: c is $c words[c] is ${words[c]}\"\n\n    local next_command\n    if [[ -n ${last_command} ]]; then\n        next_command=\"_${last_command}_${words[c]//:/__}\"\n    else\n        if [[ $c -eq 0 ]]; then\n            next_command=\"_$(basename \"${words[c]//:/__}\")\"\n        else\n            next_command=\"_${words[c]//:/__}\"\n        fi\n    fi\n    c=$((c+1))\n    __debug \"${FUNCNAME[0]}: looking for ${next_command}\"\n    declare -F $next_command >/dev/null && $next_command\n}\n\n__handle_word()\n{\n    if [[ $c -ge $cword ]]; then\n        __handle_reply\n        return\n    fi\n    __debug \"${FUNCNAME[0]}: c is $c words[c] is ${words[c]}\"\n    if [[ \"${words[c]}\" == -* ]]; then\n        __handle_flag\n    elif __contains_word \"${words[c]}\" \"${commands[@]}\"; then\n        __handle_command\n    elif [[ $c -eq 0 ]] && __contains_word \"$(basename \"${words[c]}\")\" \"${commands[@]}\"; then\n        __handle_command\n    else\n        __handle_noun\n    fi\n    __handle_word\n}\n\n`\n\t_, err = fmt.Fprint(out, preamStr)\n\treturn err\n}\n\nfunc postscript(w io.Writer, name string) error {\n\tname = strings.Replace(name, \":\", \"__\", -1)\n\t_, err := fmt.Fprintf(w, \"__start_%s()\\n\", name)\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = fmt.Fprintf(w, `{\n    local cur prev words cword\n    declare -A flaghash 2>/dev/null || :\n    if declare -F _init_completion >/dev/null 2>&1; then\n        _init_completion -s || return\n    else\n        __my_init_completion -n \"=\" || return\n    fi\n\n    local c=0\n    local flags=()\n    local two_word_flags=()\n    local local_nonpersistent_flags=()\n    local flags_with_completion=()\n    local flags_completion=()\n    local commands=(\"%s\")\n    local must_have_one_flag=()\n    local must_have_one_noun=()\n    local last_command\n    local nouns=()\n\n    __handle_word\n}\n\n`, name)\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = fmt.Fprintf(w, `if [[ $(type -t compopt) = \"builtin\" ]]; then\n    complete -o default -F __start_%s %s\nelse\n    complete -o default -o nospace -F __start_%s %s\nfi\n\n`, name, name, name, name)\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = fmt.Fprintf(w, \"# ex: ts=4 sw=4 et filetype=sh\\n\")\n\treturn err\n}\n\nfunc writeCommands(cmd *Command, w io.Writer) error {\n\tif _, err := fmt.Fprintf(w, \"    commands=()\\n\"); err != nil {\n\t\treturn err\n\t}\n\tfor _, c := range cmd.Commands() {\n\t\tif !c.IsAvailableCommand() || c == cmd.helpCommand {\n\t\t\tcontinue\n\t\t}\n\t\tif _, err := fmt.Fprintf(w, \"    commands+=(%q)\\n\", c.Name()); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\t_, err := fmt.Fprintf(w, \"\\n\")\n\treturn err\n}\n\nfunc writeFlagHandler(name string, annotations map[string][]string, w io.Writer) error {\n\tfor key, value := range annotations {\n\t\tswitch key {\n\t\tcase BashCompFilenameExt:\n\t\t\t_, err := fmt.Fprintf(w, \"    flags_with_completion+=(%q)\\n\", name)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif len(value) > 0 {\n\t\t\t\text := \"__handle_filename_extension_flag \" + strings.Join(value, \"|\")\n\t\t\t\t_, err = fmt.Fprintf(w, \"    flags_completion+=(%q)\\n\", ext)\n\t\t\t} else {\n\t\t\t\text := \"_filedir\"\n\t\t\t\t_, err = fmt.Fprintf(w, \"    flags_completion+=(%q)\\n\", ext)\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\tcase BashCompCustom:\n\t\t\t_, err := fmt.Fprintf(w, \"    flags_with_completion+=(%q)\\n\", name)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif len(value) > 0 {\n\t\t\t\thandlers := strings.Join(value, \"; \")\n\t\t\t\t_, err = fmt.Fprintf(w, \"    flags_completion+=(%q)\\n\", handlers)\n\t\t\t} else {\n\t\t\t\t_, err = fmt.Fprintf(w, \"    flags_completion+=(:)\\n\")\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\tcase BashCompSubdirsInDir:\n\t\t\t_, err := fmt.Fprintf(w, \"    flags_with_completion+=(%q)\\n\", name)\n\n\t\t\tif len(value) == 1 {\n\t\t\t\text := \"__handle_subdirs_in_dir_flag \" + value[0]\n\t\t\t\t_, err = fmt.Fprintf(w, \"    flags_completion+=(%q)\\n\", ext)\n\t\t\t} else {\n\t\t\t\text := \"_filedir -d\"\n\t\t\t\t_, err = fmt.Fprintf(w, \"    flags_completion+=(%q)\\n\", ext)\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc writeShortFlag(flag *pflag.Flag, w io.Writer) error {\n\tb := (len(flag.NoOptDefVal) > 0)\n\tname := flag.Shorthand\n\tformat := \"    \"\n\tif !b {\n\t\tformat += \"two_word_\"\n\t}\n\tformat += \"flags+=(\\\"-%s\\\")\\n\"\n\tif _, err := fmt.Fprintf(w, format, name); err != nil {\n\t\treturn err\n\t}\n\treturn writeFlagHandler(\"-\"+name, flag.Annotations, w)\n}\n\nfunc writeFlag(flag *pflag.Flag, w io.Writer) error {\n\tb := (len(flag.NoOptDefVal) > 0)\n\tname := flag.Name\n\tformat := \"    flags+=(\\\"--%s\"\n\tif !b {\n\t\tformat += \"=\"\n\t}\n\tformat += \"\\\")\\n\"\n\tif _, err := fmt.Fprintf(w, format, name); err != nil {\n\t\treturn err\n\t}\n\treturn writeFlagHandler(\"--\"+name, flag.Annotations, w)\n}\n\nfunc writeLocalNonPersistentFlag(flag *pflag.Flag, w io.Writer) error {\n\tb := (len(flag.NoOptDefVal) > 0)\n\tname := flag.Name\n\tformat := \"    local_nonpersistent_flags+=(\\\"--%s\"\n\tif !b {\n\t\tformat += \"=\"\n\t}\n\tformat += \"\\\")\\n\"\n\t_, err := fmt.Fprintf(w, format, name)\n\treturn err\n}\n\nfunc writeFlags(cmd *Command, w io.Writer) error {\n\t_, err := fmt.Fprintf(w, `    flags=()\n    two_word_flags=()\n    local_nonpersistent_flags=()\n    flags_with_completion=()\n    flags_completion=()\n\n`)\n\tif err != nil {\n\t\treturn err\n\t}\n\tlocalNonPersistentFlags := cmd.LocalNonPersistentFlags()\n\tvar visitErr error\n\tcmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {\n\t\tif nonCompletableFlag(flag) {\n\t\t\treturn\n\t\t}\n\t\tif err := writeFlag(flag, w); err != nil {\n\t\t\tvisitErr = err\n\t\t\treturn\n\t\t}\n\t\tif len(flag.Shorthand) > 0 {\n\t\t\tif err := writeShortFlag(flag, w); err != nil {\n\t\t\t\tvisitErr = err\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\tif localNonPersistentFlags.Lookup(flag.Name) != nil {\n\t\t\tif err := writeLocalNonPersistentFlag(flag, w); err != nil {\n\t\t\t\tvisitErr = err\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t})\n\tif visitErr != nil {\n\t\treturn visitErr\n\t}\n\tcmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {\n\t\tif nonCompletableFlag(flag) {\n\t\t\treturn\n\t\t}\n\t\tif err := writeFlag(flag, w); err != nil {\n\t\t\tvisitErr = err\n\t\t\treturn\n\t\t}\n\t\tif len(flag.Shorthand) > 0 {\n\t\t\tif err := writeShortFlag(flag, w); err != nil {\n\t\t\t\tvisitErr = err\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t})\n\tif visitErr != nil {\n\t\treturn visitErr\n\t}\n\n\t_, err = fmt.Fprintf(w, \"\\n\")\n\treturn err\n}\n\nfunc writeRequiredFlag(cmd *Command, w io.Writer) error {\n\tif _, err := fmt.Fprintf(w, \"    must_have_one_flag=()\\n\"); err != nil {\n\t\treturn err\n\t}\n\tflags := cmd.NonInheritedFlags()\n\tvar visitErr error\n\tflags.VisitAll(func(flag *pflag.Flag) {\n\t\tif nonCompletableFlag(flag) {\n\t\t\treturn\n\t\t}\n\t\tfor key := range flag.Annotations {\n\t\t\tswitch key {\n\t\t\tcase BashCompOneRequiredFlag:\n\t\t\t\tformat := \"    must_have_one_flag+=(\\\"--%s\"\n\t\t\t\tb := (flag.Value.Type() == \"bool\")\n\t\t\t\tif !b {\n\t\t\t\t\tformat += \"=\"\n\t\t\t\t}\n\t\t\t\tformat += \"\\\")\\n\"\n\t\t\t\tif _, err := fmt.Fprintf(w, format, flag.Name); err != nil {\n\t\t\t\t\tvisitErr = err\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif len(flag.Shorthand) > 0 {\n\t\t\t\t\tif _, err := fmt.Fprintf(w, \"    must_have_one_flag+=(\\\"-%s\\\")\\n\", flag.Shorthand); err != nil {\n\t\t\t\t\t\tvisitErr = err\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\treturn visitErr\n}\n\nfunc writeRequiredNouns(cmd *Command, w io.Writer) error {\n\tif _, err := fmt.Fprintf(w, \"    must_have_one_noun=()\\n\"); err != nil {\n\t\treturn err\n\t}\n\tsort.Sort(sort.StringSlice(cmd.ValidArgs))\n\tfor _, value := range cmd.ValidArgs {\n\t\tif _, err := fmt.Fprintf(w, \"    must_have_one_noun+=(%q)\\n\", value); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc writeArgAliases(cmd *Command, w io.Writer) error {\n\tif _, err := fmt.Fprintf(w, \"    noun_aliases=()\\n\"); err != nil {\n\t\treturn err\n\t}\n\tsort.Sort(sort.StringSlice(cmd.ArgAliases))\n\tfor _, value := range cmd.ArgAliases {\n\t\tif _, err := fmt.Fprintf(w, \"    noun_aliases+=(%q)\\n\", value); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc gen(cmd *Command, w io.Writer) error {\n\tfor _, c := range cmd.Commands() {\n\t\tif !c.IsAvailableCommand() || c == cmd.helpCommand {\n\t\t\tcontinue\n\t\t}\n\t\tif err := gen(c, w); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tcommandName := cmd.CommandPath()\n\tcommandName = strings.Replace(commandName, \" \", \"_\", -1)\n\tcommandName = strings.Replace(commandName, \":\", \"__\", -1)\n\tif _, err := fmt.Fprintf(w, \"_%s()\\n{\\n\", commandName); err != nil {\n\t\treturn err\n\t}\n\tif _, err := fmt.Fprintf(w, \"    last_command=%q\\n\", commandName); err != nil {\n\t\treturn err\n\t}\n\tif err := writeCommands(cmd, w); err != nil {\n\t\treturn err\n\t}\n\tif err := writeFlags(cmd, w); err != nil {\n\t\treturn err\n\t}\n\tif err := writeRequiredFlag(cmd, w); err != nil {\n\t\treturn err\n\t}\n\tif err := writeRequiredNouns(cmd, w); err != nil {\n\t\treturn err\n\t}\n\tif err := writeArgAliases(cmd, w); err != nil {\n\t\treturn err\n\t}\n\tif _, err := fmt.Fprintf(w, \"}\\n\\n\"); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// GenBashCompletion generates bash completion file and writes to the passed writer.\nfunc (cmd *Command) GenBashCompletion(w io.Writer) error {\n\tif err := preamble(w, cmd.Name()); err != nil {\n\t\treturn err\n\t}\n\tif len(cmd.BashCompletionFunction) > 0 {\n\t\tif _, err := fmt.Fprintf(w, \"%s\\n\", cmd.BashCompletionFunction); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif err := gen(cmd, w); err != nil {\n\t\treturn err\n\t}\n\treturn postscript(w, cmd.Name())\n}\n\nfunc nonCompletableFlag(flag *pflag.Flag) bool {\n\treturn flag.Hidden || len(flag.Deprecated) > 0\n}\n\n// GenBashCompletionFile generates bash completion file.\nfunc (cmd *Command) GenBashCompletionFile(filename string) error {\n\toutFile, err := os.Create(filename)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer outFile.Close()\n\n\treturn cmd.GenBashCompletion(outFile)\n}\n\n// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists.\nfunc (cmd *Command) MarkFlagRequired(name string) error {\n\treturn MarkFlagRequired(cmd.Flags(), name)\n}\n\n// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag, if it exists.\nfunc (cmd *Command) MarkPersistentFlagRequired(name string) error {\n\treturn MarkFlagRequired(cmd.PersistentFlags(), name)\n}\n\n// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag in the flag set, if it exists.\nfunc MarkFlagRequired(flags *pflag.FlagSet, name string) error {\n\treturn flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{\"true\"})\n}\n\n// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists.\n// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided.\nfunc (cmd *Command) MarkFlagFilename(name string, extensions ...string) error {\n\treturn MarkFlagFilename(cmd.Flags(), name, extensions...)\n}\n\n// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists.\n// Generated bash autocompletion will call the bash function f for the flag.\nfunc (cmd *Command) MarkFlagCustom(name string, f string) error {\n\treturn MarkFlagCustom(cmd.Flags(), name, f)\n}\n\n// MarkPersistentFlagFilename adds the BashCompFilenameExt annotation to the named persistent flag, if it exists.\n// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided.\nfunc (cmd *Command) MarkPersistentFlagFilename(name string, extensions ...string) error {\n\treturn MarkFlagFilename(cmd.PersistentFlags(), name, extensions...)\n}\n\n// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag in the flag set, if it exists.\n// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided.\nfunc MarkFlagFilename(flags *pflag.FlagSet, name string, extensions ...string) error {\n\treturn flags.SetAnnotation(name, BashCompFilenameExt, extensions)\n}\n\n// MarkFlagCustom adds the BashCompCustom annotation to the named flag in the flag set, if it exists.\n// Generated bash autocompletion will call the bash function f for the flag.\nfunc MarkFlagCustom(flags *pflag.FlagSet, name string, f string) error {\n\treturn flags.SetAnnotation(name, BashCompCustom, []string{f})\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/cobra/cobra.go",
    "content": "// Copyright © 2013 Steve Francia <spf@spf13.com>.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Commands similar to git, go tools and other modern CLI tools\n// inspired by go, go-Commander, gh and subcommand\n\npackage cobra\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"text/template\"\n\t\"unicode\"\n)\n\nvar templateFuncs = template.FuncMap{\n\t\"trim\":               strings.TrimSpace,\n\t\"trimRightSpace\":     trimRightSpace,\n\t\"appendIfNotPresent\": appendIfNotPresent,\n\t\"rpad\":               rpad,\n\t\"gt\":                 Gt,\n\t\"eq\":                 Eq,\n}\n\nvar initializers []func()\n\n// EnablePrefixMatching allows to set automatic prefix matching. Automatic prefix matching can be a dangerous thing\n// to automatically enable in CLI tools.\n// Set this to true to enable it.\nvar EnablePrefixMatching = false\n\n// EnableCommandSorting controls sorting of the slice of commands, which is turned on by default.\n// To disable sorting, set it to false.\nvar EnableCommandSorting = true\n\n// AddTemplateFunc adds a template function that's available to Usage and Help\n// template generation.\nfunc AddTemplateFunc(name string, tmplFunc interface{}) {\n\ttemplateFuncs[name] = tmplFunc\n}\n\n// AddTemplateFuncs adds multiple template functions availalble to Usage and\n// Help template generation.\nfunc AddTemplateFuncs(tmplFuncs template.FuncMap) {\n\tfor k, v := range tmplFuncs {\n\t\ttemplateFuncs[k] = v\n\t}\n}\n\n// OnInitialize takes a series of func() arguments and appends them to a slice of func().\nfunc OnInitialize(y ...func()) {\n\tinitializers = append(initializers, y...)\n}\n\n// Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans,\n// Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as\n// ints and then compared.\nfunc Gt(a interface{}, b interface{}) bool {\n\tvar left, right int64\n\tav := reflect.ValueOf(a)\n\n\tswitch av.Kind() {\n\tcase reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:\n\t\tleft = int64(av.Len())\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\tleft = av.Int()\n\tcase reflect.String:\n\t\tleft, _ = strconv.ParseInt(av.String(), 10, 64)\n\t}\n\n\tbv := reflect.ValueOf(b)\n\n\tswitch bv.Kind() {\n\tcase reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:\n\t\tright = int64(bv.Len())\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\tright = bv.Int()\n\tcase reflect.String:\n\t\tright, _ = strconv.ParseInt(bv.String(), 10, 64)\n\t}\n\n\treturn left > right\n}\n\n// Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic.\nfunc Eq(a interface{}, b interface{}) bool {\n\tav := reflect.ValueOf(a)\n\tbv := reflect.ValueOf(b)\n\n\tswitch av.Kind() {\n\tcase reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:\n\t\tpanic(\"Eq called on unsupported type\")\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\treturn av.Int() == bv.Int()\n\tcase reflect.String:\n\t\treturn av.String() == bv.String()\n\t}\n\treturn false\n}\n\nfunc trimRightSpace(s string) string {\n\treturn strings.TrimRightFunc(s, unicode.IsSpace)\n}\n\n// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s.\nfunc appendIfNotPresent(s, stringToAppend string) string {\n\tif strings.Contains(s, stringToAppend) {\n\t\treturn s\n\t}\n\treturn s + \" \" + stringToAppend\n}\n\n// rpad adds padding to the right of a string.\nfunc rpad(s string, padding int) string {\n\ttemplate := fmt.Sprintf(\"%%-%ds\", padding)\n\treturn fmt.Sprintf(template, s)\n}\n\n// tmpl executes the given template text on data, writing the result to w.\nfunc tmpl(w io.Writer, text string, data interface{}) error {\n\tt := template.New(\"top\")\n\tt.Funcs(templateFuncs)\n\ttemplate.Must(t.Parse(text))\n\treturn t.Execute(w, data)\n}\n\n// ld compares two strings and returns the levenshtein distance between them.\nfunc ld(s, t string, ignoreCase bool) int {\n\tif ignoreCase {\n\t\ts = strings.ToLower(s)\n\t\tt = strings.ToLower(t)\n\t}\n\td := make([][]int, len(s)+1)\n\tfor i := range d {\n\t\td[i] = make([]int, len(t)+1)\n\t}\n\tfor i := range d {\n\t\td[i][0] = i\n\t}\n\tfor j := range d[0] {\n\t\td[0][j] = j\n\t}\n\tfor j := 1; j <= len(t); j++ {\n\t\tfor i := 1; i <= len(s); i++ {\n\t\t\tif s[i-1] == t[j-1] {\n\t\t\t\td[i][j] = d[i-1][j-1]\n\t\t\t} else {\n\t\t\t\tmin := d[i-1][j]\n\t\t\t\tif d[i][j-1] < min {\n\t\t\t\t\tmin = d[i][j-1]\n\t\t\t\t}\n\t\t\t\tif d[i-1][j-1] < min {\n\t\t\t\t\tmin = d[i-1][j-1]\n\t\t\t\t}\n\t\t\t\td[i][j] = min + 1\n\t\t\t}\n\t\t}\n\n\t}\n\treturn d[len(s)][len(t)]\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/cobra/command.go",
    "content": "// Copyright © 2013 Steve Francia <spf@spf13.com>.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n//Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces.\n//In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code.\npackage cobra\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\n\tflag \"github.com/spf13/pflag\"\n)\n\n// Command is just that, a command for your application.\n// eg.  'go run' ... 'run' is the command. Cobra requires\n// you to define the usage and description as part of your command\n// definition to ensure usability.\ntype Command struct {\n\t// Name is the command name, usually the executable's name.\n\tname string\n\t// The one-line usage message.\n\tUse string\n\t// An array of aliases that can be used instead of the first word in Use.\n\tAliases []string\n\t// An array of command names for which this command will be suggested - similar to aliases but only suggests.\n\tSuggestFor []string\n\t// The short description shown in the 'help' output.\n\tShort string\n\t// The long message shown in the 'help <this-command>' output.\n\tLong string\n\t// Examples of how to use the command\n\tExample string\n\t// List of all valid non-flag arguments that are accepted in bash completions\n\tValidArgs []string\n\t// List of aliases for ValidArgs. These are not suggested to the user in the bash\n\t// completion, but accepted if entered manually.\n\tArgAliases []string\n\t// Custom functions used by the bash autocompletion generator\n\tBashCompletionFunction string\n\t// Is this command deprecated and should print this string when used?\n\tDeprecated string\n\t// Is this command hidden and should NOT show up in the list of available commands?\n\tHidden bool\n\t// Annotations are key/value pairs that can be used by applications to identify or\n\t// group commands\n\tAnnotations map[string]string\n\t// Full set of flags\n\tflags *flag.FlagSet\n\t// Set of flags childrens of this command will inherit\n\tpflags *flag.FlagSet\n\t// Flags that are declared specifically by this command (not inherited).\n\tlflags *flag.FlagSet\n\t// SilenceErrors is an option to quiet errors down stream\n\tSilenceErrors bool\n\t// Silence Usage is an option to silence usage when an error occurs.\n\tSilenceUsage bool\n\t// The *Run functions are executed in the following order:\n\t//   * PersistentPreRun()\n\t//   * PreRun()\n\t//   * Run()\n\t//   * PostRun()\n\t//   * PersistentPostRun()\n\t// All functions get the same args, the arguments after the command name\n\t// PersistentPreRun: children of this command will inherit and execute\n\tPersistentPreRun func(cmd *Command, args []string)\n\t// PersistentPreRunE: PersistentPreRun but returns an error\n\tPersistentPreRunE func(cmd *Command, args []string) error\n\t// PreRun: children of this command will not inherit.\n\tPreRun func(cmd *Command, args []string)\n\t// PreRunE: PreRun but returns an error\n\tPreRunE func(cmd *Command, args []string) error\n\t// Run: Typically the actual work function. Most commands will only implement this\n\tRun func(cmd *Command, args []string)\n\t// RunE: Run but returns an error\n\tRunE func(cmd *Command, args []string) error\n\t// PostRun: run after the Run command.\n\tPostRun func(cmd *Command, args []string)\n\t// PostRunE: PostRun but returns an error\n\tPostRunE func(cmd *Command, args []string) error\n\t// PersistentPostRun: children of this command will inherit and execute after PostRun\n\tPersistentPostRun func(cmd *Command, args []string)\n\t// PersistentPostRunE: PersistentPostRun but returns an error\n\tPersistentPostRunE func(cmd *Command, args []string) error\n\t// DisableAutoGenTag remove\n\tDisableAutoGenTag bool\n\t// Commands is the list of commands supported by this program.\n\tcommands []*Command\n\t// Parent Command for this command\n\tparent *Command\n\t// max lengths of commands' string lengths for use in padding\n\tcommandsMaxUseLen         int\n\tcommandsMaxCommandPathLen int\n\tcommandsMaxNameLen        int\n\t// is commands slice are sorted or not\n\tcommandsAreSorted bool\n\n\tflagErrorBuf *bytes.Buffer\n\n\targs          []string             // actual args parsed from flags\n\toutput        *io.Writer           // out writer if set in SetOutput(w)\n\tusageFunc     func(*Command) error // Usage can be defined by application\n\tusageTemplate string               // Can be defined by Application\n\tflagErrorFunc func(*Command, error) error\n\thelpTemplate  string                   // Can be defined by Application\n\thelpFunc      func(*Command, []string) // Help can be defined by application\n\thelpCommand   *Command                 // The help command\n\t// The global normalization function that we can use on every pFlag set and children commands\n\tglobNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName\n\n\t// Disable the suggestions based on Levenshtein distance that go along with 'unknown command' messages\n\tDisableSuggestions bool\n\t// If displaying suggestions, allows to set the minimum levenshtein distance to display, must be > 0\n\tSuggestionsMinimumDistance int\n\n\t// Disable the flag parsing. If this is true all flags will be passed to the command as arguments.\n\tDisableFlagParsing bool\n}\n\n// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden\n// particularly useful when testing.\nfunc (c *Command) SetArgs(a []string) {\n\tc.args = a\n}\n\n// SetOutput sets the destination for usage and error messages.\n// If output is nil, os.Stderr is used.\nfunc (c *Command) SetOutput(output io.Writer) {\n\tc.output = &output\n}\n\n// SetUsageFunc sets usage function. Usage can be defined by application.\nfunc (c *Command) SetUsageFunc(f func(*Command) error) {\n\tc.usageFunc = f\n}\n\n// SetUsageTemplate sets usage template. Can be defined by Application.\nfunc (c *Command) SetUsageTemplate(s string) {\n\tc.usageTemplate = s\n}\n\n// SetFlagErrorFunc sets a function to generate an error when flag parsing\n// fails.\nfunc (c *Command) SetFlagErrorFunc(f func(*Command, error) error) {\n\tc.flagErrorFunc = f\n}\n\n// SetHelpFunc sets help function. Can be defined by Application.\nfunc (c *Command) SetHelpFunc(f func(*Command, []string)) {\n\tc.helpFunc = f\n}\n\n// SetHelpCommand sets help command.\nfunc (c *Command) SetHelpCommand(cmd *Command) {\n\tc.helpCommand = cmd\n}\n\n// SetHelpTemplate sets help template to be used. Application can use it to set custom template.\nfunc (c *Command) SetHelpTemplate(s string) {\n\tc.helpTemplate = s\n}\n\n// SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands.\n// The user should not have a cyclic dependency on commands.\nfunc (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) {\n\tc.Flags().SetNormalizeFunc(n)\n\tc.PersistentFlags().SetNormalizeFunc(n)\n\tc.globNormFunc = n\n\n\tfor _, command := range c.commands {\n\t\tcommand.SetGlobalNormalizationFunc(n)\n\t}\n}\n\n// OutOrStdout returns output to stdout.\nfunc (c *Command) OutOrStdout() io.Writer {\n\treturn c.getOut(os.Stdout)\n}\n\n// OutOrStderr returns output to stderr\nfunc (c *Command) OutOrStderr() io.Writer {\n\treturn c.getOut(os.Stderr)\n}\n\nfunc (c *Command) getOut(def io.Writer) io.Writer {\n\tif c.output != nil {\n\t\treturn *c.output\n\t}\n\tif c.HasParent() {\n\t\treturn c.parent.getOut(def)\n\t}\n\treturn def\n}\n\n// UsageFunc returns either the function set by SetUsageFunc for this command\n// or a parent, or it returns a default usage function.\nfunc (c *Command) UsageFunc() (f func(*Command) error) {\n\tif c.usageFunc != nil {\n\t\treturn c.usageFunc\n\t}\n\n\tif c.HasParent() {\n\t\treturn c.parent.UsageFunc()\n\t}\n\treturn func(c *Command) error {\n\t\tc.mergePersistentFlags()\n\t\terr := tmpl(c.OutOrStderr(), c.UsageTemplate(), c)\n\t\tif err != nil {\n\t\t\tc.Println(err)\n\t\t}\n\t\treturn err\n\t}\n}\n\n// Usage puts out the usage for the command.\n// Used when a user provides invalid input.\n// Can be defined by user by overriding UsageFunc.\nfunc (c *Command) Usage() error {\n\treturn c.UsageFunc()(c)\n}\n\n// HelpFunc returns either the function set by SetHelpFunc for this command\n// or a parent, or it returns a function with default help behavior.\nfunc (c *Command) HelpFunc() func(*Command, []string) {\n\tif helpFunc := c.checkHelpFunc(); helpFunc != nil {\n\t\treturn helpFunc\n\t}\n\treturn func(*Command, []string) {\n\t\tc.mergePersistentFlags()\n\t\terr := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)\n\t\tif err != nil {\n\t\t\tc.Println(err)\n\t\t}\n\t}\n}\n\n// checkHelpFunc checks if there is helpFunc in ancestors of c.\nfunc (c *Command) checkHelpFunc() func(*Command, []string) {\n\tif c == nil {\n\t\treturn nil\n\t}\n\tif c.helpFunc != nil {\n\t\treturn c.helpFunc\n\t}\n\tif c.HasParent() {\n\t\treturn c.parent.checkHelpFunc()\n\t}\n\treturn nil\n}\n\n// Help puts out the help for the command.\n// Used when a user calls help [command].\n// Can be defined by user by overriding HelpFunc.\nfunc (c *Command) Help() error {\n\tc.HelpFunc()(c, []string{})\n\treturn nil\n}\n\n// UsageString return usage string.\nfunc (c *Command) UsageString() string {\n\ttmpOutput := c.output\n\tbb := new(bytes.Buffer)\n\tc.SetOutput(bb)\n\tc.Usage()\n\tc.output = tmpOutput\n\treturn bb.String()\n}\n\n// FlagErrorFunc returns either the function set by SetFlagErrorFunc for this\n// command or a parent, or it returns a function which returns the original\n// error.\nfunc (c *Command) FlagErrorFunc() (f func(*Command, error) error) {\n\tif c.flagErrorFunc != nil {\n\t\treturn c.flagErrorFunc\n\t}\n\n\tif c.HasParent() {\n\t\treturn c.parent.FlagErrorFunc()\n\t}\n\treturn func(c *Command, err error) error {\n\t\treturn err\n\t}\n}\n\nvar minUsagePadding = 25\n\n// UsagePadding return padding for the usage.\nfunc (c *Command) UsagePadding() int {\n\tif c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen {\n\t\treturn minUsagePadding\n\t}\n\treturn c.parent.commandsMaxUseLen\n}\n\nvar minCommandPathPadding = 11\n\n// CommandPathPadding return padding for the command path.\nfunc (c *Command) CommandPathPadding() int {\n\tif c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen {\n\t\treturn minCommandPathPadding\n\t}\n\treturn c.parent.commandsMaxCommandPathLen\n}\n\nvar minNamePadding = 11\n\n// NamePadding returns padding for the name.\nfunc (c *Command) NamePadding() int {\n\tif c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen {\n\t\treturn minNamePadding\n\t}\n\treturn c.parent.commandsMaxNameLen\n}\n\n// UsageTemplate returns usage template for the command.\nfunc (c *Command) UsageTemplate() string {\n\tif c.usageTemplate != \"\" {\n\t\treturn c.usageTemplate\n\t}\n\n\tif c.HasParent() {\n\t\treturn c.parent.UsageTemplate()\n\t}\n\treturn `Usage:{{if .Runnable}}\n  {{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine \"[flags]\"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}}\n  {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}\n\nAliases:\n  {{.NameAndAliases}}\n{{end}}{{if .HasExample}}\n\nExamples:\n{{ .Example }}{{end}}{{if .HasAvailableSubCommands}}\n\nAvailable Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name \"help\"))}}\n  {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}\n\nFlags:\n{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasAvailableInheritedFlags}}\n\nGlobal Flags:\n{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}\n\nAdditional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}\n  {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}\n\nUse \"{{.CommandPath}} [command] --help\" for more information about a command.{{end}}\n`\n}\n\n// HelpTemplate return help template for the command.\nfunc (c *Command) HelpTemplate() string {\n\tif c.helpTemplate != \"\" {\n\t\treturn c.helpTemplate\n\t}\n\n\tif c.HasParent() {\n\t\treturn c.parent.HelpTemplate()\n\t}\n\treturn `{{with or .Long .Short }}{{. | trim}}\n\n{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`\n}\n\n// Really only used when casting a command to a commander.\nfunc (c *Command) resetChildrensParents() {\n\tfor _, x := range c.commands {\n\t\tx.parent = c\n\t}\n}\n\nfunc hasNoOptDefVal(name string, f *flag.FlagSet) bool {\n\tflag := f.Lookup(name)\n\tif flag == nil {\n\t\treturn false\n\t}\n\treturn len(flag.NoOptDefVal) > 0\n}\n\nfunc shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool {\n\tresult := false\n\tfs.VisitAll(func(flag *flag.Flag) {\n\t\tif flag.Shorthand == name && len(flag.NoOptDefVal) > 0 {\n\t\t\tresult = true\n\t\t}\n\t})\n\treturn result\n}\n\nfunc stripFlags(args []string, c *Command) []string {\n\tif len(args) < 1 {\n\t\treturn args\n\t}\n\tc.mergePersistentFlags()\n\n\tcommands := []string{}\n\n\tinQuote := false\n\tinFlag := false\n\tfor _, y := range args {\n\t\tif !inQuote {\n\t\t\tswitch {\n\t\t\tcase strings.HasPrefix(y, \"\\\"\"):\n\t\t\t\tinQuote = true\n\t\t\tcase strings.Contains(y, \"=\\\"\"):\n\t\t\t\tinQuote = true\n\t\t\tcase strings.HasPrefix(y, \"--\") && !strings.Contains(y, \"=\"):\n\t\t\t\t// TODO: this isn't quite right, we should really check ahead for 'true' or 'false'\n\t\t\t\tinFlag = !hasNoOptDefVal(y[2:], c.Flags())\n\t\t\tcase strings.HasPrefix(y, \"-\") && !strings.Contains(y, \"=\") && len(y) == 2 && !shortHasNoOptDefVal(y[1:], c.Flags()):\n\t\t\t\tinFlag = true\n\t\t\tcase inFlag:\n\t\t\t\tinFlag = false\n\t\t\tcase y == \"\":\n\t\t\t// strip empty commands, as the go tests expect this to be ok....\n\t\t\tcase !strings.HasPrefix(y, \"-\"):\n\t\t\t\tcommands = append(commands, y)\n\t\t\t\tinFlag = false\n\t\t\t}\n\t\t}\n\n\t\tif strings.HasSuffix(y, \"\\\"\") && !strings.HasSuffix(y, \"\\\\\\\"\") {\n\t\t\tinQuote = false\n\t\t}\n\t}\n\n\treturn commands\n}\n\n// argsMinusFirstX removes only the first x from args.  Otherwise, commands that look like\n// openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]).\nfunc argsMinusFirstX(args []string, x string) []string {\n\tfor i, y := range args {\n\t\tif x == y {\n\t\t\tret := []string{}\n\t\t\tret = append(ret, args[:i]...)\n\t\t\tret = append(ret, args[i+1:]...)\n\t\t\treturn ret\n\t\t}\n\t}\n\treturn args\n}\n\n// Find the target command given the args and command tree\n// Meant to be run on the highest node. Only searches down.\nfunc (c *Command) Find(args []string) (*Command, []string, error) {\n\tif c == nil {\n\t\treturn nil, nil, fmt.Errorf(\"Called find() on a nil Command\")\n\t}\n\n\tvar innerfind func(*Command, []string) (*Command, []string)\n\n\tinnerfind = func(c *Command, innerArgs []string) (*Command, []string) {\n\t\targsWOflags := stripFlags(innerArgs, c)\n\t\tif len(argsWOflags) == 0 {\n\t\t\treturn c, innerArgs\n\t\t}\n\t\tnextSubCmd := argsWOflags[0]\n\t\tmatches := make([]*Command, 0)\n\t\tfor _, cmd := range c.commands {\n\t\t\tif cmd.Name() == nextSubCmd || cmd.HasAlias(nextSubCmd) { // exact name or alias match\n\t\t\t\treturn innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd))\n\t\t\t}\n\t\t\tif EnablePrefixMatching {\n\t\t\t\tif strings.HasPrefix(cmd.Name(), nextSubCmd) { // prefix match\n\t\t\t\t\tmatches = append(matches, cmd)\n\t\t\t\t}\n\t\t\t\tfor _, x := range cmd.Aliases {\n\t\t\t\t\tif strings.HasPrefix(x, nextSubCmd) {\n\t\t\t\t\t\tmatches = append(matches, cmd)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// only accept a single prefix match - multiple matches would be ambiguous\n\t\tif len(matches) == 1 {\n\t\t\treturn innerfind(matches[0], argsMinusFirstX(innerArgs, argsWOflags[0]))\n\t\t}\n\n\t\treturn c, innerArgs\n\t}\n\n\tcommandFound, a := innerfind(c, args)\n\targsWOflags := stripFlags(a, commandFound)\n\n\t// no subcommand, always take args\n\tif !commandFound.HasSubCommands() {\n\t\treturn commandFound, a, nil\n\t}\n\n\t// root command with subcommands, do subcommand checking\n\tif commandFound == c && len(argsWOflags) > 0 {\n\t\tsuggestionsString := \"\"\n\t\tif !c.DisableSuggestions {\n\t\t\tif c.SuggestionsMinimumDistance <= 0 {\n\t\t\t\tc.SuggestionsMinimumDistance = 2\n\t\t\t}\n\t\t\tif suggestions := c.SuggestionsFor(argsWOflags[0]); len(suggestions) > 0 {\n\t\t\t\tsuggestionsString += \"\\n\\nDid you mean this?\\n\"\n\t\t\t\tfor _, s := range suggestions {\n\t\t\t\t\tsuggestionsString += fmt.Sprintf(\"\\t%v\\n\", s)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn commandFound, a, fmt.Errorf(\"unknown command %q for %q%s\", argsWOflags[0], commandFound.CommandPath(), suggestionsString)\n\t}\n\n\treturn commandFound, a, nil\n}\n\n// SuggestionsFor provides suggestions for the typedName.\nfunc (c *Command) SuggestionsFor(typedName string) []string {\n\tsuggestions := []string{}\n\tfor _, cmd := range c.commands {\n\t\tif cmd.IsAvailableCommand() {\n\t\t\tlevenshteinDistance := ld(typedName, cmd.Name(), true)\n\t\t\tsuggestByLevenshtein := levenshteinDistance <= c.SuggestionsMinimumDistance\n\t\t\tsuggestByPrefix := strings.HasPrefix(strings.ToLower(cmd.Name()), strings.ToLower(typedName))\n\t\t\tif suggestByLevenshtein || suggestByPrefix {\n\t\t\t\tsuggestions = append(suggestions, cmd.Name())\n\t\t\t}\n\t\t\tfor _, explicitSuggestion := range cmd.SuggestFor {\n\t\t\t\tif strings.EqualFold(typedName, explicitSuggestion) {\n\t\t\t\t\tsuggestions = append(suggestions, cmd.Name())\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn suggestions\n}\n\n// VisitParents visits all parents of the command and invokes fn on each parent.\nfunc (c *Command) VisitParents(fn func(*Command)) {\n\tvar traverse func(*Command) *Command\n\n\ttraverse = func(x *Command) *Command {\n\t\tif x != c {\n\t\t\tfn(x)\n\t\t}\n\t\tif x.HasParent() {\n\t\t\treturn traverse(x.parent)\n\t\t}\n\t\treturn x\n\t}\n\ttraverse(c)\n}\n\n// Root finds root command.\nfunc (c *Command) Root() *Command {\n\tvar findRoot func(*Command) *Command\n\n\tfindRoot = func(x *Command) *Command {\n\t\tif x.HasParent() {\n\t\t\treturn findRoot(x.parent)\n\t\t}\n\t\treturn x\n\t}\n\n\treturn findRoot(c)\n}\n\n// ArgsLenAtDash will return the length of f.Args at the moment when a -- was\n// found during arg parsing. This allows your program to know which args were\n// before the -- and which came after. (Description from\n// https://godoc.org/github.com/spf13/pflag#FlagSet.ArgsLenAtDash).\nfunc (c *Command) ArgsLenAtDash() int {\n\treturn c.Flags().ArgsLenAtDash()\n}\n\nfunc (c *Command) execute(a []string) (err error) {\n\tif c == nil {\n\t\treturn fmt.Errorf(\"Called Execute() on a nil Command\")\n\t}\n\n\tif len(c.Deprecated) > 0 {\n\t\tc.Printf(\"Command %q is deprecated, %s\\n\", c.Name(), c.Deprecated)\n\t}\n\n\t// initialize help flag as the last point possible to allow for user\n\t// overriding\n\tc.initHelpFlag()\n\n\terr = c.ParseFlags(a)\n\tif err != nil {\n\t\treturn c.FlagErrorFunc()(c, err)\n\t}\n\t// If help is called, regardless of other flags, return we want help\n\t// Also say we need help if the command isn't runnable.\n\thelpVal, err := c.Flags().GetBool(\"help\")\n\tif err != nil {\n\t\t// should be impossible to get here as we always declare a help\n\t\t// flag in initHelpFlag()\n\t\tc.Println(\"\\\"help\\\" flag declared as non-bool. Please correct your code\")\n\t\treturn err\n\t}\n\n\tif helpVal || !c.Runnable() {\n\t\treturn flag.ErrHelp\n\t}\n\n\tc.preRun()\n\n\targWoFlags := c.Flags().Args()\n\tif c.DisableFlagParsing {\n\t\targWoFlags = a\n\t}\n\n\tfor p := c; p != nil; p = p.Parent() {\n\t\tif p.PersistentPreRunE != nil {\n\t\t\tif err := p.PersistentPreRunE(c, argWoFlags); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tbreak\n\t\t} else if p.PersistentPreRun != nil {\n\t\t\tp.PersistentPreRun(c, argWoFlags)\n\t\t\tbreak\n\t\t}\n\t}\n\tif c.PreRunE != nil {\n\t\tif err := c.PreRunE(c, argWoFlags); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else if c.PreRun != nil {\n\t\tc.PreRun(c, argWoFlags)\n\t}\n\n\tif c.RunE != nil {\n\t\tif err := c.RunE(c, argWoFlags); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tc.Run(c, argWoFlags)\n\t}\n\tif c.PostRunE != nil {\n\t\tif err := c.PostRunE(c, argWoFlags); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else if c.PostRun != nil {\n\t\tc.PostRun(c, argWoFlags)\n\t}\n\tfor p := c; p != nil; p = p.Parent() {\n\t\tif p.PersistentPostRunE != nil {\n\t\t\tif err := p.PersistentPostRunE(c, argWoFlags); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tbreak\n\t\t} else if p.PersistentPostRun != nil {\n\t\t\tp.PersistentPostRun(c, argWoFlags)\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (c *Command) preRun() {\n\tfor _, x := range initializers {\n\t\tx()\n\t}\n}\n\nfunc (c *Command) errorMsgFromParse() string {\n\ts := c.flagErrorBuf.String()\n\n\tx := strings.Split(s, \"\\n\")\n\n\tif len(x) > 0 {\n\t\treturn x[0]\n\t}\n\treturn \"\"\n}\n\n// Execute Call execute to use the args (os.Args[1:] by default)\n// and run through the command tree finding appropriate matches\n// for commands and then corresponding flags.\nfunc (c *Command) Execute() error {\n\t_, err := c.ExecuteC()\n\treturn err\n}\n\n// ExecuteC executes the command.\nfunc (c *Command) ExecuteC() (cmd *Command, err error) {\n\t// Regardless of what command execute is called on, run on Root only\n\tif c.HasParent() {\n\t\treturn c.Root().ExecuteC()\n\t}\n\n\t// windows hook\n\tif preExecHookFn != nil {\n\t\tpreExecHookFn(c)\n\t}\n\n\t// initialize help as the last point possible to allow for user\n\t// overriding\n\tc.initHelpCmd()\n\n\tvar args []string\n\n\t// Workaround FAIL with \"go test -v\" or \"cobra.test -test.v\", see #155\n\tif c.args == nil && filepath.Base(os.Args[0]) != \"cobra.test\" {\n\t\targs = os.Args[1:]\n\t} else {\n\t\targs = c.args\n\t}\n\n\tcmd, flags, err := c.Find(args)\n\tif err != nil {\n\t\t// If found parse to a subcommand and then failed, talk about the subcommand\n\t\tif cmd != nil {\n\t\t\tc = cmd\n\t\t}\n\t\tif !c.SilenceErrors {\n\t\t\tc.Println(\"Error:\", err.Error())\n\t\t\tc.Printf(\"Run '%v --help' for usage.\\n\", c.CommandPath())\n\t\t}\n\t\treturn c, err\n\t}\n\terr = cmd.execute(flags)\n\tif err != nil {\n\t\t// Always show help if requested, even if SilenceErrors is in\n\t\t// effect\n\t\tif err == flag.ErrHelp {\n\t\t\tcmd.HelpFunc()(cmd, args)\n\t\t\treturn cmd, nil\n\t\t}\n\n\t\t// If root command has SilentErrors flagged,\n\t\t// all subcommands should respect it\n\t\tif !cmd.SilenceErrors && !c.SilenceErrors {\n\t\t\tc.Println(\"Error:\", err.Error())\n\t\t}\n\n\t\t// If root command has SilentUsage flagged,\n\t\t// all subcommands should respect it\n\t\tif !cmd.SilenceUsage && !c.SilenceUsage {\n\t\t\tc.Println(cmd.UsageString())\n\t\t}\n\t\treturn cmd, err\n\t}\n\treturn cmd, nil\n}\n\nfunc (c *Command) initHelpFlag() {\n\tc.mergePersistentFlags()\n\tif c.Flags().Lookup(\"help\") == nil {\n\t\tc.Flags().BoolP(\"help\", \"h\", false, \"help for \"+c.Name())\n\t}\n}\n\nfunc (c *Command) initHelpCmd() {\n\tif c.helpCommand == nil {\n\t\tif !c.HasSubCommands() {\n\t\t\treturn\n\t\t}\n\n\t\tc.helpCommand = &Command{\n\t\t\tUse:   \"help [command]\",\n\t\t\tShort: \"Help about any command\",\n\t\t\tLong: `Help provides help for any command in the application.\n    Simply type ` + c.Name() + ` help [path to command] for full details.`,\n\t\t\tPersistentPreRun:  func(cmd *Command, args []string) {},\n\t\t\tPersistentPostRun: func(cmd *Command, args []string) {},\n\n\t\t\tRun: func(c *Command, args []string) {\n\t\t\t\tcmd, _, e := c.Root().Find(args)\n\t\t\t\tif cmd == nil || e != nil {\n\t\t\t\t\tc.Printf(\"Unknown help topic %#q\\n\", args)\n\t\t\t\t\tc.Root().Usage()\n\t\t\t\t} else {\n\t\t\t\t\tcmd.Help()\n\t\t\t\t}\n\t\t\t},\n\t\t}\n\t}\n\tc.AddCommand(c.helpCommand)\n}\n\n// ResetCommands used for testing.\nfunc (c *Command) ResetCommands() {\n\tc.commands = nil\n\tc.helpCommand = nil\n}\n\n// Sorts commands by their names.\ntype commandSorterByName []*Command\n\nfunc (c commandSorterByName) Len() int           { return len(c) }\nfunc (c commandSorterByName) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }\nfunc (c commandSorterByName) Less(i, j int) bool { return c[i].Name() < c[j].Name() }\n\n// Commands returns a sorted slice of child commands.\nfunc (c *Command) Commands() []*Command {\n\t// do not sort commands if it already sorted or sorting was disabled\n\tif EnableCommandSorting && !c.commandsAreSorted {\n\t\tsort.Sort(commandSorterByName(c.commands))\n\t\tc.commandsAreSorted = true\n\t}\n\treturn c.commands\n}\n\n// AddCommand adds one or more commands to this parent command.\nfunc (c *Command) AddCommand(cmds ...*Command) {\n\tfor i, x := range cmds {\n\t\tif cmds[i] == c {\n\t\t\tpanic(\"Command can't be a child of itself\")\n\t\t}\n\t\tcmds[i].parent = c\n\t\t// update max lengths\n\t\tusageLen := len(x.Use)\n\t\tif usageLen > c.commandsMaxUseLen {\n\t\t\tc.commandsMaxUseLen = usageLen\n\t\t}\n\t\tcommandPathLen := len(x.CommandPath())\n\t\tif commandPathLen > c.commandsMaxCommandPathLen {\n\t\t\tc.commandsMaxCommandPathLen = commandPathLen\n\t\t}\n\t\tnameLen := len(x.Name())\n\t\tif nameLen > c.commandsMaxNameLen {\n\t\t\tc.commandsMaxNameLen = nameLen\n\t\t}\n\t\t// If global normalization function exists, update all children\n\t\tif c.globNormFunc != nil {\n\t\t\tx.SetGlobalNormalizationFunc(c.globNormFunc)\n\t\t}\n\t\tc.commands = append(c.commands, x)\n\t\tc.commandsAreSorted = false\n\t}\n}\n\n// RemoveCommand removes one or more commands from a parent command.\nfunc (c *Command) RemoveCommand(cmds ...*Command) {\n\tcommands := []*Command{}\nmain:\n\tfor _, command := range c.commands {\n\t\tfor _, cmd := range cmds {\n\t\t\tif command == cmd {\n\t\t\t\tcommand.parent = nil\n\t\t\t\tcontinue main\n\t\t\t}\n\t\t}\n\t\tcommands = append(commands, command)\n\t}\n\tc.commands = commands\n\t// recompute all lengths\n\tc.commandsMaxUseLen = 0\n\tc.commandsMaxCommandPathLen = 0\n\tc.commandsMaxNameLen = 0\n\tfor _, command := range c.commands {\n\t\tusageLen := len(command.Use)\n\t\tif usageLen > c.commandsMaxUseLen {\n\t\t\tc.commandsMaxUseLen = usageLen\n\t\t}\n\t\tcommandPathLen := len(command.CommandPath())\n\t\tif commandPathLen > c.commandsMaxCommandPathLen {\n\t\t\tc.commandsMaxCommandPathLen = commandPathLen\n\t\t}\n\t\tnameLen := len(command.Name())\n\t\tif nameLen > c.commandsMaxNameLen {\n\t\t\tc.commandsMaxNameLen = nameLen\n\t\t}\n\t}\n}\n\n// Print is a convenience method to Print to the defined output, fallback to Stderr if not set.\nfunc (c *Command) Print(i ...interface{}) {\n\tfmt.Fprint(c.OutOrStderr(), i...)\n}\n\n// Println is a convenience method to Println to the defined output, fallback to Stderr if not set.\nfunc (c *Command) Println(i ...interface{}) {\n\tstr := fmt.Sprintln(i...)\n\tc.Print(str)\n}\n\n// Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set.\nfunc (c *Command) Printf(format string, i ...interface{}) {\n\tstr := fmt.Sprintf(format, i...)\n\tc.Print(str)\n}\n\n// CommandPath returns the full path to this command.\nfunc (c *Command) CommandPath() string {\n\tstr := c.Name()\n\tx := c\n\tfor x.HasParent() {\n\t\tstr = x.parent.Name() + \" \" + str\n\t\tx = x.parent\n\t}\n\treturn str\n}\n\n// UseLine puts out the full usage for a given command (including parents).\nfunc (c *Command) UseLine() string {\n\tstr := \"\"\n\tif c.HasParent() {\n\t\tstr = c.parent.CommandPath() + \" \"\n\t}\n\treturn str + c.Use\n}\n\n// DebugFlags used to determine which flags have been assigned to which commands\n// and which persist.\nfunc (c *Command) DebugFlags() {\n\tc.Println(\"DebugFlags called on\", c.Name())\n\tvar debugflags func(*Command)\n\n\tdebugflags = func(x *Command) {\n\t\tif x.HasFlags() || x.HasPersistentFlags() {\n\t\t\tc.Println(x.Name())\n\t\t}\n\t\tif x.HasFlags() {\n\t\t\tx.flags.VisitAll(func(f *flag.Flag) {\n\t\t\t\tif x.HasPersistentFlags() {\n\t\t\t\t\tif x.persistentFlag(f.Name) == nil {\n\t\t\t\t\t\tc.Println(\"  -\"+f.Shorthand+\",\", \"--\"+f.Name, \"[\"+f.DefValue+\"]\", \"\", f.Value, \"  [L]\")\n\t\t\t\t\t} else {\n\t\t\t\t\t\tc.Println(\"  -\"+f.Shorthand+\",\", \"--\"+f.Name, \"[\"+f.DefValue+\"]\", \"\", f.Value, \"  [LP]\")\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tc.Println(\"  -\"+f.Shorthand+\",\", \"--\"+f.Name, \"[\"+f.DefValue+\"]\", \"\", f.Value, \"  [L]\")\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tif x.HasPersistentFlags() {\n\t\t\tx.pflags.VisitAll(func(f *flag.Flag) {\n\t\t\t\tif x.HasFlags() {\n\t\t\t\t\tif x.flags.Lookup(f.Name) == nil {\n\t\t\t\t\t\tc.Println(\"  -\"+f.Shorthand+\",\", \"--\"+f.Name, \"[\"+f.DefValue+\"]\", \"\", f.Value, \"  [P]\")\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tc.Println(\"  -\"+f.Shorthand+\",\", \"--\"+f.Name, \"[\"+f.DefValue+\"]\", \"\", f.Value, \"  [P]\")\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tc.Println(x.flagErrorBuf)\n\t\tif x.HasSubCommands() {\n\t\t\tfor _, y := range x.commands {\n\t\t\t\tdebugflags(y)\n\t\t\t}\n\t\t}\n\t}\n\n\tdebugflags(c)\n}\n\n// Name returns the command's name: the first word in the use line.\nfunc (c *Command) Name() string {\n\tif c.name != \"\" {\n\t\treturn c.name\n\t}\n\tname := c.Use\n\ti := strings.Index(name, \" \")\n\tif i >= 0 {\n\t\tname = name[:i]\n\t}\n\tc.name = name\n\treturn c.name\n}\n\n// HasAlias determines if a given string is an alias of the command.\nfunc (c *Command) HasAlias(s string) bool {\n\tfor _, a := range c.Aliases {\n\t\tif a == s {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// NameAndAliases returns string containing name and all aliases\nfunc (c *Command) NameAndAliases() string {\n\treturn strings.Join(append([]string{c.Name()}, c.Aliases...), \", \")\n}\n\n// HasExample determines if the command has example.\nfunc (c *Command) HasExample() bool {\n\treturn len(c.Example) > 0\n}\n\n// Runnable determines if the command is itself runnable.\nfunc (c *Command) Runnable() bool {\n\treturn c.Run != nil || c.RunE != nil\n}\n\n// HasSubCommands determines if the command has children commands.\nfunc (c *Command) HasSubCommands() bool {\n\treturn len(c.commands) > 0\n}\n\n// IsAvailableCommand determines if a command is available as a non-help command\n// (this includes all non deprecated/hidden commands).\nfunc (c *Command) IsAvailableCommand() bool {\n\tif len(c.Deprecated) != 0 || c.Hidden {\n\t\treturn false\n\t}\n\n\tif c.HasParent() && c.Parent().helpCommand == c {\n\t\treturn false\n\t}\n\n\tif c.Runnable() || c.HasAvailableSubCommands() {\n\t\treturn true\n\t}\n\n\treturn false\n}\n\n// IsAdditionalHelpTopicCommand determines if a command is an additional\n// help topic command; additional help topic command is determined by the\n// fact that it is NOT runnable/hidden/deprecated, and has no sub commands that\n// are runnable/hidden/deprecated.\n// Concrete example: https://github.com/spf13/cobra/issues/393#issuecomment-282741924.\nfunc (c *Command) IsAdditionalHelpTopicCommand() bool {\n\t// if a command is runnable, deprecated, or hidden it is not a 'help' command\n\tif c.Runnable() || len(c.Deprecated) != 0 || c.Hidden {\n\t\treturn false\n\t}\n\n\t// if any non-help sub commands are found, the command is not a 'help' command\n\tfor _, sub := range c.commands {\n\t\tif !sub.IsAdditionalHelpTopicCommand() {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t// the command either has no sub commands, or no non-help sub commands\n\treturn true\n}\n\n// HasHelpSubCommands determines if a command has any available 'help' sub commands\n// that need to be shown in the usage/help default template under 'additional help\n// topics'.\nfunc (c *Command) HasHelpSubCommands() bool {\n\t// return true on the first found available 'help' sub command\n\tfor _, sub := range c.commands {\n\t\tif sub.IsAdditionalHelpTopicCommand() {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// the command either has no sub commands, or no available 'help' sub commands\n\treturn false\n}\n\n// HasAvailableSubCommands determines if a command has available sub commands that\n// need to be shown in the usage/help default template under 'available commands'.\nfunc (c *Command) HasAvailableSubCommands() bool {\n\t// return true on the first found available (non deprecated/help/hidden)\n\t// sub command\n\tfor _, sub := range c.commands {\n\t\tif sub.IsAvailableCommand() {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// the command either has no sub comamnds, or no available (non deprecated/help/hidden)\n\t// sub commands\n\treturn false\n}\n\n// HasParent determines if the command is a child command.\nfunc (c *Command) HasParent() bool {\n\treturn c.parent != nil\n}\n\n// GlobalNormalizationFunc returns the global normalization function or nil if doesn't exists.\nfunc (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName {\n\treturn c.globNormFunc\n}\n\n// Flags returns the complete FlagSet that applies\n// to this command (local and persistent declared here and by all parents).\nfunc (c *Command) Flags() *flag.FlagSet {\n\tif c.flags == nil {\n\t\tc.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)\n\t\tif c.flagErrorBuf == nil {\n\t\t\tc.flagErrorBuf = new(bytes.Buffer)\n\t\t}\n\t\tc.flags.SetOutput(c.flagErrorBuf)\n\t}\n\treturn c.flags\n}\n\n// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands.\nfunc (c *Command) LocalNonPersistentFlags() *flag.FlagSet {\n\tpersistentFlags := c.PersistentFlags()\n\n\tout := flag.NewFlagSet(c.Name(), flag.ContinueOnError)\n\tc.LocalFlags().VisitAll(func(f *flag.Flag) {\n\t\tif persistentFlags.Lookup(f.Name) == nil {\n\t\t\tout.AddFlag(f)\n\t\t}\n\t})\n\treturn out\n}\n\n// LocalFlags returns the local FlagSet specifically set in the current command.\nfunc (c *Command) LocalFlags() *flag.FlagSet {\n\tc.mergePersistentFlags()\n\n\tlocal := flag.NewFlagSet(c.Name(), flag.ContinueOnError)\n\tc.lflags.VisitAll(func(f *flag.Flag) {\n\t\tlocal.AddFlag(f)\n\t})\n\tif !c.HasParent() {\n\t\tflag.CommandLine.VisitAll(func(f *flag.Flag) {\n\t\t\tif local.Lookup(f.Name) == nil {\n\t\t\t\tlocal.AddFlag(f)\n\t\t\t}\n\t\t})\n\t}\n\treturn local\n}\n\n// InheritedFlags returns all flags which were inherited from parents commands.\nfunc (c *Command) InheritedFlags() *flag.FlagSet {\n\tc.mergePersistentFlags()\n\n\tinherited := flag.NewFlagSet(c.Name(), flag.ContinueOnError)\n\tlocal := c.LocalFlags()\n\n\tvar rmerge func(x *Command)\n\n\trmerge = func(x *Command) {\n\t\tif x.HasPersistentFlags() {\n\t\t\tx.PersistentFlags().VisitAll(func(f *flag.Flag) {\n\t\t\t\tif inherited.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil {\n\t\t\t\t\tinherited.AddFlag(f)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tif x.HasParent() {\n\t\t\trmerge(x.parent)\n\t\t}\n\t}\n\n\tif c.HasParent() {\n\t\trmerge(c.parent)\n\t}\n\n\treturn inherited\n}\n\n// NonInheritedFlags returns all flags which were not inherited from parent commands.\nfunc (c *Command) NonInheritedFlags() *flag.FlagSet {\n\treturn c.LocalFlags()\n}\n\n// PersistentFlags returns the persistent FlagSet specifically set in the current command.\nfunc (c *Command) PersistentFlags() *flag.FlagSet {\n\tif c.pflags == nil {\n\t\tc.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)\n\t\tif c.flagErrorBuf == nil {\n\t\t\tc.flagErrorBuf = new(bytes.Buffer)\n\t\t}\n\t\tc.pflags.SetOutput(c.flagErrorBuf)\n\t}\n\treturn c.pflags\n}\n\n// ResetFlags is used in testing.\nfunc (c *Command) ResetFlags() {\n\tc.flagErrorBuf = new(bytes.Buffer)\n\tc.flagErrorBuf.Reset()\n\tc.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)\n\tc.flags.SetOutput(c.flagErrorBuf)\n\tc.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)\n\tc.pflags.SetOutput(c.flagErrorBuf)\n}\n\n// HasFlags checks if the command contains any flags (local plus persistent from the entire structure).\nfunc (c *Command) HasFlags() bool {\n\treturn c.Flags().HasFlags()\n}\n\n// HasPersistentFlags checks if the command contains persistent flags.\nfunc (c *Command) HasPersistentFlags() bool {\n\treturn c.PersistentFlags().HasFlags()\n}\n\n// HasLocalFlags checks if the command has flags specifically declared locally.\nfunc (c *Command) HasLocalFlags() bool {\n\treturn c.LocalFlags().HasFlags()\n}\n\n// HasInheritedFlags checks if the command has flags inherited from its parent command.\nfunc (c *Command) HasInheritedFlags() bool {\n\treturn c.InheritedFlags().HasFlags()\n}\n\n// HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire\n// structure) which are not hidden or deprecated.\nfunc (c *Command) HasAvailableFlags() bool {\n\treturn c.Flags().HasAvailableFlags()\n}\n\n// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated.\nfunc (c *Command) HasAvailablePersistentFlags() bool {\n\treturn c.PersistentFlags().HasAvailableFlags()\n}\n\n// HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden\n// or deprecated.\nfunc (c *Command) HasAvailableLocalFlags() bool {\n\treturn c.LocalFlags().HasAvailableFlags()\n}\n\n// HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are\n// not hidden or deprecated.\nfunc (c *Command) HasAvailableInheritedFlags() bool {\n\treturn c.InheritedFlags().HasAvailableFlags()\n}\n\n// Flag climbs up the command tree looking for matching flag.\nfunc (c *Command) Flag(name string) (flag *flag.Flag) {\n\tflag = c.Flags().Lookup(name)\n\n\tif flag == nil {\n\t\tflag = c.persistentFlag(name)\n\t}\n\n\treturn\n}\n\n// Recursively find matching persistent flag.\nfunc (c *Command) persistentFlag(name string) (flag *flag.Flag) {\n\tif c.HasPersistentFlags() {\n\t\tflag = c.PersistentFlags().Lookup(name)\n\t}\n\n\tif flag == nil && c.HasParent() {\n\t\tflag = c.parent.persistentFlag(name)\n\t}\n\treturn\n}\n\n// ParseFlags parses persistent flag tree and local flags.\nfunc (c *Command) ParseFlags(args []string) (err error) {\n\tif c.DisableFlagParsing {\n\t\treturn nil\n\t}\n\tc.mergePersistentFlags()\n\terr = c.Flags().Parse(args)\n\treturn\n}\n\n// Parent returns a commands parent command.\nfunc (c *Command) Parent() *Command {\n\treturn c.parent\n}\n\nfunc (c *Command) mergePersistentFlags() {\n\tvar rmerge func(x *Command)\n\n\t// Save the set of local flags\n\tif c.lflags == nil {\n\t\tc.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)\n\t\tif c.flagErrorBuf == nil {\n\t\t\tc.flagErrorBuf = new(bytes.Buffer)\n\t\t}\n\t\tc.lflags.SetOutput(c.flagErrorBuf)\n\t\taddtolocal := func(f *flag.Flag) {\n\t\t\tc.lflags.AddFlag(f)\n\t\t}\n\t\tc.Flags().VisitAll(addtolocal)\n\t\tc.PersistentFlags().VisitAll(addtolocal)\n\t}\n\trmerge = func(x *Command) {\n\t\tif !x.HasParent() {\n\t\t\tflag.CommandLine.VisitAll(func(f *flag.Flag) {\n\t\t\t\tif x.PersistentFlags().Lookup(f.Name) == nil {\n\t\t\t\t\tx.PersistentFlags().AddFlag(f)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tif x.HasPersistentFlags() {\n\t\t\tx.PersistentFlags().VisitAll(func(f *flag.Flag) {\n\t\t\t\tif c.Flags().Lookup(f.Name) == nil {\n\t\t\t\t\tc.Flags().AddFlag(f)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tif x.HasParent() {\n\t\t\trmerge(x.parent)\n\t\t}\n\t}\n\n\trmerge(c)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/cobra/command_notwin.go",
    "content": "// +build !windows\n\npackage cobra\n\nvar preExecHookFn func(*Command)\n"
  },
  {
    "path": "vendor/github.com/spf13/cobra/command_win.go",
    "content": "// +build windows\n\npackage cobra\n\nimport (\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/inconshreveable/mousetrap\"\n)\n\nvar preExecHookFn = preExecHook\n\n// enables an information splash screen on Windows if the CLI is started from explorer.exe.\nvar MousetrapHelpText string = `This is a command line tool\n\nYou need to open cmd.exe and run it from there.\n`\n\nfunc preExecHook(c *Command) {\n\tif mousetrap.StartedByExplorer() {\n\t\tc.Print(MousetrapHelpText)\n\t\ttime.Sleep(5 * time.Second)\n\t\tos.Exit(1)\n\t}\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/cobra/doc/man_docs.go",
    "content": "// Copyright 2015 Red Hat Inc. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage doc\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\tmangen \"github.com/cpuguy83/go-md2man/md2man\"\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/pflag\"\n)\n\n// GenManTree will generate a man page for this command and all descendants\n// in the directory given. The header may be nil. This function may not work\n// correctly if your command names have - in them. If you have `cmd` with two\n// subcmds, `sub` and `sub-third`. And `sub` has a subcommand called `third`\n// it is undefined which help output will be in the file `cmd-sub-third.1`.\nfunc GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error {\n\treturn GenManTreeFromOpts(cmd, GenManTreeOptions{\n\t\tHeader:           header,\n\t\tPath:             dir,\n\t\tCommandSeparator: \"-\",\n\t})\n}\n\n// GenManTreeFromOpts generates a man page for the command and all descendants.\n// The pages are written to the opts.Path directory.\nfunc GenManTreeFromOpts(cmd *cobra.Command, opts GenManTreeOptions) error {\n\theader := opts.Header\n\tif header == nil {\n\t\theader = &GenManHeader{}\n\t}\n\tfor _, c := range cmd.Commands() {\n\t\tif !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {\n\t\t\tcontinue\n\t\t}\n\t\tif err := GenManTreeFromOpts(c, opts); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tsection := \"1\"\n\tif header.Section != \"\" {\n\t\tsection = header.Section\n\t}\n\n\tseparator := \"_\"\n\tif opts.CommandSeparator != \"\" {\n\t\tseparator = opts.CommandSeparator\n\t}\n\tbasename := strings.Replace(cmd.CommandPath(), \" \", separator, -1)\n\tfilename := filepath.Join(opts.Path, basename+\".\"+section)\n\tf, err := os.Create(filename)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer f.Close()\n\n\theaderCopy := *header\n\treturn GenMan(cmd, &headerCopy, f)\n}\n\ntype GenManTreeOptions struct {\n\tHeader           *GenManHeader\n\tPath             string\n\tCommandSeparator string\n}\n\n// GenManHeader is a lot like the .TH header at the start of man pages. These\n// include the title, section, date, source, and manual. We will use the\n// current time if Date if unset and will use \"Auto generated by spf13/cobra\"\n// if the Source is unset.\ntype GenManHeader struct {\n\tTitle   string\n\tSection string\n\tDate    *time.Time\n\tdate    string\n\tSource  string\n\tManual  string\n}\n\n// GenMan will generate a man page for the given command and write it to\n// w. The header argument may be nil, however obviously w may not.\nfunc GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error {\n\tif header == nil {\n\t\theader = &GenManHeader{}\n\t}\n\tfillHeader(header, cmd.CommandPath())\n\n\tb := genMan(cmd, header)\n\t_, err := w.Write(mangen.Render(b))\n\treturn err\n}\n\nfunc fillHeader(header *GenManHeader, name string) {\n\tif header.Title == \"\" {\n\t\theader.Title = strings.ToUpper(strings.Replace(name, \" \", \"\\\\-\", -1))\n\t}\n\tif header.Section == \"\" {\n\t\theader.Section = \"1\"\n\t}\n\tif header.Date == nil {\n\t\tnow := time.Now()\n\t\theader.Date = &now\n\t}\n\theader.date = (*header.Date).Format(\"Jan 2006\")\n\tif header.Source == \"\" {\n\t\theader.Source = \"Auto generated by spf13/cobra\"\n\t}\n}\n\nfunc manPreamble(out io.Writer, header *GenManHeader, cmd *cobra.Command, dashedName string) {\n\tdescription := cmd.Long\n\tif len(description) == 0 {\n\t\tdescription = cmd.Short\n\t}\n\n\tfmt.Fprintf(out, `%% %s(%s)%s\n%% %s\n%% %s\n# NAME\n`, header.Title, header.Section, header.date, header.Source, header.Manual)\n\tfmt.Fprintf(out, \"%s \\\\- %s\\n\\n\", dashedName, cmd.Short)\n\tfmt.Fprintf(out, \"# SYNOPSIS\\n\")\n\tfmt.Fprintf(out, \"**%s**\\n\\n\", cmd.UseLine())\n\tfmt.Fprintf(out, \"# DESCRIPTION\\n\")\n\tfmt.Fprintf(out, \"%s\\n\\n\", description)\n}\n\nfunc manPrintFlags(out io.Writer, flags *pflag.FlagSet) {\n\tflags.VisitAll(func(flag *pflag.Flag) {\n\t\tif len(flag.Deprecated) > 0 || flag.Hidden {\n\t\t\treturn\n\t\t}\n\t\tformat := \"\"\n\t\tif len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 {\n\t\t\tformat = fmt.Sprintf(\"**-%s**, **--%s**\", flag.Shorthand, flag.Name)\n\t\t} else {\n\t\t\tformat = fmt.Sprintf(\"**--%s**\", flag.Name)\n\t\t}\n\t\tif len(flag.NoOptDefVal) > 0 {\n\t\t\tformat = format + \"[\"\n\t\t}\n\t\tif flag.Value.Type() == \"string\" {\n\t\t\t// put quotes on the value\n\t\t\tformat = format + \"=%q\"\n\t\t} else {\n\t\t\tformat = format + \"=%s\"\n\t\t}\n\t\tif len(flag.NoOptDefVal) > 0 {\n\t\t\tformat = format + \"]\"\n\t\t}\n\t\tformat = format + \"\\n\\t%s\\n\\n\"\n\t\tfmt.Fprintf(out, format, flag.DefValue, flag.Usage)\n\t})\n}\n\nfunc manPrintOptions(out io.Writer, command *cobra.Command) {\n\tflags := command.NonInheritedFlags()\n\tif flags.HasFlags() {\n\t\tfmt.Fprintf(out, \"# OPTIONS\\n\")\n\t\tmanPrintFlags(out, flags)\n\t\tfmt.Fprintf(out, \"\\n\")\n\t}\n\tflags = command.InheritedFlags()\n\tif flags.HasFlags() {\n\t\tfmt.Fprintf(out, \"# OPTIONS INHERITED FROM PARENT COMMANDS\\n\")\n\t\tmanPrintFlags(out, flags)\n\t\tfmt.Fprintf(out, \"\\n\")\n\t}\n}\n\nfunc genMan(cmd *cobra.Command, header *GenManHeader) []byte {\n\t// something like `rootcmd-subcmd1-subcmd2`\n\tdashCommandName := strings.Replace(cmd.CommandPath(), \" \", \"-\", -1)\n\n\tbuf := new(bytes.Buffer)\n\n\tmanPreamble(buf, header, cmd, dashCommandName)\n\tmanPrintOptions(buf, cmd)\n\tif len(cmd.Example) > 0 {\n\t\tfmt.Fprintf(buf, \"# EXAMPLE\\n\")\n\t\tfmt.Fprintf(buf, \"```\\n%s\\n```\\n\", cmd.Example)\n\t}\n\tif hasSeeAlso(cmd) {\n\t\tfmt.Fprintf(buf, \"# SEE ALSO\\n\")\n\t\tseealsos := make([]string, 0)\n\t\tif cmd.HasParent() {\n\t\t\tparentPath := cmd.Parent().CommandPath()\n\t\t\tdashParentPath := strings.Replace(parentPath, \" \", \"-\", -1)\n\t\t\tseealso := fmt.Sprintf(\"**%s(%s)**\", dashParentPath, header.Section)\n\t\t\tseealsos = append(seealsos, seealso)\n\t\t\tcmd.VisitParents(func(c *cobra.Command) {\n\t\t\t\tif c.DisableAutoGenTag {\n\t\t\t\t\tcmd.DisableAutoGenTag = c.DisableAutoGenTag\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tchildren := cmd.Commands()\n\t\tsort.Sort(byName(children))\n\t\tfor _, c := range children {\n\t\t\tif !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tseealso := fmt.Sprintf(\"**%s-%s(%s)**\", dashCommandName, c.Name(), header.Section)\n\t\t\tseealsos = append(seealsos, seealso)\n\t\t}\n\t\tfmt.Fprintf(buf, \"%s\\n\", strings.Join(seealsos, \", \"))\n\t}\n\tif !cmd.DisableAutoGenTag {\n\t\tfmt.Fprintf(buf, \"# HISTORY\\n%s Auto generated by spf13/cobra\\n\", header.Date.Format(\"2-Jan-2006\"))\n\t}\n\treturn buf.Bytes()\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/cobra/doc/md_docs.go",
    "content": "//Copyright 2015 Red Hat Inc. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage doc\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/spf13/cobra\"\n)\n\nfunc printOptions(w io.Writer, cmd *cobra.Command, name string) error {\n\tflags := cmd.NonInheritedFlags()\n\tflags.SetOutput(w)\n\tif flags.HasFlags() {\n\t\tif _, err := fmt.Fprintf(w, \"### Options\\n\\n```\\n\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tflags.PrintDefaults()\n\t\tif _, err := fmt.Fprintf(w, \"```\\n\\n\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tparentFlags := cmd.InheritedFlags()\n\tparentFlags.SetOutput(w)\n\tif parentFlags.HasFlags() {\n\t\tif _, err := fmt.Fprintf(w, \"### Options inherited from parent commands\\n\\n```\\n\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tparentFlags.PrintDefaults()\n\t\tif _, err := fmt.Fprintf(w, \"```\\n\\n\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc GenMarkdown(cmd *cobra.Command, w io.Writer) error {\n\treturn GenMarkdownCustom(cmd, w, func(s string) string { return s })\n}\n\nfunc GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error {\n\tname := cmd.CommandPath()\n\n\tshort := cmd.Short\n\tlong := cmd.Long\n\tif len(long) == 0 {\n\t\tlong = short\n\t}\n\n\tif _, err := fmt.Fprintf(w, \"## %s\\n\\n\", name); err != nil {\n\t\treturn err\n\t}\n\tif _, err := fmt.Fprintf(w, \"%s\\n\\n\", short); err != nil {\n\t\treturn err\n\t}\n\tif _, err := fmt.Fprintf(w, \"### Synopsis\\n\\n\"); err != nil {\n\t\treturn err\n\t}\n\tif _, err := fmt.Fprintf(w, \"\\n%s\\n\\n\", long); err != nil {\n\t\treturn err\n\t}\n\n\tif cmd.Runnable() {\n\t\tif _, err := fmt.Fprintf(w, \"```\\n%s\\n```\\n\\n\", cmd.UseLine()); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif len(cmd.Example) > 0 {\n\t\tif _, err := fmt.Fprintf(w, \"### Examples\\n\\n\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif _, err := fmt.Fprintf(w, \"```\\n%s\\n```\\n\\n\", cmd.Example); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif err := printOptions(w, cmd, name); err != nil {\n\t\treturn err\n\t}\n\tif hasSeeAlso(cmd) {\n\t\tif _, err := fmt.Fprintf(w, \"### SEE ALSO\\n\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif cmd.HasParent() {\n\t\t\tparent := cmd.Parent()\n\t\t\tpname := parent.CommandPath()\n\t\t\tlink := pname + \".md\"\n\t\t\tlink = strings.Replace(link, \" \", \"_\", -1)\n\t\t\tif _, err := fmt.Fprintf(w, \"* [%s](%s)\\t - %s\\n\", pname, linkHandler(link), parent.Short); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcmd.VisitParents(func(c *cobra.Command) {\n\t\t\t\tif c.DisableAutoGenTag {\n\t\t\t\t\tcmd.DisableAutoGenTag = c.DisableAutoGenTag\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\n\t\tchildren := cmd.Commands()\n\t\tsort.Sort(byName(children))\n\n\t\tfor _, child := range children {\n\t\t\tif !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcname := name + \" \" + child.Name()\n\t\t\tlink := cname + \".md\"\n\t\t\tlink = strings.Replace(link, \" \", \"_\", -1)\n\t\t\tif _, err := fmt.Fprintf(w, \"* [%s](%s)\\t - %s\\n\", cname, linkHandler(link), child.Short); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tif _, err := fmt.Fprintf(w, \"\\n\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif !cmd.DisableAutoGenTag {\n\t\tif _, err := fmt.Fprintf(w, \"###### Auto generated by spf13/cobra on %s\\n\", time.Now().Format(\"2-Jan-2006\")); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc GenMarkdownTree(cmd *cobra.Command, dir string) error {\n\tidentity := func(s string) string { return s }\n\temptyStr := func(s string) string { return \"\" }\n\treturn GenMarkdownTreeCustom(cmd, dir, emptyStr, identity)\n}\n\nfunc GenMarkdownTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error {\n\tfor _, c := range cmd.Commands() {\n\t\tif !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {\n\t\t\tcontinue\n\t\t}\n\t\tif err := GenMarkdownTreeCustom(c, dir, filePrepender, linkHandler); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tbasename := strings.Replace(cmd.CommandPath(), \" \", \"_\", -1) + \".md\"\n\tfilename := filepath.Join(dir, basename)\n\tf, err := os.Create(filename)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer f.Close()\n\n\tif _, err := io.WriteString(f, filePrepender(filename)); err != nil {\n\t\treturn err\n\t}\n\tif err := GenMarkdownCustom(cmd, f, linkHandler); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/cobra/doc/util.go",
    "content": "// Copyright 2015 Red Hat Inc. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage doc\n\nimport (\n\t\"strings\"\n\n\t\"github.com/spf13/cobra\"\n)\n\n// Test to see if we have a reason to print See Also information in docs\n// Basically this is a test for a parent commend or a subcommand which is\n// both not deprecated and not the autogenerated help command.\nfunc hasSeeAlso(cmd *cobra.Command) bool {\n\tif cmd.HasParent() {\n\t\treturn true\n\t}\n\tfor _, c := range cmd.Commands() {\n\t\tif !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {\n\t\t\tcontinue\n\t\t}\n\t\treturn true\n\t}\n\treturn false\n}\n\n// Temporary workaround for yaml lib generating incorrect yaml with long strings\n// that do not contain \\n.\nfunc forceMultiLine(s string) string {\n\tif len(s) > 60 && !strings.Contains(s, \"\\n\") {\n\t\ts = s + \"\\n\"\n\t}\n\treturn s\n}\n\ntype byName []*cobra.Command\n\nfunc (s byName) Len() int           { return len(s) }\nfunc (s byName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }\nfunc (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }\n"
  },
  {
    "path": "vendor/github.com/spf13/cobra/doc/yaml_docs.go",
    "content": "// Copyright 2016 French Ben. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage doc\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/pflag\"\n\t\"gopkg.in/yaml.v2\"\n)\n\ntype cmdOption struct {\n\tName         string\n\tShorthand    string `yaml:\",omitempty\"`\n\tDefaultValue string `yaml:\"default_value,omitempty\"`\n\tUsage        string `yaml:\",omitempty\"`\n}\n\ntype cmdDoc struct {\n\tName             string\n\tSynopsis         string      `yaml:\",omitempty\"`\n\tDescription      string      `yaml:\",omitempty\"`\n\tOptions          []cmdOption `yaml:\",omitempty\"`\n\tInheritedOptions []cmdOption `yaml:\"inherited_options,omitempty\"`\n\tExample          string      `yaml:\",omitempty\"`\n\tSeeAlso          []string    `yaml:\"see_also,omitempty\"`\n}\n\n// GenYamlTree creates yaml structured ref files for this command and all descendants\n// in the directory given. This function may not work\n// correctly if your command names have - in them. If you have `cmd` with two\n// subcmds, `sub` and `sub-third`. And `sub` has a subcommand called `third`\n// it is undefined which help output will be in the file `cmd-sub-third.1`.\nfunc GenYamlTree(cmd *cobra.Command, dir string) error {\n\tidentity := func(s string) string { return s }\n\temptyStr := func(s string) string { return \"\" }\n\treturn GenYamlTreeCustom(cmd, dir, emptyStr, identity)\n}\n\n// GenYamlTreeCustom creates yaml structured ref files\nfunc GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error {\n\tfor _, c := range cmd.Commands() {\n\t\tif !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {\n\t\t\tcontinue\n\t\t}\n\t\tif err := GenYamlTreeCustom(c, dir, filePrepender, linkHandler); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tbasename := strings.Replace(cmd.CommandPath(), \" \", \"_\", -1) + \".yaml\"\n\tfilename := filepath.Join(dir, basename)\n\tf, err := os.Create(filename)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer f.Close()\n\n\tif _, err := io.WriteString(f, filePrepender(filename)); err != nil {\n\t\treturn err\n\t}\n\tif err := GenYamlCustom(cmd, f, linkHandler); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// GenYaml creates yaml output\nfunc GenYaml(cmd *cobra.Command, w io.Writer) error {\n\treturn GenYamlCustom(cmd, w, func(s string) string { return s })\n}\n\n// GenYamlCustom creates custom yaml output\nfunc GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error {\n\tyamlDoc := cmdDoc{}\n\tyamlDoc.Name = cmd.CommandPath()\n\n\tyamlDoc.Synopsis = forceMultiLine(cmd.Short)\n\tyamlDoc.Description = forceMultiLine(cmd.Long)\n\n\tif len(cmd.Example) > 0 {\n\t\tyamlDoc.Example = cmd.Example\n\t}\n\n\tflags := cmd.NonInheritedFlags()\n\tif flags.HasFlags() {\n\t\tyamlDoc.Options = genFlagResult(flags)\n\t}\n\tflags = cmd.InheritedFlags()\n\tif flags.HasFlags() {\n\t\tyamlDoc.InheritedOptions = genFlagResult(flags)\n\t}\n\n\tif hasSeeAlso(cmd) {\n\t\tresult := []string{}\n\t\tif cmd.HasParent() {\n\t\t\tparent := cmd.Parent()\n\t\t\tresult = append(result, parent.CommandPath()+\" - \"+parent.Short)\n\t\t}\n\t\tchildren := cmd.Commands()\n\t\tsort.Sort(byName(children))\n\t\tfor _, child := range children {\n\t\t\tif !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tresult = append(result, child.Name()+\" - \"+child.Short)\n\t\t}\n\t\tyamlDoc.SeeAlso = result\n\t}\n\n\tfinal, err := yaml.Marshal(&yamlDoc)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\tos.Exit(1)\n\t}\n\tif _, err := fmt.Fprintf(w, string(final)); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc genFlagResult(flags *pflag.FlagSet) []cmdOption {\n\tvar result []cmdOption\n\n\tflags.VisitAll(func(flag *pflag.Flag) {\n\t\t// Todo, when we mark a shorthand is deprecated, but specify an empty message.\n\t\t// The flag.ShorthandDeprecated is empty as the shorthand is deprecated.\n\t\t// Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok.\n\t\tif !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 {\n\t\t\topt := cmdOption{\n\t\t\t\tflag.Name,\n\t\t\t\tflag.Shorthand,\n\t\t\t\tflag.DefValue,\n\t\t\t\tforceMultiLine(flag.Usage),\n\t\t\t}\n\t\t\tresult = append(result, opt)\n\t\t} else {\n\t\t\topt := cmdOption{\n\t\t\t\tName:         flag.Name,\n\t\t\t\tDefaultValue: forceMultiLine(flag.DefValue),\n\t\t\t\tUsage:        forceMultiLine(flag.Usage),\n\t\t\t}\n\t\t\tresult = append(result, opt)\n\t\t}\n\t})\n\n\treturn result\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/LICENSE",
    "content": "Copyright (c) 2012 Alex Ogier. All rights reserved.\nCopyright (c) 2012 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n   * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n   * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n   * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/bool.go",
    "content": "package pflag\n\nimport \"strconv\"\n\n// optional interface to indicate boolean flags that can be\n// supplied without \"=value\" text\ntype boolFlag interface {\n\tValue\n\tIsBoolFlag() bool\n}\n\n// -- bool Value\ntype boolValue bool\n\nfunc newBoolValue(val bool, p *bool) *boolValue {\n\t*p = val\n\treturn (*boolValue)(p)\n}\n\nfunc (b *boolValue) Set(s string) error {\n\tv, err := strconv.ParseBool(s)\n\t*b = boolValue(v)\n\treturn err\n}\n\nfunc (b *boolValue) Type() string {\n\treturn \"bool\"\n}\n\nfunc (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) }\n\nfunc (b *boolValue) IsBoolFlag() bool { return true }\n\nfunc boolConv(sval string) (interface{}, error) {\n\treturn strconv.ParseBool(sval)\n}\n\n// GetBool return the bool value of a flag with the given name\nfunc (f *FlagSet) GetBool(name string) (bool, error) {\n\tval, err := f.getFlagType(name, \"bool\", boolConv)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\treturn val.(bool), nil\n}\n\n// BoolVar defines a bool flag with specified name, default value, and usage string.\n// The argument p points to a bool variable in which to store the value of the flag.\nfunc (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) {\n\tf.BoolVarP(p, name, \"\", value, usage)\n}\n\n// BoolVarP is like BoolVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) BoolVarP(p *bool, name, shorthand string, value bool, usage string) {\n\tflag := f.VarPF(newBoolValue(value, p), name, shorthand, usage)\n\tflag.NoOptDefVal = \"true\"\n}\n\n// BoolVar defines a bool flag with specified name, default value, and usage string.\n// The argument p points to a bool variable in which to store the value of the flag.\nfunc BoolVar(p *bool, name string, value bool, usage string) {\n\tBoolVarP(p, name, \"\", value, usage)\n}\n\n// BoolVarP is like BoolVar, but accepts a shorthand letter that can be used after a single dash.\nfunc BoolVarP(p *bool, name, shorthand string, value bool, usage string) {\n\tflag := CommandLine.VarPF(newBoolValue(value, p), name, shorthand, usage)\n\tflag.NoOptDefVal = \"true\"\n}\n\n// Bool defines a bool flag with specified name, default value, and usage string.\n// The return value is the address of a bool variable that stores the value of the flag.\nfunc (f *FlagSet) Bool(name string, value bool, usage string) *bool {\n\treturn f.BoolP(name, \"\", value, usage)\n}\n\n// BoolP is like Bool, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) BoolP(name, shorthand string, value bool, usage string) *bool {\n\tp := new(bool)\n\tf.BoolVarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// Bool defines a bool flag with specified name, default value, and usage string.\n// The return value is the address of a bool variable that stores the value of the flag.\nfunc Bool(name string, value bool, usage string) *bool {\n\treturn BoolP(name, \"\", value, usage)\n}\n\n// BoolP is like Bool, but accepts a shorthand letter that can be used after a single dash.\nfunc BoolP(name, shorthand string, value bool, usage string) *bool {\n\tb := CommandLine.BoolP(name, shorthand, value, usage)\n\treturn b\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/bool_slice.go",
    "content": "package pflag\n\nimport (\n\t\"io\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// -- boolSlice Value\ntype boolSliceValue struct {\n\tvalue   *[]bool\n\tchanged bool\n}\n\nfunc newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue {\n\tbsv := new(boolSliceValue)\n\tbsv.value = p\n\t*bsv.value = val\n\treturn bsv\n}\n\n// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag.\n// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended.\nfunc (s *boolSliceValue) Set(val string) error {\n\n\t// remove all quote characters\n\trmQuote := strings.NewReplacer(`\"`, \"\", `'`, \"\", \"`\", \"\")\n\n\t// read flag arguments with CSV parser\n\tboolStrSlice, err := readAsCSV(rmQuote.Replace(val))\n\tif err != nil && err != io.EOF {\n\t\treturn err\n\t}\n\n\t// parse boolean values into slice\n\tout := make([]bool, 0, len(boolStrSlice))\n\tfor _, boolStr := range boolStrSlice {\n\t\tb, err := strconv.ParseBool(strings.TrimSpace(boolStr))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tout = append(out, b)\n\t}\n\n\tif !s.changed {\n\t\t*s.value = out\n\t} else {\n\t\t*s.value = append(*s.value, out...)\n\t}\n\n\ts.changed = true\n\n\treturn nil\n}\n\n// Type returns a string that uniquely represents this flag's type.\nfunc (s *boolSliceValue) Type() string {\n\treturn \"boolSlice\"\n}\n\n// String defines a \"native\" format for this boolean slice flag value.\nfunc (s *boolSliceValue) String() string {\n\n\tboolStrSlice := make([]string, len(*s.value))\n\tfor i, b := range *s.value {\n\t\tboolStrSlice[i] = strconv.FormatBool(b)\n\t}\n\n\tout, _ := writeAsCSV(boolStrSlice)\n\n\treturn \"[\" + out + \"]\"\n}\n\nfunc boolSliceConv(val string) (interface{}, error) {\n\tval = strings.Trim(val, \"[]\")\n\t// Empty string would cause a slice with one (empty) entry\n\tif len(val) == 0 {\n\t\treturn []bool{}, nil\n\t}\n\tss := strings.Split(val, \",\")\n\tout := make([]bool, len(ss))\n\tfor i, t := range ss {\n\t\tvar err error\n\t\tout[i], err = strconv.ParseBool(t)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn out, nil\n}\n\n// GetBoolSlice returns the []bool value of a flag with the given name.\nfunc (f *FlagSet) GetBoolSlice(name string) ([]bool, error) {\n\tval, err := f.getFlagType(name, \"boolSlice\", boolSliceConv)\n\tif err != nil {\n\t\treturn []bool{}, err\n\t}\n\treturn val.([]bool), nil\n}\n\n// BoolSliceVar defines a boolSlice flag with specified name, default value, and usage string.\n// The argument p points to a []bool variable in which to store the value of the flag.\nfunc (f *FlagSet) BoolSliceVar(p *[]bool, name string, value []bool, usage string) {\n\tf.VarP(newBoolSliceValue(value, p), name, \"\", usage)\n}\n\n// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {\n\tf.VarP(newBoolSliceValue(value, p), name, shorthand, usage)\n}\n\n// BoolSliceVar defines a []bool flag with specified name, default value, and usage string.\n// The argument p points to a []bool variable in which to store the value of the flag.\nfunc BoolSliceVar(p *[]bool, name string, value []bool, usage string) {\n\tCommandLine.VarP(newBoolSliceValue(value, p), name, \"\", usage)\n}\n\n// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.\nfunc BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {\n\tCommandLine.VarP(newBoolSliceValue(value, p), name, shorthand, usage)\n}\n\n// BoolSlice defines a []bool flag with specified name, default value, and usage string.\n// The return value is the address of a []bool variable that stores the value of the flag.\nfunc (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool {\n\tp := []bool{}\n\tf.BoolSliceVarP(&p, name, \"\", value, usage)\n\treturn &p\n}\n\n// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {\n\tp := []bool{}\n\tf.BoolSliceVarP(&p, name, shorthand, value, usage)\n\treturn &p\n}\n\n// BoolSlice defines a []bool flag with specified name, default value, and usage string.\n// The return value is the address of a []bool variable that stores the value of the flag.\nfunc BoolSlice(name string, value []bool, usage string) *[]bool {\n\treturn CommandLine.BoolSliceP(name, \"\", value, usage)\n}\n\n// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.\nfunc BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {\n\treturn CommandLine.BoolSliceP(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/count.go",
    "content": "package pflag\n\nimport \"strconv\"\n\n// -- count Value\ntype countValue int\n\nfunc newCountValue(val int, p *int) *countValue {\n\t*p = val\n\treturn (*countValue)(p)\n}\n\nfunc (i *countValue) Set(s string) error {\n\tv, err := strconv.ParseInt(s, 0, 64)\n\t// -1 means that no specific value was passed, so increment\n\tif v == -1 {\n\t\t*i = countValue(*i + 1)\n\t} else {\n\t\t*i = countValue(v)\n\t}\n\treturn err\n}\n\nfunc (i *countValue) Type() string {\n\treturn \"count\"\n}\n\nfunc (i *countValue) String() string { return strconv.Itoa(int(*i)) }\n\nfunc countConv(sval string) (interface{}, error) {\n\ti, err := strconv.Atoi(sval)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn i, nil\n}\n\n// GetCount return the int value of a flag with the given name\nfunc (f *FlagSet) GetCount(name string) (int, error) {\n\tval, err := f.getFlagType(name, \"count\", countConv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn val.(int), nil\n}\n\n// CountVar defines a count flag with specified name, default value, and usage string.\n// The argument p points to an int variable in which to store the value of the flag.\n// A count flag will add 1 to its value evey time it is found on the command line\nfunc (f *FlagSet) CountVar(p *int, name string, usage string) {\n\tf.CountVarP(p, name, \"\", usage)\n}\n\n// CountVarP is like CountVar only take a shorthand for the flag name.\nfunc (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) {\n\tflag := f.VarPF(newCountValue(0, p), name, shorthand, usage)\n\tflag.NoOptDefVal = \"-1\"\n}\n\n// CountVar like CountVar only the flag is placed on the CommandLine instead of a given flag set\nfunc CountVar(p *int, name string, usage string) {\n\tCommandLine.CountVar(p, name, usage)\n}\n\n// CountVarP is like CountVar only take a shorthand for the flag name.\nfunc CountVarP(p *int, name, shorthand string, usage string) {\n\tCommandLine.CountVarP(p, name, shorthand, usage)\n}\n\n// Count defines a count flag with specified name, default value, and usage string.\n// The return value is the address of an int variable that stores the value of the flag.\n// A count flag will add 1 to its value evey time it is found on the command line\nfunc (f *FlagSet) Count(name string, usage string) *int {\n\tp := new(int)\n\tf.CountVarP(p, name, \"\", usage)\n\treturn p\n}\n\n// CountP is like Count only takes a shorthand for the flag name.\nfunc (f *FlagSet) CountP(name, shorthand string, usage string) *int {\n\tp := new(int)\n\tf.CountVarP(p, name, shorthand, usage)\n\treturn p\n}\n\n// Count like Count only the flag is placed on the CommandLine isntead of a given flag set\nfunc Count(name string, usage string) *int {\n\treturn CommandLine.CountP(name, \"\", usage)\n}\n\n// CountP is like Count only takes a shorthand for the flag name.\nfunc CountP(name, shorthand string, usage string) *int {\n\treturn CommandLine.CountP(name, shorthand, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/duration.go",
    "content": "package pflag\n\nimport (\n\t\"time\"\n)\n\n// -- time.Duration Value\ntype durationValue time.Duration\n\nfunc newDurationValue(val time.Duration, p *time.Duration) *durationValue {\n\t*p = val\n\treturn (*durationValue)(p)\n}\n\nfunc (d *durationValue) Set(s string) error {\n\tv, err := time.ParseDuration(s)\n\t*d = durationValue(v)\n\treturn err\n}\n\nfunc (d *durationValue) Type() string {\n\treturn \"duration\"\n}\n\nfunc (d *durationValue) String() string { return (*time.Duration)(d).String() }\n\nfunc durationConv(sval string) (interface{}, error) {\n\treturn time.ParseDuration(sval)\n}\n\n// GetDuration return the duration value of a flag with the given name\nfunc (f *FlagSet) GetDuration(name string) (time.Duration, error) {\n\tval, err := f.getFlagType(name, \"duration\", durationConv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn val.(time.Duration), nil\n}\n\n// DurationVar defines a time.Duration flag with specified name, default value, and usage string.\n// The argument p points to a time.Duration variable in which to store the value of the flag.\nfunc (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) {\n\tf.VarP(newDurationValue(value, p), name, \"\", usage)\n}\n\n// DurationVarP is like DurationVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) DurationVarP(p *time.Duration, name, shorthand string, value time.Duration, usage string) {\n\tf.VarP(newDurationValue(value, p), name, shorthand, usage)\n}\n\n// DurationVar defines a time.Duration flag with specified name, default value, and usage string.\n// The argument p points to a time.Duration variable in which to store the value of the flag.\nfunc DurationVar(p *time.Duration, name string, value time.Duration, usage string) {\n\tCommandLine.VarP(newDurationValue(value, p), name, \"\", usage)\n}\n\n// DurationVarP is like DurationVar, but accepts a shorthand letter that can be used after a single dash.\nfunc DurationVarP(p *time.Duration, name, shorthand string, value time.Duration, usage string) {\n\tCommandLine.VarP(newDurationValue(value, p), name, shorthand, usage)\n}\n\n// Duration defines a time.Duration flag with specified name, default value, and usage string.\n// The return value is the address of a time.Duration variable that stores the value of the flag.\nfunc (f *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration {\n\tp := new(time.Duration)\n\tf.DurationVarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// DurationP is like Duration, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) DurationP(name, shorthand string, value time.Duration, usage string) *time.Duration {\n\tp := new(time.Duration)\n\tf.DurationVarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// Duration defines a time.Duration flag with specified name, default value, and usage string.\n// The return value is the address of a time.Duration variable that stores the value of the flag.\nfunc Duration(name string, value time.Duration, usage string) *time.Duration {\n\treturn CommandLine.DurationP(name, \"\", value, usage)\n}\n\n// DurationP is like Duration, but accepts a shorthand letter that can be used after a single dash.\nfunc DurationP(name, shorthand string, value time.Duration, usage string) *time.Duration {\n\treturn CommandLine.DurationP(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/flag.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage pflag is a drop-in replacement for Go's flag package, implementing\nPOSIX/GNU-style --flags.\n\npflag is compatible with the GNU extensions to the POSIX recommendations\nfor command-line options. See\nhttp://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html\n\nUsage:\n\npflag is a drop-in replacement of Go's native flag package. If you import\npflag under the name \"flag\" then all code should continue to function\nwith no changes.\n\n\timport flag \"github.com/ogier/pflag\"\n\n\tThere is one exception to this: if you directly instantiate the Flag struct\nthere is one more field \"Shorthand\" that you will need to set.\nMost code never instantiates this struct directly, and instead uses\nfunctions such as String(), BoolVar(), and Var(), and is therefore\nunaffected.\n\nDefine flags using flag.String(), Bool(), Int(), etc.\n\nThis declares an integer flag, -flagname, stored in the pointer ip, with type *int.\n\tvar ip = flag.Int(\"flagname\", 1234, \"help message for flagname\")\nIf you like, you can bind the flag to a variable using the Var() functions.\n\tvar flagvar int\n\tfunc init() {\n\t\tflag.IntVar(&flagvar, \"flagname\", 1234, \"help message for flagname\")\n\t}\nOr you can create custom flags that satisfy the Value interface (with\npointer receivers) and couple them to flag parsing by\n\tflag.Var(&flagVal, \"name\", \"help message for flagname\")\nFor such flags, the default value is just the initial value of the variable.\n\nAfter all flags are defined, call\n\tflag.Parse()\nto parse the command line into the defined flags.\n\nFlags may then be used directly. If you're using the flags themselves,\nthey are all pointers; if you bind to variables, they're values.\n\tfmt.Println(\"ip has value \", *ip)\n\tfmt.Println(\"flagvar has value \", flagvar)\n\nAfter parsing, the arguments after the flag are available as the\nslice flag.Args() or individually as flag.Arg(i).\nThe arguments are indexed from 0 through flag.NArg()-1.\n\nThe pflag package also defines some new functions that are not in flag,\nthat give one-letter shorthands for flags. You can use these by appending\n'P' to the name of any function that defines a flag.\n\tvar ip = flag.IntP(\"flagname\", \"f\", 1234, \"help message\")\n\tvar flagvar bool\n\tfunc init() {\n\t\tflag.BoolVarP(\"boolname\", \"b\", true, \"help message\")\n\t}\n\tflag.VarP(&flagVar, \"varname\", \"v\", 1234, \"help message\")\nShorthand letters can be used with single dashes on the command line.\nBoolean shorthand flags can be combined with other shorthand flags.\n\nCommand line flag syntax:\n\t--flag    // boolean flags only\n\t--flag=x\n\nUnlike the flag package, a single dash before an option means something\ndifferent than a double dash. Single dashes signify a series of shorthand\nletters for flags. All but the last shorthand letter must be boolean flags.\n\t// boolean flags\n\t-f\n\t-abc\n\t// non-boolean flags\n\t-n 1234\n\t-Ifile\n\t// mixed\n\t-abcs \"hello\"\n\t-abcn1234\n\nFlag parsing stops after the terminator \"--\". Unlike the flag package,\nflags can be interspersed with arguments anywhere on the command line\nbefore this terminator.\n\nInteger flags accept 1234, 0664, 0x1234 and may be negative.\nBoolean flags (in their long form) accept 1, 0, t, f, true, false,\nTRUE, FALSE, True, False.\nDuration flags accept any input valid for time.ParseDuration.\n\nThe default set of command-line flags is controlled by\ntop-level functions.  The FlagSet type allows one to define\nindependent sets of flags, such as to implement subcommands\nin a command-line interface. The methods of FlagSet are\nanalogous to the top-level functions for the command-line\nflag set.\n*/\npackage pflag\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n)\n\n// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined.\nvar ErrHelp = errors.New(\"pflag: help requested\")\n\n// ErrorHandling defines how to handle flag parsing errors.\ntype ErrorHandling int\n\nconst (\n\t// ContinueOnError will return an err from Parse() if an error is found\n\tContinueOnError ErrorHandling = iota\n\t// ExitOnError will call os.Exit(2) if an error is found when parsing\n\tExitOnError\n\t// PanicOnError will panic() if an error is found when parsing flags\n\tPanicOnError\n)\n\n// NormalizedName is a flag name that has been normalized according to rules\n// for the FlagSet (e.g. making '-' and '_' equivalent).\ntype NormalizedName string\n\n// A FlagSet represents a set of defined flags.\ntype FlagSet struct {\n\t// Usage is the function called when an error occurs while parsing flags.\n\t// The field is a function (not a method) that may be changed to point to\n\t// a custom error handler.\n\tUsage func()\n\n\tname              string\n\tparsed            bool\n\tactual            map[NormalizedName]*Flag\n\tformal            map[NormalizedName]*Flag\n\tshorthands        map[byte]*Flag\n\targs              []string // arguments after flags\n\targsLenAtDash     int      // len(args) when a '--' was located when parsing, or -1 if no --\n\texitOnError       bool     // does the program exit if there's an error?\n\terrorHandling     ErrorHandling\n\toutput            io.Writer // nil means stderr; use out() accessor\n\tinterspersed      bool      // allow interspersed option/non-option args\n\tnormalizeNameFunc func(f *FlagSet, name string) NormalizedName\n}\n\n// A Flag represents the state of a flag.\ntype Flag struct {\n\tName                string              // name as it appears on command line\n\tShorthand           string              // one-letter abbreviated flag\n\tUsage               string              // help message\n\tValue               Value               // value as set\n\tDefValue            string              // default value (as text); for usage message\n\tChanged             bool                // If the user set the value (or if left to default)\n\tNoOptDefVal         string              //default value (as text); if the flag is on the command line without any options\n\tDeprecated          string              // If this flag is deprecated, this string is the new or now thing to use\n\tHidden              bool                // used by cobra.Command to allow flags to be hidden from help/usage text\n\tShorthandDeprecated string              // If the shorthand of this flag is deprecated, this string is the new or now thing to use\n\tAnnotations         map[string][]string // used by cobra.Command bash autocomple code\n}\n\n// Value is the interface to the dynamic value stored in a flag.\n// (The default value is represented as a string.)\ntype Value interface {\n\tString() string\n\tSet(string) error\n\tType() string\n}\n\n// sortFlags returns the flags as a slice in lexicographical sorted order.\nfunc sortFlags(flags map[NormalizedName]*Flag) []*Flag {\n\tlist := make(sort.StringSlice, len(flags))\n\ti := 0\n\tfor k := range flags {\n\t\tlist[i] = string(k)\n\t\ti++\n\t}\n\tlist.Sort()\n\tresult := make([]*Flag, len(list))\n\tfor i, name := range list {\n\t\tresult[i] = flags[NormalizedName(name)]\n\t}\n\treturn result\n}\n\n// SetNormalizeFunc allows you to add a function which can translate flag names.\n// Flags added to the FlagSet will be translated and then when anything tries to\n// look up the flag that will also be translated. So it would be possible to create\n// a flag named \"getURL\" and have it translated to \"geturl\".  A user could then pass\n// \"--getUrl\" which may also be translated to \"geturl\" and everything will work.\nfunc (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {\n\tf.normalizeNameFunc = n\n\tfor k, v := range f.formal {\n\t\tdelete(f.formal, k)\n\t\tnname := f.normalizeFlagName(string(k))\n\t\tf.formal[nname] = v\n\t\tv.Name = string(nname)\n\t}\n}\n\n// GetNormalizeFunc returns the previously set NormalizeFunc of a function which\n// does no translation, if not set previously.\nfunc (f *FlagSet) GetNormalizeFunc() func(f *FlagSet, name string) NormalizedName {\n\tif f.normalizeNameFunc != nil {\n\t\treturn f.normalizeNameFunc\n\t}\n\treturn func(f *FlagSet, name string) NormalizedName { return NormalizedName(name) }\n}\n\nfunc (f *FlagSet) normalizeFlagName(name string) NormalizedName {\n\tn := f.GetNormalizeFunc()\n\treturn n(f, name)\n}\n\nfunc (f *FlagSet) out() io.Writer {\n\tif f.output == nil {\n\t\treturn os.Stderr\n\t}\n\treturn f.output\n}\n\n// SetOutput sets the destination for usage and error messages.\n// If output is nil, os.Stderr is used.\nfunc (f *FlagSet) SetOutput(output io.Writer) {\n\tf.output = output\n}\n\n// VisitAll visits the flags in lexicographical order, calling fn for each.\n// It visits all flags, even those not set.\nfunc (f *FlagSet) VisitAll(fn func(*Flag)) {\n\tfor _, flag := range sortFlags(f.formal) {\n\t\tfn(flag)\n\t}\n}\n\n// HasFlags returns a bool to indicate if the FlagSet has any flags definied.\nfunc (f *FlagSet) HasFlags() bool {\n\treturn len(f.formal) > 0\n}\n\n// HasAvailableFlags returns a bool to indicate if the FlagSet has any flags\n// definied that are not hidden or deprecated.\nfunc (f *FlagSet) HasAvailableFlags() bool {\n\tfor _, flag := range f.formal {\n\t\tif !flag.Hidden && len(flag.Deprecated) == 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// VisitAll visits the command-line flags in lexicographical order, calling\n// fn for each.  It visits all flags, even those not set.\nfunc VisitAll(fn func(*Flag)) {\n\tCommandLine.VisitAll(fn)\n}\n\n// Visit visits the flags in lexicographical order, calling fn for each.\n// It visits only those flags that have been set.\nfunc (f *FlagSet) Visit(fn func(*Flag)) {\n\tfor _, flag := range sortFlags(f.actual) {\n\t\tfn(flag)\n\t}\n}\n\n// Visit visits the command-line flags in lexicographical order, calling fn\n// for each.  It visits only those flags that have been set.\nfunc Visit(fn func(*Flag)) {\n\tCommandLine.Visit(fn)\n}\n\n// Lookup returns the Flag structure of the named flag, returning nil if none exists.\nfunc (f *FlagSet) Lookup(name string) *Flag {\n\treturn f.lookup(f.normalizeFlagName(name))\n}\n\n// lookup returns the Flag structure of the named flag, returning nil if none exists.\nfunc (f *FlagSet) lookup(name NormalizedName) *Flag {\n\treturn f.formal[name]\n}\n\n// func to return a given type for a given flag name\nfunc (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) {\n\tflag := f.Lookup(name)\n\tif flag == nil {\n\t\terr := fmt.Errorf(\"flag accessed but not defined: %s\", name)\n\t\treturn nil, err\n\t}\n\n\tif flag.Value.Type() != ftype {\n\t\terr := fmt.Errorf(\"trying to get %s value of flag of type %s\", ftype, flag.Value.Type())\n\t\treturn nil, err\n\t}\n\n\tsval := flag.Value.String()\n\tresult, err := convFunc(sval)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\n\n// ArgsLenAtDash will return the length of f.Args at the moment when a -- was\n// found during arg parsing. This allows your program to know which args were\n// before the -- and which came after.\nfunc (f *FlagSet) ArgsLenAtDash() int {\n\treturn f.argsLenAtDash\n}\n\n// MarkDeprecated indicated that a flag is deprecated in your program. It will\n// continue to function but will not show up in help or usage messages. Using\n// this flag will also print the given usageMessage.\nfunc (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {\n\tflag := f.Lookup(name)\n\tif flag == nil {\n\t\treturn fmt.Errorf(\"flag %q does not exist\", name)\n\t}\n\tif len(usageMessage) == 0 {\n\t\treturn fmt.Errorf(\"deprecated message for flag %q must be set\", name)\n\t}\n\tflag.Deprecated = usageMessage\n\treturn nil\n}\n\n// MarkShorthandDeprecated will mark the shorthand of a flag deprecated in your\n// program. It will continue to function but will not show up in help or usage\n// messages. Using this flag will also print the given usageMessage.\nfunc (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error {\n\tflag := f.Lookup(name)\n\tif flag == nil {\n\t\treturn fmt.Errorf(\"flag %q does not exist\", name)\n\t}\n\tif len(usageMessage) == 0 {\n\t\treturn fmt.Errorf(\"deprecated message for flag %q must be set\", name)\n\t}\n\tflag.ShorthandDeprecated = usageMessage\n\treturn nil\n}\n\n// MarkHidden sets a flag to 'hidden' in your program. It will continue to\n// function but will not show up in help or usage messages.\nfunc (f *FlagSet) MarkHidden(name string) error {\n\tflag := f.Lookup(name)\n\tif flag == nil {\n\t\treturn fmt.Errorf(\"flag %q does not exist\", name)\n\t}\n\tflag.Hidden = true\n\treturn nil\n}\n\n// Lookup returns the Flag structure of the named command-line flag,\n// returning nil if none exists.\nfunc Lookup(name string) *Flag {\n\treturn CommandLine.Lookup(name)\n}\n\n// Set sets the value of the named flag.\nfunc (f *FlagSet) Set(name, value string) error {\n\tnormalName := f.normalizeFlagName(name)\n\tflag, ok := f.formal[normalName]\n\tif !ok {\n\t\treturn fmt.Errorf(\"no such flag -%v\", name)\n\t}\n\terr := flag.Value.Set(value)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif f.actual == nil {\n\t\tf.actual = make(map[NormalizedName]*Flag)\n\t}\n\tf.actual[normalName] = flag\n\tflag.Changed = true\n\tif len(flag.Deprecated) > 0 {\n\t\tfmt.Fprintf(os.Stderr, \"Flag --%s has been deprecated, %s\\n\", flag.Name, flag.Deprecated)\n\t}\n\treturn nil\n}\n\n// SetAnnotation allows one to set arbitrary annotations on a flag in the FlagSet.\n// This is sometimes used by spf13/cobra programs which want to generate additional\n// bash completion information.\nfunc (f *FlagSet) SetAnnotation(name, key string, values []string) error {\n\tnormalName := f.normalizeFlagName(name)\n\tflag, ok := f.formal[normalName]\n\tif !ok {\n\t\treturn fmt.Errorf(\"no such flag -%v\", name)\n\t}\n\tif flag.Annotations == nil {\n\t\tflag.Annotations = map[string][]string{}\n\t}\n\tflag.Annotations[key] = values\n\treturn nil\n}\n\n// Changed returns true if the flag was explicitly set during Parse() and false\n// otherwise\nfunc (f *FlagSet) Changed(name string) bool {\n\tflag := f.Lookup(name)\n\t// If a flag doesn't exist, it wasn't changed....\n\tif flag == nil {\n\t\treturn false\n\t}\n\treturn flag.Changed\n}\n\n// Set sets the value of the named command-line flag.\nfunc Set(name, value string) error {\n\treturn CommandLine.Set(name, value)\n}\n\n// PrintDefaults prints, to standard error unless configured\n// otherwise, the default values of all defined flags in the set.\nfunc (f *FlagSet) PrintDefaults() {\n\tusages := f.FlagUsages()\n\tfmt.Fprint(f.out(), usages)\n}\n\n// defaultIsZeroValue returns true if the default value for this flag represents\n// a zero value.\nfunc (f *Flag) defaultIsZeroValue() bool {\n\tswitch f.Value.(type) {\n\tcase boolFlag:\n\t\treturn f.DefValue == \"false\"\n\tcase *durationValue:\n\t\t// Beginning in Go 1.7, duration zero values are \"0s\"\n\t\treturn f.DefValue == \"0\" || f.DefValue == \"0s\"\n\tcase *intValue, *int8Value, *int32Value, *int64Value, *uintValue, *uint8Value, *uint16Value, *uint32Value, *uint64Value, *countValue, *float32Value, *float64Value:\n\t\treturn f.DefValue == \"0\"\n\tcase *stringValue:\n\t\treturn f.DefValue == \"\"\n\tcase *ipValue, *ipMaskValue, *ipNetValue:\n\t\treturn f.DefValue == \"<nil>\"\n\tcase *intSliceValue, *stringSliceValue, *stringArrayValue:\n\t\treturn f.DefValue == \"[]\"\n\tdefault:\n\t\tswitch f.Value.String() {\n\t\tcase \"false\":\n\t\t\treturn true\n\t\tcase \"<nil>\":\n\t\t\treturn true\n\t\tcase \"\":\n\t\t\treturn true\n\t\tcase \"0\":\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t}\n}\n\n// UnquoteUsage extracts a back-quoted name from the usage\n// string for a flag and returns it and the un-quoted usage.\n// Given \"a `name` to show\" it returns (\"name\", \"a name to show\").\n// If there are no back quotes, the name is an educated guess of the\n// type of the flag's value, or the empty string if the flag is boolean.\nfunc UnquoteUsage(flag *Flag) (name string, usage string) {\n\t// Look for a back-quoted name, but avoid the strings package.\n\tusage = flag.Usage\n\tfor i := 0; i < len(usage); i++ {\n\t\tif usage[i] == '`' {\n\t\t\tfor j := i + 1; j < len(usage); j++ {\n\t\t\t\tif usage[j] == '`' {\n\t\t\t\t\tname = usage[i+1 : j]\n\t\t\t\t\tusage = usage[:i] + name + usage[j+1:]\n\t\t\t\t\treturn name, usage\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak // Only one back quote; use type name.\n\t\t}\n\t}\n\n\tname = flag.Value.Type()\n\tswitch name {\n\tcase \"bool\":\n\t\tname = \"\"\n\tcase \"float64\":\n\t\tname = \"float\"\n\tcase \"int64\":\n\t\tname = \"int\"\n\tcase \"uint64\":\n\t\tname = \"uint\"\n\t}\n\n\treturn\n}\n\n// Splits the string `s` on whitespace into an initial substring up to\n// `i` runes in length and the remainder. Will go `slop` over `i` if\n// that encompasses the entire string (which allows the caller to\n// avoid short orphan words on the final line).\nfunc wrapN(i, slop int, s string) (string, string) {\n\tif i+slop > len(s) {\n\t\treturn s, \"\"\n\t}\n\n\tw := strings.LastIndexAny(s[:i], \" \\t\")\n\tif w <= 0 {\n\t\treturn s, \"\"\n\t}\n\n\treturn s[:w], s[w+1:]\n}\n\n// Wraps the string `s` to a maximum width `w` with leading indent\n// `i`. The first line is not indented (this is assumed to be done by\n// caller). Pass `w` == 0 to do no wrapping\nfunc wrap(i, w int, s string) string {\n\tif w == 0 {\n\t\treturn s\n\t}\n\n\t// space between indent i and end of line width w into which\n\t// we should wrap the text.\n\twrap := w - i\n\n\tvar r, l string\n\n\t// Not enough space for sensible wrapping. Wrap as a block on\n\t// the next line instead.\n\tif wrap < 24 {\n\t\ti = 16\n\t\twrap = w - i\n\t\tr += \"\\n\" + strings.Repeat(\" \", i)\n\t}\n\t// If still not enough space then don't even try to wrap.\n\tif wrap < 24 {\n\t\treturn s\n\t}\n\n\t// Try to avoid short orphan words on the final line, by\n\t// allowing wrapN to go a bit over if that would fit in the\n\t// remainder of the line.\n\tslop := 5\n\twrap = wrap - slop\n\n\t// Handle first line, which is indented by the caller (or the\n\t// special case above)\n\tl, s = wrapN(wrap, slop, s)\n\tr = r + l\n\n\t// Now wrap the rest\n\tfor s != \"\" {\n\t\tvar t string\n\n\t\tt, s = wrapN(wrap, slop, s)\n\t\tr = r + \"\\n\" + strings.Repeat(\" \", i) + t\n\t}\n\n\treturn r\n\n}\n\n// FlagUsagesWrapped returns a string containing the usage information\n// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no\n// wrapping)\nfunc (f *FlagSet) FlagUsagesWrapped(cols int) string {\n\tx := new(bytes.Buffer)\n\n\tlines := make([]string, 0, len(f.formal))\n\n\tmaxlen := 0\n\tf.VisitAll(func(flag *Flag) {\n\t\tif len(flag.Deprecated) > 0 || flag.Hidden {\n\t\t\treturn\n\t\t}\n\n\t\tline := \"\"\n\t\tif len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 {\n\t\t\tline = fmt.Sprintf(\"  -%s, --%s\", flag.Shorthand, flag.Name)\n\t\t} else {\n\t\t\tline = fmt.Sprintf(\"      --%s\", flag.Name)\n\t\t}\n\n\t\tvarname, usage := UnquoteUsage(flag)\n\t\tif len(varname) > 0 {\n\t\t\tline += \" \" + varname\n\t\t}\n\t\tif len(flag.NoOptDefVal) > 0 {\n\t\t\tswitch flag.Value.Type() {\n\t\t\tcase \"string\":\n\t\t\t\tline += fmt.Sprintf(\"[=\\\"%s\\\"]\", flag.NoOptDefVal)\n\t\t\tcase \"bool\":\n\t\t\t\tif flag.NoOptDefVal != \"true\" {\n\t\t\t\t\tline += fmt.Sprintf(\"[=%s]\", flag.NoOptDefVal)\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tline += fmt.Sprintf(\"[=%s]\", flag.NoOptDefVal)\n\t\t\t}\n\t\t}\n\n\t\t// This special character will be replaced with spacing once the\n\t\t// correct alignment is calculated\n\t\tline += \"\\x00\"\n\t\tif len(line) > maxlen {\n\t\t\tmaxlen = len(line)\n\t\t}\n\n\t\tline += usage\n\t\tif !flag.defaultIsZeroValue() {\n\t\t\tif flag.Value.Type() == \"string\" {\n\t\t\t\tline += fmt.Sprintf(\" (default \\\"%s\\\")\", flag.DefValue)\n\t\t\t} else {\n\t\t\t\tline += fmt.Sprintf(\" (default %s)\", flag.DefValue)\n\t\t\t}\n\t\t}\n\n\t\tlines = append(lines, line)\n\t})\n\n\tfor _, line := range lines {\n\t\tsidx := strings.Index(line, \"\\x00\")\n\t\tspacing := strings.Repeat(\" \", maxlen-sidx)\n\t\t// maxlen + 2 comes from + 1 for the \\x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx\n\t\tfmt.Fprintln(x, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:]))\n\t}\n\n\treturn x.String()\n}\n\n// FlagUsages returns a string containing the usage information for all flags in\n// the FlagSet\nfunc (f *FlagSet) FlagUsages() string {\n\treturn f.FlagUsagesWrapped(0)\n}\n\n// PrintDefaults prints to standard error the default values of all defined command-line flags.\nfunc PrintDefaults() {\n\tCommandLine.PrintDefaults()\n}\n\n// defaultUsage is the default function to print a usage message.\nfunc defaultUsage(f *FlagSet) {\n\tfmt.Fprintf(f.out(), \"Usage of %s:\\n\", f.name)\n\tf.PrintDefaults()\n}\n\n// NOTE: Usage is not just defaultUsage(CommandLine)\n// because it serves (via godoc flag Usage) as the example\n// for how to write your own usage function.\n\n// Usage prints to standard error a usage message documenting all defined command-line flags.\n// The function is a variable that may be changed to point to a custom function.\n// By default it prints a simple header and calls PrintDefaults; for details about the\n// format of the output and how to control it, see the documentation for PrintDefaults.\nvar Usage = func() {\n\tfmt.Fprintf(os.Stderr, \"Usage of %s:\\n\", os.Args[0])\n\tPrintDefaults()\n}\n\n// NFlag returns the number of flags that have been set.\nfunc (f *FlagSet) NFlag() int { return len(f.actual) }\n\n// NFlag returns the number of command-line flags that have been set.\nfunc NFlag() int { return len(CommandLine.actual) }\n\n// Arg returns the i'th argument.  Arg(0) is the first remaining argument\n// after flags have been processed.\nfunc (f *FlagSet) Arg(i int) string {\n\tif i < 0 || i >= len(f.args) {\n\t\treturn \"\"\n\t}\n\treturn f.args[i]\n}\n\n// Arg returns the i'th command-line argument.  Arg(0) is the first remaining argument\n// after flags have been processed.\nfunc Arg(i int) string {\n\treturn CommandLine.Arg(i)\n}\n\n// NArg is the number of arguments remaining after flags have been processed.\nfunc (f *FlagSet) NArg() int { return len(f.args) }\n\n// NArg is the number of arguments remaining after flags have been processed.\nfunc NArg() int { return len(CommandLine.args) }\n\n// Args returns the non-flag arguments.\nfunc (f *FlagSet) Args() []string { return f.args }\n\n// Args returns the non-flag command-line arguments.\nfunc Args() []string { return CommandLine.args }\n\n// Var defines a flag with the specified name and usage string. The type and\n// value of the flag are represented by the first argument, of type Value, which\n// typically holds a user-defined implementation of Value. For instance, the\n// caller could create a flag that turns a comma-separated string into a slice\n// of strings by giving the slice the methods of Value; in particular, Set would\n// decompose the comma-separated string into the slice.\nfunc (f *FlagSet) Var(value Value, name string, usage string) {\n\tf.VarP(value, name, \"\", usage)\n}\n\n// VarPF is like VarP, but returns the flag created\nfunc (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag {\n\t// Remember the default value as a string; it won't change.\n\tflag := &Flag{\n\t\tName:      name,\n\t\tShorthand: shorthand,\n\t\tUsage:     usage,\n\t\tValue:     value,\n\t\tDefValue:  value.String(),\n\t}\n\tf.AddFlag(flag)\n\treturn flag\n}\n\n// VarP is like Var, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) VarP(value Value, name, shorthand, usage string) {\n\tf.VarPF(value, name, shorthand, usage)\n}\n\n// AddFlag will add the flag to the FlagSet\nfunc (f *FlagSet) AddFlag(flag *Flag) {\n\t// Call normalizeFlagName function only once\n\tnormalizedFlagName := f.normalizeFlagName(flag.Name)\n\n\t_, alreadythere := f.formal[normalizedFlagName]\n\tif alreadythere {\n\t\tmsg := fmt.Sprintf(\"%s flag redefined: %s\", f.name, flag.Name)\n\t\tfmt.Fprintln(f.out(), msg)\n\t\tpanic(msg) // Happens only if flags are declared with identical names\n\t}\n\tif f.formal == nil {\n\t\tf.formal = make(map[NormalizedName]*Flag)\n\t}\n\n\tflag.Name = string(normalizedFlagName)\n\tf.formal[normalizedFlagName] = flag\n\n\tif len(flag.Shorthand) == 0 {\n\t\treturn\n\t}\n\tif len(flag.Shorthand) > 1 {\n\t\tfmt.Fprintf(f.out(), \"%s shorthand more than ASCII character: %s\\n\", f.name, flag.Shorthand)\n\t\tpanic(\"shorthand is more than one character\")\n\t}\n\tif f.shorthands == nil {\n\t\tf.shorthands = make(map[byte]*Flag)\n\t}\n\tc := flag.Shorthand[0]\n\told, alreadythere := f.shorthands[c]\n\tif alreadythere {\n\t\tfmt.Fprintf(f.out(), \"%s shorthand reused: %q for %s already used for %s\\n\", f.name, c, flag.Name, old.Name)\n\t\tpanic(\"shorthand redefinition\")\n\t}\n\tf.shorthands[c] = flag\n}\n\n// AddFlagSet adds one FlagSet to another. If a flag is already present in f\n// the flag from newSet will be ignored\nfunc (f *FlagSet) AddFlagSet(newSet *FlagSet) {\n\tif newSet == nil {\n\t\treturn\n\t}\n\tnewSet.VisitAll(func(flag *Flag) {\n\t\tif f.Lookup(flag.Name) == nil {\n\t\t\tf.AddFlag(flag)\n\t\t}\n\t})\n}\n\n// Var defines a flag with the specified name and usage string. The type and\n// value of the flag are represented by the first argument, of type Value, which\n// typically holds a user-defined implementation of Value. For instance, the\n// caller could create a flag that turns a comma-separated string into a slice\n// of strings by giving the slice the methods of Value; in particular, Set would\n// decompose the comma-separated string into the slice.\nfunc Var(value Value, name string, usage string) {\n\tCommandLine.VarP(value, name, \"\", usage)\n}\n\n// VarP is like Var, but accepts a shorthand letter that can be used after a single dash.\nfunc VarP(value Value, name, shorthand, usage string) {\n\tCommandLine.VarP(value, name, shorthand, usage)\n}\n\n// failf prints to standard error a formatted error and usage message and\n// returns the error.\nfunc (f *FlagSet) failf(format string, a ...interface{}) error {\n\terr := fmt.Errorf(format, a...)\n\tfmt.Fprintln(f.out(), err)\n\tf.usage()\n\treturn err\n}\n\n// usage calls the Usage method for the flag set, or the usage function if\n// the flag set is CommandLine.\nfunc (f *FlagSet) usage() {\n\tif f == CommandLine {\n\t\tUsage()\n\t} else if f.Usage == nil {\n\t\tdefaultUsage(f)\n\t} else {\n\t\tf.Usage()\n\t}\n}\n\nfunc (f *FlagSet) setFlag(flag *Flag, value string, origArg string) error {\n\tif err := flag.Value.Set(value); err != nil {\n\t\treturn f.failf(\"invalid argument %q for %s: %v\", value, origArg, err)\n\t}\n\t// mark as visited for Visit()\n\tif f.actual == nil {\n\t\tf.actual = make(map[NormalizedName]*Flag)\n\t}\n\tf.actual[f.normalizeFlagName(flag.Name)] = flag\n\tflag.Changed = true\n\tif len(flag.Deprecated) > 0 {\n\t\tfmt.Fprintf(os.Stderr, \"Flag --%s has been deprecated, %s\\n\", flag.Name, flag.Deprecated)\n\t}\n\tif len(flag.ShorthandDeprecated) > 0 && containsShorthand(origArg, flag.Shorthand) {\n\t\tfmt.Fprintf(os.Stderr, \"Flag shorthand -%s has been deprecated, %s\\n\", flag.Shorthand, flag.ShorthandDeprecated)\n\t}\n\treturn nil\n}\n\nfunc containsShorthand(arg, shorthand string) bool {\n\t// filter out flags --<flag_name>\n\tif strings.HasPrefix(arg, \"-\") {\n\t\treturn false\n\t}\n\targ = strings.SplitN(arg, \"=\", 2)[0]\n\treturn strings.Contains(arg, shorthand)\n}\n\nfunc (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {\n\ta = args\n\tname := s[2:]\n\tif len(name) == 0 || name[0] == '-' || name[0] == '=' {\n\t\terr = f.failf(\"bad flag syntax: %s\", s)\n\t\treturn\n\t}\n\tsplit := strings.SplitN(name, \"=\", 2)\n\tname = split[0]\n\tflag, alreadythere := f.formal[f.normalizeFlagName(name)]\n\tif !alreadythere {\n\t\tif name == \"help\" { // special case for nice help message.\n\t\t\tf.usage()\n\t\t\treturn a, ErrHelp\n\t\t}\n\t\terr = f.failf(\"unknown flag: --%s\", name)\n\t\treturn\n\t}\n\tvar value string\n\tif len(split) == 2 {\n\t\t// '--flag=arg'\n\t\tvalue = split[1]\n\t} else if len(flag.NoOptDefVal) > 0 {\n\t\t// '--flag' (arg was optional)\n\t\tvalue = flag.NoOptDefVal\n\t} else if len(a) > 0 {\n\t\t// '--flag arg'\n\t\tvalue = a[0]\n\t\ta = a[1:]\n\t} else {\n\t\t// '--flag' (arg was required)\n\t\terr = f.failf(\"flag needs an argument: %s\", s)\n\t\treturn\n\t}\n\terr = fn(flag, value, s)\n\treturn\n}\n\nfunc (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {\n\tif strings.HasPrefix(shorthands, \"test.\") {\n\t\treturn\n\t}\n\toutArgs = args\n\toutShorts = shorthands[1:]\n\tc := shorthands[0]\n\n\tflag, alreadythere := f.shorthands[c]\n\tif !alreadythere {\n\t\tif c == 'h' { // special case for nice help message.\n\t\t\tf.usage()\n\t\t\terr = ErrHelp\n\t\t\treturn\n\t\t}\n\t\t//TODO continue on error\n\t\terr = f.failf(\"unknown shorthand flag: %q in -%s\", c, shorthands)\n\t\treturn\n\t}\n\tvar value string\n\tif len(shorthands) > 2 && shorthands[1] == '=' {\n\t\tvalue = shorthands[2:]\n\t\toutShorts = \"\"\n\t} else if len(flag.NoOptDefVal) > 0 {\n\t\tvalue = flag.NoOptDefVal\n\t} else if len(shorthands) > 1 {\n\t\tvalue = shorthands[1:]\n\t\toutShorts = \"\"\n\t} else if len(args) > 0 {\n\t\tvalue = args[0]\n\t\toutArgs = args[1:]\n\t} else {\n\t\terr = f.failf(\"flag needs an argument: %q in -%s\", c, shorthands)\n\t\treturn\n\t}\n\terr = fn(flag, value, shorthands)\n\treturn\n}\n\nfunc (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) {\n\ta = args\n\tshorthands := s[1:]\n\n\tfor len(shorthands) > 0 {\n\t\tshorthands, a, err = f.parseSingleShortArg(shorthands, args, fn)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t}\n\n\treturn\n}\n\nfunc (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {\n\tfor len(args) > 0 {\n\t\ts := args[0]\n\t\targs = args[1:]\n\t\tif len(s) == 0 || s[0] != '-' || len(s) == 1 {\n\t\t\tif !f.interspersed {\n\t\t\t\tf.args = append(f.args, s)\n\t\t\t\tf.args = append(f.args, args...)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tf.args = append(f.args, s)\n\t\t\tcontinue\n\t\t}\n\n\t\tif s[1] == '-' {\n\t\t\tif len(s) == 2 { // \"--\" terminates the flags\n\t\t\t\tf.argsLenAtDash = len(f.args)\n\t\t\t\tf.args = append(f.args, args...)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\targs, err = f.parseLongArg(s, args, fn)\n\t\t} else {\n\t\t\targs, err = f.parseShortArg(s, args, fn)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t}\n\treturn\n}\n\n// Parse parses flag definitions from the argument list, which should not\n// include the command name.  Must be called after all flags in the FlagSet\n// are defined and before flags are accessed by the program.\n// The return value will be ErrHelp if -help was set but not defined.\nfunc (f *FlagSet) Parse(arguments []string) error {\n\tf.parsed = true\n\tf.args = make([]string, 0, len(arguments))\n\n\tassign := func(flag *Flag, value, origArg string) error {\n\t\treturn f.setFlag(flag, value, origArg)\n\t}\n\n\terr := f.parseArgs(arguments, assign)\n\tif err != nil {\n\t\tswitch f.errorHandling {\n\t\tcase ContinueOnError:\n\t\t\treturn err\n\t\tcase ExitOnError:\n\t\t\tos.Exit(2)\n\t\tcase PanicOnError:\n\t\t\tpanic(err)\n\t\t}\n\t}\n\treturn nil\n}\n\ntype parseFunc func(flag *Flag, value, origArg string) error\n\n// ParseAll parses flag definitions from the argument list, which should not\n// include the command name. The arguments for fn are flag and value. Must be\n// called after all flags in the FlagSet are defined and before flags are\n// accessed by the program. The return value will be ErrHelp if -help was set\n// but not defined.\nfunc (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error {\n\tf.parsed = true\n\tf.args = make([]string, 0, len(arguments))\n\n\tassign := func(flag *Flag, value, origArg string) error {\n\t\treturn fn(flag, value)\n\t}\n\n\terr := f.parseArgs(arguments, assign)\n\tif err != nil {\n\t\tswitch f.errorHandling {\n\t\tcase ContinueOnError:\n\t\t\treturn err\n\t\tcase ExitOnError:\n\t\t\tos.Exit(2)\n\t\tcase PanicOnError:\n\t\t\tpanic(err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// Parsed reports whether f.Parse has been called.\nfunc (f *FlagSet) Parsed() bool {\n\treturn f.parsed\n}\n\n// Parse parses the command-line flags from os.Args[1:].  Must be called\n// after all flags are defined and before flags are accessed by the program.\nfunc Parse() {\n\t// Ignore errors; CommandLine is set for ExitOnError.\n\tCommandLine.Parse(os.Args[1:])\n}\n\n// ParseAll parses the command-line flags from os.Args[1:] and called fn for each.\n// The arguments for fn are flag and value. Must be called after all flags are\n// defined and before flags are accessed by the program.\nfunc ParseAll(fn func(flag *Flag, value string) error) {\n\t// Ignore errors; CommandLine is set for ExitOnError.\n\tCommandLine.ParseAll(os.Args[1:], fn)\n}\n\n// SetInterspersed sets whether to support interspersed option/non-option arguments.\nfunc SetInterspersed(interspersed bool) {\n\tCommandLine.SetInterspersed(interspersed)\n}\n\n// Parsed returns true if the command-line flags have been parsed.\nfunc Parsed() bool {\n\treturn CommandLine.Parsed()\n}\n\n// CommandLine is the default set of command-line flags, parsed from os.Args.\nvar CommandLine = NewFlagSet(os.Args[0], ExitOnError)\n\n// NewFlagSet returns a new, empty flag set with the specified name and\n// error handling property.\nfunc NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {\n\tf := &FlagSet{\n\t\tname:          name,\n\t\terrorHandling: errorHandling,\n\t\targsLenAtDash: -1,\n\t\tinterspersed:  true,\n\t}\n\treturn f\n}\n\n// SetInterspersed sets whether to support interspersed option/non-option arguments.\nfunc (f *FlagSet) SetInterspersed(interspersed bool) {\n\tf.interspersed = interspersed\n}\n\n// Init sets the name and error handling property for a flag set.\n// By default, the zero FlagSet uses an empty name and the\n// ContinueOnError error handling policy.\nfunc (f *FlagSet) Init(name string, errorHandling ErrorHandling) {\n\tf.name = name\n\tf.errorHandling = errorHandling\n\tf.argsLenAtDash = -1\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/float32.go",
    "content": "package pflag\n\nimport \"strconv\"\n\n// -- float32 Value\ntype float32Value float32\n\nfunc newFloat32Value(val float32, p *float32) *float32Value {\n\t*p = val\n\treturn (*float32Value)(p)\n}\n\nfunc (f *float32Value) Set(s string) error {\n\tv, err := strconv.ParseFloat(s, 32)\n\t*f = float32Value(v)\n\treturn err\n}\n\nfunc (f *float32Value) Type() string {\n\treturn \"float32\"\n}\n\nfunc (f *float32Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 32) }\n\nfunc float32Conv(sval string) (interface{}, error) {\n\tv, err := strconv.ParseFloat(sval, 32)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn float32(v), nil\n}\n\n// GetFloat32 return the float32 value of a flag with the given name\nfunc (f *FlagSet) GetFloat32(name string) (float32, error) {\n\tval, err := f.getFlagType(name, \"float32\", float32Conv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn val.(float32), nil\n}\n\n// Float32Var defines a float32 flag with specified name, default value, and usage string.\n// The argument p points to a float32 variable in which to store the value of the flag.\nfunc (f *FlagSet) Float32Var(p *float32, name string, value float32, usage string) {\n\tf.VarP(newFloat32Value(value, p), name, \"\", usage)\n}\n\n// Float32VarP is like Float32Var, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Float32VarP(p *float32, name, shorthand string, value float32, usage string) {\n\tf.VarP(newFloat32Value(value, p), name, shorthand, usage)\n}\n\n// Float32Var defines a float32 flag with specified name, default value, and usage string.\n// The argument p points to a float32 variable in which to store the value of the flag.\nfunc Float32Var(p *float32, name string, value float32, usage string) {\n\tCommandLine.VarP(newFloat32Value(value, p), name, \"\", usage)\n}\n\n// Float32VarP is like Float32Var, but accepts a shorthand letter that can be used after a single dash.\nfunc Float32VarP(p *float32, name, shorthand string, value float32, usage string) {\n\tCommandLine.VarP(newFloat32Value(value, p), name, shorthand, usage)\n}\n\n// Float32 defines a float32 flag with specified name, default value, and usage string.\n// The return value is the address of a float32 variable that stores the value of the flag.\nfunc (f *FlagSet) Float32(name string, value float32, usage string) *float32 {\n\tp := new(float32)\n\tf.Float32VarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// Float32P is like Float32, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Float32P(name, shorthand string, value float32, usage string) *float32 {\n\tp := new(float32)\n\tf.Float32VarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// Float32 defines a float32 flag with specified name, default value, and usage string.\n// The return value is the address of a float32 variable that stores the value of the flag.\nfunc Float32(name string, value float32, usage string) *float32 {\n\treturn CommandLine.Float32P(name, \"\", value, usage)\n}\n\n// Float32P is like Float32, but accepts a shorthand letter that can be used after a single dash.\nfunc Float32P(name, shorthand string, value float32, usage string) *float32 {\n\treturn CommandLine.Float32P(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/float64.go",
    "content": "package pflag\n\nimport \"strconv\"\n\n// -- float64 Value\ntype float64Value float64\n\nfunc newFloat64Value(val float64, p *float64) *float64Value {\n\t*p = val\n\treturn (*float64Value)(p)\n}\n\nfunc (f *float64Value) Set(s string) error {\n\tv, err := strconv.ParseFloat(s, 64)\n\t*f = float64Value(v)\n\treturn err\n}\n\nfunc (f *float64Value) Type() string {\n\treturn \"float64\"\n}\n\nfunc (f *float64Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 64) }\n\nfunc float64Conv(sval string) (interface{}, error) {\n\treturn strconv.ParseFloat(sval, 64)\n}\n\n// GetFloat64 return the float64 value of a flag with the given name\nfunc (f *FlagSet) GetFloat64(name string) (float64, error) {\n\tval, err := f.getFlagType(name, \"float64\", float64Conv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn val.(float64), nil\n}\n\n// Float64Var defines a float64 flag with specified name, default value, and usage string.\n// The argument p points to a float64 variable in which to store the value of the flag.\nfunc (f *FlagSet) Float64Var(p *float64, name string, value float64, usage string) {\n\tf.VarP(newFloat64Value(value, p), name, \"\", usage)\n}\n\n// Float64VarP is like Float64Var, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Float64VarP(p *float64, name, shorthand string, value float64, usage string) {\n\tf.VarP(newFloat64Value(value, p), name, shorthand, usage)\n}\n\n// Float64Var defines a float64 flag with specified name, default value, and usage string.\n// The argument p points to a float64 variable in which to store the value of the flag.\nfunc Float64Var(p *float64, name string, value float64, usage string) {\n\tCommandLine.VarP(newFloat64Value(value, p), name, \"\", usage)\n}\n\n// Float64VarP is like Float64Var, but accepts a shorthand letter that can be used after a single dash.\nfunc Float64VarP(p *float64, name, shorthand string, value float64, usage string) {\n\tCommandLine.VarP(newFloat64Value(value, p), name, shorthand, usage)\n}\n\n// Float64 defines a float64 flag with specified name, default value, and usage string.\n// The return value is the address of a float64 variable that stores the value of the flag.\nfunc (f *FlagSet) Float64(name string, value float64, usage string) *float64 {\n\tp := new(float64)\n\tf.Float64VarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// Float64P is like Float64, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Float64P(name, shorthand string, value float64, usage string) *float64 {\n\tp := new(float64)\n\tf.Float64VarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// Float64 defines a float64 flag with specified name, default value, and usage string.\n// The return value is the address of a float64 variable that stores the value of the flag.\nfunc Float64(name string, value float64, usage string) *float64 {\n\treturn CommandLine.Float64P(name, \"\", value, usage)\n}\n\n// Float64P is like Float64, but accepts a shorthand letter that can be used after a single dash.\nfunc Float64P(name, shorthand string, value float64, usage string) *float64 {\n\treturn CommandLine.Float64P(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/golangflag.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage pflag\n\nimport (\n\tgoflag \"flag\"\n\t\"reflect\"\n\t\"strings\"\n)\n\n// flagValueWrapper implements pflag.Value around a flag.Value.  The main\n// difference here is the addition of the Type method that returns a string\n// name of the type.  As this is generally unknown, we approximate that with\n// reflection.\ntype flagValueWrapper struct {\n\tinner    goflag.Value\n\tflagType string\n}\n\n// We are just copying the boolFlag interface out of goflag as that is what\n// they use to decide if a flag should get \"true\" when no arg is given.\ntype goBoolFlag interface {\n\tgoflag.Value\n\tIsBoolFlag() bool\n}\n\nfunc wrapFlagValue(v goflag.Value) Value {\n\t// If the flag.Value happens to also be a pflag.Value, just use it directly.\n\tif pv, ok := v.(Value); ok {\n\t\treturn pv\n\t}\n\n\tpv := &flagValueWrapper{\n\t\tinner: v,\n\t}\n\n\tt := reflect.TypeOf(v)\n\tif t.Kind() == reflect.Interface || t.Kind() == reflect.Ptr {\n\t\tt = t.Elem()\n\t}\n\n\tpv.flagType = strings.TrimSuffix(t.Name(), \"Value\")\n\treturn pv\n}\n\nfunc (v *flagValueWrapper) String() string {\n\treturn v.inner.String()\n}\n\nfunc (v *flagValueWrapper) Set(s string) error {\n\treturn v.inner.Set(s)\n}\n\nfunc (v *flagValueWrapper) Type() string {\n\treturn v.flagType\n}\n\n// PFlagFromGoFlag will return a *pflag.Flag given a *flag.Flag\n// If the *flag.Flag.Name was a single character (ex: `v`) it will be accessiblei\n// with both `-v` and `--v` in flags. If the golang flag was more than a single\n// character (ex: `verbose`) it will only be accessible via `--verbose`\nfunc PFlagFromGoFlag(goflag *goflag.Flag) *Flag {\n\t// Remember the default value as a string; it won't change.\n\tflag := &Flag{\n\t\tName:  goflag.Name,\n\t\tUsage: goflag.Usage,\n\t\tValue: wrapFlagValue(goflag.Value),\n\t\t// Looks like golang flags don't set DefValue correctly  :-(\n\t\t//DefValue: goflag.DefValue,\n\t\tDefValue: goflag.Value.String(),\n\t}\n\t// Ex: if the golang flag was -v, allow both -v and --v to work\n\tif len(flag.Name) == 1 {\n\t\tflag.Shorthand = flag.Name\n\t}\n\tif fv, ok := goflag.Value.(goBoolFlag); ok && fv.IsBoolFlag() {\n\t\tflag.NoOptDefVal = \"true\"\n\t}\n\treturn flag\n}\n\n// AddGoFlag will add the given *flag.Flag to the pflag.FlagSet\nfunc (f *FlagSet) AddGoFlag(goflag *goflag.Flag) {\n\tif f.Lookup(goflag.Name) != nil {\n\t\treturn\n\t}\n\tnewflag := PFlagFromGoFlag(goflag)\n\tf.AddFlag(newflag)\n}\n\n// AddGoFlagSet will add the given *flag.FlagSet to the pflag.FlagSet\nfunc (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) {\n\tif newSet == nil {\n\t\treturn\n\t}\n\tnewSet.VisitAll(func(goflag *goflag.Flag) {\n\t\tf.AddGoFlag(goflag)\n\t})\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/int.go",
    "content": "package pflag\n\nimport \"strconv\"\n\n// -- int Value\ntype intValue int\n\nfunc newIntValue(val int, p *int) *intValue {\n\t*p = val\n\treturn (*intValue)(p)\n}\n\nfunc (i *intValue) Set(s string) error {\n\tv, err := strconv.ParseInt(s, 0, 64)\n\t*i = intValue(v)\n\treturn err\n}\n\nfunc (i *intValue) Type() string {\n\treturn \"int\"\n}\n\nfunc (i *intValue) String() string { return strconv.Itoa(int(*i)) }\n\nfunc intConv(sval string) (interface{}, error) {\n\treturn strconv.Atoi(sval)\n}\n\n// GetInt return the int value of a flag with the given name\nfunc (f *FlagSet) GetInt(name string) (int, error) {\n\tval, err := f.getFlagType(name, \"int\", intConv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn val.(int), nil\n}\n\n// IntVar defines an int flag with specified name, default value, and usage string.\n// The argument p points to an int variable in which to store the value of the flag.\nfunc (f *FlagSet) IntVar(p *int, name string, value int, usage string) {\n\tf.VarP(newIntValue(value, p), name, \"\", usage)\n}\n\n// IntVarP is like IntVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) IntVarP(p *int, name, shorthand string, value int, usage string) {\n\tf.VarP(newIntValue(value, p), name, shorthand, usage)\n}\n\n// IntVar defines an int flag with specified name, default value, and usage string.\n// The argument p points to an int variable in which to store the value of the flag.\nfunc IntVar(p *int, name string, value int, usage string) {\n\tCommandLine.VarP(newIntValue(value, p), name, \"\", usage)\n}\n\n// IntVarP is like IntVar, but accepts a shorthand letter that can be used after a single dash.\nfunc IntVarP(p *int, name, shorthand string, value int, usage string) {\n\tCommandLine.VarP(newIntValue(value, p), name, shorthand, usage)\n}\n\n// Int defines an int flag with specified name, default value, and usage string.\n// The return value is the address of an int variable that stores the value of the flag.\nfunc (f *FlagSet) Int(name string, value int, usage string) *int {\n\tp := new(int)\n\tf.IntVarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// IntP is like Int, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) IntP(name, shorthand string, value int, usage string) *int {\n\tp := new(int)\n\tf.IntVarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// Int defines an int flag with specified name, default value, and usage string.\n// The return value is the address of an int variable that stores the value of the flag.\nfunc Int(name string, value int, usage string) *int {\n\treturn CommandLine.IntP(name, \"\", value, usage)\n}\n\n// IntP is like Int, but accepts a shorthand letter that can be used after a single dash.\nfunc IntP(name, shorthand string, value int, usage string) *int {\n\treturn CommandLine.IntP(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/int32.go",
    "content": "package pflag\n\nimport \"strconv\"\n\n// -- int32 Value\ntype int32Value int32\n\nfunc newInt32Value(val int32, p *int32) *int32Value {\n\t*p = val\n\treturn (*int32Value)(p)\n}\n\nfunc (i *int32Value) Set(s string) error {\n\tv, err := strconv.ParseInt(s, 0, 32)\n\t*i = int32Value(v)\n\treturn err\n}\n\nfunc (i *int32Value) Type() string {\n\treturn \"int32\"\n}\n\nfunc (i *int32Value) String() string { return strconv.FormatInt(int64(*i), 10) }\n\nfunc int32Conv(sval string) (interface{}, error) {\n\tv, err := strconv.ParseInt(sval, 0, 32)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn int32(v), nil\n}\n\n// GetInt32 return the int32 value of a flag with the given name\nfunc (f *FlagSet) GetInt32(name string) (int32, error) {\n\tval, err := f.getFlagType(name, \"int32\", int32Conv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn val.(int32), nil\n}\n\n// Int32Var defines an int32 flag with specified name, default value, and usage string.\n// The argument p points to an int32 variable in which to store the value of the flag.\nfunc (f *FlagSet) Int32Var(p *int32, name string, value int32, usage string) {\n\tf.VarP(newInt32Value(value, p), name, \"\", usage)\n}\n\n// Int32VarP is like Int32Var, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Int32VarP(p *int32, name, shorthand string, value int32, usage string) {\n\tf.VarP(newInt32Value(value, p), name, shorthand, usage)\n}\n\n// Int32Var defines an int32 flag with specified name, default value, and usage string.\n// The argument p points to an int32 variable in which to store the value of the flag.\nfunc Int32Var(p *int32, name string, value int32, usage string) {\n\tCommandLine.VarP(newInt32Value(value, p), name, \"\", usage)\n}\n\n// Int32VarP is like Int32Var, but accepts a shorthand letter that can be used after a single dash.\nfunc Int32VarP(p *int32, name, shorthand string, value int32, usage string) {\n\tCommandLine.VarP(newInt32Value(value, p), name, shorthand, usage)\n}\n\n// Int32 defines an int32 flag with specified name, default value, and usage string.\n// The return value is the address of an int32 variable that stores the value of the flag.\nfunc (f *FlagSet) Int32(name string, value int32, usage string) *int32 {\n\tp := new(int32)\n\tf.Int32VarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// Int32P is like Int32, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Int32P(name, shorthand string, value int32, usage string) *int32 {\n\tp := new(int32)\n\tf.Int32VarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// Int32 defines an int32 flag with specified name, default value, and usage string.\n// The return value is the address of an int32 variable that stores the value of the flag.\nfunc Int32(name string, value int32, usage string) *int32 {\n\treturn CommandLine.Int32P(name, \"\", value, usage)\n}\n\n// Int32P is like Int32, but accepts a shorthand letter that can be used after a single dash.\nfunc Int32P(name, shorthand string, value int32, usage string) *int32 {\n\treturn CommandLine.Int32P(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/int64.go",
    "content": "package pflag\n\nimport \"strconv\"\n\n// -- int64 Value\ntype int64Value int64\n\nfunc newInt64Value(val int64, p *int64) *int64Value {\n\t*p = val\n\treturn (*int64Value)(p)\n}\n\nfunc (i *int64Value) Set(s string) error {\n\tv, err := strconv.ParseInt(s, 0, 64)\n\t*i = int64Value(v)\n\treturn err\n}\n\nfunc (i *int64Value) Type() string {\n\treturn \"int64\"\n}\n\nfunc (i *int64Value) String() string { return strconv.FormatInt(int64(*i), 10) }\n\nfunc int64Conv(sval string) (interface{}, error) {\n\treturn strconv.ParseInt(sval, 0, 64)\n}\n\n// GetInt64 return the int64 value of a flag with the given name\nfunc (f *FlagSet) GetInt64(name string) (int64, error) {\n\tval, err := f.getFlagType(name, \"int64\", int64Conv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn val.(int64), nil\n}\n\n// Int64Var defines an int64 flag with specified name, default value, and usage string.\n// The argument p points to an int64 variable in which to store the value of the flag.\nfunc (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string) {\n\tf.VarP(newInt64Value(value, p), name, \"\", usage)\n}\n\n// Int64VarP is like Int64Var, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Int64VarP(p *int64, name, shorthand string, value int64, usage string) {\n\tf.VarP(newInt64Value(value, p), name, shorthand, usage)\n}\n\n// Int64Var defines an int64 flag with specified name, default value, and usage string.\n// The argument p points to an int64 variable in which to store the value of the flag.\nfunc Int64Var(p *int64, name string, value int64, usage string) {\n\tCommandLine.VarP(newInt64Value(value, p), name, \"\", usage)\n}\n\n// Int64VarP is like Int64Var, but accepts a shorthand letter that can be used after a single dash.\nfunc Int64VarP(p *int64, name, shorthand string, value int64, usage string) {\n\tCommandLine.VarP(newInt64Value(value, p), name, shorthand, usage)\n}\n\n// Int64 defines an int64 flag with specified name, default value, and usage string.\n// The return value is the address of an int64 variable that stores the value of the flag.\nfunc (f *FlagSet) Int64(name string, value int64, usage string) *int64 {\n\tp := new(int64)\n\tf.Int64VarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// Int64P is like Int64, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Int64P(name, shorthand string, value int64, usage string) *int64 {\n\tp := new(int64)\n\tf.Int64VarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// Int64 defines an int64 flag with specified name, default value, and usage string.\n// The return value is the address of an int64 variable that stores the value of the flag.\nfunc Int64(name string, value int64, usage string) *int64 {\n\treturn CommandLine.Int64P(name, \"\", value, usage)\n}\n\n// Int64P is like Int64, but accepts a shorthand letter that can be used after a single dash.\nfunc Int64P(name, shorthand string, value int64, usage string) *int64 {\n\treturn CommandLine.Int64P(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/int8.go",
    "content": "package pflag\n\nimport \"strconv\"\n\n// -- int8 Value\ntype int8Value int8\n\nfunc newInt8Value(val int8, p *int8) *int8Value {\n\t*p = val\n\treturn (*int8Value)(p)\n}\n\nfunc (i *int8Value) Set(s string) error {\n\tv, err := strconv.ParseInt(s, 0, 8)\n\t*i = int8Value(v)\n\treturn err\n}\n\nfunc (i *int8Value) Type() string {\n\treturn \"int8\"\n}\n\nfunc (i *int8Value) String() string { return strconv.FormatInt(int64(*i), 10) }\n\nfunc int8Conv(sval string) (interface{}, error) {\n\tv, err := strconv.ParseInt(sval, 0, 8)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn int8(v), nil\n}\n\n// GetInt8 return the int8 value of a flag with the given name\nfunc (f *FlagSet) GetInt8(name string) (int8, error) {\n\tval, err := f.getFlagType(name, \"int8\", int8Conv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn val.(int8), nil\n}\n\n// Int8Var defines an int8 flag with specified name, default value, and usage string.\n// The argument p points to an int8 variable in which to store the value of the flag.\nfunc (f *FlagSet) Int8Var(p *int8, name string, value int8, usage string) {\n\tf.VarP(newInt8Value(value, p), name, \"\", usage)\n}\n\n// Int8VarP is like Int8Var, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Int8VarP(p *int8, name, shorthand string, value int8, usage string) {\n\tf.VarP(newInt8Value(value, p), name, shorthand, usage)\n}\n\n// Int8Var defines an int8 flag with specified name, default value, and usage string.\n// The argument p points to an int8 variable in which to store the value of the flag.\nfunc Int8Var(p *int8, name string, value int8, usage string) {\n\tCommandLine.VarP(newInt8Value(value, p), name, \"\", usage)\n}\n\n// Int8VarP is like Int8Var, but accepts a shorthand letter that can be used after a single dash.\nfunc Int8VarP(p *int8, name, shorthand string, value int8, usage string) {\n\tCommandLine.VarP(newInt8Value(value, p), name, shorthand, usage)\n}\n\n// Int8 defines an int8 flag with specified name, default value, and usage string.\n// The return value is the address of an int8 variable that stores the value of the flag.\nfunc (f *FlagSet) Int8(name string, value int8, usage string) *int8 {\n\tp := new(int8)\n\tf.Int8VarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// Int8P is like Int8, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Int8P(name, shorthand string, value int8, usage string) *int8 {\n\tp := new(int8)\n\tf.Int8VarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// Int8 defines an int8 flag with specified name, default value, and usage string.\n// The return value is the address of an int8 variable that stores the value of the flag.\nfunc Int8(name string, value int8, usage string) *int8 {\n\treturn CommandLine.Int8P(name, \"\", value, usage)\n}\n\n// Int8P is like Int8, but accepts a shorthand letter that can be used after a single dash.\nfunc Int8P(name, shorthand string, value int8, usage string) *int8 {\n\treturn CommandLine.Int8P(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/int_slice.go",
    "content": "package pflag\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// -- intSlice Value\ntype intSliceValue struct {\n\tvalue   *[]int\n\tchanged bool\n}\n\nfunc newIntSliceValue(val []int, p *[]int) *intSliceValue {\n\tisv := new(intSliceValue)\n\tisv.value = p\n\t*isv.value = val\n\treturn isv\n}\n\nfunc (s *intSliceValue) Set(val string) error {\n\tss := strings.Split(val, \",\")\n\tout := make([]int, len(ss))\n\tfor i, d := range ss {\n\t\tvar err error\n\t\tout[i], err = strconv.Atoi(d)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t}\n\tif !s.changed {\n\t\t*s.value = out\n\t} else {\n\t\t*s.value = append(*s.value, out...)\n\t}\n\ts.changed = true\n\treturn nil\n}\n\nfunc (s *intSliceValue) Type() string {\n\treturn \"intSlice\"\n}\n\nfunc (s *intSliceValue) String() string {\n\tout := make([]string, len(*s.value))\n\tfor i, d := range *s.value {\n\t\tout[i] = fmt.Sprintf(\"%d\", d)\n\t}\n\treturn \"[\" + strings.Join(out, \",\") + \"]\"\n}\n\nfunc intSliceConv(val string) (interface{}, error) {\n\tval = strings.Trim(val, \"[]\")\n\t// Empty string would cause a slice with one (empty) entry\n\tif len(val) == 0 {\n\t\treturn []int{}, nil\n\t}\n\tss := strings.Split(val, \",\")\n\tout := make([]int, len(ss))\n\tfor i, d := range ss {\n\t\tvar err error\n\t\tout[i], err = strconv.Atoi(d)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t}\n\treturn out, nil\n}\n\n// GetIntSlice return the []int value of a flag with the given name\nfunc (f *FlagSet) GetIntSlice(name string) ([]int, error) {\n\tval, err := f.getFlagType(name, \"intSlice\", intSliceConv)\n\tif err != nil {\n\t\treturn []int{}, err\n\t}\n\treturn val.([]int), nil\n}\n\n// IntSliceVar defines a intSlice flag with specified name, default value, and usage string.\n// The argument p points to a []int variable in which to store the value of the flag.\nfunc (f *FlagSet) IntSliceVar(p *[]int, name string, value []int, usage string) {\n\tf.VarP(newIntSliceValue(value, p), name, \"\", usage)\n}\n\n// IntSliceVarP is like IntSliceVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) IntSliceVarP(p *[]int, name, shorthand string, value []int, usage string) {\n\tf.VarP(newIntSliceValue(value, p), name, shorthand, usage)\n}\n\n// IntSliceVar defines a int[] flag with specified name, default value, and usage string.\n// The argument p points to a int[] variable in which to store the value of the flag.\nfunc IntSliceVar(p *[]int, name string, value []int, usage string) {\n\tCommandLine.VarP(newIntSliceValue(value, p), name, \"\", usage)\n}\n\n// IntSliceVarP is like IntSliceVar, but accepts a shorthand letter that can be used after a single dash.\nfunc IntSliceVarP(p *[]int, name, shorthand string, value []int, usage string) {\n\tCommandLine.VarP(newIntSliceValue(value, p), name, shorthand, usage)\n}\n\n// IntSlice defines a []int flag with specified name, default value, and usage string.\n// The return value is the address of a []int variable that stores the value of the flag.\nfunc (f *FlagSet) IntSlice(name string, value []int, usage string) *[]int {\n\tp := []int{}\n\tf.IntSliceVarP(&p, name, \"\", value, usage)\n\treturn &p\n}\n\n// IntSliceP is like IntSlice, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) IntSliceP(name, shorthand string, value []int, usage string) *[]int {\n\tp := []int{}\n\tf.IntSliceVarP(&p, name, shorthand, value, usage)\n\treturn &p\n}\n\n// IntSlice defines a []int flag with specified name, default value, and usage string.\n// The return value is the address of a []int variable that stores the value of the flag.\nfunc IntSlice(name string, value []int, usage string) *[]int {\n\treturn CommandLine.IntSliceP(name, \"\", value, usage)\n}\n\n// IntSliceP is like IntSlice, but accepts a shorthand letter that can be used after a single dash.\nfunc IntSliceP(name, shorthand string, value []int, usage string) *[]int {\n\treturn CommandLine.IntSliceP(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/ip.go",
    "content": "package pflag\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"strings\"\n)\n\n// -- net.IP value\ntype ipValue net.IP\n\nfunc newIPValue(val net.IP, p *net.IP) *ipValue {\n\t*p = val\n\treturn (*ipValue)(p)\n}\n\nfunc (i *ipValue) String() string { return net.IP(*i).String() }\nfunc (i *ipValue) Set(s string) error {\n\tip := net.ParseIP(strings.TrimSpace(s))\n\tif ip == nil {\n\t\treturn fmt.Errorf(\"failed to parse IP: %q\", s)\n\t}\n\t*i = ipValue(ip)\n\treturn nil\n}\n\nfunc (i *ipValue) Type() string {\n\treturn \"ip\"\n}\n\nfunc ipConv(sval string) (interface{}, error) {\n\tip := net.ParseIP(sval)\n\tif ip != nil {\n\t\treturn ip, nil\n\t}\n\treturn nil, fmt.Errorf(\"invalid string being converted to IP address: %s\", sval)\n}\n\n// GetIP return the net.IP value of a flag with the given name\nfunc (f *FlagSet) GetIP(name string) (net.IP, error) {\n\tval, err := f.getFlagType(name, \"ip\", ipConv)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn val.(net.IP), nil\n}\n\n// IPVar defines an net.IP flag with specified name, default value, and usage string.\n// The argument p points to an net.IP variable in which to store the value of the flag.\nfunc (f *FlagSet) IPVar(p *net.IP, name string, value net.IP, usage string) {\n\tf.VarP(newIPValue(value, p), name, \"\", usage)\n}\n\n// IPVarP is like IPVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) IPVarP(p *net.IP, name, shorthand string, value net.IP, usage string) {\n\tf.VarP(newIPValue(value, p), name, shorthand, usage)\n}\n\n// IPVar defines an net.IP flag with specified name, default value, and usage string.\n// The argument p points to an net.IP variable in which to store the value of the flag.\nfunc IPVar(p *net.IP, name string, value net.IP, usage string) {\n\tCommandLine.VarP(newIPValue(value, p), name, \"\", usage)\n}\n\n// IPVarP is like IPVar, but accepts a shorthand letter that can be used after a single dash.\nfunc IPVarP(p *net.IP, name, shorthand string, value net.IP, usage string) {\n\tCommandLine.VarP(newIPValue(value, p), name, shorthand, usage)\n}\n\n// IP defines an net.IP flag with specified name, default value, and usage string.\n// The return value is the address of an net.IP variable that stores the value of the flag.\nfunc (f *FlagSet) IP(name string, value net.IP, usage string) *net.IP {\n\tp := new(net.IP)\n\tf.IPVarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// IPP is like IP, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) IPP(name, shorthand string, value net.IP, usage string) *net.IP {\n\tp := new(net.IP)\n\tf.IPVarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// IP defines an net.IP flag with specified name, default value, and usage string.\n// The return value is the address of an net.IP variable that stores the value of the flag.\nfunc IP(name string, value net.IP, usage string) *net.IP {\n\treturn CommandLine.IPP(name, \"\", value, usage)\n}\n\n// IPP is like IP, but accepts a shorthand letter that can be used after a single dash.\nfunc IPP(name, shorthand string, value net.IP, usage string) *net.IP {\n\treturn CommandLine.IPP(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/ip_slice.go",
    "content": "package pflag\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"strings\"\n)\n\n// -- ipSlice Value\ntype ipSliceValue struct {\n\tvalue   *[]net.IP\n\tchanged bool\n}\n\nfunc newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue {\n\tipsv := new(ipSliceValue)\n\tipsv.value = p\n\t*ipsv.value = val\n\treturn ipsv\n}\n\n// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag.\n// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended.\nfunc (s *ipSliceValue) Set(val string) error {\n\n\t// remove all quote characters\n\trmQuote := strings.NewReplacer(`\"`, \"\", `'`, \"\", \"`\", \"\")\n\n\t// read flag arguments with CSV parser\n\tipStrSlice, err := readAsCSV(rmQuote.Replace(val))\n\tif err != nil && err != io.EOF {\n\t\treturn err\n\t}\n\n\t// parse ip values into slice\n\tout := make([]net.IP, 0, len(ipStrSlice))\n\tfor _, ipStr := range ipStrSlice {\n\t\tip := net.ParseIP(strings.TrimSpace(ipStr))\n\t\tif ip == nil {\n\t\t\treturn fmt.Errorf(\"invalid string being converted to IP address: %s\", ipStr)\n\t\t}\n\t\tout = append(out, ip)\n\t}\n\n\tif !s.changed {\n\t\t*s.value = out\n\t} else {\n\t\t*s.value = append(*s.value, out...)\n\t}\n\n\ts.changed = true\n\n\treturn nil\n}\n\n// Type returns a string that uniquely represents this flag's type.\nfunc (s *ipSliceValue) Type() string {\n\treturn \"ipSlice\"\n}\n\n// String defines a \"native\" format for this net.IP slice flag value.\nfunc (s *ipSliceValue) String() string {\n\n\tipStrSlice := make([]string, len(*s.value))\n\tfor i, ip := range *s.value {\n\t\tipStrSlice[i] = ip.String()\n\t}\n\n\tout, _ := writeAsCSV(ipStrSlice)\n\n\treturn \"[\" + out + \"]\"\n}\n\nfunc ipSliceConv(val string) (interface{}, error) {\n\tval = strings.Trim(val, \"[]\")\n\t// Emtpy string would cause a slice with one (empty) entry\n\tif len(val) == 0 {\n\t\treturn []net.IP{}, nil\n\t}\n\tss := strings.Split(val, \",\")\n\tout := make([]net.IP, len(ss))\n\tfor i, sval := range ss {\n\t\tip := net.ParseIP(strings.TrimSpace(sval))\n\t\tif ip == nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid string being converted to IP address: %s\", sval)\n\t\t}\n\t\tout[i] = ip\n\t}\n\treturn out, nil\n}\n\n// GetIPSlice returns the []net.IP value of a flag with the given name\nfunc (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) {\n\tval, err := f.getFlagType(name, \"ipSlice\", ipSliceConv)\n\tif err != nil {\n\t\treturn []net.IP{}, err\n\t}\n\treturn val.([]net.IP), nil\n}\n\n// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string.\n// The argument p points to a []net.IP variable in which to store the value of the flag.\nfunc (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {\n\tf.VarP(newIPSliceValue(value, p), name, \"\", usage)\n}\n\n// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {\n\tf.VarP(newIPSliceValue(value, p), name, shorthand, usage)\n}\n\n// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string.\n// The argument p points to a []net.IP variable in which to store the value of the flag.\nfunc IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {\n\tCommandLine.VarP(newIPSliceValue(value, p), name, \"\", usage)\n}\n\n// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.\nfunc IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {\n\tCommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage)\n}\n\n// IPSlice defines a []net.IP flag with specified name, default value, and usage string.\n// The return value is the address of a []net.IP variable that stores the value of that flag.\nfunc (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP {\n\tp := []net.IP{}\n\tf.IPSliceVarP(&p, name, \"\", value, usage)\n\treturn &p\n}\n\n// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {\n\tp := []net.IP{}\n\tf.IPSliceVarP(&p, name, shorthand, value, usage)\n\treturn &p\n}\n\n// IPSlice defines a []net.IP flag with specified name, default value, and usage string.\n// The return value is the address of a []net.IP variable that stores the value of the flag.\nfunc IPSlice(name string, value []net.IP, usage string) *[]net.IP {\n\treturn CommandLine.IPSliceP(name, \"\", value, usage)\n}\n\n// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.\nfunc IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {\n\treturn CommandLine.IPSliceP(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/ipmask.go",
    "content": "package pflag\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"strconv\"\n)\n\n// -- net.IPMask value\ntype ipMaskValue net.IPMask\n\nfunc newIPMaskValue(val net.IPMask, p *net.IPMask) *ipMaskValue {\n\t*p = val\n\treturn (*ipMaskValue)(p)\n}\n\nfunc (i *ipMaskValue) String() string { return net.IPMask(*i).String() }\nfunc (i *ipMaskValue) Set(s string) error {\n\tip := ParseIPv4Mask(s)\n\tif ip == nil {\n\t\treturn fmt.Errorf(\"failed to parse IP mask: %q\", s)\n\t}\n\t*i = ipMaskValue(ip)\n\treturn nil\n}\n\nfunc (i *ipMaskValue) Type() string {\n\treturn \"ipMask\"\n}\n\n// ParseIPv4Mask written in IP form (e.g. 255.255.255.0).\n// This function should really belong to the net package.\nfunc ParseIPv4Mask(s string) net.IPMask {\n\tmask := net.ParseIP(s)\n\tif mask == nil {\n\t\tif len(s) != 8 {\n\t\t\treturn nil\n\t\t}\n\t\t// net.IPMask.String() actually outputs things like ffffff00\n\t\t// so write a horrible parser for that as well  :-(\n\t\tm := []int{}\n\t\tfor i := 0; i < 4; i++ {\n\t\t\tb := \"0x\" + s[2*i:2*i+2]\n\t\t\td, err := strconv.ParseInt(b, 0, 0)\n\t\t\tif err != nil {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tm = append(m, int(d))\n\t\t}\n\t\ts := fmt.Sprintf(\"%d.%d.%d.%d\", m[0], m[1], m[2], m[3])\n\t\tmask = net.ParseIP(s)\n\t\tif mask == nil {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn net.IPv4Mask(mask[12], mask[13], mask[14], mask[15])\n}\n\nfunc parseIPv4Mask(sval string) (interface{}, error) {\n\tmask := ParseIPv4Mask(sval)\n\tif mask == nil {\n\t\treturn nil, fmt.Errorf(\"unable to parse %s as net.IPMask\", sval)\n\t}\n\treturn mask, nil\n}\n\n// GetIPv4Mask return the net.IPv4Mask value of a flag with the given name\nfunc (f *FlagSet) GetIPv4Mask(name string) (net.IPMask, error) {\n\tval, err := f.getFlagType(name, \"ipMask\", parseIPv4Mask)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn val.(net.IPMask), nil\n}\n\n// IPMaskVar defines an net.IPMask flag with specified name, default value, and usage string.\n// The argument p points to an net.IPMask variable in which to store the value of the flag.\nfunc (f *FlagSet) IPMaskVar(p *net.IPMask, name string, value net.IPMask, usage string) {\n\tf.VarP(newIPMaskValue(value, p), name, \"\", usage)\n}\n\n// IPMaskVarP is like IPMaskVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) IPMaskVarP(p *net.IPMask, name, shorthand string, value net.IPMask, usage string) {\n\tf.VarP(newIPMaskValue(value, p), name, shorthand, usage)\n}\n\n// IPMaskVar defines an net.IPMask flag with specified name, default value, and usage string.\n// The argument p points to an net.IPMask variable in which to store the value of the flag.\nfunc IPMaskVar(p *net.IPMask, name string, value net.IPMask, usage string) {\n\tCommandLine.VarP(newIPMaskValue(value, p), name, \"\", usage)\n}\n\n// IPMaskVarP is like IPMaskVar, but accepts a shorthand letter that can be used after a single dash.\nfunc IPMaskVarP(p *net.IPMask, name, shorthand string, value net.IPMask, usage string) {\n\tCommandLine.VarP(newIPMaskValue(value, p), name, shorthand, usage)\n}\n\n// IPMask defines an net.IPMask flag with specified name, default value, and usage string.\n// The return value is the address of an net.IPMask variable that stores the value of the flag.\nfunc (f *FlagSet) IPMask(name string, value net.IPMask, usage string) *net.IPMask {\n\tp := new(net.IPMask)\n\tf.IPMaskVarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// IPMaskP is like IPMask, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) IPMaskP(name, shorthand string, value net.IPMask, usage string) *net.IPMask {\n\tp := new(net.IPMask)\n\tf.IPMaskVarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// IPMask defines an net.IPMask flag with specified name, default value, and usage string.\n// The return value is the address of an net.IPMask variable that stores the value of the flag.\nfunc IPMask(name string, value net.IPMask, usage string) *net.IPMask {\n\treturn CommandLine.IPMaskP(name, \"\", value, usage)\n}\n\n// IPMaskP is like IP, but accepts a shorthand letter that can be used after a single dash.\nfunc IPMaskP(name, shorthand string, value net.IPMask, usage string) *net.IPMask {\n\treturn CommandLine.IPMaskP(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/ipnet.go",
    "content": "package pflag\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"strings\"\n)\n\n// IPNet adapts net.IPNet for use as a flag.\ntype ipNetValue net.IPNet\n\nfunc (ipnet ipNetValue) String() string {\n\tn := net.IPNet(ipnet)\n\treturn n.String()\n}\n\nfunc (ipnet *ipNetValue) Set(value string) error {\n\t_, n, err := net.ParseCIDR(strings.TrimSpace(value))\n\tif err != nil {\n\t\treturn err\n\t}\n\t*ipnet = ipNetValue(*n)\n\treturn nil\n}\n\nfunc (*ipNetValue) Type() string {\n\treturn \"ipNet\"\n}\n\nfunc newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue {\n\t*p = val\n\treturn (*ipNetValue)(p)\n}\n\nfunc ipNetConv(sval string) (interface{}, error) {\n\t_, n, err := net.ParseCIDR(strings.TrimSpace(sval))\n\tif err == nil {\n\t\treturn *n, nil\n\t}\n\treturn nil, fmt.Errorf(\"invalid string being converted to IPNet: %s\", sval)\n}\n\n// GetIPNet return the net.IPNet value of a flag with the given name\nfunc (f *FlagSet) GetIPNet(name string) (net.IPNet, error) {\n\tval, err := f.getFlagType(name, \"ipNet\", ipNetConv)\n\tif err != nil {\n\t\treturn net.IPNet{}, err\n\t}\n\treturn val.(net.IPNet), nil\n}\n\n// IPNetVar defines an net.IPNet flag with specified name, default value, and usage string.\n// The argument p points to an net.IPNet variable in which to store the value of the flag.\nfunc (f *FlagSet) IPNetVar(p *net.IPNet, name string, value net.IPNet, usage string) {\n\tf.VarP(newIPNetValue(value, p), name, \"\", usage)\n}\n\n// IPNetVarP is like IPNetVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) IPNetVarP(p *net.IPNet, name, shorthand string, value net.IPNet, usage string) {\n\tf.VarP(newIPNetValue(value, p), name, shorthand, usage)\n}\n\n// IPNetVar defines an net.IPNet flag with specified name, default value, and usage string.\n// The argument p points to an net.IPNet variable in which to store the value of the flag.\nfunc IPNetVar(p *net.IPNet, name string, value net.IPNet, usage string) {\n\tCommandLine.VarP(newIPNetValue(value, p), name, \"\", usage)\n}\n\n// IPNetVarP is like IPNetVar, but accepts a shorthand letter that can be used after a single dash.\nfunc IPNetVarP(p *net.IPNet, name, shorthand string, value net.IPNet, usage string) {\n\tCommandLine.VarP(newIPNetValue(value, p), name, shorthand, usage)\n}\n\n// IPNet defines an net.IPNet flag with specified name, default value, and usage string.\n// The return value is the address of an net.IPNet variable that stores the value of the flag.\nfunc (f *FlagSet) IPNet(name string, value net.IPNet, usage string) *net.IPNet {\n\tp := new(net.IPNet)\n\tf.IPNetVarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// IPNetP is like IPNet, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) IPNetP(name, shorthand string, value net.IPNet, usage string) *net.IPNet {\n\tp := new(net.IPNet)\n\tf.IPNetVarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// IPNet defines an net.IPNet flag with specified name, default value, and usage string.\n// The return value is the address of an net.IPNet variable that stores the value of the flag.\nfunc IPNet(name string, value net.IPNet, usage string) *net.IPNet {\n\treturn CommandLine.IPNetP(name, \"\", value, usage)\n}\n\n// IPNetP is like IPNet, but accepts a shorthand letter that can be used after a single dash.\nfunc IPNetP(name, shorthand string, value net.IPNet, usage string) *net.IPNet {\n\treturn CommandLine.IPNetP(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/string.go",
    "content": "package pflag\n\n// -- string Value\ntype stringValue string\n\nfunc newStringValue(val string, p *string) *stringValue {\n\t*p = val\n\treturn (*stringValue)(p)\n}\n\nfunc (s *stringValue) Set(val string) error {\n\t*s = stringValue(val)\n\treturn nil\n}\nfunc (s *stringValue) Type() string {\n\treturn \"string\"\n}\n\nfunc (s *stringValue) String() string { return string(*s) }\n\nfunc stringConv(sval string) (interface{}, error) {\n\treturn sval, nil\n}\n\n// GetString return the string value of a flag with the given name\nfunc (f *FlagSet) GetString(name string) (string, error) {\n\tval, err := f.getFlagType(name, \"string\", stringConv)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn val.(string), nil\n}\n\n// StringVar defines a string flag with specified name, default value, and usage string.\n// The argument p points to a string variable in which to store the value of the flag.\nfunc (f *FlagSet) StringVar(p *string, name string, value string, usage string) {\n\tf.VarP(newStringValue(value, p), name, \"\", usage)\n}\n\n// StringVarP is like StringVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) StringVarP(p *string, name, shorthand string, value string, usage string) {\n\tf.VarP(newStringValue(value, p), name, shorthand, usage)\n}\n\n// StringVar defines a string flag with specified name, default value, and usage string.\n// The argument p points to a string variable in which to store the value of the flag.\nfunc StringVar(p *string, name string, value string, usage string) {\n\tCommandLine.VarP(newStringValue(value, p), name, \"\", usage)\n}\n\n// StringVarP is like StringVar, but accepts a shorthand letter that can be used after a single dash.\nfunc StringVarP(p *string, name, shorthand string, value string, usage string) {\n\tCommandLine.VarP(newStringValue(value, p), name, shorthand, usage)\n}\n\n// String defines a string flag with specified name, default value, and usage string.\n// The return value is the address of a string variable that stores the value of the flag.\nfunc (f *FlagSet) String(name string, value string, usage string) *string {\n\tp := new(string)\n\tf.StringVarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// StringP is like String, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) StringP(name, shorthand string, value string, usage string) *string {\n\tp := new(string)\n\tf.StringVarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// String defines a string flag with specified name, default value, and usage string.\n// The return value is the address of a string variable that stores the value of the flag.\nfunc String(name string, value string, usage string) *string {\n\treturn CommandLine.StringP(name, \"\", value, usage)\n}\n\n// StringP is like String, but accepts a shorthand letter that can be used after a single dash.\nfunc StringP(name, shorthand string, value string, usage string) *string {\n\treturn CommandLine.StringP(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/string_array.go",
    "content": "package pflag\n\n// -- stringArray Value\ntype stringArrayValue struct {\n\tvalue   *[]string\n\tchanged bool\n}\n\nfunc newStringArrayValue(val []string, p *[]string) *stringArrayValue {\n\tssv := new(stringArrayValue)\n\tssv.value = p\n\t*ssv.value = val\n\treturn ssv\n}\n\nfunc (s *stringArrayValue) Set(val string) error {\n\tif !s.changed {\n\t\t*s.value = []string{val}\n\t\ts.changed = true\n\t} else {\n\t\t*s.value = append(*s.value, val)\n\t}\n\treturn nil\n}\n\nfunc (s *stringArrayValue) Type() string {\n\treturn \"stringArray\"\n}\n\nfunc (s *stringArrayValue) String() string {\n\tstr, _ := writeAsCSV(*s.value)\n\treturn \"[\" + str + \"]\"\n}\n\nfunc stringArrayConv(sval string) (interface{}, error) {\n\tsval = sval[1 : len(sval)-1]\n\t// An empty string would cause a array with one (empty) string\n\tif len(sval) == 0 {\n\t\treturn []string{}, nil\n\t}\n\treturn readAsCSV(sval)\n}\n\n// GetStringArray return the []string value of a flag with the given name\nfunc (f *FlagSet) GetStringArray(name string) ([]string, error) {\n\tval, err := f.getFlagType(name, \"stringArray\", stringArrayConv)\n\tif err != nil {\n\t\treturn []string{}, err\n\t}\n\treturn val.([]string), nil\n}\n\n// StringArrayVar defines a string flag with specified name, default value, and usage string.\n// The argument p points to a []string variable in which to store the values of the multiple flags.\n// The value of each argument will not try to be separated by comma\nfunc (f *FlagSet) StringArrayVar(p *[]string, name string, value []string, usage string) {\n\tf.VarP(newStringArrayValue(value, p), name, \"\", usage)\n}\n\n// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) {\n\tf.VarP(newStringArrayValue(value, p), name, shorthand, usage)\n}\n\n// StringArrayVar defines a string flag with specified name, default value, and usage string.\n// The argument p points to a []string variable in which to store the value of the flag.\n// The value of each argument will not try to be separated by comma\nfunc StringArrayVar(p *[]string, name string, value []string, usage string) {\n\tCommandLine.VarP(newStringArrayValue(value, p), name, \"\", usage)\n}\n\n// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash.\nfunc StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) {\n\tCommandLine.VarP(newStringArrayValue(value, p), name, shorthand, usage)\n}\n\n// StringArray defines a string flag with specified name, default value, and usage string.\n// The return value is the address of a []string variable that stores the value of the flag.\n// The value of each argument will not try to be separated by comma\nfunc (f *FlagSet) StringArray(name string, value []string, usage string) *[]string {\n\tp := []string{}\n\tf.StringArrayVarP(&p, name, \"\", value, usage)\n\treturn &p\n}\n\n// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) StringArrayP(name, shorthand string, value []string, usage string) *[]string {\n\tp := []string{}\n\tf.StringArrayVarP(&p, name, shorthand, value, usage)\n\treturn &p\n}\n\n// StringArray defines a string flag with specified name, default value, and usage string.\n// The return value is the address of a []string variable that stores the value of the flag.\n// The value of each argument will not try to be separated by comma\nfunc StringArray(name string, value []string, usage string) *[]string {\n\treturn CommandLine.StringArrayP(name, \"\", value, usage)\n}\n\n// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash.\nfunc StringArrayP(name, shorthand string, value []string, usage string) *[]string {\n\treturn CommandLine.StringArrayP(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/string_slice.go",
    "content": "package pflag\n\nimport (\n\t\"bytes\"\n\t\"encoding/csv\"\n\t\"strings\"\n)\n\n// -- stringSlice Value\ntype stringSliceValue struct {\n\tvalue   *[]string\n\tchanged bool\n}\n\nfunc newStringSliceValue(val []string, p *[]string) *stringSliceValue {\n\tssv := new(stringSliceValue)\n\tssv.value = p\n\t*ssv.value = val\n\treturn ssv\n}\n\nfunc readAsCSV(val string) ([]string, error) {\n\tif val == \"\" {\n\t\treturn []string{}, nil\n\t}\n\tstringReader := strings.NewReader(val)\n\tcsvReader := csv.NewReader(stringReader)\n\treturn csvReader.Read()\n}\n\nfunc writeAsCSV(vals []string) (string, error) {\n\tb := &bytes.Buffer{}\n\tw := csv.NewWriter(b)\n\terr := w.Write(vals)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tw.Flush()\n\treturn strings.TrimSuffix(b.String(), \"\\n\"), nil\n}\n\nfunc (s *stringSliceValue) Set(val string) error {\n\tv, err := readAsCSV(val)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !s.changed {\n\t\t*s.value = v\n\t} else {\n\t\t*s.value = append(*s.value, v...)\n\t}\n\ts.changed = true\n\treturn nil\n}\n\nfunc (s *stringSliceValue) Type() string {\n\treturn \"stringSlice\"\n}\n\nfunc (s *stringSliceValue) String() string {\n\tstr, _ := writeAsCSV(*s.value)\n\treturn \"[\" + str + \"]\"\n}\n\nfunc stringSliceConv(sval string) (interface{}, error) {\n\tsval = sval[1 : len(sval)-1]\n\t// An empty string would cause a slice with one (empty) string\n\tif len(sval) == 0 {\n\t\treturn []string{}, nil\n\t}\n\treturn readAsCSV(sval)\n}\n\n// GetStringSlice return the []string value of a flag with the given name\nfunc (f *FlagSet) GetStringSlice(name string) ([]string, error) {\n\tval, err := f.getFlagType(name, \"stringSlice\", stringSliceConv)\n\tif err != nil {\n\t\treturn []string{}, err\n\t}\n\treturn val.([]string), nil\n}\n\n// StringSliceVar defines a string flag with specified name, default value, and usage string.\n// The argument p points to a []string variable in which to store the value of the flag.\nfunc (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {\n\tf.VarP(newStringSliceValue(value, p), name, \"\", usage)\n}\n\n// StringSliceVarP is like StringSliceVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) {\n\tf.VarP(newStringSliceValue(value, p), name, shorthand, usage)\n}\n\n// StringSliceVar defines a string flag with specified name, default value, and usage string.\n// The argument p points to a []string variable in which to store the value of the flag.\nfunc StringSliceVar(p *[]string, name string, value []string, usage string) {\n\tCommandLine.VarP(newStringSliceValue(value, p), name, \"\", usage)\n}\n\n// StringSliceVarP is like StringSliceVar, but accepts a shorthand letter that can be used after a single dash.\nfunc StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) {\n\tCommandLine.VarP(newStringSliceValue(value, p), name, shorthand, usage)\n}\n\n// StringSlice defines a string flag with specified name, default value, and usage string.\n// The return value is the address of a []string variable that stores the value of the flag.\nfunc (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {\n\tp := []string{}\n\tf.StringSliceVarP(&p, name, \"\", value, usage)\n\treturn &p\n}\n\n// StringSliceP is like StringSlice, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage string) *[]string {\n\tp := []string{}\n\tf.StringSliceVarP(&p, name, shorthand, value, usage)\n\treturn &p\n}\n\n// StringSlice defines a string flag with specified name, default value, and usage string.\n// The return value is the address of a []string variable that stores the value of the flag.\nfunc StringSlice(name string, value []string, usage string) *[]string {\n\treturn CommandLine.StringSliceP(name, \"\", value, usage)\n}\n\n// StringSliceP is like StringSlice, but accepts a shorthand letter that can be used after a single dash.\nfunc StringSliceP(name, shorthand string, value []string, usage string) *[]string {\n\treturn CommandLine.StringSliceP(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/uint.go",
    "content": "package pflag\n\nimport \"strconv\"\n\n// -- uint Value\ntype uintValue uint\n\nfunc newUintValue(val uint, p *uint) *uintValue {\n\t*p = val\n\treturn (*uintValue)(p)\n}\n\nfunc (i *uintValue) Set(s string) error {\n\tv, err := strconv.ParseUint(s, 0, 64)\n\t*i = uintValue(v)\n\treturn err\n}\n\nfunc (i *uintValue) Type() string {\n\treturn \"uint\"\n}\n\nfunc (i *uintValue) String() string { return strconv.FormatUint(uint64(*i), 10) }\n\nfunc uintConv(sval string) (interface{}, error) {\n\tv, err := strconv.ParseUint(sval, 0, 0)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn uint(v), nil\n}\n\n// GetUint return the uint value of a flag with the given name\nfunc (f *FlagSet) GetUint(name string) (uint, error) {\n\tval, err := f.getFlagType(name, \"uint\", uintConv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn val.(uint), nil\n}\n\n// UintVar defines a uint flag with specified name, default value, and usage string.\n// The argument p points to a uint variable in which to store the value of the flag.\nfunc (f *FlagSet) UintVar(p *uint, name string, value uint, usage string) {\n\tf.VarP(newUintValue(value, p), name, \"\", usage)\n}\n\n// UintVarP is like UintVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) UintVarP(p *uint, name, shorthand string, value uint, usage string) {\n\tf.VarP(newUintValue(value, p), name, shorthand, usage)\n}\n\n// UintVar defines a uint flag with specified name, default value, and usage string.\n// The argument p points to a uint  variable in which to store the value of the flag.\nfunc UintVar(p *uint, name string, value uint, usage string) {\n\tCommandLine.VarP(newUintValue(value, p), name, \"\", usage)\n}\n\n// UintVarP is like UintVar, but accepts a shorthand letter that can be used after a single dash.\nfunc UintVarP(p *uint, name, shorthand string, value uint, usage string) {\n\tCommandLine.VarP(newUintValue(value, p), name, shorthand, usage)\n}\n\n// Uint defines a uint flag with specified name, default value, and usage string.\n// The return value is the address of a uint  variable that stores the value of the flag.\nfunc (f *FlagSet) Uint(name string, value uint, usage string) *uint {\n\tp := new(uint)\n\tf.UintVarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// UintP is like Uint, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) UintP(name, shorthand string, value uint, usage string) *uint {\n\tp := new(uint)\n\tf.UintVarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// Uint defines a uint flag with specified name, default value, and usage string.\n// The return value is the address of a uint  variable that stores the value of the flag.\nfunc Uint(name string, value uint, usage string) *uint {\n\treturn CommandLine.UintP(name, \"\", value, usage)\n}\n\n// UintP is like Uint, but accepts a shorthand letter that can be used after a single dash.\nfunc UintP(name, shorthand string, value uint, usage string) *uint {\n\treturn CommandLine.UintP(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/uint16.go",
    "content": "package pflag\n\nimport \"strconv\"\n\n// -- uint16 value\ntype uint16Value uint16\n\nfunc newUint16Value(val uint16, p *uint16) *uint16Value {\n\t*p = val\n\treturn (*uint16Value)(p)\n}\n\nfunc (i *uint16Value) Set(s string) error {\n\tv, err := strconv.ParseUint(s, 0, 16)\n\t*i = uint16Value(v)\n\treturn err\n}\n\nfunc (i *uint16Value) Type() string {\n\treturn \"uint16\"\n}\n\nfunc (i *uint16Value) String() string { return strconv.FormatUint(uint64(*i), 10) }\n\nfunc uint16Conv(sval string) (interface{}, error) {\n\tv, err := strconv.ParseUint(sval, 0, 16)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn uint16(v), nil\n}\n\n// GetUint16 return the uint16 value of a flag with the given name\nfunc (f *FlagSet) GetUint16(name string) (uint16, error) {\n\tval, err := f.getFlagType(name, \"uint16\", uint16Conv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn val.(uint16), nil\n}\n\n// Uint16Var defines a uint flag with specified name, default value, and usage string.\n// The argument p points to a uint variable in which to store the value of the flag.\nfunc (f *FlagSet) Uint16Var(p *uint16, name string, value uint16, usage string) {\n\tf.VarP(newUint16Value(value, p), name, \"\", usage)\n}\n\n// Uint16VarP is like Uint16Var, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Uint16VarP(p *uint16, name, shorthand string, value uint16, usage string) {\n\tf.VarP(newUint16Value(value, p), name, shorthand, usage)\n}\n\n// Uint16Var defines a uint flag with specified name, default value, and usage string.\n// The argument p points to a uint  variable in which to store the value of the flag.\nfunc Uint16Var(p *uint16, name string, value uint16, usage string) {\n\tCommandLine.VarP(newUint16Value(value, p), name, \"\", usage)\n}\n\n// Uint16VarP is like Uint16Var, but accepts a shorthand letter that can be used after a single dash.\nfunc Uint16VarP(p *uint16, name, shorthand string, value uint16, usage string) {\n\tCommandLine.VarP(newUint16Value(value, p), name, shorthand, usage)\n}\n\n// Uint16 defines a uint flag with specified name, default value, and usage string.\n// The return value is the address of a uint  variable that stores the value of the flag.\nfunc (f *FlagSet) Uint16(name string, value uint16, usage string) *uint16 {\n\tp := new(uint16)\n\tf.Uint16VarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// Uint16P is like Uint16, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Uint16P(name, shorthand string, value uint16, usage string) *uint16 {\n\tp := new(uint16)\n\tf.Uint16VarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// Uint16 defines a uint flag with specified name, default value, and usage string.\n// The return value is the address of a uint  variable that stores the value of the flag.\nfunc Uint16(name string, value uint16, usage string) *uint16 {\n\treturn CommandLine.Uint16P(name, \"\", value, usage)\n}\n\n// Uint16P is like Uint16, but accepts a shorthand letter that can be used after a single dash.\nfunc Uint16P(name, shorthand string, value uint16, usage string) *uint16 {\n\treturn CommandLine.Uint16P(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/uint32.go",
    "content": "package pflag\n\nimport \"strconv\"\n\n// -- uint32 value\ntype uint32Value uint32\n\nfunc newUint32Value(val uint32, p *uint32) *uint32Value {\n\t*p = val\n\treturn (*uint32Value)(p)\n}\n\nfunc (i *uint32Value) Set(s string) error {\n\tv, err := strconv.ParseUint(s, 0, 32)\n\t*i = uint32Value(v)\n\treturn err\n}\n\nfunc (i *uint32Value) Type() string {\n\treturn \"uint32\"\n}\n\nfunc (i *uint32Value) String() string { return strconv.FormatUint(uint64(*i), 10) }\n\nfunc uint32Conv(sval string) (interface{}, error) {\n\tv, err := strconv.ParseUint(sval, 0, 32)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn uint32(v), nil\n}\n\n// GetUint32 return the uint32 value of a flag with the given name\nfunc (f *FlagSet) GetUint32(name string) (uint32, error) {\n\tval, err := f.getFlagType(name, \"uint32\", uint32Conv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn val.(uint32), nil\n}\n\n// Uint32Var defines a uint32 flag with specified name, default value, and usage string.\n// The argument p points to a uint32 variable in which to store the value of the flag.\nfunc (f *FlagSet) Uint32Var(p *uint32, name string, value uint32, usage string) {\n\tf.VarP(newUint32Value(value, p), name, \"\", usage)\n}\n\n// Uint32VarP is like Uint32Var, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Uint32VarP(p *uint32, name, shorthand string, value uint32, usage string) {\n\tf.VarP(newUint32Value(value, p), name, shorthand, usage)\n}\n\n// Uint32Var defines a uint32 flag with specified name, default value, and usage string.\n// The argument p points to a uint32  variable in which to store the value of the flag.\nfunc Uint32Var(p *uint32, name string, value uint32, usage string) {\n\tCommandLine.VarP(newUint32Value(value, p), name, \"\", usage)\n}\n\n// Uint32VarP is like Uint32Var, but accepts a shorthand letter that can be used after a single dash.\nfunc Uint32VarP(p *uint32, name, shorthand string, value uint32, usage string) {\n\tCommandLine.VarP(newUint32Value(value, p), name, shorthand, usage)\n}\n\n// Uint32 defines a uint32 flag with specified name, default value, and usage string.\n// The return value is the address of a uint32  variable that stores the value of the flag.\nfunc (f *FlagSet) Uint32(name string, value uint32, usage string) *uint32 {\n\tp := new(uint32)\n\tf.Uint32VarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// Uint32P is like Uint32, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Uint32P(name, shorthand string, value uint32, usage string) *uint32 {\n\tp := new(uint32)\n\tf.Uint32VarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// Uint32 defines a uint32 flag with specified name, default value, and usage string.\n// The return value is the address of a uint32  variable that stores the value of the flag.\nfunc Uint32(name string, value uint32, usage string) *uint32 {\n\treturn CommandLine.Uint32P(name, \"\", value, usage)\n}\n\n// Uint32P is like Uint32, but accepts a shorthand letter that can be used after a single dash.\nfunc Uint32P(name, shorthand string, value uint32, usage string) *uint32 {\n\treturn CommandLine.Uint32P(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/uint64.go",
    "content": "package pflag\n\nimport \"strconv\"\n\n// -- uint64 Value\ntype uint64Value uint64\n\nfunc newUint64Value(val uint64, p *uint64) *uint64Value {\n\t*p = val\n\treturn (*uint64Value)(p)\n}\n\nfunc (i *uint64Value) Set(s string) error {\n\tv, err := strconv.ParseUint(s, 0, 64)\n\t*i = uint64Value(v)\n\treturn err\n}\n\nfunc (i *uint64Value) Type() string {\n\treturn \"uint64\"\n}\n\nfunc (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i), 10) }\n\nfunc uint64Conv(sval string) (interface{}, error) {\n\tv, err := strconv.ParseUint(sval, 0, 64)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn uint64(v), nil\n}\n\n// GetUint64 return the uint64 value of a flag with the given name\nfunc (f *FlagSet) GetUint64(name string) (uint64, error) {\n\tval, err := f.getFlagType(name, \"uint64\", uint64Conv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn val.(uint64), nil\n}\n\n// Uint64Var defines a uint64 flag with specified name, default value, and usage string.\n// The argument p points to a uint64 variable in which to store the value of the flag.\nfunc (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) {\n\tf.VarP(newUint64Value(value, p), name, \"\", usage)\n}\n\n// Uint64VarP is like Uint64Var, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Uint64VarP(p *uint64, name, shorthand string, value uint64, usage string) {\n\tf.VarP(newUint64Value(value, p), name, shorthand, usage)\n}\n\n// Uint64Var defines a uint64 flag with specified name, default value, and usage string.\n// The argument p points to a uint64 variable in which to store the value of the flag.\nfunc Uint64Var(p *uint64, name string, value uint64, usage string) {\n\tCommandLine.VarP(newUint64Value(value, p), name, \"\", usage)\n}\n\n// Uint64VarP is like Uint64Var, but accepts a shorthand letter that can be used after a single dash.\nfunc Uint64VarP(p *uint64, name, shorthand string, value uint64, usage string) {\n\tCommandLine.VarP(newUint64Value(value, p), name, shorthand, usage)\n}\n\n// Uint64 defines a uint64 flag with specified name, default value, and usage string.\n// The return value is the address of a uint64 variable that stores the value of the flag.\nfunc (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 {\n\tp := new(uint64)\n\tf.Uint64VarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// Uint64P is like Uint64, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Uint64P(name, shorthand string, value uint64, usage string) *uint64 {\n\tp := new(uint64)\n\tf.Uint64VarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// Uint64 defines a uint64 flag with specified name, default value, and usage string.\n// The return value is the address of a uint64 variable that stores the value of the flag.\nfunc Uint64(name string, value uint64, usage string) *uint64 {\n\treturn CommandLine.Uint64P(name, \"\", value, usage)\n}\n\n// Uint64P is like Uint64, but accepts a shorthand letter that can be used after a single dash.\nfunc Uint64P(name, shorthand string, value uint64, usage string) *uint64 {\n\treturn CommandLine.Uint64P(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/uint8.go",
    "content": "package pflag\n\nimport \"strconv\"\n\n// -- uint8 Value\ntype uint8Value uint8\n\nfunc newUint8Value(val uint8, p *uint8) *uint8Value {\n\t*p = val\n\treturn (*uint8Value)(p)\n}\n\nfunc (i *uint8Value) Set(s string) error {\n\tv, err := strconv.ParseUint(s, 0, 8)\n\t*i = uint8Value(v)\n\treturn err\n}\n\nfunc (i *uint8Value) Type() string {\n\treturn \"uint8\"\n}\n\nfunc (i *uint8Value) String() string { return strconv.FormatUint(uint64(*i), 10) }\n\nfunc uint8Conv(sval string) (interface{}, error) {\n\tv, err := strconv.ParseUint(sval, 0, 8)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn uint8(v), nil\n}\n\n// GetUint8 return the uint8 value of a flag with the given name\nfunc (f *FlagSet) GetUint8(name string) (uint8, error) {\n\tval, err := f.getFlagType(name, \"uint8\", uint8Conv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn val.(uint8), nil\n}\n\n// Uint8Var defines a uint8 flag with specified name, default value, and usage string.\n// The argument p points to a uint8 variable in which to store the value of the flag.\nfunc (f *FlagSet) Uint8Var(p *uint8, name string, value uint8, usage string) {\n\tf.VarP(newUint8Value(value, p), name, \"\", usage)\n}\n\n// Uint8VarP is like Uint8Var, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Uint8VarP(p *uint8, name, shorthand string, value uint8, usage string) {\n\tf.VarP(newUint8Value(value, p), name, shorthand, usage)\n}\n\n// Uint8Var defines a uint8 flag with specified name, default value, and usage string.\n// The argument p points to a uint8 variable in which to store the value of the flag.\nfunc Uint8Var(p *uint8, name string, value uint8, usage string) {\n\tCommandLine.VarP(newUint8Value(value, p), name, \"\", usage)\n}\n\n// Uint8VarP is like Uint8Var, but accepts a shorthand letter that can be used after a single dash.\nfunc Uint8VarP(p *uint8, name, shorthand string, value uint8, usage string) {\n\tCommandLine.VarP(newUint8Value(value, p), name, shorthand, usage)\n}\n\n// Uint8 defines a uint8 flag with specified name, default value, and usage string.\n// The return value is the address of a uint8 variable that stores the value of the flag.\nfunc (f *FlagSet) Uint8(name string, value uint8, usage string) *uint8 {\n\tp := new(uint8)\n\tf.Uint8VarP(p, name, \"\", value, usage)\n\treturn p\n}\n\n// Uint8P is like Uint8, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) Uint8P(name, shorthand string, value uint8, usage string) *uint8 {\n\tp := new(uint8)\n\tf.Uint8VarP(p, name, shorthand, value, usage)\n\treturn p\n}\n\n// Uint8 defines a uint8 flag with specified name, default value, and usage string.\n// The return value is the address of a uint8 variable that stores the value of the flag.\nfunc Uint8(name string, value uint8, usage string) *uint8 {\n\treturn CommandLine.Uint8P(name, \"\", value, usage)\n}\n\n// Uint8P is like Uint8, but accepts a shorthand letter that can be used after a single dash.\nfunc Uint8P(name, shorthand string, value uint8, usage string) *uint8 {\n\treturn CommandLine.Uint8P(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/spf13/pflag/uint_slice.go",
    "content": "package pflag\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// -- uintSlice Value\ntype uintSliceValue struct {\n\tvalue   *[]uint\n\tchanged bool\n}\n\nfunc newUintSliceValue(val []uint, p *[]uint) *uintSliceValue {\n\tuisv := new(uintSliceValue)\n\tuisv.value = p\n\t*uisv.value = val\n\treturn uisv\n}\n\nfunc (s *uintSliceValue) Set(val string) error {\n\tss := strings.Split(val, \",\")\n\tout := make([]uint, len(ss))\n\tfor i, d := range ss {\n\t\tu, err := strconv.ParseUint(d, 10, 0)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tout[i] = uint(u)\n\t}\n\tif !s.changed {\n\t\t*s.value = out\n\t} else {\n\t\t*s.value = append(*s.value, out...)\n\t}\n\ts.changed = true\n\treturn nil\n}\n\nfunc (s *uintSliceValue) Type() string {\n\treturn \"uintSlice\"\n}\n\nfunc (s *uintSliceValue) String() string {\n\tout := make([]string, len(*s.value))\n\tfor i, d := range *s.value {\n\t\tout[i] = fmt.Sprintf(\"%d\", d)\n\t}\n\treturn \"[\" + strings.Join(out, \",\") + \"]\"\n}\n\nfunc uintSliceConv(val string) (interface{}, error) {\n\tval = strings.Trim(val, \"[]\")\n\t// Empty string would cause a slice with one (empty) entry\n\tif len(val) == 0 {\n\t\treturn []uint{}, nil\n\t}\n\tss := strings.Split(val, \",\")\n\tout := make([]uint, len(ss))\n\tfor i, d := range ss {\n\t\tu, err := strconv.ParseUint(d, 10, 0)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tout[i] = uint(u)\n\t}\n\treturn out, nil\n}\n\n// GetUintSlice returns the []uint value of a flag with the given name.\nfunc (f *FlagSet) GetUintSlice(name string) ([]uint, error) {\n\tval, err := f.getFlagType(name, \"uintSlice\", uintSliceConv)\n\tif err != nil {\n\t\treturn []uint{}, err\n\t}\n\treturn val.([]uint), nil\n}\n\n// UintSliceVar defines a uintSlice flag with specified name, default value, and usage string.\n// The argument p points to a []uint variable in which to store the value of the flag.\nfunc (f *FlagSet) UintSliceVar(p *[]uint, name string, value []uint, usage string) {\n\tf.VarP(newUintSliceValue(value, p), name, \"\", usage)\n}\n\n// UintSliceVarP is like UintSliceVar, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {\n\tf.VarP(newUintSliceValue(value, p), name, shorthand, usage)\n}\n\n// UintSliceVar defines a uint[] flag with specified name, default value, and usage string.\n// The argument p points to a uint[] variable in which to store the value of the flag.\nfunc UintSliceVar(p *[]uint, name string, value []uint, usage string) {\n\tCommandLine.VarP(newUintSliceValue(value, p), name, \"\", usage)\n}\n\n// UintSliceVarP is like the UintSliceVar, but accepts a shorthand letter that can be used after a single dash.\nfunc UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {\n\tCommandLine.VarP(newUintSliceValue(value, p), name, shorthand, usage)\n}\n\n// UintSlice defines a []uint flag with specified name, default value, and usage string.\n// The return value is the address of a []uint variable that stores the value of the flag.\nfunc (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint {\n\tp := []uint{}\n\tf.UintSliceVarP(&p, name, \"\", value, usage)\n\treturn &p\n}\n\n// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.\nfunc (f *FlagSet) UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {\n\tp := []uint{}\n\tf.UintSliceVarP(&p, name, shorthand, value, usage)\n\treturn &p\n}\n\n// UintSlice defines a []uint flag with specified name, default value, and usage string.\n// The return value is the address of a []uint variable that stores the value of the flag.\nfunc UintSlice(name string, value []uint, usage string) *[]uint {\n\treturn CommandLine.UintSliceP(name, \"\", value, usage)\n}\n\n// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.\nfunc UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {\n\treturn CommandLine.UintSliceP(name, shorthand, value, usage)\n}\n"
  },
  {
    "path": "vendor/github.com/willf/bitset/LICENSE",
    "content": "Copyright (c) 2014 Will Fitzgerald. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n   * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n   * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n   * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "vendor/github.com/willf/bitset/bitset.go",
    "content": "/*\nPackage bitset implements bitsets, a mapping\nbetween non-negative integers and boolean values. It should be more\nefficient than map[uint] bool.\n\nIt provides methods for setting, clearing, flipping, and testing\nindividual integers.\n\nBut it also provides set intersection, union, difference,\ncomplement, and symmetric operations, as well as tests to\ncheck whether any, all, or no bits are set, and querying a\nbitset's current length and number of positive bits.\n\nBitSets are expanded to the size of the largest set bit; the\nmemory allocation is approximately Max bits, where Max is\nthe largest set bit. BitSets are never shrunk. On creation,\na hint can be given for the number of bits that will be used.\n\nMany of the methods, including Set,Clear, and Flip, return\na BitSet pointer, which allows for chaining.\n\nExample use:\n\n\timport \"bitset\"\n\tvar b BitSet\n\tb.Set(10).Set(11)\n\tif b.Test(1000) {\n\t\tb.Clear(1000)\n\t}\n\tif B.Intersection(bitset.New(100).Set(10)).Count() > 1 {\n\t\tfmt.Println(\"Intersection works.\")\n\t}\n\nAs an alternative to BitSets, one should check out the 'big' package,\nwhich provides a (less set-theoretical) view of bitsets.\n\n*/\npackage bitset\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"encoding/base64\"\n\t\"encoding/binary\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"strconv\"\n)\n\n// the wordSize of a bit set\nconst wordSize = uint(64)\n\n// log2WordSize is lg(wordSize)\nconst log2WordSize = uint(6)\n\n// allBits has every bit set\nconst allBits uint64 = 0xffffffffffffffff\n\n// A BitSet is a set of bits. The zero value of a BitSet is an empty set of length 0.\ntype BitSet struct {\n\tlength uint\n\tset    []uint64\n}\n\n// Error is used to distinguish errors (panics) generated in this package.\ntype Error string\n\n// safeSet will fixup b.set to be non-nil and return the field value\nfunc (b *BitSet) safeSet() []uint64 {\n\tif b.set == nil {\n\t\tb.set = make([]uint64, wordsNeeded(0))\n\t}\n\treturn b.set\n}\n\n// From is a constructor used to create a BitSet from an array of integers\nfunc From(buf []uint64) *BitSet {\n\treturn &BitSet{uint(len(buf)) * 64, buf}\n}\n\n// Bytes returns the bitset as array of integers\nfunc (b *BitSet) Bytes() []uint64 {\n\treturn b.set\n}\n\n// wordsNeeded calculates the number of words needed for i bits\nfunc wordsNeeded(i uint) int {\n\tif i > ((^uint(0)) - wordSize + 1) {\n\t\treturn int((^uint(0)) >> log2WordSize)\n\t}\n\treturn int((i + (wordSize - 1)) >> log2WordSize)\n}\n\n// New creates a new BitSet with a hint that length bits will be required\nfunc New(length uint) (bset *BitSet) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tbset = &BitSet{\n\t\t\t\t0,\n\t\t\t\tmake([]uint64, 0),\n\t\t\t}\n\t\t}\n\t}()\n\n\tbset = &BitSet{\n\t\tlength,\n\t\tmake([]uint64, wordsNeeded(length)),\n\t}\n\n\treturn bset\n}\n\n// Cap returns the total possible capicity, or number of bits\nfunc Cap() uint {\n\treturn ^uint(0)\n}\n\n// Len returns the length of the BitSet in words\nfunc (b *BitSet) Len() uint {\n\treturn b.length\n}\n\n// extendSetMaybe adds additional words to incorporate new bits if needed\nfunc (b *BitSet) extendSetMaybe(i uint) {\n\tif i >= b.length { // if we need more bits, make 'em\n\t\tnsize := wordsNeeded(i + 1)\n\t\tif b.set == nil {\n\t\t\tb.set = make([]uint64, nsize)\n\t\t} else if cap(b.set) >= nsize {\n\t\t\tb.set = b.set[:nsize] // fast resize\n\t\t} else if len(b.set) < nsize {\n\t\t\tnewset := make([]uint64, nsize, 2*nsize) // increase capacity 2x\n\t\t\tcopy(newset, b.set)\n\t\t\tb.set = newset\n\t\t}\n\t\tb.length = i + 1\n\t}\n}\n\n// Test whether bit i is set.\nfunc (b *BitSet) Test(i uint) bool {\n\tif i >= b.length {\n\t\treturn false\n\t}\n\treturn b.set[i>>log2WordSize]&(1<<(i&(wordSize-1))) != 0\n}\n\n// Set bit i to 1\nfunc (b *BitSet) Set(i uint) *BitSet {\n\tb.extendSetMaybe(i)\n\tb.set[i>>log2WordSize] |= 1 << (i & (wordSize - 1))\n\treturn b\n}\n\n// Clear bit i to 0\nfunc (b *BitSet) Clear(i uint) *BitSet {\n\tif i >= b.length {\n\t\treturn b\n\t}\n\tb.set[i>>log2WordSize] &^= 1 << (i & (wordSize - 1))\n\treturn b\n}\n\n// SetTo sets bit i to value\nfunc (b *BitSet) SetTo(i uint, value bool) *BitSet {\n\tif value {\n\t\treturn b.Set(i)\n\t}\n\treturn b.Clear(i)\n}\n\n// Flip bit at i\nfunc (b *BitSet) Flip(i uint) *BitSet {\n\tif i >= b.length {\n\t\treturn b.Set(i)\n\t}\n\tb.set[i>>log2WordSize] ^= 1 << (i & (wordSize - 1))\n\treturn b\n}\n\n// String creates a string representation of the Bitmap\nfunc (b *BitSet) String() string {\n\t// follows code from https://github.com/RoaringBitmap/roaring\n\tvar buffer bytes.Buffer\n\tstart := []byte(\"{\")\n\tbuffer.Write(start)\n\tcounter := 0\n\ti, e := b.NextSet(0)\n\tfor e {\n\t\tcounter = counter + 1\n\t\t// to avoid exhausting the memory\n\t\tif counter > 0x40000 {\n\t\t\tbuffer.WriteString(\"...\")\n\t\t\tbreak\n\t\t}\n\t\tbuffer.WriteString(strconv.FormatInt(int64(i), 10))\n\t\ti, e = b.NextSet(i + 1)\n\t\tif e {\n\t\t\tbuffer.WriteString(\",\")\n\t\t}\n\t}\n\tbuffer.WriteString(\"}\")\n\treturn buffer.String()\n}\n\n// NextSet returns the next bit set from the specified index,\n// including possibly the current index\n// along with an error code (true = valid, false = no set bit found)\n// for i,e := v.NextSet(0); e; i,e = v.NextSet(i + 1) {...}\nfunc (b *BitSet) NextSet(i uint) (uint, bool) {\n\tx := int(i >> log2WordSize)\n\tif x >= len(b.set) {\n\t\treturn 0, false\n\t}\n\tw := b.set[x]\n\tw = w >> (i & (wordSize - 1))\n\tif w != 0 {\n\t\treturn i + trailingZeroes64(w), true\n\t}\n\tx = x + 1\n\tfor x < len(b.set) {\n\t\tif b.set[x] != 0 {\n\t\t\treturn uint(x)*wordSize + trailingZeroes64(b.set[x]), true\n\t\t}\n\t\tx = x + 1\n\n\t}\n\treturn 0, false\n}\n\n// NextClear returns the next clear bit from the specified index,\n// including possibly the current index\n// along with an error code (true = valid, false = no bit found i.e. all bits are set)\nfunc (b *BitSet) NextClear(i uint) (uint, bool) {\n\tx := int(i >> log2WordSize)\n\tif x >= len(b.set) {\n\t\treturn 0, false\n\t}\n\tw := b.set[x]\n\tw = w >> (i & (wordSize - 1))\n\twA := allBits >> (i & (wordSize - 1))\n\tif w != wA {\n\t\treturn i + trailingZeroes64(^w), true\n\t}\n\tx++\n\tfor x < len(b.set) {\n\t\tif b.set[x] != allBits {\n\t\t\treturn uint(x)*wordSize + trailingZeroes64(^b.set[x]), true\n\t\t}\n\t\tx++\n\t}\n\treturn 0, false\n}\n\n// ClearAll clears the entire BitSet\nfunc (b *BitSet) ClearAll() *BitSet {\n\tif b != nil && b.set != nil {\n\t\tfor i := range b.set {\n\t\t\tb.set[i] = 0\n\t\t}\n\t}\n\treturn b\n}\n\n// wordCount returns the number of words used in a bit set\nfunc (b *BitSet) wordCount() int {\n\treturn len(b.set)\n}\n\n// Clone this BitSet\nfunc (b *BitSet) Clone() *BitSet {\n\tc := New(b.length)\n\tif b.set != nil { // Clone should not modify current object\n\t\tcopy(c.set, b.set)\n\t}\n\treturn c\n}\n\n// Copy into a destination BitSet\n// Returning the size of the destination BitSet\n// like array copy\nfunc (b *BitSet) Copy(c *BitSet) (count uint) {\n\tif c == nil {\n\t\treturn\n\t}\n\tif b.set != nil { // Copy should not modify current object\n\t\tcopy(c.set, b.set)\n\t}\n\tcount = c.length\n\tif b.length < c.length {\n\t\tcount = b.length\n\t}\n\treturn\n}\n\n// Count (number of set bits)\nfunc (b *BitSet) Count() uint {\n\tif b != nil && b.set != nil {\n\t\treturn uint(popcntSlice(b.set))\n\t}\n\treturn 0\n}\n\nvar deBruijn = [...]byte{\n\t0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,\n\t62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,\n\t63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,\n\t54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,\n}\n\nfunc trailingZeroes64(v uint64) uint {\n\treturn uint(deBruijn[((v&-v)*0x03f79d71b4ca8b09)>>58])\n}\n\n// Equal tests the equvalence of two BitSets.\n// False if they are of different sizes, otherwise true\n// only if all the same bits are set\nfunc (b *BitSet) Equal(c *BitSet) bool {\n\tif c == nil {\n\t\treturn false\n\t}\n\tif b.length != c.length {\n\t\treturn false\n\t}\n\tif b.length == 0 { // if they have both length == 0, then could have nil set\n\t\treturn true\n\t}\n\t// testing for equality shoud not transform the bitset (no call to safeSet)\n\n\tfor p, v := range b.set {\n\t\tif c.set[p] != v {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc panicIfNull(b *BitSet) {\n\tif b == nil {\n\t\tpanic(Error(\"BitSet must not be null\"))\n\t}\n}\n\n// Difference of base set and other set\n// This is the BitSet equivalent of &^ (and not)\nfunc (b *BitSet) Difference(compare *BitSet) (result *BitSet) {\n\tpanicIfNull(b)\n\tpanicIfNull(compare)\n\tresult = b.Clone() // clone b (in case b is bigger than compare)\n\tl := int(compare.wordCount())\n\tif l > int(b.wordCount()) {\n\t\tl = int(b.wordCount())\n\t}\n\tfor i := 0; i < l; i++ {\n\t\tresult.set[i] = b.set[i] &^ compare.set[i]\n\t}\n\treturn\n}\n\n// DifferenceCardinality computes the cardinality of the differnce\nfunc (b *BitSet) DifferenceCardinality(compare *BitSet) uint {\n\tpanicIfNull(b)\n\tpanicIfNull(compare)\n\tl := int(compare.wordCount())\n\tif l > int(b.wordCount()) {\n\t\tl = int(b.wordCount())\n\t}\n\tcnt := uint64(0)\n\tcnt += popcntMaskSlice(b.set[:l], compare.set[:l])\n\tcnt += popcntSlice(b.set[l:])\n\treturn uint(cnt)\n}\n\n// InPlaceDifference computes the difference of base set and other set\n// This is the BitSet equivalent of &^ (and not)\nfunc (b *BitSet) InPlaceDifference(compare *BitSet) {\n\tpanicIfNull(b)\n\tpanicIfNull(compare)\n\tl := int(compare.wordCount())\n\tif l > int(b.wordCount()) {\n\t\tl = int(b.wordCount())\n\t}\n\tfor i := 0; i < l; i++ {\n\t\tb.set[i] &^= compare.set[i]\n\t}\n}\n\n// Convenience function: return two bitsets ordered by\n// increasing length. Note: neither can be nil\nfunc sortByLength(a *BitSet, b *BitSet) (ap *BitSet, bp *BitSet) {\n\tif a.length <= b.length {\n\t\tap, bp = a, b\n\t} else {\n\t\tap, bp = b, a\n\t}\n\treturn\n}\n\n// Intersection of base set and other set\n// This is the BitSet equivalent of & (and)\nfunc (b *BitSet) Intersection(compare *BitSet) (result *BitSet) {\n\tpanicIfNull(b)\n\tpanicIfNull(compare)\n\tb, compare = sortByLength(b, compare)\n\tresult = New(b.length)\n\tfor i, word := range b.set {\n\t\tresult.set[i] = word & compare.set[i]\n\t}\n\treturn\n}\n\n// IntersectionCardinality computes the cardinality of the union\nfunc (b *BitSet) IntersectionCardinality(compare *BitSet) uint {\n\tpanicIfNull(b)\n\tpanicIfNull(compare)\n\tb, compare = sortByLength(b, compare)\n\tcnt := popcntAndSlice(b.set, compare.set)\n\treturn uint(cnt)\n}\n\n// InPlaceIntersection destructively computes the intersection of\n// base set and the compare set.\n// This is the BitSet equivalent of & (and)\nfunc (b *BitSet) InPlaceIntersection(compare *BitSet) {\n\tpanicIfNull(b)\n\tpanicIfNull(compare)\n\tl := int(compare.wordCount())\n\tif l > int(b.wordCount()) {\n\t\tl = int(b.wordCount())\n\t}\n\tfor i := 0; i < l; i++ {\n\t\tb.set[i] &= compare.set[i]\n\t}\n\tfor i := l; i < len(b.set); i++ {\n\t\tb.set[i] = 0\n\t}\n\tif compare.length > 0 {\n\t\tb.extendSetMaybe(compare.length - 1)\n\t}\n\treturn\n}\n\n// Union of base set and other set\n// This is the BitSet equivalent of | (or)\nfunc (b *BitSet) Union(compare *BitSet) (result *BitSet) {\n\tpanicIfNull(b)\n\tpanicIfNull(compare)\n\tb, compare = sortByLength(b, compare)\n\tresult = compare.Clone()\n\tfor i, word := range b.set {\n\t\tresult.set[i] = word | compare.set[i]\n\t}\n\treturn\n}\n\n// UnionCardinality computes the cardinality of the uniton of the base set\n// and the compare set.\nfunc (b *BitSet) UnionCardinality(compare *BitSet) uint {\n\tpanicIfNull(b)\n\tpanicIfNull(compare)\n\tb, compare = sortByLength(b, compare)\n\tcnt := popcntOrSlice(b.set, compare.set)\n\tif len(compare.set) > len(b.set) {\n\t\tcnt += popcntSlice(compare.set[len(b.set):])\n\t}\n\treturn uint(cnt)\n}\n\n// InPlaceUnion creates the destructive union of base set and compare set.\n// This is the BitSet equivalent of | (or).\nfunc (b *BitSet) InPlaceUnion(compare *BitSet) {\n\tpanicIfNull(b)\n\tpanicIfNull(compare)\n\tl := int(compare.wordCount())\n\tif l > int(b.wordCount()) {\n\t\tl = int(b.wordCount())\n\t}\n\tif compare.length > 0 {\n\t\tb.extendSetMaybe(compare.length - 1)\n\t}\n\tfor i := 0; i < l; i++ {\n\t\tb.set[i] |= compare.set[i]\n\t}\n\tif len(compare.set) > l {\n\t\tfor i := l; i < len(compare.set); i++ {\n\t\t\tb.set[i] = compare.set[i]\n\t\t}\n\t}\n}\n\n// SymmetricDifference of base set and other set\n// This is the BitSet equivalent of ^ (xor)\nfunc (b *BitSet) SymmetricDifference(compare *BitSet) (result *BitSet) {\n\tpanicIfNull(b)\n\tpanicIfNull(compare)\n\tb, compare = sortByLength(b, compare)\n\t// compare is bigger, so clone it\n\tresult = compare.Clone()\n\tfor i, word := range b.set {\n\t\tresult.set[i] = word ^ compare.set[i]\n\t}\n\treturn\n}\n\n// SymmetricDifferenceCardinality computes the cardinality of the symmetric difference\nfunc (b *BitSet) SymmetricDifferenceCardinality(compare *BitSet) uint {\n\tpanicIfNull(b)\n\tpanicIfNull(compare)\n\tb, compare = sortByLength(b, compare)\n\tcnt := popcntXorSlice(b.set, compare.set)\n\tif len(compare.set) > len(b.set) {\n\t\tcnt += popcntSlice(compare.set[len(b.set):])\n\t}\n\treturn uint(cnt)\n}\n\n// InPlaceSymmetricDifference creates the destructive SymmetricDifference of base set and other set\n// This is the BitSet equivalent of ^ (xor)\nfunc (b *BitSet) InPlaceSymmetricDifference(compare *BitSet) {\n\tpanicIfNull(b)\n\tpanicIfNull(compare)\n\tl := int(compare.wordCount())\n\tif l > int(b.wordCount()) {\n\t\tl = int(b.wordCount())\n\t}\n\tif compare.length > 0 {\n\t\tb.extendSetMaybe(compare.length - 1)\n\t}\n\tfor i := 0; i < l; i++ {\n\t\tb.set[i] ^= compare.set[i]\n\t}\n\tif len(compare.set) > l {\n\t\tfor i := l; i < len(compare.set); i++ {\n\t\t\tb.set[i] = compare.set[i]\n\t\t}\n\t}\n}\n\n// Is the length an exact multiple of word sizes?\nfunc (b *BitSet) isLenExactMultiple() bool {\n\treturn b.length%wordSize == 0\n}\n\n// Clean last word by setting unused bits to 0\nfunc (b *BitSet) cleanLastWord() {\n\tif !b.isLenExactMultiple() {\n\t\tb.set[len(b.set)-1] &= allBits >> (wordSize - b.length%wordSize)\n\t}\n}\n\n// Complement computes the (local) complement of a biset (up to length bits)\nfunc (b *BitSet) Complement() (result *BitSet) {\n\tpanicIfNull(b)\n\tresult = New(b.length)\n\tfor i, word := range b.set {\n\t\tresult.set[i] = ^word\n\t}\n\tresult.cleanLastWord()\n\treturn\n}\n\n// All returns true if all bits are set, false otherwise. Returns true for\n// empty sets.\nfunc (b *BitSet) All() bool {\n\tpanicIfNull(b)\n\treturn b.Count() == b.length\n}\n\n// None returns true if no bit is set, false otherwise. Retursn true for\n// empty sets.\nfunc (b *BitSet) None() bool {\n\tpanicIfNull(b)\n\tif b != nil && b.set != nil {\n\t\tfor _, word := range b.set {\n\t\t\tif word > 0 {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\treturn true\n}\n\n// Any returns true if any bit is set, false otherwise\nfunc (b *BitSet) Any() bool {\n\tpanicIfNull(b)\n\treturn !b.None()\n}\n\n// IsSuperSet returns true if this is a superset of the other set\nfunc (b *BitSet) IsSuperSet(other *BitSet) bool {\n\tfor i, e := other.NextSet(0); e; i, e = other.NextSet(i + 1) {\n\t\tif !b.Test(i) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// IsStrictSuperSet returns true if this is a strict superset of the other set\nfunc (b *BitSet) IsStrictSuperSet(other *BitSet) bool {\n\treturn b.Count() > other.Count() && b.IsSuperSet(other)\n}\n\n// DumpAsBits dumps a bit set as a string of bits\nfunc (b *BitSet) DumpAsBits() string {\n\tif b.set == nil {\n\t\treturn \".\"\n\t}\n\tbuffer := bytes.NewBufferString(\"\")\n\ti := len(b.set) - 1\n\tfor ; i >= 0; i-- {\n\t\tfmt.Fprintf(buffer, \"%064b.\", b.set[i])\n\t}\n\treturn string(buffer.Bytes())\n}\n\n// BinaryStorageSize returns the binary storage requirements\nfunc (b *BitSet) BinaryStorageSize() int {\n\treturn binary.Size(uint64(0)) + binary.Size(b.set)\n}\n\n// WriteTo writes a BitSet to a stream\nfunc (b *BitSet) WriteTo(stream io.Writer) (int64, error) {\n\tlength := uint64(b.length)\n\n\t// Write length\n\terr := binary.Write(stream, binary.BigEndian, length)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\t// Write set\n\terr = binary.Write(stream, binary.BigEndian, b.set)\n\treturn int64(b.BinaryStorageSize()), err\n}\n\n// ReadFrom reads a BitSet from a stream written using WriteTo\nfunc (b *BitSet) ReadFrom(stream io.Reader) (int64, error) {\n\tvar length uint64\n\n\t// Read length first\n\terr := binary.Read(stream, binary.BigEndian, &length)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tnewset := New(uint(length))\n\n\tif uint64(newset.length) != length {\n\t\treturn 0, errors.New(\"Unmarshalling error: type mismatch\")\n\t}\n\n\t// Read remaining bytes as set\n\terr = binary.Read(stream, binary.BigEndian, newset.set)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\t*b = *newset\n\treturn int64(b.BinaryStorageSize()), nil\n}\n\n// MarshalBinary encodes a BitSet into a binary form and returns the result.\nfunc (b *BitSet) MarshalBinary() ([]byte, error) {\n\tvar buf bytes.Buffer\n\twriter := bufio.NewWriter(&buf)\n\n\t_, err := b.WriteTo(writer)\n\tif err != nil {\n\t\treturn []byte{}, err\n\t}\n\n\terr = writer.Flush()\n\n\treturn buf.Bytes(), err\n}\n\n// UnmarshalBinary decodes the binary form generated by MarshalBinary.\nfunc (b *BitSet) UnmarshalBinary(data []byte) error {\n\tbuf := bytes.NewReader(data)\n\treader := bufio.NewReader(buf)\n\n\t_, err := b.ReadFrom(reader)\n\n\treturn err\n}\n\n// MarshalJSON marshals a BitSet as a JSON structure\nfunc (b *BitSet) MarshalJSON() ([]byte, error) {\n\tbuffer := bytes.NewBuffer(make([]byte, 0, b.BinaryStorageSize()))\n\t_, err := b.WriteTo(buffer)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// URLEncode all bytes\n\treturn json.Marshal(base64.URLEncoding.EncodeToString(buffer.Bytes()))\n}\n\n// UnmarshalJSON unmarshals a BitSet from JSON created using MarshalJSON\nfunc (b *BitSet) UnmarshalJSON(data []byte) error {\n\t// Unmarshal as string\n\tvar s string\n\terr := json.Unmarshal(data, &s)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// URLDecode string\n\tbuf, err := base64.URLEncoding.DecodeString(s)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t_, err = b.ReadFrom(bytes.NewReader(buf))\n\treturn err\n}\n"
  },
  {
    "path": "vendor/github.com/willf/bitset/popcnt.go",
    "content": "package bitset\n\n// bit population count, take from\n// https://code.google.com/p/go/issues/detail?id=4988#c11\n// credit: https://code.google.com/u/arnehormann/\nfunc popcount(x uint64) (n uint64) {\n\tx -= (x >> 1) & 0x5555555555555555\n\tx = (x>>2)&0x3333333333333333 + x&0x3333333333333333\n\tx += x >> 4\n\tx &= 0x0f0f0f0f0f0f0f0f\n\tx *= 0x0101010101010101\n\treturn x >> 56\n}\n\nfunc popcntSliceGo(s []uint64) uint64 {\n\tcnt := uint64(0)\n\tfor _, x := range s {\n\t\tcnt += popcount(x)\n\t}\n\treturn cnt\n}\n\nfunc popcntMaskSliceGo(s, m []uint64) uint64 {\n\tcnt := uint64(0)\n\tfor i := range s {\n\t\tcnt += popcount(s[i] &^ m[i])\n\t}\n\treturn cnt\n}\n\nfunc popcntAndSliceGo(s, m []uint64) uint64 {\n\tcnt := uint64(0)\n\tfor i := range s {\n\t\tcnt += popcount(s[i] & m[i])\n\t}\n\treturn cnt\n}\n\nfunc popcntOrSliceGo(s, m []uint64) uint64 {\n\tcnt := uint64(0)\n\tfor i := range s {\n\t\tcnt += popcount(s[i] | m[i])\n\t}\n\treturn cnt\n}\n\nfunc popcntXorSliceGo(s, m []uint64) uint64 {\n\tcnt := uint64(0)\n\tfor i := range s {\n\t\tcnt += popcount(s[i] ^ m[i])\n\t}\n\treturn cnt\n}\n"
  },
  {
    "path": "vendor/github.com/willf/bitset/popcnt_amd64.go",
    "content": "// +build amd64,!appengine\n\npackage bitset\n\n// *** the following functions are defined in popcnt_amd64.s\n\n//go:noescape\n\nfunc hasAsm() bool\n\n// useAsm is a flag used to select the GO or ASM implementation of the popcnt function\nvar useAsm = hasAsm()\n\n//go:noescape\n\nfunc popcntSliceAsm(s []uint64) uint64\n\n//go:noescape\n\nfunc popcntMaskSliceAsm(s, m []uint64) uint64\n\n//go:noescape\n\nfunc popcntAndSliceAsm(s, m []uint64) uint64\n\n//go:noescape\n\nfunc popcntOrSliceAsm(s, m []uint64) uint64\n\n//go:noescape\n\nfunc popcntXorSliceAsm(s, m []uint64) uint64\n\nfunc popcntSlice(s []uint64) uint64 {\n\tif useAsm {\n\t\treturn popcntSliceAsm(s)\n\t}\n\treturn popcntSliceGo(s)\n}\n\nfunc popcntMaskSlice(s, m []uint64) uint64 {\n\tif useAsm {\n\t\treturn popcntMaskSliceAsm(s, m)\n\t}\n\treturn popcntMaskSliceGo(s, m)\n}\n\nfunc popcntAndSlice(s, m []uint64) uint64 {\n\tif useAsm {\n\t\treturn popcntAndSliceAsm(s, m)\n\t}\n\treturn popcntAndSliceGo(s, m)\n}\n\nfunc popcntOrSlice(s, m []uint64) uint64 {\n\tif useAsm {\n\t\treturn popcntOrSliceAsm(s, m)\n\t}\n\treturn popcntOrSliceGo(s, m)\n}\n\nfunc popcntXorSlice(s, m []uint64) uint64 {\n\tif useAsm {\n\t\treturn popcntXorSliceAsm(s, m)\n\t}\n\treturn popcntXorSliceGo(s, m)\n}\n"
  },
  {
    "path": "vendor/github.com/willf/bitset/popcnt_amd64.s",
    "content": "// +build amd64,!appengine\n\nTEXT ·hasAsm(SB),4,$0-1\nMOVQ $1, AX\nCPUID\nSHRQ $23, CX\nANDQ $1, CX\nMOVB CX, ret+0(FP)\nRET\n\n#define POPCNTQ_DX_DX BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0xd2\n\nTEXT ·popcntSliceAsm(SB),4,$0-32\nXORQ\tAX, AX\nMOVQ\ts+0(FP), SI\nMOVQ\ts_len+8(FP), CX\nTESTQ\tCX, CX\nJZ\t\tpopcntSliceEnd\npopcntSliceLoop:\nBYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0x16 // POPCNTQ (SI), DX\nADDQ\tDX, AX\nADDQ\t$8, SI\nLOOP\tpopcntSliceLoop\npopcntSliceEnd:\nMOVQ\tAX, ret+24(FP)\nRET\n\nTEXT ·popcntMaskSliceAsm(SB),4,$0-56\nXORQ\tAX, AX\nMOVQ\ts+0(FP), SI\nMOVQ\ts_len+8(FP), CX\nTESTQ\tCX, CX\nJZ\t\tpopcntMaskSliceEnd\nMOVQ\tm+24(FP), DI\npopcntMaskSliceLoop:\nMOVQ\t(DI), DX\nNOTQ\tDX\nANDQ\t(SI), DX\nPOPCNTQ_DX_DX\nADDQ\tDX, AX\nADDQ\t$8, SI\nADDQ\t$8, DI\nLOOP\tpopcntMaskSliceLoop\npopcntMaskSliceEnd:\nMOVQ\tAX, ret+48(FP)\nRET\n\nTEXT ·popcntAndSliceAsm(SB),4,$0-56\nXORQ\tAX, AX\nMOVQ\ts+0(FP), SI\nMOVQ\ts_len+8(FP), CX\nTESTQ\tCX, CX\nJZ\t\tpopcntAndSliceEnd\nMOVQ\tm+24(FP), DI\npopcntAndSliceLoop:\nMOVQ\t(DI), DX\nANDQ\t(SI), DX\nPOPCNTQ_DX_DX\nADDQ\tDX, AX\nADDQ\t$8, SI\nADDQ\t$8, DI\nLOOP\tpopcntAndSliceLoop\npopcntAndSliceEnd:\nMOVQ\tAX, ret+48(FP)\nRET\n\nTEXT ·popcntOrSliceAsm(SB),4,$0-56\nXORQ\tAX, AX\nMOVQ\ts+0(FP), SI\nMOVQ\ts_len+8(FP), CX\nTESTQ\tCX, CX\nJZ\t\tpopcntOrSliceEnd\nMOVQ\tm+24(FP), DI\npopcntOrSliceLoop:\nMOVQ\t(DI), DX\nORQ\t\t(SI), DX\nPOPCNTQ_DX_DX\nADDQ\tDX, AX\nADDQ\t$8, SI\nADDQ\t$8, DI\nLOOP\tpopcntOrSliceLoop\npopcntOrSliceEnd:\nMOVQ\tAX, ret+48(FP)\nRET\n\nTEXT ·popcntXorSliceAsm(SB),4,$0-56\nXORQ\tAX, AX\nMOVQ\ts+0(FP), SI\nMOVQ\ts_len+8(FP), CX\nTESTQ\tCX, CX\nJZ\t\tpopcntXorSliceEnd\nMOVQ\tm+24(FP), DI\npopcntXorSliceLoop:\nMOVQ\t(DI), DX\nXORQ\t(SI), DX\nPOPCNTQ_DX_DX\nADDQ\tDX, AX\nADDQ\t$8, SI\nADDQ\t$8, DI\nLOOP\tpopcntXorSliceLoop\npopcntXorSliceEnd:\nMOVQ\tAX, ret+48(FP)\nRET\n"
  },
  {
    "path": "vendor/github.com/willf/bitset/popcnt_generic.go",
    "content": "// +build !amd64 appengine\n\npackage bitset\n\nfunc popcntSlice(s []uint64) uint64 {\n\treturn popcntSliceGo(s)\n}\n\nfunc popcntMaskSlice(s, m []uint64) uint64 {\n\treturn popcntMaskSliceGo(s, m)\n}\n\nfunc popcntAndSlice(s, m []uint64) uint64 {\n\treturn popcntAndSliceGo(s, m)\n}\n\nfunc popcntOrSlice(s, m []uint64) uint64 {\n\treturn popcntOrSliceGo(s, m)\n}\n\nfunc popcntXorSlice(s, m []uint64) uint64 {\n\treturn popcntXorSliceGo(s, m)\n}\n"
  },
  {
    "path": "vendor/manifest",
    "content": "{\n\t\"version\": 0,\n\t\"dependencies\": [\n\t\t{\n\t\t\t\"importpath\": \"github.com/edsrzf/mmap-go\",\n\t\t\t\"repository\": \"https://github.com/edsrzf/mmap-go\",\n\t\t\t\"vcs\": \"git\",\n\t\t\t\"revision\": \"935e0e8a636ca4ba70b713f3e38a19e1b77739e8\",\n\t\t\t\"branch\": \"master\",\n\t\t\t\"notests\": true\n\t\t},\n\t\t{\n\t\t\t\"importpath\": \"github.com/inconshreveable/mousetrap\",\n\t\t\t\"repository\": \"https://github.com/inconshreveable/mousetrap\",\n\t\t\t\"vcs\": \"git\",\n\t\t\t\"revision\": \"76626ae9c91c4f2a10f34cad8ce83ea42c93bb75\",\n\t\t\t\"branch\": \"master\",\n\t\t\t\"notests\": true\n\t\t},\n\t\t{\n\t\t\t\"importpath\": \"github.com/spf13/cobra\",\n\t\t\t\"repository\": \"https://github.com/spf13/cobra\",\n\t\t\t\"vcs\": \"git\",\n\t\t\t\"revision\": \"16c014f1a19d865b765b420e74508f80eb831ada\",\n\t\t\t\"branch\": \"master\",\n\t\t\t\"notests\": true\n\t\t},\n\t\t{\n\t\t\t\"importpath\": \"github.com/spf13/pflag\",\n\t\t\t\"repository\": \"https://github.com/spf13/pflag\",\n\t\t\t\"vcs\": \"git\",\n\t\t\t\"revision\": \"9ff6c6923cfffbcd502984b8e0c80539a94968b7\",\n\t\t\t\"branch\": \"master\",\n\t\t\t\"notests\": true\n\t\t},\n\t\t{\n\t\t\t\"importpath\": \"github.com/willf/bitset\",\n\t\t\t\"repository\": \"https://github.com/willf/bitset\",\n\t\t\t\"vcs\": \"git\",\n\t\t\t\"revision\": \"5c3c0fce48842b2c0bbaa99b4e61b0175d84b47c\",\n\t\t\t\"branch\": \"master\",\n\t\t\t\"notests\": true\n\t\t}\n\t]\n}"
  },
  {
    "path": "writer.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"bufio\"\n\t\"io\"\n)\n\n// A writer is a buffered writer used by vellum. It counts how many bytes have\n// been written and has some convenience methods used for encoding the data.\ntype writer struct {\n\tw       *bufio.Writer\n\tcounter int\n}\n\nfunc newWriter(w io.Writer) *writer {\n\treturn &writer{\n\t\tw: bufio.NewWriter(w),\n\t}\n}\n\nfunc (w *writer) Reset(newWriter io.Writer) {\n\tw.w.Reset(newWriter)\n\tw.counter = 0\n}\n\nfunc (w *writer) WriteByte(c byte) error {\n\terr := w.w.WriteByte(c)\n\tif err != nil {\n\t\treturn err\n\t}\n\tw.counter++\n\treturn nil\n}\n\nfunc (w *writer) Write(p []byte) (int, error) {\n\tn, err := w.w.Write(p)\n\tw.counter += n\n\treturn n, err\n}\n\nfunc (w *writer) Flush() error {\n\treturn w.w.Flush()\n}\n\nfunc (w *writer) WritePackedUintIn(v uint64, n int) error {\n\tfor shift := uint(0); shift < uint(n*8); shift += 8 {\n\t\terr := w.WriteByte(byte(v >> shift))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (w *writer) WritePackedUint(v uint64) error {\n\tn := packedSize(v)\n\treturn w.WritePackedUintIn(v, n)\n}\n\nfunc packedSize(n uint64) int {\n\tif n < 1<<8 {\n\t\treturn 1\n\t} else if n < 1<<16 {\n\t\treturn 2\n\t} else if n < 1<<24 {\n\t\treturn 3\n\t} else if n < 1<<32 {\n\t\treturn 4\n\t} else if n < 1<<40 {\n\t\treturn 5\n\t} else if n < 1<<48 {\n\t\treturn 6\n\t} else if n < 1<<56 {\n\t\treturn 7\n\t}\n\treturn 8\n}\n"
  },
  {
    "path": "writer_test.go",
    "content": "//  Copyright (c) 2017 Couchbase, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// \t\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage vellum\n\nimport (\n\t\"bufio\"\n\t\"errors\"\n\t\"fmt\"\n\t\"testing\"\n)\n\nfunc TestPackedSize(t *testing.T) {\n\ttests := []struct {\n\t\tinput uint64\n\t\twant  int\n\t}{\n\t\t{0, 1},\n\t\t{1<<8 - 1, 1},\n\t\t{1 << 8, 2},\n\t\t{1<<16 - 1, 2},\n\t\t{1 << 16, 3},\n\t\t{1<<24 - 1, 3},\n\t\t{1 << 24, 4},\n\t\t{1<<32 - 1, 4},\n\t\t{1 << 32, 5},\n\t\t{1<<40 - 1, 5},\n\t\t{1 << 40, 6},\n\t\t{1<<48 - 1, 6},\n\t\t{1 << 48, 7},\n\t\t{1<<56 - 1, 7},\n\t\t{1 << 56, 8},\n\t\t{1<<64 - 1, 8},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(fmt.Sprintf(\"input %d\", test.input), func(t *testing.T) {\n\t\t\tgot := packedSize(test.input)\n\t\t\tif got != test.want {\n\t\t\t\tt.Errorf(\"wanted: %d, got: %d\", test.want, got)\n\t\t\t}\n\t\t})\n\t}\n}\n\nvar errStub = errors.New(\"stub error\")\n\ntype stubWriter struct {\n\terr error\n}\n\nfunc (s *stubWriter) Write(p []byte) (n int, err error) {\n\terr = s.err\n\treturn\n}\n\nfunc TestWriteByteErr(t *testing.T) {\n\t// create writer, force underlying buffered writer to size 1\n\tw := &writer{\n\t\tw: bufio.NewWriterSize(&stubWriter{errStub}, 1),\n\t}\n\n\t// then write 2 bytes, which should force error\n\t_ = w.WriteByte('a')\n\terr := w.WriteByte('a')\n\tif err != errStub {\n\t\tt.Errorf(\"expected %v, got %v\", errStub, err)\n\t}\n}\n\nfunc TestWritePackedUintErr(t *testing.T) {\n\t// create writer, force underlying buffered writer to size 1\n\tw := &writer{\n\t\tw: bufio.NewWriterSize(&stubWriter{errStub}, 1),\n\t}\n\n\terr := w.WritePackedUint(36592)\n\tif err != errStub {\n\t\tt.Errorf(\"expected %v, got %v\", errStub, err)\n\t}\n}\n"
  }
]