├── .github ├── CODEOWNERS ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ ├── other.md │ └── question.md ├── auto_assign.yml ├── dependabot.yml └── workflows │ ├── ci.yml │ └── codeql-analysis.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── Makefile ├── README.md ├── assert.go ├── auto_assign.yml ├── doc ├── all.md ├── amb.md ├── assert.md ├── average.md ├── backoffretry.md ├── buffer.md ├── catch.md ├── combinelatest.md ├── concat.md ├── contains.md ├── count.md ├── create.md ├── debounce.md ├── defaultifempty.md ├── defer.md ├── distinct.md ├── distinctuntilchanged.md ├── do.md ├── elementat.md ├── empty.md ├── error.md ├── errors.md ├── filter.md ├── find.md ├── first.md ├── firstordefault.md ├── flatmap.md ├── foreach.md ├── fromchannel.md ├── fromeventsource.md ├── groupby.md ├── groupbydynamic.md ├── ignoreelements.md ├── interval.md ├── join.md ├── just.md ├── justitem.md ├── last.md ├── lastordefault.md ├── map.md ├── marshal.md ├── max.md ├── merge.md ├── min.md ├── never.md ├── options.md ├── range.md ├── reduce.md ├── repeat.md ├── retry.md ├── run.md ├── rx.png ├── sample.md ├── scan.md ├── send.md ├── sequenceequal.md ├── serialize.md ├── skip.md ├── skiplast.md ├── skipwhile.md ├── start.md ├── startwithiterable.md ├── sum.md ├── take.md ├── takelast.md ├── takeuntil.md ├── takewhile.md ├── thrown.md ├── timeinterval.md ├── timer.md ├── timestamp.md ├── tomap.md ├── tomapwithvalueselector.md ├── toslice.md ├── unmarshal.md ├── window.md └── zipfromiterable.md ├── duration.go ├── duration_test.go ├── errors.go ├── factory.go ├── factory_connectable_test.go ├── factory_test.go ├── go.mod ├── go.sum ├── item.go ├── item_test.go ├── iterable.go ├── iterable_channel.go ├── iterable_create.go ├── iterable_defer.go ├── iterable_eventsource.go ├── iterable_factory.go ├── iterable_just.go ├── iterable_range.go ├── iterable_slice.go ├── observable.go ├── observable_operator.go ├── observable_operator_bench_test.go ├── observable_operator_option_test.go ├── observable_operator_random_test.go ├── observable_operator_test.go ├── optionalsingle.go ├── optionalsingle_test.go ├── options.go ├── single.go ├── single_test.go ├── types.go ├── util_test.go └── vendor ├── github.com ├── cenkalti │ └── backoff │ │ └── v4 │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── backoff.go │ │ ├── context.go │ │ ├── exponential.go │ │ ├── go.mod │ │ ├── retry.go │ │ ├── ticker.go │ │ ├── timer.go │ │ └── tries.go ├── davecgh │ └── go-spew │ │ ├── LICENSE │ │ └── spew │ │ ├── bypass.go │ │ ├── bypasssafe.go │ │ ├── common.go │ │ ├── config.go │ │ ├── doc.go │ │ ├── dump.go │ │ ├── format.go │ │ └── spew.go ├── emirpasic │ └── gods │ │ ├── LICENSE │ │ ├── containers │ │ ├── containers.go │ │ ├── enumerable.go │ │ ├── iterator.go │ │ └── serialization.go │ │ ├── lists │ │ ├── arraylist │ │ │ ├── arraylist.go │ │ │ ├── enumerable.go │ │ │ ├── iterator.go │ │ │ └── serialization.go │ │ └── lists.go │ │ ├── trees │ │ ├── binaryheap │ │ │ ├── binaryheap.go │ │ │ ├── iterator.go │ │ │ └── serialization.go │ │ └── trees.go │ │ └── utils │ │ ├── comparator.go │ │ ├── sort.go │ │ └── utils.go ├── pmezard │ └── go-difflib │ │ ├── LICENSE │ │ └── difflib │ │ └── difflib.go ├── stretchr │ ├── objx │ │ ├── .codeclimate.yml │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── README.md │ │ ├── Taskfile.yml │ │ ├── accessors.go │ │ ├── conversions.go │ │ ├── doc.go │ │ ├── go.mod │ │ ├── go.sum │ │ ├── map.go │ │ ├── mutations.go │ │ ├── security.go │ │ ├── tests.go │ │ ├── type_specific.go │ │ ├── type_specific_codegen.go │ │ └── value.go │ └── testify │ │ ├── LICENSE │ │ ├── assert │ │ ├── assertion_compare.go │ │ ├── assertion_compare_can_convert.go │ │ ├── assertion_compare_legacy.go │ │ ├── assertion_format.go │ │ ├── assertion_format.go.tmpl │ │ ├── assertion_forward.go │ │ ├── assertion_forward.go.tmpl │ │ ├── assertion_order.go │ │ ├── assertions.go │ │ ├── doc.go │ │ ├── errors.go │ │ ├── forward_assertions.go │ │ └── http_assertions.go │ │ └── mock │ │ ├── doc.go │ │ └── mock.go └── teivah │ └── onecontext │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── go.mod │ ├── go.sum │ └── onecontext.go ├── go.uber.org └── goleak │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── Makefile │ ├── README.md │ ├── doc.go │ ├── glide.yaml │ ├── go.mod │ ├── go.sum │ ├── internal │ └── stack │ │ └── stacks.go │ ├── leaks.go │ ├── options.go │ ├── testmain.go │ ├── tracestack_new.go │ └── tracestack_old.go ├── golang.org └── x │ └── sync │ ├── AUTHORS │ ├── CONTRIBUTORS │ ├── LICENSE │ ├── PATENTS │ └── errgroup │ └── errgroup.go ├── gopkg.in └── yaml.v3 │ ├── LICENSE │ ├── NOTICE │ ├── README.md │ ├── apic.go │ ├── decode.go │ ├── emitterc.go │ ├── encode.go │ ├── go.mod │ ├── parserc.go │ ├── readerc.go │ ├── resolve.go │ ├── scannerc.go │ ├── sorter.go │ ├── writerc.go │ ├── yaml.go │ ├── yamlh.go │ └── yamlprivateh.go └── modules.txt /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This is a comment. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | # These owners will be the default owners for everything in 5 | # the repo. Unless a later match takes precedence, 6 | # @global-owner1 and @global-owner2 will be requested for 7 | # review when someone opens a pull request. 8 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [jochasinga] 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve. 4 | title: '' 5 | labels: bug report 6 | 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 1. Go to '...' 15 | 2. Click on '....' 16 | 3. Scroll down to '....' 17 | 4. See error 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Additional context** 23 | Add any other context about the problem here. 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for RxGo. 4 | title: '' 5 | labels: enhancement 6 | 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Additional context** 16 | Add any other context or screenshots about the feature request here. 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/other.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Other 3 | about: Neither a bug report, a question, nor a feature request. 4 | title: '' 5 | labels: '' 6 | 7 | --- 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask a question about RxGo. 4 | title: '' 5 | labels: question 6 | 7 | --- 8 | -------------------------------------------------------------------------------- /.github/auto_assign.yml: -------------------------------------------------------------------------------- 1 | # Set to true to add reviewers to pull requests 2 | addReviewers: true 3 | 4 | # Set to true to add assignees to pull requests 5 | addAssignees: false 6 | 7 | # A list of reviewers to be added to pull requests (GitHub user name) 8 | reviewers: 9 | 10 | # A number of reviewers added to the pull request 11 | # Set 0 to add all the reviewers (default: 0) 12 | numberOfReviewers: 0 13 | 14 | # A list of assignees, overrides reviewers if set 15 | # assignees: 16 | # - assigneeA 17 | 18 | # A number of assignees to add to the pull request 19 | # Set to 0 to add all of the assignees. 20 | # Uses numberOfReviewers if unset. 21 | # numberOfAssignees: 2 22 | 23 | # A list of keywords to be skipped the process that add reviewers if pull requests include it 24 | # skipKeywords: 25 | # - wip 26 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | - package-ecosystem: "gomod" 8 | directory: "/" 9 | schedule: 10 | interval: "daily" 11 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: [pull_request] 2 | name: CI 3 | jobs: 4 | test: 5 | strategy: 6 | matrix: 7 | go-version: [1.15.x, 1.16.x] 8 | os: [ubuntu-latest, macos-latest, windows-latest] 9 | runs-on: ${{ matrix.os }} 10 | steps: 11 | - name: Install Go 12 | uses: actions/setup-go@v3.2.0 13 | with: 14 | go-version: ${{ matrix.go-version }} 15 | - name: Checkout code 16 | uses: actions/checkout@v2.4.0 17 | - name: Linting 18 | uses: golangci/golangci-lint-action@v2.5.2 19 | with: 20 | version: v1.29 21 | - name: test 22 | run: make test 23 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '28 5 * * 5' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | language: [ 'go' ] 32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 33 | # Learn more: 34 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@v2.4.0 39 | 40 | # Initializes the CodeQL tools for scanning. 41 | - name: Initialize CodeQL 42 | uses: github/codeql-action/init@v1 43 | with: 44 | languages: ${{ matrix.language }} 45 | # If you wish to specify custom queries, you can do so here or in a config file. 46 | # By default, queries listed here will override any specified in a config file. 47 | # Prefix the list here with "+" to use these queries and those in the config file. 48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 49 | 50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 51 | # If this step fails, then you should remove it and run the build manually (see below) 52 | - name: Autobuild 53 | uses: github/codeql-action/autobuild@v1 54 | 55 | # ℹ️ Command-line programs to run using the OS shell. 56 | # 📚 https://git.io/JvXDl 57 | 58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 59 | # and modify them (or add more) to build your code if your project 60 | # uses a compiled language 61 | 62 | #- run: | 63 | # make bootstrap 64 | # make release 65 | 66 | - name: Perform CodeQL Analysis 67 | uses: github/codeql-action/analyze@v1 68 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | 26 | # Backup files 27 | *~ 28 | *# 29 | 30 | # Dep directories 31 | bower_components 32 | node_modules 33 | 34 | # IntelliJ 35 | .idea 36 | *.iml 37 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributions Guidelines 2 | 3 | Contributions are always welcome. However, to make this a smooth collaboration experience for everyone and to maintain the quality of the code, here is a few things to consider before and after making a pull request: 4 | 5 | ## Consistency 6 | 7 | There are already +80 operators and +250 unit tests. Please don't try necessarily to reinvent the wheel and make sure to check first how the current implementation solves the most common problems. 8 | 9 | ## Edge Case 10 | 11 | When we develop a new operator, there are a lot of edge cases to handle (eager/lazy observation, sequential vs parallel, on error strategy, etc.). The utility functions `observable()`, `single()` and `optionalSingle()` are there to help. Yet, it is not always possible to use them (observation of multiple Observables, etc.). In this case, you may want to take a look at existing operators like `WindowWithTime` to see an exhaustive implementation. 12 | 13 | ## Unit Tests 14 | 15 | Make sure to include unit tests. Again, consistency is key. In most of the unit tests, we use the RxGo assertion API. 16 | 17 | ## Duration 18 | 19 | If an operator input contains a duration, we should use `rxgo.Duration`. It allows us to mock it and to implement deterministic tests whenever possible using `timeCausality()`. 20 | 21 | ## Write Nice Code 22 | 23 | Try to write idiomatic code according to [Go style guide](https://github.com/golang/go/wiki/CodeReviewComments). Also, see this project style guide for project-specific idioms (when in doubt, consult the first). 24 | 25 | ## Code Formatting 26 | 27 | Before to create a pull request, make sure to format your code using: 28 | 29 | * [gofumpt](https://github.com/mvdan/gofumpt): 30 | * Install: `go get mvdan.cc/gofumpt` 31 | * Execute: `gofumpt -s -w .` 32 | 33 | * [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports): 34 | * Install: `go get golang.o` 35 | * Execute: `goimports -w .` 36 | 37 | ## Open an issue 38 | 39 | This is to encourage discussions and reach a sound design decision before implementing an additional feature or fixing a bug. If you're proposing a new feature, make it obvious in the subject. 40 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Joe Chasinga 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | go clean -testcache ./... 3 | go test -race -timeout 10s ./... --tags=all 4 | go test -timeout 10s -run TestLeak 5 | -------------------------------------------------------------------------------- /auto_assign.yml: -------------------------------------------------------------------------------- 1 | addReviewers: true 2 | 3 | addAssignees: false 4 | 5 | reviewers: 6 | - teivah -------------------------------------------------------------------------------- /doc/all.md: -------------------------------------------------------------------------------- 1 | # All Operator 2 | 3 | ## Overview 4 | 5 | Determine whether all items emitted by an Observable meet some criteria. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/all.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3, 4)(). 13 | All(func(i interface{}) bool { 14 | // Check all items are less than 10 15 | return i.(int) < 10 16 | }) 17 | ``` 18 | 19 | Output: 20 | 21 | ``` 22 | true 23 | ``` 24 | 25 | ## Options 26 | 27 | * [WithBufferedChannel](options.md#withbufferedchannel) 28 | 29 | * [WithContext](options.md#withcontext) 30 | 31 | * [WithObservationStrategy](options.md#withobservationstrategy) 32 | 33 | * [WithErrorStrategy](options.md#witherrorstrategy) 34 | 35 | * [WithPool](options.md#withpool) 36 | 37 | * [WithCPUPool](options.md#withcpupool) 38 | 39 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/amb.md: -------------------------------------------------------------------------------- 1 | # Amb Operator 2 | 3 | ## Overview 4 | 5 | Given two or more source Observables, emit all of the items from only the first of these Observables to emit an item. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/amb.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Amb([]rxgo.Observable{ 13 | rxgo.Just(1, 2, 3)(), 14 | rxgo.Just(4, 5, 6)(), 15 | }) 16 | ``` 17 | 18 | Output: 19 | 20 | ``` 21 | 1 22 | 2 23 | 3 24 | ``` 25 | or 26 | ``` 27 | 4 28 | 5 29 | 6 30 | ``` 31 | 32 | ## Options 33 | 34 | * [WithBufferedChannel](options.md#withbufferedchannel) 35 | 36 | * [WithContext](options.md#withcontext) 37 | 38 | * [WithObservationStrategy](options.md#withobservationstrategy) 39 | 40 | * [WithErrorStrategy](options.md#witherrorstrategy) -------------------------------------------------------------------------------- /doc/assert.md: -------------------------------------------------------------------------------- 1 | # Assert API 2 | 3 | ## Overview 4 | 5 | There is a public API to facilitate writing unit tests while using RxGo. This is based on `rxgo.Assert`. It automatically creates an Observer on an Iterable (Observable, Single or OptionalSingle). 6 | 7 | ```go 8 | func TestMap(t *testing.T) { 9 | err := errors.New("foo") 10 | observable := rxgo.Just(1, 2, 3)(). 11 | Map(func(_ context.Context, i interface{}) (interface{}, error) { 12 | if i == 3 { 13 | return nil, err 14 | } 15 | return i, nil 16 | }) 17 | 18 | rxgo.Assert(context.Background(), t, observable, 19 | rxgo.HasItems(1, 2), 20 | rxgo.HasError(err)) 21 | } 22 | ``` 23 | 24 | ``` 25 | === RUN TestMap 26 | --- PASS: TestMap (0.00s) 27 | PASS 28 | ``` 29 | 30 | ## Predicates 31 | 32 | The API accepts the following list of predicates: 33 | 34 | ### HasItems 35 | 36 | Check whether an Observable produced a given list of items. 37 | 38 | ```go 39 | rxgo.Assert(ctx, t, observable, rxgo.HasItems(1, 2, 3)) 40 | ``` 41 | 42 | ### HasItem 43 | 44 | Check whether an Single or OptionalSingle produced a given item. 45 | 46 | ```go 47 | rxgo.Assert(ctx, t, single, rxgo.HasItem(1)) 48 | ``` 49 | 50 | ### HasItemsNoOrder 51 | 52 | Check whether an Observable produced a given item regardless of the ordering (useful when we use a pool option) 53 | 54 | ```go 55 | rxgo.Assert(ctx, t, single, rxgo.HasItemsNoOrder(1, 2, 3)) 56 | ``` 57 | 58 | ### IsEmpty 59 | 60 | Check whether an Iterable produced no item(s). 61 | 62 | ```go 63 | rxgo.Assert(ctx, t, single, rxgo.IsEmpty()) 64 | ``` 65 | 66 | ### IsNotEmpty 67 | 68 | Check whether an Iterable produced any item(s). 69 | 70 | ```go 71 | rxgo.Assert(ctx, t, single, rxgo.IsNotEmpty()) 72 | ``` 73 | 74 | ### HasError 75 | 76 | Check whether an Iterable produced a given error. 77 | 78 | ```go 79 | rxgo.Assert(ctx, t, single, rxgo.HasError(expectedErr)) 80 | ``` 81 | 82 | ### HasAnError 83 | 84 | Check whether an Iterable produced an error. 85 | 86 | ```go 87 | rxgo.Assert(ctx, t, single, rxgo.HasAnError()) 88 | ``` 89 | 90 | ### HasErrors 91 | 92 | Check whether an Iterable produced a given list of errors (useful when we use `rxgo.ContinueOnError` strategy). 93 | 94 | ```go 95 | rxgo.Assert(ctx, t, single, rxgo.HasErrors(expectedErr1, expectedErr2, expectedErr3)) 96 | ``` 97 | 98 | ### HasNoError 99 | 100 | Check whether an Iterable did not produced any error. 101 | 102 | ```go 103 | rxgo.Assert(ctx, t, single, rxgo.HasNoError()) 104 | ``` 105 | 106 | ### CustomPredicate 107 | 108 | Implement a custom predicate. 109 | 110 | ```go 111 | rxgo.Assert(ctx, t, observable, rxgo.CustomPredicate(func(items []interface{}) error { 112 | if len(items) != 3 { 113 | return errors.New("wrong number of items") 114 | } 115 | return nil 116 | })) 117 | ``` -------------------------------------------------------------------------------- /doc/average.md: -------------------------------------------------------------------------------- 1 | # Average Operator 2 | 3 | ## Overview 4 | 5 | Calculate the average of numbers emitted by an Observable and emits this average. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/average.png) 8 | 9 | ## Instances 10 | 11 | * `AverageFloat32` 12 | * `AverageFloat64` 13 | * `AverageInt` 14 | * `AverageInt8` 15 | * `AverageInt16` 16 | * `AverageInt32` 17 | * `AverageInt64` 18 | 19 | ## Example 20 | 21 | ```go 22 | observable := rxgo.Just(1, 2, 3, 4)().AverageInt() 23 | ``` 24 | 25 | Output: 26 | 27 | ``` 28 | 2 29 | ``` 30 | 31 | ## Options 32 | 33 | * [WithBufferedChannel](options.md#withbufferedchannel) 34 | 35 | * [WithContext](options.md#withcontext) 36 | 37 | * [WithObservationStrategy](options.md#withobservationstrategy) 38 | 39 | * [WithErrorStrategy](options.md#witherrorstrategy) 40 | 41 | * [WithPool](options.md#withpool) 42 | 43 | * [WithCPUPool](options.md#withcpupool) 44 | 45 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/backoffretry.md: -------------------------------------------------------------------------------- 1 | # BackOffRetry Operator 2 | 3 | ## Overview 4 | 5 | Implements a backoff retry if a source Observable sends an error, resubscribe to it in the hopes that it will complete without error. 6 | 7 | The backoff configuration relies on [github.com/cenkalti/backoff/v4](github.com/cenkalti/backoff/v4). 8 | 9 | ![](http://reactivex.io/documentation/operators/images/retry.png) 10 | 11 | ## Example 12 | 13 | ```go 14 | // Backoff retry configuration 15 | backOffCfg := backoff.NewExponentialBackOff() 16 | backOffCfg.InitialInterval = 10 * time.Millisecond 17 | 18 | observable := rxgo.Defer([]rxgo.Producer{func(ctx context.Context, next chan<- rxgo.Item, done func()) { 19 | next <- rxgo.Of(1) 20 | next <- rxgo.Of(2) 21 | next <- rxgo.Error(errors.New("foo")) 22 | done() 23 | }}).BackOffRetry(backoff.WithMaxRetries(backOffCfg, 2)) 24 | ``` 25 | 26 | Output: 27 | 28 | ``` 29 | 1 30 | 2 31 | 1 32 | 2 33 | 1 34 | 2 35 | foo 36 | ``` 37 | 38 | ## Options 39 | 40 | * [WithBufferedChannel](options.md#withbufferedchannel) 41 | 42 | * [WithContext](options.md#withcontext) 43 | 44 | * [WithObservationStrategy](options.md#withobservationstrategy) 45 | 46 | * [WithErrorStrategy](options.md#witherrorstrategy) 47 | 48 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/buffer.md: -------------------------------------------------------------------------------- 1 | # Buffer Operator 2 | 3 | ## Overview 4 | 5 | Periodically gather items emitted by an Observable into bundles and emit these bundles rather than emitting the items one at a time 6 | 7 | ![](http://reactivex.io/documentation/operators/images/Buffer.png) 8 | 9 | ## Instances 10 | 11 | * `BufferWithCount`: 12 | 13 | ![](http://reactivex.io/documentation/operators/images/bufferWithCount3.png) 14 | 15 | ```go 16 | observable := rxgo.Just(1, 2, 3, 4)().BufferWithCount(3) 17 | ``` 18 | 19 | Output: 20 | 21 | ``` 22 | 1 2 3 23 | 4 24 | ``` 25 | 26 | * `BufferWithTime`: 27 | 28 | ![](http://reactivex.io/documentation/operators/images/bufferWithTime5.png) 29 | 30 | ```go 31 | // Create the producer 32 | ch := make(chan rxgo.Item, 1) 33 | go func() { 34 | i := 0 35 | for range time.Tick(time.Second) { 36 | ch <- rxgo.Of(i) 37 | i++ 38 | } 39 | }() 40 | 41 | observable := rxgo.FromChannel(ch). 42 | BufferWithTime(rxgo.WithDuration(3*time.Second), nil) 43 | ``` 44 | 45 | Output: 46 | 47 | ``` 48 | 0 1 2 49 | 3 4 5 50 | 6 7 8 51 | ... 52 | ``` 53 | 54 | * `BufferWithTimeOrCount`: 55 | 56 | ![](http://reactivex.io/documentation/operators/images/bufferWithTimeOrCount6.png) 57 | 58 | ```go 59 | // Create the producer 60 | ch := make(chan rxgo.Item, 1) 61 | go func() { 62 | i := 0 63 | for range time.Tick(time.Second) { 64 | ch <- rxgo.Of(i) 65 | i++ 66 | } 67 | }() 68 | 69 | observable := rxgo.FromChannel(ch). 70 | BufferWithTimeOrCount(rxgo.WithDuration(3*time.Second), 2) 71 | ``` 72 | 73 | Output: 74 | 75 | ``` 76 | 0 1 77 | 2 3 78 | 4 5 79 | ... 80 | ``` 81 | 82 | ## Options 83 | 84 | * [WithBufferedChannel](options.md#withbufferedchannel) 85 | 86 | * [WithContext](options.md#withcontext) 87 | 88 | * [WithObservationStrategy](options.md#withobservationstrategy) 89 | 90 | * [WithErrorStrategy](options.md#witherrorstrategy) 91 | 92 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/catch.md: -------------------------------------------------------------------------------- 1 | # Catch Operator 2 | 3 | ## Overview 4 | 5 | Recover from an error by continuing the sequence without error. 6 | 7 | ## Instances 8 | 9 | * `OnErrorResumeNext`: instructs an Observable to pass control to another Observable rather than invoking onError if it encounters an error. 10 | * `OnErrorReturn`: instructs an Observable to emit an item (returned by a specified function) rather than invoking onError if it encounters an error. 11 | * `OnErrorReturnItem`: instructs on Observable to emit an item if it encounters an error. 12 | 13 | ## Example 14 | 15 | ### OnErrorResumeNext 16 | 17 | ```go 18 | observable := rxgo.Just(1, 2, errors.New("foo"))(). 19 | OnErrorResumeNext(func(e error) rxgo.Observable { 20 | return rxgo.Just(3, 4)() 21 | }) 22 | ``` 23 | 24 | Output: 25 | 26 | ``` 27 | 1 28 | 2 29 | 3 30 | 4 31 | ``` 32 | 33 | ### OnErrorReturn 34 | 35 | ```go 36 | observable := rxgo.Just(1, errors.New("2"), 3, errors.New("4"), 5)(). 37 | OnErrorReturn(func(err error) interface{} { 38 | return err.Error() 39 | }) 40 | ``` 41 | 42 | Output: 43 | 44 | ``` 45 | 1 46 | 2 47 | 3 48 | 4 49 | 5 50 | ``` 51 | 52 | ### OnErrorReturnItem 53 | 54 | ```go 55 | observable := rxgo.Just(1, errors.New("2"), 3, errors.New("4"), 5)(). 56 | OnErrorReturnItem("foo") 57 | ``` 58 | 59 | Output: 60 | 61 | ``` 62 | 1 63 | foo 64 | 3 65 | foo 66 | 5 67 | ``` 68 | 69 | ## Options 70 | 71 | * [WithBufferedChannel](options.md#withbufferedchannel) 72 | 73 | * [WithContext](options.md#withcontext) 74 | 75 | * [WithObservationStrategy](options.md#withobservationstrategy) 76 | 77 | * [WithErrorStrategy](options.md#witherrorstrategy) -------------------------------------------------------------------------------- /doc/combinelatest.md: -------------------------------------------------------------------------------- 1 | # CombineLatest Operator 2 | 3 | ## Overview 4 | 5 | When an item is emitted by either of two Observables, combine the latest item emitted by each Observable via a specified function and emit items based on the results of this function. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/combineLatest.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.CombineLatest(func(i ...interface{}) interface{} { 13 | sum := 0 14 | for _, v := range i { 15 | if v == nil { 16 | continue 17 | } 18 | sum += v.(int) 19 | } 20 | return sum 21 | }, []rxgo.Observable{ 22 | rxgo.Just(1, 2)(), 23 | rxgo.Just(10, 11)(), 24 | }) 25 | ``` 26 | 27 | Output: 28 | 29 | ``` 30 | 12 31 | 13 32 | ``` 33 | 34 | ## Options 35 | 36 | * [WithBufferedChannel](options.md#withbufferedchannel) 37 | 38 | * [WithContext](options.md#withcontext) 39 | 40 | * [WithObservationStrategy](options.md#withobservationstrategy) 41 | 42 | * [WithErrorStrategy](options.md#witherrorstrategy) 43 | 44 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/concat.md: -------------------------------------------------------------------------------- 1 | # Concat Operator 2 | 3 | ## Overview 4 | 5 | Emit the emissions from two or more Observables without interleaving them. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/concat.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Concat([]rxgo.Observable{ 13 | rxgo.Just(1, 2, 3)(), 14 | rxgo.Just(4, 5, 6)(), 15 | }) 16 | ``` 17 | 18 | Output: 19 | 20 | ``` 21 | 1 22 | 2 23 | 3 24 | 4 25 | 5 26 | 6 27 | ``` 28 | 29 | ## Options 30 | 31 | * [WithBufferedChannel](options.md#withbufferedchannel) 32 | 33 | * [WithContext](options.md#withcontext) 34 | 35 | * [WithObservationStrategy](options.md#withobservationstrategy) 36 | 37 | * [WithErrorStrategy](options.md#witherrorstrategy) 38 | 39 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/contains.md: -------------------------------------------------------------------------------- 1 | # Contains Operator 2 | 3 | ## Overview 4 | 5 | Determine whether an Observable emits a particular item or not. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/contains.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3)().Contains(func(i interface{}) bool { 13 | return i == 2 14 | }) 15 | ``` 16 | 17 | Output: 18 | 19 | ``` 20 | true 21 | ``` 22 | 23 | ## Options 24 | 25 | * [WithBufferedChannel](options.md#withbufferedchannel) 26 | 27 | * [WithContext](options.md#withcontext) 28 | 29 | * [WithPool](options.md#withpool) 30 | 31 | * [WithCPUPool](options.md#withcpupool) 32 | 33 | * [WithObservationStrategy](options.md#withobservationstrategy) 34 | 35 | * [WithErrorStrategy](options.md#witherrorstrategy) 36 | 37 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/count.md: -------------------------------------------------------------------------------- 1 | # Count Operator 2 | 3 | ## Overview 4 | 5 | Count the number of items emitted by the source Observable and emit only this value. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/Count.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3)().Count() 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 3 19 | ``` 20 | 21 | ## Options 22 | 23 | * [WithBufferedChannel](options.md#withbufferedchannel) 24 | 25 | * [WithContext](options.md#withcontext) 26 | 27 | * [WithObservationStrategy](options.md#withobservationstrategy) 28 | 29 | * [WithErrorStrategy](options.md#witherrorstrategy) 30 | 31 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/create.md: -------------------------------------------------------------------------------- 1 | # Create Operator 2 | 3 | ## Overview 4 | 5 | Create an Observable from scratch by calling observer methods programmatically. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/create.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Create([]rxgo.Producer{func(ctx context.Context, next chan<- rxgo.Item) { 13 | next <- rxgo.Of(1) 14 | next <- rxgo.Of(2) 15 | next <- rxgo.Of(3) 16 | }}) 17 | ``` 18 | 19 | Output: 20 | 21 | ``` 22 | 1 23 | 2 24 | 3 25 | ``` 26 | 27 | ## Options 28 | 29 | * [WithBufferedChannel](options.md#withbufferedchannel) 30 | 31 | * [WithContext](options.md#withcontext) 32 | 33 | * [WithObservationStrategy](options.md#withobservationstrategy) 34 | 35 | * [WithErrorStrategy](options.md#witherrorstrategy) 36 | 37 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/debounce.md: -------------------------------------------------------------------------------- 1 | # Debounce Operator 2 | 3 | ## Overview 4 | 5 | Only emit an item from an Observable if a particular timespan has passed without it emitting another item. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/debounce.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable.Debounce(rxgo.WithDuration(250 * time.Millisecond)) 13 | ``` 14 | 15 | Output: each item emitted by the Observable if not item has been emitted after 250 milliseconds. 16 | 17 | ## Options 18 | 19 | * [WithBufferedChannel](options.md#withbufferedchannel) 20 | 21 | * [WithContext](options.md#withcontext) 22 | 23 | * [WithObservationStrategy](options.md#withobservationstrategy) 24 | 25 | * [WithErrorStrategy](options.md#witherrorstrategy) 26 | 27 | * [WithPool](options.md#withpool) 28 | 29 | * [WithCPUPool](options.md#withcpupool) 30 | 31 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/defaultifempty.md: -------------------------------------------------------------------------------- 1 | # DefaultIfEmpty Operator 2 | 3 | ## Overview 4 | 5 | Emit items from the source Observable, or a default item if the source Observable emits nothing. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/defaultIfEmpty.c.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Empty().DefaultIfEmpty(1) 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 1 19 | ``` 20 | 21 | ## Options 22 | 23 | * [WithBufferedChannel](options.md#withbufferedchannel) 24 | 25 | * [WithContext](options.md#withcontext) 26 | 27 | * [WithObservationStrategy](options.md#withobservationstrategy) 28 | 29 | * [WithErrorStrategy](options.md#witherrorstrategy) 30 | 31 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/defer.md: -------------------------------------------------------------------------------- 1 | # Defer Operator 2 | 3 | ## Overview 4 | 5 | do not create the Observable until the observer subscribes, and create a fresh Observable for each observer. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/defer.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Defer([]rxgo.Producer{func(ctx context.Context, next chan<- rxgo.Item) { 13 | next <- rxgo.Of(1) 14 | next <- rxgo.Of(2) 15 | next <- rxgo.Of(3) 16 | }}) 17 | ``` 18 | 19 | Output: 20 | 21 | ``` 22 | 1 23 | 2 24 | 3 25 | ``` 26 | 27 | ## Options 28 | 29 | * [WithBufferedChannel](options.md#withbufferedchannel) 30 | 31 | * [WithContext](options.md#withcontext) 32 | 33 | * [WithObservationStrategy](options.md#withobservationstrategy) 34 | 35 | * [WithErrorStrategy](options.md#witherrorstrategy) -------------------------------------------------------------------------------- /doc/distinct.md: -------------------------------------------------------------------------------- 1 | # Distinct Operator 2 | 3 | ## Overview 4 | 5 | Suppress duplicate items emitted by an Observable. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/distinct.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 2, 3, 4, 4, 5)(). 13 | Distinct(func(_ context.Context, i interface{}) (interface{}, error) { 14 | return i, nil 15 | }) 16 | ``` 17 | 18 | Output: 19 | 20 | ``` 21 | 1 22 | 2 23 | 3 24 | 4 25 | 5 26 | ``` 27 | 28 | ## Options 29 | 30 | * [WithBufferedChannel](options.md#withbufferedchannel) 31 | 32 | * [WithContext](options.md#withcontext) 33 | 34 | * [WithObservationStrategy](options.md#withobservationstrategy) 35 | 36 | * [WithErrorStrategy](options.md#witherrorstrategy) 37 | 38 | * [WithPool](options.md#withpool) 39 | 40 | * [WithCPUPool](options.md#withcpupool) 41 | 42 | ### Serialize 43 | 44 | [Detail](options.md#serialize) 45 | 46 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/distinctuntilchanged.md: -------------------------------------------------------------------------------- 1 | # DistinctUntilChanged Operator 2 | 3 | ## Overview 4 | 5 | Suppress consecutive duplicate items in the original Observable. 6 | 7 | ## Example 8 | 9 | ```go 10 | observable := rxgo.Just(1, 2, 2, 1, 1, 3)(). 11 | DistinctUntilChanged(func(_ context.Context, i interface{}) (interface{}, error) { 12 | return i, nil 13 | }) 14 | ``` 15 | 16 | Output: 17 | 18 | ``` 19 | 1 20 | 2 21 | 1 22 | 3 23 | ``` 24 | 25 | ## Options 26 | 27 | * [WithBufferedChannel](options.md#withbufferedchannel) 28 | 29 | * [WithContext](options.md#withcontext) 30 | 31 | * [WithObservationStrategy](options.md#withobservationstrategy) 32 | 33 | * [WithErrorStrategy](options.md#witherrorstrategy) 34 | 35 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/do.md: -------------------------------------------------------------------------------- 1 | # Do Operator 2 | 3 | ## Overview 4 | 5 | Register an action to take upon a variety of Observable lifecycle events. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/do.c.png) 8 | 9 | ## Instances 10 | 11 | * `DoOnNext` 12 | * `DoOnError` 13 | * `DoOnCompleted` 14 | 15 | Each one returns a `<-chan struct{}` that closes once the Observable terminates. 16 | 17 | ## Example 18 | 19 | ### DoOnNext 20 | 21 | ```go 22 | <-rxgo.Just(1, 2, 3)(). 23 | DoOnNext(func(i interface{}) { 24 | fmt.Println(i) 25 | }) 26 | ``` 27 | 28 | Output: 29 | 30 | ``` 31 | 1 32 | 2 33 | 3 34 | ``` 35 | 36 | ### DoOnError 37 | 38 | ```go 39 | <-rxgo.Just(1, 2, errors.New("foo"))(). 40 | DoOnError(func(err error) { 41 | fmt.Println(err) 42 | }) 43 | ``` 44 | 45 | Output: 46 | 47 | ``` 48 | foo 49 | ``` 50 | 51 | ### DoOnCompleted 52 | 53 | ```go 54 | <-rxgo.Just(1, 2, 3)(). 55 | DoOnCompleted(func() { 56 | fmt.Println("done") 57 | }) 58 | ``` 59 | 60 | Output: 61 | 62 | ``` 63 | done 64 | ``` 65 | 66 | ## Options 67 | 68 | * [WithContext](options.md#withcontext) -------------------------------------------------------------------------------- /doc/elementat.md: -------------------------------------------------------------------------------- 1 | # ElementAt Operator 2 | 3 | ## Overview 4 | 5 | Emit only item n emitted by an Observable. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/elementAt.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(0, 1, 2, 3, 4)().ElementAt(2) 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 2 19 | ``` 20 | 21 | ## Options 22 | 23 | * [WithBufferedChannel](options.md#withbufferedchannel) 24 | 25 | * [WithContext](options.md#withcontext) 26 | 27 | * [WithObservationStrategy](options.md#withobservationstrategy) 28 | 29 | * [WithErrorStrategy](options.md#witherrorstrategy) 30 | 31 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/empty.md: -------------------------------------------------------------------------------- 1 | # Empty Operator 2 | 3 | ## Overview 4 | 5 | Create an Observable that emits no items but terminates normally. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/empty.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Empty() 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | ``` -------------------------------------------------------------------------------- /doc/error.md: -------------------------------------------------------------------------------- 1 | # Error Operator 2 | 3 | ## Overview 4 | 5 | Return the first error thrown by an Observable. 6 | 7 | This method is blocking. 8 | 9 | ## Example 10 | 11 | ```go 12 | err := rxgo.Just(1, 2, errors.New("foo"))().Error() 13 | fmt.Println(err) 14 | ``` 15 | 16 | Output: 17 | 18 | ``` 19 | foo 20 | ``` 21 | 22 | ## Options 23 | 24 | * [WithContext](options.md#withcontext) -------------------------------------------------------------------------------- /doc/errors.md: -------------------------------------------------------------------------------- 1 | # Errors Operator 2 | 3 | ## Overview 4 | 5 | Return all the errors thrown by an Observable. 6 | 7 | This method is blocking. 8 | 9 | ## Example 10 | 11 | ```go 12 | errs := rxgo.Just( 13 | errors.New("foo"), 14 | errors.New("bar"), 15 | errors.New("baz"), 16 | )().Errors(rxgo.WithErrorStrategy(rxgo.Continue)) 17 | fmt.Println(errs) 18 | ``` 19 | 20 | Output: 21 | 22 | ``` 23 | [foo bar baz] 24 | ``` 25 | 26 | ## Options 27 | 28 | * [WithContext](options.md#withcontext) -------------------------------------------------------------------------------- /doc/filter.md: -------------------------------------------------------------------------------- 1 | # Filter Operator 2 | 3 | ## Overview 4 | 5 | Emit only those items from an Observable that pass a predicate test. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/filter.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3)(). 13 | Filter(func(i interface{}) bool { 14 | return i != 2 15 | }) 16 | ``` 17 | 18 | Output: 19 | 20 | ``` 21 | 1 22 | 3 23 | ``` 24 | 25 | ## Options 26 | 27 | * [WithBufferedChannel](options.md#withbufferedchannel) 28 | 29 | * [WithContext](options.md#withcontext) 30 | 31 | * [WithObservationStrategy](options.md#withobservationstrategy) 32 | 33 | * [WithErrorStrategy](options.md#witherrorstrategy) 34 | 35 | * [WithPool](options.md#withpool) 36 | 37 | * [WithCPUPool](options.md#withcpupool) 38 | 39 | ### Serialize 40 | 41 | [Detail](options.md#serialize) 42 | 43 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/find.md: -------------------------------------------------------------------------------- 1 | # Find Operator 2 | 3 | ## Overview 4 | 5 | Emit the first item passing a predicate then complete. 6 | 7 | ## Example 8 | 9 | ```go 10 | observable := rxgo.Just(1, 2, 3)().Find(func(i interface{}) bool { 11 | return i == 2 12 | }) 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 2 19 | ``` 20 | 21 | ## Options 22 | 23 | * [WithBufferedChannel](options.md#withbufferedchannel) 24 | 25 | * [WithContext](options.md#withcontext) 26 | 27 | * [WithPool](options.md#withpool) 28 | 29 | * [WithCPUPool](options.md#withcpupool) 30 | 31 | * [WithObservationStrategy](options.md#withobservationstrategy) 32 | 33 | * [WithErrorStrategy](options.md#witherrorstrategy) 34 | 35 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/first.md: -------------------------------------------------------------------------------- 1 | # First Operator 2 | 3 | ## Overview 4 | 5 | Emit only the first item emitted by an Observable. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/first.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3)().First() 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | true 19 | ``` 20 | 21 | ## Options 22 | 23 | * [WithBufferedChannel](options.md#withbufferedchannel) 24 | 25 | * [WithContext](options.md#withcontext) 26 | 27 | * [WithObservationStrategy](options.md#withobservationstrategy) 28 | 29 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/firstordefault.md: -------------------------------------------------------------------------------- 1 | # FirstOrDefault Operator 2 | 3 | ## Overview 4 | 5 | Similar to `First`, but we pass a default item that will be emitted if the source Observable fails to emit any items. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/firstOrDefault.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Empty().FirstOrDefault(1) 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 1 19 | ``` 20 | 21 | ## Options 22 | 23 | * [WithBufferedChannel](options.md#withbufferedchannel) 24 | 25 | * [WithContext](options.md#withcontext) 26 | 27 | * [WithObservationStrategy](options.md#withobservationstrategy) 28 | 29 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/flatmap.md: -------------------------------------------------------------------------------- 1 | # FlatMap Operator 2 | 3 | ## Overview 4 | 5 | Transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/flatMap.c.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3)().FlatMap(func(i rxgo.Item) rxgo.Observable { 13 | return rxgo.Just(i.V.(int) * 10, i.V.(int) * 100)() 14 | }) 15 | ``` 16 | 17 | Output: 18 | 19 | ``` 20 | 10 21 | 100 22 | 20 23 | 200 24 | 30 25 | 300 26 | ``` 27 | 28 | ## Options 29 | 30 | * [WithBufferedChannel](options.md#withbufferedchannel) 31 | 32 | * [WithContext](options.md#withcontext) 33 | 34 | * [WithObservationStrategy](options.md#withobservationstrategy) 35 | 36 | * [WithErrorStrategy](options.md#witherrorstrategy) 37 | 38 | * [WithPool](options.md#withpool) 39 | 40 | * [WithCPUPool](options.md#withcpupool) 41 | 42 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/foreach.md: -------------------------------------------------------------------------------- 1 | # ForEach Operator 2 | 3 | ## Overview 4 | 5 | Subscribe to an Observable and register `OnNext`, `OnError` and `OnCompleted` actions. 6 | 7 | It returns a `<-chan struct{}` that closes once the Observable terminates. 8 | 9 | ## Example 10 | 11 | ```go 12 | <-rxgo.Just(1, errors.New("foo"))(). 13 | ForEach( 14 | func(i interface{}) { 15 | fmt.Printf("next: %v\n", i) 16 | }, func(err error) { 17 | fmt.Printf("error: %v\n", err) 18 | }, func() { 19 | fmt.Println("done") 20 | }) 21 | ``` 22 | 23 | Output: 24 | 25 | ``` 26 | next: 1 27 | error: foo 28 | done 29 | ``` 30 | 31 | ## Options 32 | 33 | * [WithContext](options.md#withcontext) 34 | 35 | # FromChannel Operator 36 | 37 | ## Overview 38 | 39 | Create a cold observable from a channel. 40 | 41 | ## Example 42 | 43 | ```go 44 | ch := make(chan rxgo.Item) 45 | observable := rxgo.FromChannel(ch) 46 | ``` 47 | 48 | The items are buffered in the channel until an Observer subscribes. -------------------------------------------------------------------------------- /doc/fromchannel.md: -------------------------------------------------------------------------------- 1 | # FromChannel Operator 2 | 3 | ## Overview 4 | 5 | Create a cold observable from a channel. 6 | 7 | The items are consumed when an Observer subscribes. 8 | 9 | ## Example 10 | 11 | ```go 12 | ch := make(chan rxgo.Item) 13 | observable := rxgo.FromChannel(ch) 14 | ``` 15 | 16 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/fromeventsource.md: -------------------------------------------------------------------------------- 1 | # FromEventSource Operator 2 | 3 | ## Overview 4 | 5 | Create a hot observable from a channel. 6 | 7 | The items are consumed as soon as the observable is created. An Observer will see only the items since the moment he subscribed to the Observable. 8 | 9 | ## Example 10 | 11 | ```go 12 | ch := make(chan rxgo.Item) 13 | observable := rxgo.FromEventSource(ch) 14 | ``` 15 | 16 | ## Options 17 | 18 | * WithBackPressureStrategy 19 | 20 | * Block (default): block until the Observer is ready to consume the next item using `rxgo.WithBackPressureStrategy(rxgo.Block)` 21 | 22 | * Drop: drop the item if the Observer isn't ready using `rxgo.WithBackPressureStrategy(rxgo.Drop)` 23 | 24 | * [WithBufferedChannel](options.md#withbufferedchannel) 25 | 26 | * [WithContext](options.md#withcontext) 27 | 28 | * [WithObservationStrategy](options.md#withobservationstrategy) 29 | 30 | * [WithErrorStrategy](options.md#witherrorstrategy) -------------------------------------------------------------------------------- /doc/groupby.md: -------------------------------------------------------------------------------- 1 | # GroupBy Operator 2 | 3 | ## Overview 4 | 5 | Divide an Observable into a set of Observables that each emit a different group of items from the original Observable, organized by key. 6 | 7 | It requires to pass the length of the set. If we require a dynamic set, we need to use [GroupByDynamic](groupbydynamic.md) instead. 8 | 9 | ![](http://reactivex.io/documentation/operators/images/groupBy.c.png) 10 | 11 | ## Example 12 | 13 | ```go 14 | count := 3 15 | observable := rxgo.Range(0, 10).GroupBy(count, func(item rxgo.Item) int { 16 | return item.V.(int) % count 17 | }, rxgo.WithBufferedChannel(10)) 18 | 19 | for i := range observable.Observe() { 20 | fmt.Println("New observable:") 21 | 22 | for i := range i.V.(rxgo.Observable).Observe() { 23 | fmt.Printf("item: %v\n", i.V) 24 | } 25 | } 26 | ``` 27 | 28 | Output: 29 | 30 | ``` 31 | New observable: 32 | item: 0 33 | item: 3 34 | item: 6 35 | item: 9 36 | New observable: 37 | item: 1 38 | item: 4 39 | item: 7 40 | item: 10 41 | New observable: 42 | item: 2 43 | item: 5 44 | item: 8 45 | ``` 46 | 47 | ## Options 48 | 49 | * [WithBufferedChannel](options.md#withbufferedchannel) 50 | 51 | * [WithContext](options.md#withcontext) 52 | 53 | * [WithObservationStrategy](options.md#withobservationstrategy) 54 | 55 | * [WithErrorStrategy](options.md#witherrorstrategy) 56 | 57 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/groupbydynamic.md: -------------------------------------------------------------------------------- 1 | # GroupBy Operator 2 | 3 | ## Overview 4 | 5 | Divides an Observable into a dynamic set of Observables that each emit GroupedObservable from the original Observable, organized by key. 6 | 7 | `GroupByDynamic` differs from [GroupBy](groupby.md) for two reasons: 8 | * We don't need to pass a fixed set length. 9 | * The distribution function is a `func(rxgo.Item) string` instead of a `func(rxgo.Item) int`. The rationale is because of possible collisions. For example, if our distribution function produces 128-bit UUIDs, there is a collision risk if such a UUID has to be casted into an int. 10 | 11 | ![](http://reactivex.io/documentation/operators/images/groupBy.c.png) 12 | 13 | ## Example 14 | 15 | ```go 16 | count := 3 17 | observable := rxgo.Range(0, 10).GroupByDynamic(func(item rxgo.Item) string { 18 | return strconv.Itoa(item.V.(int) % count) 19 | }, rxgo.WithBufferedChannel(10)) 20 | 21 | for i := range observable.Observe() { 22 | groupedObservable := i.V.(rxgo.GroupedObservable) 23 | fmt.Printf("New observable: %d\n", groupedObservable.Key) 24 | 25 | for i := range groupedObservable.Observe() { 26 | fmt.Printf("item: %v\n", i.V) 27 | } 28 | } 29 | ``` 30 | 31 | Output: 32 | 33 | ``` 34 | New observable: 0 35 | item: 0 36 | item: 3 37 | item: 6 38 | item: 9 39 | New observable: 1 40 | item: 1 41 | item: 4 42 | item: 7 43 | item: 10 44 | New observable: 2 45 | item: 2 46 | item: 5 47 | item: 8 48 | ``` 49 | 50 | ## Options 51 | 52 | * [WithBufferedChannel](options.md#withbufferedchannel) 53 | 54 | * [WithContext](options.md#withcontext) 55 | 56 | * [WithObservationStrategy](options.md#withobservationstrategy) 57 | 58 | * [WithErrorStrategy](options.md#witherrorstrategy) 59 | 60 | * [WithPublishStrategy](options.md#withpublishstrategy) 61 | -------------------------------------------------------------------------------- /doc/ignoreelements.md: -------------------------------------------------------------------------------- 1 | # IgnoreElements Operator 2 | 3 | ## Overview 4 | 5 | Do not emit any items from an Observable but mirror its termination notification. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/ignoreElements.c.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, errors.New("foo"))(). 13 | IgnoreElements() 14 | ``` 15 | 16 | Output: 17 | 18 | ``` 19 | foo 20 | ``` 21 | 22 | ## Options 23 | 24 | * [WithBufferedChannel](options.md#withbufferedchannel) 25 | 26 | * [WithContext](options.md#withcontext) 27 | 28 | * [WithObservationStrategy](options.md#withobservationstrategy) 29 | 30 | * [WithErrorStrategy](options.md#witherrorstrategy) 31 | 32 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/interval.md: -------------------------------------------------------------------------------- 1 | # Interval Operator 2 | 3 | ## Overview 4 | 5 | Create an Observable that emits a sequence of integers spaced by a particular time interval. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/interval.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Interval(rxgo.WithDuration(5 * time.Second)) 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 0 // After 5 seconds 19 | 1 // After 10 seconds 20 | 2 // After 15 seconds 21 | 3 // After 20 seconds 22 | ... 23 | ``` 24 | 25 | ## Options 26 | 27 | * [WithBufferedChannel](options.md#withbufferedchannel) 28 | 29 | * [WithContext](options.md#withcontext) -------------------------------------------------------------------------------- /doc/join.md: -------------------------------------------------------------------------------- 1 | # Join Operator 2 | 3 | ## Overview 4 | 5 | Combine items emitted by two Observables whenever an item from one Observable is emitted during a time window defined according to an item emitted by the other Observable. 6 | 7 | The time is extracted using a timeExtractor function. 8 | 9 | ![](http://reactivex.io/documentation/operators/images/join.c.png) 10 | 11 | ## Example 12 | 13 | ```go 14 | observable := rxgo.Just( 15 | map[string]int64{"tt": 1, "V": 1}, 16 | map[string]int64{"tt": 4, "V": 2}, 17 | map[string]int64{"tt": 7, "V": 3}, 18 | )().Join(func(ctx context.Context, l interface{}, r interface{}) (interface{}, error) { 19 | return map[string]interface{}{ 20 | "l": l, 21 | "r": r, 22 | }, nil 23 | }, rxgo.Just( 24 | map[string]int64{"tt": 2, "V": 5}, 25 | map[string]int64{"tt": 3, "V": 6}, 26 | map[string]int64{"tt": 5, "V": 7}, 27 | )(), func(i interface{}) time.Time { 28 | return time.Unix(i.(map[string]int64)["tt"], 0) 29 | }, rxgo.WithDuration(2)) 30 | ``` 31 | 32 | Output: 33 | 34 | ``` 35 | map[l:map[V:1 tt:1] r:map[V:5 tt:2]] 36 | map[l:map[V:1 tt:1] r:map[V:6 tt:3]] 37 | map[l:map[V:2 tt:4] r:map[V:5 tt:2]] 38 | map[l:map[V:2 tt:4] r:map[V:6 tt:3]] 39 | map[l:map[V:2 tt:4] r:map[V:7 tt:5]] 40 | map[l:map[V:3 tt:7] r:map[V:7 tt:5]] 41 | ``` 42 | 43 | ## Options 44 | 45 | * [WithBufferedChannel](options.md#withbufferedchannel) 46 | 47 | * [WithContext](options.md#withcontext) 48 | 49 | * [WithObservationStrategy](options.md#withobservationstrategy) 50 | 51 | * [WithErrorStrategy](options.md#witherrorstrategy) 52 | 53 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/just.md: -------------------------------------------------------------------------------- 1 | # Just Operator 2 | 3 | ## Overview 4 | 5 | Convert an object or a set of objects into an Observable that emits that or those objects. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/just.png) 8 | 9 | ## Examples 10 | 11 | ### Single Item 12 | 13 | ```go 14 | observable := rxgo.Just(1)() 15 | ``` 16 | 17 | Output: 18 | 19 | ``` 20 | 1 21 | ``` 22 | 23 | ### Multiple Items 24 | 25 | ```go 26 | observable := rxgo.Just(1, 2, 3)() 27 | ``` 28 | 29 | Output: 30 | 31 | ``` 32 | 1 33 | 2 34 | 3 35 | ``` 36 | 37 | ### Channel 38 | 39 | ```go 40 | externalCh := make(chan int) 41 | observable := rxgo.Just(externalCh)() 42 | ``` 43 | 44 | ## Options 45 | 46 | * [WithBufferedChannel](options.md#withbufferedchannel) 47 | 48 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/justitem.md: -------------------------------------------------------------------------------- 1 | # JustItem Operator 2 | 3 | ## Overview 4 | 5 | Convert an object into a Single that emits that object. 6 | 7 | ## Examples 8 | 9 | ```go 10 | observable := rxgo.Just(1) 11 | ``` 12 | 13 | Output: 14 | 15 | ``` 16 | 1 17 | ``` 18 | 19 | ## Options 20 | 21 | * [WithBufferedChannel](options.md#withbufferedchannel) 22 | 23 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/last.md: -------------------------------------------------------------------------------- 1 | # Last Operator 2 | 3 | ## Overview 4 | 5 | Emit only the last item emitted by an Observable. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/last.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3)().Last() 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 3 19 | ``` 20 | 21 | ## Options 22 | 23 | * [WithBufferedChannel](options.md#withbufferedchannel) 24 | 25 | * [WithContext](options.md#withcontext) 26 | 27 | * [WithObservationStrategy](options.md#withobservationstrategy) 28 | 29 | * [WithErrorStrategy](options.md#witherrorstrategy) 30 | 31 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/lastordefault.md: -------------------------------------------------------------------------------- 1 | # LastOrDefault Operator 2 | 3 | ## Overview 4 | 5 | Similar to `Last`, but you pass it a default item that it can emit if the source Observable fails to emit any items. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/lastOrDefault.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Empty().LastOrDefault(1) 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 1 19 | ``` 20 | 21 | ## Options 22 | 23 | * [WithBufferedChannel](options.md#withbufferedchannel) 24 | 25 | * [WithContext](options.md#withcontext) 26 | 27 | * [WithObservationStrategy](options.md#withobservationstrategy) 28 | 29 | * [WithErrorStrategy](options.md#witherrorstrategy) 30 | 31 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/map.md: -------------------------------------------------------------------------------- 1 | 2 | # Map Operator 3 | 4 | ## Overview 5 | 6 | Transform the items emitted by an Observable by applying a function to each item. 7 | 8 | ![](http://reactivex.io/documentation/operators/images/map.png) 9 | 10 | ## Example 11 | 12 | ```go 13 | observable := rxgo.Just(1, 2, 3)(). 14 | Map(func(_ context.Context, i interface{}) (interface{}, error) { 15 | return i.(int) * 10, nil 16 | }) 17 | ``` 18 | 19 | Output: 20 | 21 | ``` 22 | 10 23 | 20 24 | 30 25 | ``` 26 | 27 | ## Options 28 | 29 | * [WithBufferedChannel](options.md#withbufferedchannel) 30 | 31 | * [WithContext](options.md#withcontext) 32 | 33 | * [WithObservationStrategy](options.md#withobservationstrategy) 34 | 35 | * [WithErrorStrategy](options.md#witherrorstrategy) 36 | 37 | * [WithPool](options.md#withpool) 38 | 39 | * [WithCPUPool](options.md#withcpupool) 40 | 41 | ### Serialize 42 | 43 | [Detail](options.md#serialize) 44 | 45 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/marshal.md: -------------------------------------------------------------------------------- 1 | # Marshal Operator 2 | 3 | ## Overview 4 | 5 | Transform the items emitted by an Observable by applying a marshaller function (`func(interface{}) ([]byte, error)`) to each item. 6 | 7 | ## Example 8 | 9 | ```go 10 | type customer struct { 11 | ID int `json:"id"` 12 | } 13 | 14 | observable := rxgo.Just( 15 | customer{ 16 | ID: 1, 17 | }, 18 | customer{ 19 | ID: 2, 20 | }, 21 | )().Marshal(json.Marshal) 22 | ``` 23 | 24 | Output: 25 | 26 | ``` 27 | {"id":1} 28 | {"id":2} 29 | ``` 30 | 31 | ## Options 32 | 33 | * [WithBufferedChannel](options.md#withbufferedchannel) 34 | 35 | * [WithContext](options.md#withcontext) 36 | 37 | * [WithObservationStrategy](options.md#withobservationstrategy) 38 | 39 | * [WithErrorStrategy](options.md#witherrorstrategy) 40 | 41 | * [WithPool](options.md#withpool) 42 | 43 | * [WithCPUPool](options.md#withcpupool) 44 | 45 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/max.md: -------------------------------------------------------------------------------- 1 | # Max Operator 2 | 3 | ## Overview 4 | 5 | Determine, and emit, the maximum-valued item emitted by an Observable. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/max.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(2, 5, 1, 6, 3, 4)(). 13 | Max(func(i1 interface{}, i2 interface{}) int { 14 | return i1.(int) - i2.(int) 15 | }) 16 | ``` 17 | 18 | Output: 19 | 20 | ``` 21 | 6 22 | ``` 23 | 24 | ## Options 25 | 26 | * [WithBufferedChannel](options.md#withbufferedchannel) 27 | 28 | * [WithContext](options.md#withcontext) 29 | 30 | * [WithObservationStrategy](options.md#withobservationstrategy) 31 | 32 | * [WithErrorStrategy](options.md#witherrorstrategy) 33 | 34 | * [WithPool](options.md#withpool) 35 | 36 | * [WithCPUPool](options.md#withcpupool) 37 | 38 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/merge.md: -------------------------------------------------------------------------------- 1 | # Merge Operator 2 | 3 | ## Overview 4 | 5 | Combine multiple Observables into one by merging their emissions. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/merge.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Merge([]rxgo.Observable{ 13 | rxgo.Just(1, 2)(), 14 | rxgo.Just(3, 4)(), 15 | }) 16 | ``` 17 | 18 | Output: 19 | 20 | ``` 21 | 1 22 | 2 23 | 3 24 | 4 25 | ``` 26 | 27 | ## Options 28 | 29 | * [WithBufferedChannel](options.md#withbufferedchannel) 30 | 31 | * [WithContext](options.md#withcontext) 32 | 33 | * [WithObservationStrategy](options.md#withobservationstrategy) 34 | 35 | * [WithErrorStrategy](options.md#witherrorstrategy) 36 | 37 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/min.md: -------------------------------------------------------------------------------- 1 | # Min Operator 2 | 3 | ## Overview 4 | 5 | Determine, and emit, the minimum-valued item emitted by an Observable. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/min.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(2, 5, 1, 6, 3, 4)(). 13 | Min(func(i1 interface{}, i2 interface{}) int { 14 | return i1.(int) - i2.(int) 15 | }) 16 | ``` 17 | 18 | Output: 19 | 20 | ``` 21 | 1 22 | ``` 23 | 24 | ## Options 25 | 26 | * [WithBufferedChannel](options.md#withbufferedchannel) 27 | 28 | * [WithContext](options.md#withcontext) 29 | 30 | * [WithObservationStrategy](options.md#withobservationstrategy) 31 | 32 | * [WithErrorStrategy](options.md#witherrorstrategy) 33 | 34 | * [WithPool](options.md#withpool) 35 | 36 | * [WithCPUPool](options.md#withcpupool) 37 | 38 | * [WithPublishStrategy](options.md#withpublishstrategy) 39 | -------------------------------------------------------------------------------- /doc/never.md: -------------------------------------------------------------------------------- 1 | # Never Operator 2 | 3 | ## Overview 4 | 5 | Create an Observable that emits no items and does not terminate. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/never.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Never() 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | ``` -------------------------------------------------------------------------------- /doc/options.md: -------------------------------------------------------------------------------- 1 | # Operator Options 2 | 3 | Most of the operators accept a list of functional options to impact the Observable behaviour. 4 | 5 | As an example: 6 | 7 | ```go 8 | observable.Map(func(_ context.Context, i interface{}) (interface{}, error) { 9 | return i.(int) * 10, nil 10 | }, rxgo.WithContext(), 11 | rxgo.WithCPUPool(), 12 | rxgo.WithBufferedChannel(1)) 13 | ``` 14 | 15 | ## WithBufferedChannel 16 | 17 | Configure the capacity of the output channel. 18 | 19 | ```go 20 | rxgo.WithBufferedChannel(1) // Create a buffered channel with a 1 capacity 21 | ``` 22 | 23 | ## WithContext 24 | 25 | Allows passing a context. The Observable will listen to its done signal to close itself. 26 | 27 | ```go 28 | rxgo.WithContext(ctx) 29 | ``` 30 | 31 | ## WithObservationStrategy 32 | 33 | * Lazy (default): consume when an Observer starts to subscribe. 34 | 35 | ```go 36 | rxgo.WithObservationStrategy(rxgo.Lazy) 37 | ``` 38 | 39 | * Eager: consumer when the Observable is created: 40 | 41 | ```go 42 | rxgo.WithObservationStrategy(rxgo.Eager) 43 | ``` 44 | 45 | ## WithErrorStrategy 46 | 47 | * StopOnError (default): stop processing if the Observable produces an error. 48 | 49 | ```go 50 | rxgo.WithErrorStrategy(rxgo.StopOnError) 51 | ``` 52 | 53 | * ContinueOnError: continue processing items if the Observable produces an error. 54 | 55 | ```go 56 | rxgo.WithErrorStrategy(rxgo.ContinueOnError) 57 | ``` 58 | 59 | This strategy is propagated to the parent(s) Observable(s). 60 | 61 | ## WithPool 62 | 63 | Convert the operator in a parallel operator and specify the number of concurrent goroutines. 64 | 65 | ```go 66 | rxgo.WithPool(8) // Creates a pool of 8 goroutines 67 | ``` 68 | 69 | ## WithCPUPool 70 | 71 | Convert the operator in a parallel operator and specify the number of concurrent goroutines as `runtime.NumCPU()`. 72 | 73 | ```go 74 | rxgo.WithCPUPool() 75 | ``` 76 | 77 | ## Serialize 78 | 79 | Force an Observable to produce items sequentially. 80 | 81 | ```go 82 | rxgo.Serialize() 83 | ``` 84 | 85 | This option should be used in coordination with `rxgo.WithPool(n)` or `rxgo.WithCPUPool()`. 86 | 87 | ## WithPublishStrategy 88 | 89 | Create a [Connectable Observable](../README.md#connectable-observable). 90 | 91 | ```go 92 | rxgo.WithPublishStrategy() 93 | ``` 94 | 95 | This option is propagated to the parent(s) Observable(s). -------------------------------------------------------------------------------- /doc/range.md: -------------------------------------------------------------------------------- 1 | # Range Operator 2 | 3 | ## Overview 4 | 5 | Create an Observable that emits a range of sequential integers. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/range.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Range(0, 3) 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 0 19 | 1 20 | 2 21 | 3 22 | ``` 23 | 24 | ## Options 25 | 26 | * [WithBufferedChannel](options.md#withbufferedchannel) 27 | 28 | * [WithContext](options.md#withcontext) -------------------------------------------------------------------------------- /doc/reduce.md: -------------------------------------------------------------------------------- 1 | # Reduce Operator 2 | 3 | ## Overview 4 | 5 | Apply a function to each item emitted by an Observable, sequentially, and emit the final value. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/reduce.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3)(). 13 | Reduce(func(_ context.Context, acc interface{}, elem interface{}) (interface{}, error) { 14 | if acc == nil { 15 | return elem, nil 16 | } 17 | return acc.(int) + elem.(int), nil 18 | }) 19 | ``` 20 | 21 | Output: 22 | 23 | ``` 24 | 6 25 | ``` 26 | 27 | ## Options 28 | 29 | * [WithBufferedChannel](options.md#withbufferedchannel) 30 | 31 | * [WithContext](options.md#withcontext) 32 | 33 | * [WithObservationStrategy](options.md#withobservationstrategy) 34 | 35 | * [WithErrorStrategy](options.md#witherrorstrategy) 36 | 37 | * [WithPool](options.md#withpool) 38 | 39 | * [WithCPUPool](options.md#withcpupool) 40 | 41 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/repeat.md: -------------------------------------------------------------------------------- 1 | # Repeat Operator 2 | 3 | ## Overview 4 | 5 | Create an Observable that emits a particular item multiple times at a particular frequency. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/repeat.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3)(). 13 | Repeat(3, rxgo.WithDuration(time.Second)) 14 | ``` 15 | 16 | Output: 17 | 18 | ``` 19 | // Immediately 20 | 1 21 | 2 22 | 3 23 | // After 1 second 24 | 1 25 | 2 26 | 3 27 | // After 2 seconds 28 | 1 29 | 2 30 | 3 31 | ... 32 | ``` 33 | 34 | ## Options 35 | 36 | * [WithBufferedChannel](options.md#withbufferedchannel) 37 | 38 | * [WithContext](options.md#withcontext) 39 | 40 | * [WithObservationStrategy](options.md#withobservationstrategy) 41 | 42 | * [WithErrorStrategy](options.md#witherrorstrategy) 43 | 44 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/retry.md: -------------------------------------------------------------------------------- 1 | # Retry Operator 2 | 3 | ## Overview 4 | 5 | Implements a retry if a source Observable sends an error, resubscribe to it in the hopes that it will complete without error. 6 | 7 | It accepts a `shouldRetry func(error) bool` function to determine whether an error should by retried. 8 | 9 | ![](http://reactivex.io/documentation/operators/images/retry.png) 10 | 11 | ## Example 12 | 13 | ```go 14 | observable := rxgo.Just(1, 2, errors.New("foo"))(). 15 | Retry(2, func(err error) bool { 16 | return err.Error() == "foo" 17 | }) 18 | ``` 19 | 20 | Output: 21 | 22 | ``` 23 | 1 24 | 2 25 | 1 26 | 2 27 | 1 28 | 2 29 | foo 30 | ``` 31 | 32 | ## Options 33 | 34 | * [WithBufferedChannel](options.md#withbufferedchannel) 35 | 36 | * [WithContext](options.md#withcontext) 37 | 38 | * [WithObservationStrategy](options.md#withobservationstrategy) 39 | 40 | * [WithErrorStrategy](options.md#witherrorstrategy) 41 | 42 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/run.md: -------------------------------------------------------------------------------- 1 | # Run Operator 2 | 3 | ## Overview 4 | 5 | Create an Observer without consuming the emitted items. 6 | 7 | It returns a `<-chan struct{}` that closes once the Observable terminates. 8 | 9 | ## Example 10 | 11 | ```go 12 | <-rxgo.Just(1, 2, errors.New("foo"))().Run() 13 | ``` 14 | 15 | ## Options 16 | 17 | * [WithContext](options.md#withcontext) -------------------------------------------------------------------------------- /doc/rx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactiveX/RxGo/d7b6b958d4aa93c72505e487cdfae4c3b6a213fc/doc/rx.png -------------------------------------------------------------------------------- /doc/sample.md: -------------------------------------------------------------------------------- 1 | # Sample Operator 2 | 3 | ## Overview 4 | 5 | Emit the most recent item emitted by an Observable within periodic time intervals. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/sample.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | sampledObservable := observable1.Sample(observable2) 13 | ``` 14 | 15 | ## Options 16 | 17 | * [WithBufferedChannel](options.md#withbufferedchannel) 18 | 19 | * [WithContext](options.md#withcontext) 20 | 21 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/scan.md: -------------------------------------------------------------------------------- 1 | # Scan Operator 2 | 3 | ## Overview 4 | 5 | Apply a function to each item emitted by an Observable, sequentially, and emit each successive value. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/scan.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3, 4, 5)(). 13 | Scan(func(_ context.Context, acc interface{}, elem interface{}) (interface{}, error) { 14 | if acc == nil { 15 | return elem, nil 16 | } 17 | return acc.(int) + elem.(int), nil 18 | }) 19 | ``` 20 | 21 | Output: 22 | 23 | ``` 24 | 1 25 | 3 26 | 6 27 | 10 28 | 15 29 | ``` 30 | 31 | ## Options 32 | 33 | * [WithBufferedChannel](options.md#withbufferedchannel) 34 | 35 | * [WithContext](options.md#withcontext) 36 | 37 | * [WithObservationStrategy](options.md#withobservationstrategy) 38 | 39 | * [WithErrorStrategy](options.md#witherrorstrategy) 40 | 41 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/send.md: -------------------------------------------------------------------------------- 1 | # Send Operator 2 | 3 | ## Overview 4 | 5 | Send the Observable items to a given channel that will closed once the operation completes. 6 | 7 | ## Example 8 | 9 | ```go 10 | ch := make(chan rxgo.Item) 11 | rxgo.Just(1, 2, 3)().Send(ch) 12 | for item := range ch { 13 | fmt.Println(item.V) 14 | } 15 | ``` 16 | 17 | Output: 18 | 19 | ``` 20 | 1 21 | 2 22 | 3 23 | ``` 24 | 25 | ## Options 26 | 27 | * [WithContext](options.md#withcontext) -------------------------------------------------------------------------------- /doc/sequenceequal.md: -------------------------------------------------------------------------------- 1 | # SequenceEqual Operator 2 | 3 | ## Overview 4 | 5 | Determine whether two Observables emit the same sequence of items. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/sequenceEqual.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3, 4, 5)(). 13 | SequenceEqual(rxgo.Just(1, 2, 42, 4, 5)()) 14 | ``` 15 | 16 | Output: 17 | 18 | ``` 19 | false 20 | ``` 21 | 22 | ## Options 23 | 24 | * [WithBufferedChannel](options.md#withbufferedchannel) 25 | 26 | * [WithContext](options.md#withcontext) 27 | 28 | * [WithObservationStrategy](options.md#withobservationstrategy) 29 | 30 | * [WithErrorStrategy](options.md#witherrorstrategy) 31 | 32 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/serialize.md: -------------------------------------------------------------------------------- 1 | # Serialize Operator 2 | 3 | ## Overview 4 | 5 | Force an Observable to make serialized calls and to be well-behaved. 6 | It takes the starting index and a function that transforms an item value into an index. 7 | 8 | ![](http://reactivex.io/documentation/operators/images/serialize.c.png) 9 | 10 | ## Example 11 | 12 | ```go 13 | observable := rxgo.Range(0, 1_000_000, rxgo.WithBufferedChannel(capacity)). 14 | Map(func(_ context.Context, i interface{}) (interface{}, error) { 15 | return i, nil 16 | }, rxgo.WithCPUPool(), rxgo.WithBufferedChannel(capacity)). 17 | Serialize(0, func(i interface{}) int { 18 | return i.(int) 19 | }) 20 | ``` 21 | 22 | Output: 23 | 24 | ``` 25 | true 26 | ``` 27 | 28 | ## Options 29 | 30 | * [WithBufferedChannel](options.md#withbufferedchannel) 31 | 32 | * [WithContext](options.md#withcontext) 33 | 34 | * [WithObservationStrategy](options.md#withobservationstrategy) 35 | 36 | * [WithErrorStrategy](options.md#witherrorstrategy) 37 | 38 | * [WithPool](options.md#withpool) 39 | 40 | * [WithCPUPool](options.md#withcpupool) 41 | 42 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/skip.md: -------------------------------------------------------------------------------- 1 | # Skip Operator 2 | 3 | ## Overview 4 | 5 | Suppress the first n items emitted by an Observable. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/skip.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3, 4, 5)().Skip(2) 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 3 19 | 4 20 | 5 21 | ``` 22 | 23 | ## Options 24 | 25 | * [WithBufferedChannel](options.md#withbufferedchannel) 26 | 27 | * [WithContext](options.md#withcontext) 28 | 29 | * [WithObservationStrategy](options.md#withobservationstrategy) 30 | 31 | * [WithErrorStrategy](options.md#witherrorstrategy) 32 | 33 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/skiplast.md: -------------------------------------------------------------------------------- 1 | # SkipLast Operator 2 | 3 | ## Overview 4 | 5 | Suppress the last n items emitted by an Observable. 6 | 7 | ## Example 8 | 9 | ```go 10 | observable := rxgo.Just(1, 2, 3, 4, 5)().SkipLast(2) 11 | ``` 12 | 13 | Output: 14 | 15 | ``` 16 | 1 17 | 2 18 | ``` 19 | 20 | ## Options 21 | 22 | * [WithBufferedChannel](options.md#withbufferedchannel) 23 | 24 | * [WithContext](options.md#withcontext) 25 | 26 | * [WithObservationStrategy](options.md#withobservationstrategy) 27 | 28 | * [WithErrorStrategy](options.md#witherrorstrategy) 29 | 30 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/skipwhile.md: -------------------------------------------------------------------------------- 1 | # SkipWhile Operator 2 | 3 | ## Overview 4 | 5 | Suppress the Observable items while a condition is not met. 6 | 7 | ## Example 8 | 9 | ```go 10 | observable := rxgo.Just(1, 2, 3, 4, 5)().SkipWhile(func(i interface{}) bool { 11 | return i != 2 12 | }) 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 2 19 | 3 20 | 4 21 | 5 22 | ``` 23 | 24 | ## Options 25 | 26 | * [WithBufferedChannel](options.md#withbufferedchannel) 27 | 28 | * [WithContext](options.md#withcontext) 29 | 30 | * [WithObservationStrategy](options.md#withobservationstrategy) 31 | 32 | * [WithErrorStrategy](options.md#witherrorstrategy) 33 | 34 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/start.md: -------------------------------------------------------------------------------- 1 | # Start Operator 2 | 3 | ## Overview 4 | 5 | Create an Observable that emits the return value of a function. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/start.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Start([]rxgo.Supplier{func(ctx context.Context) rxgo.Item { 13 | return rxgo.Of(1) 14 | }, func(ctx context.Context) rxgo.Item { 15 | return rxgo.Of(2) 16 | }}) 17 | ``` 18 | 19 | Output: 20 | 21 | ``` 22 | 1 23 | 2 24 | ``` 25 | 26 | ## Options 27 | 28 | * [WithBufferedChannel](options.md#withbufferedchannel) 29 | 30 | * [WithContext](options.md#withcontext) 31 | 32 | * [WithObservationStrategy](options.md#withobservationstrategy) 33 | 34 | * [WithErrorStrategy](options.md#witherrorstrategy) 35 | 36 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/startwithiterable.md: -------------------------------------------------------------------------------- 1 | # StartWithIterable Operator 2 | 3 | ## Overview 4 | 5 | Emit a specified Iterable before beginning to emit the items from the source Observable. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/startWith.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(3, 4)().StartWith( 13 | rxgo.Just(1, 2)()) 14 | ``` 15 | 16 | Output: 17 | 18 | ``` 19 | 1 20 | 2 21 | 3 22 | 4 23 | ``` 24 | 25 | ## Options 26 | 27 | * [WithBufferedChannel](options.md#withbufferedchannel) 28 | 29 | * [WithContext](options.md#withcontext) 30 | 31 | * [WithObservationStrategy](options.md#withobservationstrategy) 32 | 33 | * [WithErrorStrategy](options.md#witherrorstrategy) 34 | 35 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/sum.md: -------------------------------------------------------------------------------- 1 | # Sum Operator 2 | 3 | ## Overview 4 | 5 | Calculate the sum of numbers emitted by an Observable and emit this sum. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/sum.f.png) 8 | 9 | ## Instances 10 | 11 | * `SumFloat32` 12 | * `SumFloat64` 13 | * `SumInt64` 14 | 15 | ## Example 16 | 17 | ```go 18 | observable := rxgo.Just(1, 2, 3, 4)().SumInt64() 19 | ``` 20 | 21 | Output: 22 | 23 | ``` 24 | 10 25 | ``` 26 | 27 | ## Options 28 | 29 | * [WithBufferedChannel](options.md#withbufferedchannel) 30 | 31 | * [WithContext](options.md#withcontext) 32 | 33 | * [WithObservationStrategy](options.md#withobservationstrategy) 34 | 35 | * [WithErrorStrategy](options.md#witherrorstrategy) 36 | 37 | * [WithPool](options.md#withpool) 38 | 39 | * [WithCPUPool](options.md#withcpupool) 40 | 41 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/take.md: -------------------------------------------------------------------------------- 1 | # Take Operator 2 | 3 | ## Overview 4 | 5 | Emit only the first n items emitted by an Observable. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/take.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3, 4, 5)().Take(2) 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 1 19 | 2 20 | ``` 21 | 22 | ## Options 23 | 24 | * [WithBufferedChannel](options.md#withbufferedchannel) 25 | 26 | * [WithContext](options.md#withcontext) 27 | 28 | * [WithObservationStrategy](options.md#withobservationstrategy) 29 | 30 | * [WithErrorStrategy](options.md#witherrorstrategy) 31 | 32 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/takelast.md: -------------------------------------------------------------------------------- 1 | # TakeLast Operator 2 | 3 | ## Overview 4 | 5 | Emit only the final n items emitted by an Observable. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/takeLast.n.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3, 4, 5)().TakeLast(2) 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 4 19 | 5 20 | ``` 21 | 22 | ## Options 23 | 24 | * [WithBufferedChannel](options.md#withbufferedchannel) 25 | 26 | * [WithContext](options.md#withcontext) 27 | 28 | * [WithObservationStrategy](options.md#withobservationstrategy) 29 | 30 | * [WithErrorStrategy](options.md#witherrorstrategy) 31 | 32 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/takeuntil.md: -------------------------------------------------------------------------------- 1 | # TakeUntil Operator 2 | 3 | ## Overview 4 | 5 | Discard any items emitted by an Observable after a second Observable emits an item or terminates. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/takeUntil.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3, 4, 5)().TakeUntil(func(i interface{}) bool { 13 | return i == 3 14 | }) 15 | ``` 16 | 17 | Output: 18 | 19 | ``` 20 | 1 21 | 2 22 | 3 23 | ``` 24 | 25 | ## Options 26 | 27 | * [WithBufferedChannel](options.md#withbufferedchannel) 28 | 29 | * [WithContext](options.md#withcontext) 30 | 31 | * [WithObservationStrategy](options.md#withobservationstrategy) 32 | 33 | * [WithErrorStrategy](options.md#witherrorstrategy) 34 | 35 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/takewhile.md: -------------------------------------------------------------------------------- 1 | # TakeWhile Operator 2 | 3 | ## Overview 4 | 5 | Mirror items emitted by an Observable until a specified condition becomes false. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/takeWhile.c.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3, 4, 5)().TakeWhile(func(i interface{}) bool { 13 | return i != 3 14 | }) 15 | ``` 16 | 17 | Output: 18 | 19 | ``` 20 | 1 21 | 2 22 | ``` 23 | 24 | ## Options 25 | 26 | * [WithBufferedChannel](options.md#withbufferedchannel) 27 | 28 | * [WithContext](options.md#withcontext) 29 | 30 | * [WithObservationStrategy](options.md#withobservationstrategy) 31 | 32 | * [WithErrorStrategy](options.md#witherrorstrategy) 33 | 34 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/thrown.md: -------------------------------------------------------------------------------- 1 | # Thrown Operator 2 | 3 | ## Overview 4 | 5 | Create an Observable that emits no items and terminates with an error. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/throw.c.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Thrown(errors.New("foo")) 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | foo 19 | ``` -------------------------------------------------------------------------------- /doc/timeinterval.md: -------------------------------------------------------------------------------- 1 | # TimeInterval Operator 2 | 3 | ## Overview 4 | 5 | Convert an Observable that emits items into one that emits indications of the amount of time elapsed between those emissions. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/timeInterval.c.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Interval(rxgo.WithDuration(time.Second)).TimeInterval() 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | 1.002664s 19 | 1.004267s 20 | 1.00044s 21 | ... 22 | ``` 23 | 24 | ## Options 25 | 26 | * [WithBufferedChannel](options.md#withbufferedchannel) 27 | 28 | * [WithContext](options.md#withcontext) 29 | 30 | * [WithObservationStrategy](options.md#withobservationstrategy) 31 | 32 | * [WithErrorStrategy](options.md#witherrorstrategy) 33 | 34 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/timer.md: -------------------------------------------------------------------------------- 1 | # Timer Operator 2 | 3 | ## Overview 4 | 5 | Create an Observable that completes after a specified delay. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/timer.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Timer(rxgo.WithDuration(5 * time.Second)) 13 | ``` 14 | 15 | Output: 16 | 17 | ``` 18 | {} // After 5 seconds 19 | ``` 20 | 21 | ## Options 22 | 23 | * [WithContext](options.md#withcontext) -------------------------------------------------------------------------------- /doc/timestamp.md: -------------------------------------------------------------------------------- 1 | # Timestamp Operator 2 | 3 | ## Overview 4 | 5 | Attach a timestamp to each item emitted by an Observable. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/timestamp.c.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observe := rxgo.Just(1, 2, 3)().Timestamp().Observe() 13 | var timestampItem rxgo.TimestampItem 14 | timestampItem = (<-observe).V.(rxgo.TimestampItem) 15 | fmt.Println(timestampItem) 16 | ``` 17 | 18 | Output: 19 | 20 | ``` 21 | {2020-02-23 15:26:02.231197 +0000 UTC 1} 22 | ``` 23 | 24 | ## Options 25 | 26 | * [WithBufferedChannel](options.md#withbufferedchannel) 27 | 28 | * [WithContext](options.md#withcontext) 29 | 30 | * [WithObservationStrategy](options.md#withobservationstrategy) 31 | 32 | * [WithErrorStrategy](options.md#witherrorstrategy) 33 | 34 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/tomap.md: -------------------------------------------------------------------------------- 1 | # ToMap Operator 2 | 3 | ## Overview 4 | 5 | Transform the Observable items into a Single emitting a map. It accepts a function that transforms each item into its corresponding key in the map. 6 | 7 | ## Example 8 | 9 | ```go 10 | observable := rxgo.Just(1, 2, 3)(). 11 | ToMap(func(_ context.Context, i interface{}) (interface{}, error) { 12 | return i.(int) * 10, nil 13 | }) 14 | ``` 15 | 16 | Output: 17 | 18 | ``` 19 | map[10:1 20:2 30:3] 20 | ``` 21 | 22 | ## Options 23 | 24 | * [WithContext](options.md#withcontext) 25 | 26 | * [WithObservationStrategy](options.md#withobservationstrategy) 27 | 28 | * [WithErrorStrategy](options.md#witherrorstrategy) -------------------------------------------------------------------------------- /doc/tomapwithvalueselector.md: -------------------------------------------------------------------------------- 1 | # ToMapWithValueSelector Operator 2 | 3 | ## Overview 4 | 5 | Transform the Observable items into a Single emitting a map. It accepts: 6 | * A function that transforms each item into its corresponding key in the map. 7 | * A function that transforms each item into its corresponding value in the map. 8 | 9 | ## Example 10 | 11 | ```go 12 | observable := rxgo.Just(1, 2, 3)(). 13 | ToMapWithValueSelector(func(_ context.Context, i interface{}) (interface{}, error) { 14 | return i.(int) * 10, nil 15 | }, func(_ context.Context, i interface{}) (interface{}, error) { 16 | return i, nil 17 | }) 18 | ``` 19 | 20 | Output: 21 | 22 | ``` 23 | map[10:1 20:2 30:3] 24 | ``` 25 | 26 | ## Options 27 | 28 | * [WithContext](options.md#withcontext) 29 | 30 | * [WithObservationStrategy](options.md#withobservationstrategy) 31 | 32 | * [WithErrorStrategy](options.md#witherrorstrategy) -------------------------------------------------------------------------------- /doc/toslice.md: -------------------------------------------------------------------------------- 1 | # ToSlice Operator 2 | 3 | ## Overview 4 | 5 | Transform the Observable items into a slice. It accepts a capacity that will be used as the initial capacity of the slice produced. 6 | 7 | ## Example 8 | 9 | ```go 10 | s, err := rxgo.Just(1, 2, 3)().ToSlice(3) 11 | if err != nil { 12 | return err 13 | } 14 | fmt.Println(s) 15 | ``` 16 | 17 | Output: 18 | 19 | ``` 20 | [1 2 3] 21 | ``` 22 | 23 | ## Options 24 | 25 | * [WithContext](options.md#withcontext) 26 | 27 | * [WithObservationStrategy](options.md#withobservationstrategy) 28 | 29 | * [WithErrorStrategy](options.md#witherrorstrategy) -------------------------------------------------------------------------------- /doc/unmarshal.md: -------------------------------------------------------------------------------- 1 | # Unmarshal Operator 2 | 3 | ## Overview 4 | 5 | Transform the items emitted by an Observable by applying an unmarshaller function (`func([]byte, interface{}) error`) to each item. It takes a factory function that initializes the target structure. 6 | 7 | ## Example 8 | 9 | ```go 10 | observable := rxgo.Just( 11 | []byte(`{"id":1}`), 12 | []byte(`{"id":2}`), 13 | )().Unmarshal(json.Unmarshal, 14 | func() interface{} { 15 | return &customer{} 16 | }) 17 | ``` 18 | 19 | Output: 20 | 21 | ``` 22 | &{ID:1} 23 | &{ID:2} 24 | ``` 25 | 26 | ## Options 27 | 28 | * [WithBufferedChannel](options.md#withbufferedchannel) 29 | 30 | * [WithContext](options.md#withcontext) 31 | 32 | * [WithObservationStrategy](options.md#withobservationstrategy) 33 | 34 | * [WithErrorStrategy](options.md#witherrorstrategy) 35 | 36 | * [WithPool](options.md#withpool) 37 | 38 | * [WithCPUPool](options.md#withcpupool) 39 | 40 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/window.md: -------------------------------------------------------------------------------- 1 | # Window Operator 2 | 3 | ## Overview 4 | 5 | Periodically subdivide items from an Observable into Observable windows and emit these windows rather than emitting the items one at a time. 6 | 7 | ## Instances 8 | 9 | * `WindowWithCount` 10 | 11 | ![](http://reactivex.io/documentation/operators/images/window3.png) 12 | 13 | * `WindowWithTime` 14 | 15 | ![](http://reactivex.io/documentation/operators/images/window5.png) 16 | 17 | * `WindowWithTimeOrCount` 18 | 19 | ![](http://reactivex.io/documentation/operators/images/window6.png) 20 | 21 | ## Example 22 | 23 | ```go 24 | observe := rxgo.Just(1, 2, 3)().WindowWithCount(2).Observe() 25 | 26 | fmt.Println("First Observable") 27 | for item := range (<-observe).V.(rxgo.Observable).Observe() { 28 | if item.Error() { 29 | return item.E 30 | } 31 | fmt.Println(item.V) 32 | } 33 | 34 | fmt.Println("Second Observable") 35 | for item := range (<-observe).V.(rxgo.Observable).Observe() { 36 | if item.Error() { 37 | return item.E 38 | } 39 | fmt.Println(item.V) 40 | } 41 | ``` 42 | 43 | Output: 44 | 45 | ``` 46 | First Observable 47 | 1 48 | 2 49 | Second Observable 50 | 3 51 | ``` 52 | 53 | ## Options 54 | 55 | * [WithBufferedChannel](options.md#withbufferedchannel) 56 | 57 | * [WithContext](options.md#withcontext) 58 | 59 | * [WithObservationStrategy](options.md#withobservationstrategy) 60 | 61 | * [WithErrorStrategy](options.md#witherrorstrategy) 62 | 63 | * [WithPublishStrategy](options.md#withpublishstrategy) -------------------------------------------------------------------------------- /doc/zipfromiterable.md: -------------------------------------------------------------------------------- 1 | # ZipFromIterable Operator 2 | 3 | ## Overview 4 | 5 | Merge the emissions of an Iterable via a specified function and emit single items for each combination based on the results of this function. 6 | 7 | ![](http://reactivex.io/documentation/operators/images/zip.o.png) 8 | 9 | ## Example 10 | 11 | ```go 12 | observable1 := rxgo.Just(1, 2, 3)() 13 | observable2 := rxgo.Just(10, 20, 30)() 14 | zipper := func(_ context.Context, i1 interface{}, i2 interface{}) (interface{}, error) { 15 | return i1.(int) + i2.(int), nil 16 | } 17 | zippedObservable := observable1.ZipFromIterable(observable2, zipper) 18 | ``` 19 | 20 | Output: 21 | 22 | ``` 23 | 11 24 | 22 25 | 33 26 | ``` 27 | 28 | ## Options 29 | 30 | * [WithBufferedChannel](options.md#withbufferedchannel) 31 | 32 | * [WithContext](options.md#withcontext) 33 | 34 | * [WithObservationStrategy](options.md#withobservationstrategy) 35 | 36 | * [WithErrorStrategy](options.md#witherrorstrategy) 37 | 38 | * [WithPublishStrategy](options.md#withpublishstrategy) 39 | -------------------------------------------------------------------------------- /duration.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/stretchr/testify/mock" 8 | ) 9 | 10 | // Infinite represents an infinite wait time 11 | var Infinite int64 = -1 12 | 13 | // Duration represents a duration 14 | type Duration interface { 15 | duration() time.Duration 16 | } 17 | 18 | type duration struct { 19 | d time.Duration 20 | } 21 | 22 | func (d *duration) duration() time.Duration { 23 | return d.d 24 | } 25 | 26 | // WithDuration is a duration option 27 | func WithDuration(d time.Duration) Duration { 28 | return &duration{ 29 | d: d, 30 | } 31 | } 32 | 33 | var tick = struct{}{} 34 | 35 | type causalityDuration struct { 36 | fs []execution 37 | } 38 | 39 | type execution struct { 40 | f func() 41 | isTick bool 42 | } 43 | 44 | func timeCausality(elems ...interface{}) (context.Context, Observable, Duration) { 45 | ch := make(chan Item, 1) 46 | fs := make([]execution, len(elems)+1) 47 | ctx, cancel := context.WithCancel(context.Background()) 48 | for i, elem := range elems { 49 | i := i 50 | elem := elem 51 | if elem == tick { 52 | fs[i] = execution{ 53 | f: func() {}, 54 | isTick: true, 55 | } 56 | } else { 57 | switch elem := elem.(type) { 58 | default: 59 | fs[i] = execution{ 60 | f: func() { 61 | ch <- Of(elem) 62 | }, 63 | isTick: false, 64 | } 65 | case error: 66 | fs[i] = execution{ 67 | f: func() { 68 | ch <- Error(elem) 69 | }, 70 | isTick: false, 71 | } 72 | } 73 | } 74 | } 75 | fs[len(elems)] = execution{ 76 | f: func() { 77 | cancel() 78 | }, 79 | isTick: false, 80 | } 81 | return ctx, FromChannel(ch), &causalityDuration{fs: fs} 82 | } 83 | 84 | func (d *causalityDuration) duration() time.Duration { 85 | pop := d.fs[0] 86 | pop.f() 87 | d.fs = d.fs[1:] 88 | if pop.isTick { 89 | return time.Nanosecond 90 | } 91 | return time.Minute 92 | } 93 | 94 | type mockDuration struct { 95 | mock.Mock 96 | } 97 | 98 | func (m *mockDuration) duration() time.Duration { 99 | args := m.Called() 100 | return args.Get(0).(time.Duration) 101 | } 102 | -------------------------------------------------------------------------------- /duration_test.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestWithFrequency(t *testing.T) { 11 | frequency := WithDuration(100 * time.Millisecond) 12 | assert.Equal(t, 100*time.Millisecond, frequency.duration()) 13 | } 14 | -------------------------------------------------------------------------------- /errors.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | // IllegalInputError is triggered when the observable receives an illegal input. 4 | type IllegalInputError struct { 5 | error string 6 | } 7 | 8 | func (e IllegalInputError) Error() string { 9 | return "illegal input: " + e.error 10 | } 11 | 12 | // IndexOutOfBoundError is triggered when the observable cannot access to the specified index. 13 | type IndexOutOfBoundError struct { 14 | error string 15 | } 16 | 17 | func (e IndexOutOfBoundError) Error() string { 18 | return "index out of bound: " + e.error 19 | } 20 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/reactivex/rxgo/v2 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/cenkalti/backoff/v4 v4.1.1 7 | github.com/emirpasic/gods v1.12.0 8 | github.com/stretchr/testify v1.8.0 9 | github.com/teivah/onecontext v0.0.0-20200513185103-40f981bfd775 10 | go.uber.org/goleak v1.1.12 11 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c 12 | ) 13 | -------------------------------------------------------------------------------- /item.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | import ( 4 | "context" 5 | "reflect" 6 | "time" 7 | ) 8 | 9 | type ( 10 | // Item is a wrapper having either a value or an error. 11 | Item struct { 12 | V interface{} 13 | E error 14 | } 15 | 16 | // TimestampItem attach a timestamp to an item. 17 | TimestampItem struct { 18 | Timestamp time.Time 19 | V interface{} 20 | } 21 | 22 | // CloseChannelStrategy indicates a strategy on whether to close a channel. 23 | CloseChannelStrategy uint32 24 | ) 25 | 26 | const ( 27 | // LeaveChannelOpen indicates to leave the channel open after completion. 28 | LeaveChannelOpen CloseChannelStrategy = iota 29 | // CloseChannel indicates to close the channel open after completion. 30 | CloseChannel 31 | ) 32 | 33 | // Of creates an item from a value. 34 | func Of(i interface{}) Item { 35 | return Item{V: i} 36 | } 37 | 38 | // Error creates an item from an error. 39 | func Error(err error) Item { 40 | return Item{E: err} 41 | } 42 | 43 | // SendItems is an utility function that send a list of interface{} and indicate a strategy on whether to close 44 | // the channel once the function completes. 45 | func SendItems(ctx context.Context, ch chan<- Item, strategy CloseChannelStrategy, items ...interface{}) { 46 | if strategy == CloseChannel { 47 | defer close(ch) 48 | } 49 | send(ctx, ch, items...) 50 | } 51 | 52 | func send(ctx context.Context, ch chan<- Item, items ...interface{}) { 53 | for _, currentItem := range items { 54 | switch item := currentItem.(type) { 55 | default: 56 | rt := reflect.TypeOf(item) 57 | switch rt.Kind() { 58 | default: 59 | Of(item).SendContext(ctx, ch) 60 | case reflect.Chan: 61 | in := reflect.ValueOf(currentItem) 62 | for { 63 | v, ok := in.Recv() 64 | if !ok { 65 | return 66 | } 67 | currentItem := v.Interface() 68 | switch item := currentItem.(type) { 69 | default: 70 | Of(item).SendContext(ctx, ch) 71 | case error: 72 | Error(item).SendContext(ctx, ch) 73 | } 74 | } 75 | case reflect.Slice: 76 | s := reflect.ValueOf(currentItem) 77 | for i := 0; i < s.Len(); i++ { 78 | send(ctx, ch, s.Index(i).Interface()) 79 | } 80 | } 81 | case error: 82 | Error(item).SendContext(ctx, ch) 83 | } 84 | } 85 | } 86 | 87 | // Error checks if an item is an error. 88 | func (i Item) Error() bool { 89 | return i.E != nil 90 | } 91 | 92 | // SendBlocking sends an item and blocks until it is sent. 93 | func (i Item) SendBlocking(ch chan<- Item) { 94 | ch <- i 95 | } 96 | 97 | // SendContext sends an item and blocks until it is sent or a context canceled. 98 | // It returns a boolean to indicate whether the item was sent. 99 | func (i Item) SendContext(ctx context.Context, ch chan<- Item) bool { 100 | select { 101 | case <-ctx.Done(): // Context's done channel has the highest priority 102 | return false 103 | default: 104 | select { 105 | case <-ctx.Done(): 106 | return false 107 | case ch <- i: 108 | return true 109 | } 110 | } 111 | } 112 | 113 | // SendNonBlocking sends an item without blocking. 114 | // It returns a boolean to indicate whether the item was sent. 115 | func (i Item) SendNonBlocking(ch chan<- Item) bool { 116 | select { 117 | default: 118 | return false 119 | case ch <- i: 120 | return true 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /item_test.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | "go.uber.org/goleak" 9 | ) 10 | 11 | func Test_SendItems_Variadic(t *testing.T) { 12 | defer goleak.VerifyNone(t) 13 | ch := make(chan Item, 3) 14 | go SendItems(context.Background(), ch, CloseChannel, 1, 2, 3) 15 | Assert(context.Background(), t, FromChannel(ch), HasItems(1, 2, 3), HasNoError()) 16 | } 17 | 18 | func Test_SendItems_VariadicWithError(t *testing.T) { 19 | defer goleak.VerifyNone(t) 20 | ch := make(chan Item, 3) 21 | go SendItems(context.Background(), ch, CloseChannel, 1, errFoo, 3) 22 | Assert(context.Background(), t, FromChannel(ch), HasItems(1, 3), HasError(errFoo)) 23 | } 24 | 25 | func Test_SendItems_Slice(t *testing.T) { 26 | defer goleak.VerifyNone(t) 27 | ch := make(chan Item, 3) 28 | go SendItems(context.Background(), ch, CloseChannel, []int{1, 2, 3}) 29 | Assert(context.Background(), t, FromChannel(ch), HasItems(1, 2, 3), HasNoError()) 30 | } 31 | 32 | func Test_SendItems_SliceWithError(t *testing.T) { 33 | defer goleak.VerifyNone(t) 34 | ch := make(chan Item, 3) 35 | go SendItems(context.Background(), ch, CloseChannel, []interface{}{1, errFoo, 3}) 36 | Assert(context.Background(), t, FromChannel(ch), HasItems(1, 3), HasError(errFoo)) 37 | } 38 | 39 | func Test_Item_SendBlocking(t *testing.T) { 40 | defer goleak.VerifyNone(t) 41 | ch := make(chan Item, 1) 42 | defer close(ch) 43 | Of(5).SendBlocking(ch) 44 | assert.Equal(t, 5, (<-ch).V) 45 | } 46 | 47 | func Test_Item_SendContext_True(t *testing.T) { 48 | defer goleak.VerifyNone(t) 49 | ch := make(chan Item, 1) 50 | defer close(ch) 51 | ctx, cancel := context.WithCancel(context.Background()) 52 | defer cancel() 53 | assert.True(t, Of(5).SendContext(ctx, ch)) 54 | } 55 | 56 | func Test_Item_SendContext_False(t *testing.T) { 57 | defer goleak.VerifyNone(t) 58 | ch := make(chan Item, 1) 59 | defer close(ch) 60 | ctx, cancel := context.WithCancel(context.Background()) 61 | cancel() 62 | assert.False(t, Of(5).SendContext(ctx, ch)) 63 | } 64 | 65 | func Test_Item_SendNonBlocking(t *testing.T) { 66 | defer goleak.VerifyNone(t) 67 | ch := make(chan Item, 1) 68 | defer close(ch) 69 | assert.True(t, Of(5).SendNonBlocking(ch)) 70 | assert.False(t, Of(5).SendNonBlocking(ch)) 71 | } 72 | -------------------------------------------------------------------------------- /iterable.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | // Iterable is the basic type that can be observed. 4 | type Iterable interface { 5 | Observe(opts ...Option) <-chan Item 6 | } 7 | -------------------------------------------------------------------------------- /iterable_channel.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | import ( 4 | "context" 5 | "sync" 6 | ) 7 | 8 | type channelIterable struct { 9 | next <-chan Item 10 | opts []Option 11 | subscribers []chan Item 12 | mutex sync.RWMutex 13 | producerAlreadyCreated bool 14 | } 15 | 16 | func newChannelIterable(next <-chan Item, opts ...Option) Iterable { 17 | return &channelIterable{ 18 | next: next, 19 | subscribers: make([]chan Item, 0), 20 | opts: opts, 21 | } 22 | } 23 | 24 | func (i *channelIterable) Observe(opts ...Option) <-chan Item { 25 | mergedOptions := append(i.opts, opts...) 26 | option := parseOptions(mergedOptions...) 27 | 28 | if !option.isConnectable() { 29 | return i.next 30 | } 31 | 32 | if option.isConnectOperation() { 33 | i.connect(option.buildContext(emptyContext)) 34 | return nil 35 | } 36 | 37 | ch := option.buildChannel() 38 | i.mutex.Lock() 39 | i.subscribers = append(i.subscribers, ch) 40 | i.mutex.Unlock() 41 | return ch 42 | } 43 | 44 | func (i *channelIterable) connect(ctx context.Context) { 45 | i.mutex.Lock() 46 | if !i.producerAlreadyCreated { 47 | go i.produce(ctx) 48 | i.producerAlreadyCreated = true 49 | } 50 | i.mutex.Unlock() 51 | } 52 | 53 | func (i *channelIterable) produce(ctx context.Context) { 54 | defer func() { 55 | i.mutex.RLock() 56 | for _, subscriber := range i.subscribers { 57 | close(subscriber) 58 | } 59 | i.mutex.RUnlock() 60 | }() 61 | 62 | for { 63 | select { 64 | case <-ctx.Done(): 65 | return 66 | case item, ok := <-i.next: 67 | if !ok { 68 | return 69 | } 70 | i.mutex.RLock() 71 | for _, subscriber := range i.subscribers { 72 | subscriber <- item 73 | } 74 | i.mutex.RUnlock() 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /iterable_create.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | import ( 4 | "context" 5 | "sync" 6 | ) 7 | 8 | type createIterable struct { 9 | next <-chan Item 10 | opts []Option 11 | subscribers []chan Item 12 | mutex sync.RWMutex 13 | producerAlreadyCreated bool 14 | } 15 | 16 | func newCreateIterable(fs []Producer, opts ...Option) Iterable { 17 | option := parseOptions(opts...) 18 | next := option.buildChannel() 19 | ctx := option.buildContext(emptyContext) 20 | 21 | go func() { 22 | defer close(next) 23 | for _, f := range fs { 24 | f(ctx, next) 25 | } 26 | }() 27 | 28 | return &createIterable{ 29 | opts: opts, 30 | next: next, 31 | } 32 | } 33 | 34 | func (i *createIterable) Observe(opts ...Option) <-chan Item { 35 | mergedOptions := append(i.opts, opts...) 36 | option := parseOptions(mergedOptions...) 37 | 38 | if !option.isConnectable() { 39 | return i.next 40 | } 41 | 42 | if option.isConnectOperation() { 43 | i.connect(option.buildContext(emptyContext)) 44 | return nil 45 | } 46 | 47 | ch := option.buildChannel() 48 | i.mutex.Lock() 49 | i.subscribers = append(i.subscribers, ch) 50 | i.mutex.Unlock() 51 | return ch 52 | } 53 | 54 | func (i *createIterable) connect(ctx context.Context) { 55 | i.mutex.Lock() 56 | if !i.producerAlreadyCreated { 57 | go i.produce(ctx) 58 | i.producerAlreadyCreated = true 59 | } 60 | i.mutex.Unlock() 61 | } 62 | 63 | func (i *createIterable) produce(ctx context.Context) { 64 | defer func() { 65 | i.mutex.RLock() 66 | for _, subscriber := range i.subscribers { 67 | close(subscriber) 68 | } 69 | i.mutex.RUnlock() 70 | }() 71 | 72 | for { 73 | select { 74 | case <-ctx.Done(): 75 | return 76 | case item, ok := <-i.next: 77 | if !ok { 78 | return 79 | } 80 | i.mutex.RLock() 81 | for _, subscriber := range i.subscribers { 82 | subscriber <- item 83 | } 84 | i.mutex.RUnlock() 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /iterable_defer.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | type deferIterable struct { 4 | fs []Producer 5 | opts []Option 6 | } 7 | 8 | func newDeferIterable(f []Producer, opts ...Option) Iterable { 9 | return &deferIterable{ 10 | fs: f, 11 | opts: opts, 12 | } 13 | } 14 | 15 | func (i *deferIterable) Observe(opts ...Option) <-chan Item { 16 | option := parseOptions(append(i.opts, opts...)...) 17 | next := option.buildChannel() 18 | ctx := option.buildContext(emptyContext) 19 | 20 | go func() { 21 | defer close(next) 22 | for _, f := range i.fs { 23 | f(ctx, next) 24 | } 25 | }() 26 | 27 | return next 28 | } 29 | -------------------------------------------------------------------------------- /iterable_eventsource.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | import ( 4 | "context" 5 | "sync" 6 | ) 7 | 8 | type eventSourceIterable struct { 9 | sync.RWMutex 10 | observers []chan Item 11 | disposed bool 12 | opts []Option 13 | } 14 | 15 | func newEventSourceIterable(ctx context.Context, next <-chan Item, strategy BackpressureStrategy, opts ...Option) Iterable { 16 | it := &eventSourceIterable{ 17 | observers: make([]chan Item, 0), 18 | opts: opts, 19 | } 20 | 21 | go func() { 22 | defer func() { 23 | it.closeAllObservers() 24 | }() 25 | 26 | deliver := func(item Item) (done bool) { 27 | it.RLock() 28 | defer it.RUnlock() 29 | 30 | switch strategy { 31 | default: 32 | fallthrough 33 | case Block: 34 | for _, observer := range it.observers { 35 | if !item.SendContext(ctx, observer) { 36 | return true 37 | } 38 | } 39 | case Drop: 40 | for _, observer := range it.observers { 41 | select { 42 | default: 43 | case <-ctx.Done(): 44 | return true 45 | case observer <- item: 46 | } 47 | } 48 | } 49 | return 50 | } 51 | 52 | for { 53 | select { 54 | case <-ctx.Done(): 55 | return 56 | case item, ok := <-next: 57 | if !ok { 58 | return 59 | } 60 | 61 | if done := deliver(item); done { 62 | return 63 | } 64 | } 65 | } 66 | }() 67 | 68 | return it 69 | } 70 | 71 | func (i *eventSourceIterable) closeAllObservers() { 72 | i.Lock() 73 | for _, observer := range i.observers { 74 | close(observer) 75 | } 76 | i.disposed = true 77 | i.Unlock() 78 | } 79 | 80 | func (i *eventSourceIterable) Observe(opts ...Option) <-chan Item { 81 | option := parseOptions(append(i.opts, opts...)...) 82 | next := option.buildChannel() 83 | 84 | i.Lock() 85 | if i.disposed { 86 | close(next) 87 | } else { 88 | i.observers = append(i.observers, next) 89 | } 90 | i.Unlock() 91 | return next 92 | } 93 | -------------------------------------------------------------------------------- /iterable_factory.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | type factoryIterable struct { 4 | factory func(opts ...Option) <-chan Item 5 | } 6 | 7 | func newFactoryIterable(factory func(opts ...Option) <-chan Item) Iterable { 8 | return &factoryIterable{factory: factory} 9 | } 10 | 11 | func (i *factoryIterable) Observe(opts ...Option) <-chan Item { 12 | return i.factory(opts...) 13 | } 14 | -------------------------------------------------------------------------------- /iterable_just.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | type justIterable struct { 4 | items []interface{} 5 | opts []Option 6 | } 7 | 8 | func newJustIterable(items ...interface{}) func(opts ...Option) Iterable { 9 | return func(opts ...Option) Iterable { 10 | return &justIterable{ 11 | items: items, 12 | opts: opts, 13 | } 14 | } 15 | } 16 | 17 | func (i *justIterable) Observe(opts ...Option) <-chan Item { 18 | option := parseOptions(append(i.opts, opts...)...) 19 | next := option.buildChannel() 20 | 21 | go SendItems(option.buildContext(emptyContext), next, CloseChannel, i.items) 22 | return next 23 | } 24 | -------------------------------------------------------------------------------- /iterable_range.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | type rangeIterable struct { 4 | start, count int 5 | opts []Option 6 | } 7 | 8 | func newRangeIterable(start, count int, opts ...Option) Iterable { 9 | return &rangeIterable{ 10 | start: start, 11 | count: count, 12 | opts: opts, 13 | } 14 | } 15 | 16 | func (i *rangeIterable) Observe(opts ...Option) <-chan Item { 17 | option := parseOptions(append(i.opts, opts...)...) 18 | ctx := option.buildContext(emptyContext) 19 | next := option.buildChannel() 20 | 21 | go func() { 22 | for idx := i.start; idx <= i.start+i.count-1; idx++ { 23 | select { 24 | case <-ctx.Done(): 25 | return 26 | case next <- Of(idx): 27 | } 28 | } 29 | close(next) 30 | }() 31 | return next 32 | } 33 | -------------------------------------------------------------------------------- /iterable_slice.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | type sliceIterable struct { 4 | items []Item 5 | opts []Option 6 | } 7 | 8 | func newSliceIterable(items []Item, opts ...Option) Iterable { 9 | return &sliceIterable{ 10 | items: items, 11 | opts: opts, 12 | } 13 | } 14 | 15 | func (i *sliceIterable) Observe(opts ...Option) <-chan Item { 16 | option := parseOptions(append(i.opts, opts...)...) 17 | next := option.buildChannel() 18 | ctx := option.buildContext(emptyContext) 19 | 20 | go func() { 21 | for _, item := range i.items { 22 | select { 23 | case <-ctx.Done(): 24 | return 25 | case next <- item: 26 | } 27 | } 28 | close(next) 29 | }() 30 | return next 31 | } 32 | -------------------------------------------------------------------------------- /optionalsingle.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | import "context" 4 | 5 | // OptionalSingleEmpty is the constant returned when an OptionalSingle is empty. 6 | var OptionalSingleEmpty = Item{} 7 | 8 | // OptionalSingle is an optional single. 9 | type OptionalSingle interface { 10 | Iterable 11 | Get(opts ...Option) (Item, error) 12 | Map(apply Func, opts ...Option) OptionalSingle 13 | Run(opts ...Option) Disposed 14 | } 15 | 16 | // OptionalSingleImpl implements OptionalSingle. 17 | type OptionalSingleImpl struct { 18 | parent context.Context 19 | iterable Iterable 20 | } 21 | 22 | // Get returns the item or rxgo.OptionalEmpty. The error returned is if the context has been cancelled. 23 | // This method is blocking. 24 | func (o *OptionalSingleImpl) Get(opts ...Option) (Item, error) { 25 | option := parseOptions(opts...) 26 | ctx := option.buildContext(o.parent) 27 | 28 | observe := o.Observe(opts...) 29 | for { 30 | select { 31 | case <-ctx.Done(): 32 | return Item{}, ctx.Err() 33 | case v, ok := <-observe: 34 | if !ok { 35 | return OptionalSingleEmpty, nil 36 | } 37 | return v, nil 38 | } 39 | } 40 | } 41 | 42 | // Map transforms the items emitted by an OptionalSingle by applying a function to each item. 43 | func (o *OptionalSingleImpl) Map(apply Func, opts ...Option) OptionalSingle { 44 | return optionalSingle(o.parent, o, func() operator { 45 | return &mapOperatorOptionalSingle{apply: apply} 46 | }, false, true, opts...) 47 | } 48 | 49 | // Observe observes an OptionalSingle by returning its channel. 50 | func (o *OptionalSingleImpl) Observe(opts ...Option) <-chan Item { 51 | return o.iterable.Observe(opts...) 52 | } 53 | 54 | type mapOperatorOptionalSingle struct { 55 | apply Func 56 | } 57 | 58 | func (op *mapOperatorOptionalSingle) next(ctx context.Context, item Item, dst chan<- Item, operatorOptions operatorOptions) { 59 | res, err := op.apply(ctx, item.V) 60 | if err != nil { 61 | dst <- Error(err) 62 | operatorOptions.stop() 63 | return 64 | } 65 | dst <- Of(res) 66 | } 67 | 68 | func (op *mapOperatorOptionalSingle) err(ctx context.Context, item Item, dst chan<- Item, operatorOptions operatorOptions) { 69 | defaultErrorFuncOperator(ctx, item, dst, operatorOptions) 70 | } 71 | 72 | func (op *mapOperatorOptionalSingle) end(_ context.Context, _ chan<- Item) { 73 | } 74 | 75 | func (op *mapOperatorOptionalSingle) gatherNext(_ context.Context, item Item, dst chan<- Item, _ operatorOptions) { 76 | switch item.V.(type) { 77 | case *mapOperatorOptionalSingle: 78 | return 79 | } 80 | dst <- item 81 | } 82 | 83 | // Run creates an observer without consuming the emitted items. 84 | func (o *OptionalSingleImpl) Run(opts ...Option) Disposed { 85 | dispose := make(chan struct{}) 86 | option := parseOptions(opts...) 87 | ctx := option.buildContext(o.parent) 88 | 89 | go func() { 90 | defer close(dispose) 91 | observe := o.Observe(opts...) 92 | for { 93 | select { 94 | case <-ctx.Done(): 95 | return 96 | case _, ok := <-observe: 97 | if !ok { 98 | return 99 | } 100 | } 101 | } 102 | }() 103 | 104 | return dispose 105 | } 106 | -------------------------------------------------------------------------------- /optionalsingle_test.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | "go.uber.org/goleak" 9 | ) 10 | 11 | func Test_OptionalSingle_Get_Item(t *testing.T) { 12 | defer goleak.VerifyNone(t) 13 | var os OptionalSingle = &OptionalSingleImpl{iterable: Just(1)()} 14 | get, err := os.Get() 15 | assert.NoError(t, err) 16 | assert.Equal(t, 1, get.V) 17 | } 18 | 19 | func Test_OptionalSingle_Get_Empty(t *testing.T) { 20 | defer goleak.VerifyNone(t) 21 | var os OptionalSingle = &OptionalSingleImpl{iterable: Empty()} 22 | get, err := os.Get() 23 | assert.NoError(t, err) 24 | assert.Equal(t, OptionalSingleEmpty, get) 25 | } 26 | 27 | func Test_OptionalSingle_Get_Error(t *testing.T) { 28 | defer goleak.VerifyNone(t) 29 | var os OptionalSingle = &OptionalSingleImpl{iterable: Just(errFoo)()} 30 | get, err := os.Get() 31 | assert.NoError(t, err) 32 | assert.Equal(t, errFoo, get.E) 33 | } 34 | 35 | func Test_OptionalSingle_Get_ContextCanceled(t *testing.T) { 36 | defer goleak.VerifyNone(t) 37 | ctx, cancel := context.WithCancel(context.Background()) 38 | var os OptionalSingle = &OptionalSingleImpl{iterable: Never()} 39 | cancel() 40 | _, err := os.Get(WithContext(ctx)) 41 | assert.Equal(t, ctx.Err(), err) 42 | } 43 | 44 | func Test_OptionalSingle_Map(t *testing.T) { 45 | defer goleak.VerifyNone(t) 46 | single := Just(1)().Max(func(_, _ interface{}) int { 47 | return 1 48 | }).Map(func(_ context.Context, i interface{}) (interface{}, error) { 49 | return i.(int) + 1, nil 50 | }) 51 | Assert(context.Background(), t, single, HasItem(2), HasNoError()) 52 | } 53 | 54 | func Test_OptionalSingle_Observe(t *testing.T) { 55 | defer goleak.VerifyNone(t) 56 | os := JustItem(1).Filter(func(i interface{}) bool { 57 | return i == 1 58 | }) 59 | Assert(context.Background(), t, os, HasItem(1), HasNoError()) 60 | } 61 | -------------------------------------------------------------------------------- /single_test.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | "go.uber.org/goleak" 9 | ) 10 | 11 | func Test_Single_Get_Item(t *testing.T) { 12 | defer goleak.VerifyNone(t) 13 | var s Single = &SingleImpl{iterable: Just(1)()} 14 | get, err := s.Get() 15 | assert.NoError(t, err) 16 | assert.Equal(t, 1, get.V) 17 | } 18 | 19 | func Test_Single_Get_Error(t *testing.T) { 20 | defer goleak.VerifyNone(t) 21 | var s Single = &SingleImpl{iterable: Just(errFoo)()} 22 | get, err := s.Get() 23 | assert.NoError(t, err) 24 | assert.Equal(t, errFoo, get.E) 25 | } 26 | 27 | func Test_Single_Get_ContextCanceled(t *testing.T) { 28 | defer goleak.VerifyNone(t) 29 | ch := make(chan Item) 30 | defer close(ch) 31 | ctx, cancel := context.WithCancel(context.Background()) 32 | var s Single = &SingleImpl{iterable: FromChannel(ch)} 33 | cancel() 34 | _, err := s.Get(WithContext(ctx)) 35 | assert.Equal(t, ctx.Err(), err) 36 | } 37 | 38 | func Test_Single_Filter_True(t *testing.T) { 39 | defer goleak.VerifyNone(t) 40 | os := JustItem(1).Filter(func(i interface{}) bool { 41 | return i == 1 42 | }) 43 | Assert(context.Background(), t, os, HasItem(1), HasNoError()) 44 | } 45 | 46 | func Test_Single_Filter_False(t *testing.T) { 47 | defer goleak.VerifyNone(t) 48 | os := JustItem(1).Filter(func(i interface{}) bool { 49 | return i == 0 50 | }) 51 | Assert(context.Background(), t, os, IsEmpty(), HasNoError()) 52 | } 53 | 54 | func Test_Single_Map(t *testing.T) { 55 | defer goleak.VerifyNone(t) 56 | single := JustItem(1).Map(func(_ context.Context, i interface{}) (interface{}, error) { 57 | return i.(int) + 1, nil 58 | }) 59 | Assert(context.Background(), t, single, HasItem(2), HasNoError()) 60 | } 61 | -------------------------------------------------------------------------------- /types.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | import "context" 4 | 5 | type ( 6 | operatorOptions struct { 7 | stop func() 8 | resetIterable func(Iterable) 9 | } 10 | 11 | // Comparator defines a func that returns an int: 12 | // - 0 if two elements are equals 13 | // - A negative value if the first argument is less than the second 14 | // - A positive value if the first argument is greater than the second 15 | Comparator func(interface{}, interface{}) int 16 | // ItemToObservable defines a function that computes an observable from an item. 17 | ItemToObservable func(Item) Observable 18 | // ErrorToObservable defines a function that transforms an observable from an error. 19 | ErrorToObservable func(error) Observable 20 | // Func defines a function that computes a value from an input value. 21 | Func func(context.Context, interface{}) (interface{}, error) 22 | // Func2 defines a function that computes a value from two input values. 23 | Func2 func(context.Context, interface{}, interface{}) (interface{}, error) 24 | // FuncN defines a function that computes a value from N input values. 25 | FuncN func(...interface{}) interface{} 26 | // ErrorFunc defines a function that computes a value from an error. 27 | ErrorFunc func(error) interface{} 28 | // Predicate defines a func that returns a bool from an input value. 29 | Predicate func(interface{}) bool 30 | // Marshaller defines a marshaller type (interface{} to []byte). 31 | Marshaller func(interface{}) ([]byte, error) 32 | // Unmarshaller defines an unmarshaller type ([]byte to interface). 33 | Unmarshaller func([]byte, interface{}) error 34 | // Producer defines a producer implementation. 35 | Producer func(ctx context.Context, next chan<- Item) 36 | // Supplier defines a function that supplies a result from nothing. 37 | Supplier func(ctx context.Context) Item 38 | // Disposed is a notification channel indicating when an Observable is closed. 39 | Disposed <-chan struct{} 40 | // Disposable is a function to be called in order to dispose a subscription. 41 | Disposable context.CancelFunc 42 | 43 | // NextFunc handles a next item in a stream. 44 | NextFunc func(interface{}) 45 | // ErrFunc handles an error in a stream. 46 | ErrFunc func(error) 47 | // CompletedFunc handles the end of a stream. 48 | CompletedFunc func() 49 | ) 50 | 51 | // BackpressureStrategy is the backpressure strategy type. 52 | type BackpressureStrategy uint32 53 | 54 | const ( 55 | // Block blocks until the channel is available. 56 | Block BackpressureStrategy = iota 57 | // Drop drops the message. 58 | Drop 59 | ) 60 | 61 | // OnErrorStrategy is the Observable error strategy. 62 | type OnErrorStrategy uint32 63 | 64 | const ( 65 | // StopOnError is the default error strategy. 66 | // An operator will stop processing items on error. 67 | StopOnError OnErrorStrategy = iota 68 | // ContinueOnError means an operator will continue processing items after an error. 69 | ContinueOnError 70 | ) 71 | 72 | // ObservationStrategy defines the strategy to consume from an Observable. 73 | type ObservationStrategy uint32 74 | 75 | const ( 76 | // Lazy is the default observation strategy, when an Observer subscribes. 77 | Lazy ObservationStrategy = iota 78 | // Eager means consuming as soon as the Observable is created. 79 | Eager 80 | ) 81 | -------------------------------------------------------------------------------- /util_test.go: -------------------------------------------------------------------------------- 1 | package rxgo 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | ) 7 | 8 | type testStruct struct { 9 | ID int `json:"id"` 10 | } 11 | 12 | var ( 13 | errFoo = errors.New("foo") 14 | errBar = errors.New("bar") 15 | ) 16 | 17 | func channelValue(ctx context.Context, items ...interface{}) chan Item { 18 | next := make(chan Item) 19 | go func() { 20 | for _, item := range items { 21 | switch item := item.(type) { 22 | default: 23 | Of(item).SendContext(ctx, next) 24 | case error: 25 | Error(item).SendContext(ctx, next) 26 | } 27 | } 28 | close(next) 29 | }() 30 | return next 31 | } 32 | 33 | func testObservable(ctx context.Context, items ...interface{}) Observable { 34 | return FromChannel(channelValue(ctx, items...)) 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/cenkalti/backoff/v4/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | 24 | # IDEs 25 | .idea/ 26 | -------------------------------------------------------------------------------- /vendor/github.com/cenkalti/backoff/v4/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.13 4 | - 1.x 5 | - tip 6 | before_install: 7 | - go get github.com/mattn/goveralls 8 | - go get golang.org/x/tools/cmd/cover 9 | script: 10 | - $HOME/gopath/bin/goveralls -service=travis-ci 11 | -------------------------------------------------------------------------------- /vendor/github.com/cenkalti/backoff/v4/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Cenk Altı 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/github.com/cenkalti/backoff/v4/README.md: -------------------------------------------------------------------------------- 1 | # Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls] 2 | 3 | This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client]. 4 | 5 | [Exponential backoff][exponential backoff wiki] 6 | is an algorithm that uses feedback to multiplicatively decrease the rate of some process, 7 | in order to gradually find an acceptable rate. 8 | The retries exponentially increase and stop increasing when a certain threshold is met. 9 | 10 | ## Usage 11 | 12 | Import path is `github.com/cenkalti/backoff/v4`. Please note the version part at the end. 13 | 14 | Use https://pkg.go.dev/github.com/cenkalti/backoff/v4 to view the documentation. 15 | 16 | ## Contributing 17 | 18 | * I would like to keep this library as small as possible. 19 | * Please don't send a PR without opening an issue and discussing it first. 20 | * If proposed change is not a common use case, I will probably not accept it. 21 | 22 | [godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v4 23 | [godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png 24 | [travis]: https://travis-ci.org/cenkalti/backoff 25 | [travis image]: https://travis-ci.org/cenkalti/backoff.png?branch=master 26 | [coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master 27 | [coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master 28 | 29 | [google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java 30 | [exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff 31 | 32 | [advanced example]: https://pkg.go.dev/github.com/cenkalti/backoff/v4?tab=doc#pkg-examples 33 | -------------------------------------------------------------------------------- /vendor/github.com/cenkalti/backoff/v4/backoff.go: -------------------------------------------------------------------------------- 1 | // Package backoff implements backoff algorithms for retrying operations. 2 | // 3 | // Use Retry function for retrying operations that may fail. 4 | // If Retry does not meet your needs, 5 | // copy/paste the function into your project and modify as you wish. 6 | // 7 | // There is also Ticker type similar to time.Ticker. 8 | // You can use it if you need to work with channels. 9 | // 10 | // See Examples section below for usage examples. 11 | package backoff 12 | 13 | import "time" 14 | 15 | // BackOff is a backoff policy for retrying an operation. 16 | type BackOff interface { 17 | // NextBackOff returns the duration to wait before retrying the operation, 18 | // or backoff. Stop to indicate that no more retries should be made. 19 | // 20 | // Example usage: 21 | // 22 | // duration := backoff.NextBackOff(); 23 | // if (duration == backoff.Stop) { 24 | // // Do not retry operation. 25 | // } else { 26 | // // Sleep for duration and retry operation. 27 | // } 28 | // 29 | NextBackOff() time.Duration 30 | 31 | // Reset to initial state. 32 | Reset() 33 | } 34 | 35 | // Stop indicates that no more retries should be made for use in NextBackOff(). 36 | const Stop time.Duration = -1 37 | 38 | // ZeroBackOff is a fixed backoff policy whose backoff time is always zero, 39 | // meaning that the operation is retried immediately without waiting, indefinitely. 40 | type ZeroBackOff struct{} 41 | 42 | func (b *ZeroBackOff) Reset() {} 43 | 44 | func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 } 45 | 46 | // StopBackOff is a fixed backoff policy that always returns backoff.Stop for 47 | // NextBackOff(), meaning that the operation should never be retried. 48 | type StopBackOff struct{} 49 | 50 | func (b *StopBackOff) Reset() {} 51 | 52 | func (b *StopBackOff) NextBackOff() time.Duration { return Stop } 53 | 54 | // ConstantBackOff is a backoff policy that always returns the same backoff delay. 55 | // This is in contrast to an exponential backoff policy, 56 | // which returns a delay that grows longer as you call NextBackOff() over and over again. 57 | type ConstantBackOff struct { 58 | Interval time.Duration 59 | } 60 | 61 | func (b *ConstantBackOff) Reset() {} 62 | func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval } 63 | 64 | func NewConstantBackOff(d time.Duration) *ConstantBackOff { 65 | return &ConstantBackOff{Interval: d} 66 | } 67 | -------------------------------------------------------------------------------- /vendor/github.com/cenkalti/backoff/v4/context.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import ( 4 | "context" 5 | "time" 6 | ) 7 | 8 | // BackOffContext is a backoff policy that stops retrying after the context 9 | // is canceled. 10 | type BackOffContext interface { // nolint: golint 11 | BackOff 12 | Context() context.Context 13 | } 14 | 15 | type backOffContext struct { 16 | BackOff 17 | ctx context.Context 18 | } 19 | 20 | // WithContext returns a BackOffContext with context ctx 21 | // 22 | // ctx must not be nil 23 | func WithContext(b BackOff, ctx context.Context) BackOffContext { // nolint: golint 24 | if ctx == nil { 25 | panic("nil context") 26 | } 27 | 28 | if b, ok := b.(*backOffContext); ok { 29 | return &backOffContext{ 30 | BackOff: b.BackOff, 31 | ctx: ctx, 32 | } 33 | } 34 | 35 | return &backOffContext{ 36 | BackOff: b, 37 | ctx: ctx, 38 | } 39 | } 40 | 41 | func getContext(b BackOff) context.Context { 42 | if cb, ok := b.(BackOffContext); ok { 43 | return cb.Context() 44 | } 45 | if tb, ok := b.(*backOffTries); ok { 46 | return getContext(tb.delegate) 47 | } 48 | return context.Background() 49 | } 50 | 51 | func (b *backOffContext) Context() context.Context { 52 | return b.ctx 53 | } 54 | 55 | func (b *backOffContext) NextBackOff() time.Duration { 56 | select { 57 | case <-b.ctx.Done(): 58 | return Stop 59 | default: 60 | return b.BackOff.NextBackOff() 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /vendor/github.com/cenkalti/backoff/v4/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/cenkalti/backoff/v4 2 | 3 | go 1.13 4 | -------------------------------------------------------------------------------- /vendor/github.com/cenkalti/backoff/v4/retry.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import ( 4 | "errors" 5 | "time" 6 | ) 7 | 8 | // An Operation is executing by Retry() or RetryNotify(). 9 | // The operation will be retried using a backoff policy if it returns an error. 10 | type Operation func() error 11 | 12 | // Notify is a notify-on-error function. It receives an operation error and 13 | // backoff delay if the operation failed (with an error). 14 | // 15 | // NOTE that if the backoff policy stated to stop retrying, 16 | // the notify function isn't called. 17 | type Notify func(error, time.Duration) 18 | 19 | // Retry the operation o until it does not return error or BackOff stops. 20 | // o is guaranteed to be run at least once. 21 | // 22 | // If o returns a *PermanentError, the operation is not retried, and the 23 | // wrapped error is returned. 24 | // 25 | // Retry sleeps the goroutine for the duration returned by BackOff after a 26 | // failed operation returns. 27 | func Retry(o Operation, b BackOff) error { 28 | return RetryNotify(o, b, nil) 29 | } 30 | 31 | // RetryNotify calls notify function with the error and wait duration 32 | // for each failed attempt before sleep. 33 | func RetryNotify(operation Operation, b BackOff, notify Notify) error { 34 | return RetryNotifyWithTimer(operation, b, notify, nil) 35 | } 36 | 37 | // RetryNotifyWithTimer calls notify function with the error and wait duration using the given Timer 38 | // for each failed attempt before sleep. 39 | // A default timer that uses system timer is used when nil is passed. 40 | func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer) error { 41 | var err error 42 | var next time.Duration 43 | if t == nil { 44 | t = &defaultTimer{} 45 | } 46 | 47 | defer func() { 48 | t.Stop() 49 | }() 50 | 51 | ctx := getContext(b) 52 | 53 | b.Reset() 54 | for { 55 | if err = operation(); err == nil { 56 | return nil 57 | } 58 | 59 | var permanent *PermanentError 60 | if errors.As(err, &permanent) { 61 | return permanent.Err 62 | } 63 | 64 | if next = b.NextBackOff(); next == Stop { 65 | if cerr := ctx.Err(); cerr != nil { 66 | return cerr 67 | } 68 | 69 | return err 70 | } 71 | 72 | if notify != nil { 73 | notify(err, next) 74 | } 75 | 76 | t.Start(next) 77 | 78 | select { 79 | case <-ctx.Done(): 80 | return ctx.Err() 81 | case <-t.C(): 82 | } 83 | } 84 | } 85 | 86 | // PermanentError signals that the operation should not be retried. 87 | type PermanentError struct { 88 | Err error 89 | } 90 | 91 | func (e *PermanentError) Error() string { 92 | return e.Err.Error() 93 | } 94 | 95 | func (e *PermanentError) Unwrap() error { 96 | return e.Err 97 | } 98 | 99 | func (e *PermanentError) Is(target error) bool { 100 | _, ok := target.(*PermanentError) 101 | return ok 102 | } 103 | 104 | // Permanent wraps the given err in a *PermanentError. 105 | func Permanent(err error) error { 106 | if err == nil { 107 | return nil 108 | } 109 | return &PermanentError{ 110 | Err: err, 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /vendor/github.com/cenkalti/backoff/v4/ticker.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import ( 4 | "context" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | // Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff. 10 | // 11 | // Ticks will continue to arrive when the previous operation is still running, 12 | // so operations that take a while to fail could run in quick succession. 13 | type Ticker struct { 14 | C <-chan time.Time 15 | c chan time.Time 16 | b BackOff 17 | ctx context.Context 18 | timer Timer 19 | stop chan struct{} 20 | stopOnce sync.Once 21 | } 22 | 23 | // NewTicker returns a new Ticker containing a channel that will send 24 | // the time at times specified by the BackOff argument. Ticker is 25 | // guaranteed to tick at least once. The channel is closed when Stop 26 | // method is called or BackOff stops. It is not safe to manipulate the 27 | // provided backoff policy (notably calling NextBackOff or Reset) 28 | // while the ticker is running. 29 | func NewTicker(b BackOff) *Ticker { 30 | return NewTickerWithTimer(b, &defaultTimer{}) 31 | } 32 | 33 | // NewTickerWithTimer returns a new Ticker with a custom timer. 34 | // A default timer that uses system timer is used when nil is passed. 35 | func NewTickerWithTimer(b BackOff, timer Timer) *Ticker { 36 | if timer == nil { 37 | timer = &defaultTimer{} 38 | } 39 | c := make(chan time.Time) 40 | t := &Ticker{ 41 | C: c, 42 | c: c, 43 | b: b, 44 | ctx: getContext(b), 45 | timer: timer, 46 | stop: make(chan struct{}), 47 | } 48 | t.b.Reset() 49 | go t.run() 50 | return t 51 | } 52 | 53 | // Stop turns off a ticker. After Stop, no more ticks will be sent. 54 | func (t *Ticker) Stop() { 55 | t.stopOnce.Do(func() { close(t.stop) }) 56 | } 57 | 58 | func (t *Ticker) run() { 59 | c := t.c 60 | defer close(c) 61 | 62 | // Ticker is guaranteed to tick at least once. 63 | afterC := t.send(time.Now()) 64 | 65 | for { 66 | if afterC == nil { 67 | return 68 | } 69 | 70 | select { 71 | case tick := <-afterC: 72 | afterC = t.send(tick) 73 | case <-t.stop: 74 | t.c = nil // Prevent future ticks from being sent to the channel. 75 | return 76 | case <-t.ctx.Done(): 77 | return 78 | } 79 | } 80 | } 81 | 82 | func (t *Ticker) send(tick time.Time) <-chan time.Time { 83 | select { 84 | case t.c <- tick: 85 | case <-t.stop: 86 | return nil 87 | } 88 | 89 | next := t.b.NextBackOff() 90 | if next == Stop { 91 | t.Stop() 92 | return nil 93 | } 94 | 95 | t.timer.Start(next) 96 | return t.timer.C() 97 | } 98 | -------------------------------------------------------------------------------- /vendor/github.com/cenkalti/backoff/v4/timer.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import "time" 4 | 5 | type Timer interface { 6 | Start(duration time.Duration) 7 | Stop() 8 | C() <-chan time.Time 9 | } 10 | 11 | // defaultTimer implements Timer interface using time.Timer 12 | type defaultTimer struct { 13 | timer *time.Timer 14 | } 15 | 16 | // C returns the timers channel which receives the current time when the timer fires. 17 | func (t *defaultTimer) C() <-chan time.Time { 18 | return t.timer.C 19 | } 20 | 21 | // Start starts the timer to fire after the given duration 22 | func (t *defaultTimer) Start(duration time.Duration) { 23 | if t.timer == nil { 24 | t.timer = time.NewTimer(duration) 25 | } else { 26 | t.timer.Reset(duration) 27 | } 28 | } 29 | 30 | // Stop is called when the timer is not used anymore and resources may be freed. 31 | func (t *defaultTimer) Stop() { 32 | if t.timer != nil { 33 | t.timer.Stop() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/cenkalti/backoff/v4/tries.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import "time" 4 | 5 | /* 6 | WithMaxRetries creates a wrapper around another BackOff, which will 7 | return Stop if NextBackOff() has been called too many times since 8 | the last time Reset() was called 9 | 10 | Note: Implementation is not thread-safe. 11 | */ 12 | func WithMaxRetries(b BackOff, max uint64) BackOff { 13 | return &backOffTries{delegate: b, maxTries: max} 14 | } 15 | 16 | type backOffTries struct { 17 | delegate BackOff 18 | maxTries uint64 19 | numTries uint64 20 | } 21 | 22 | func (b *backOffTries) NextBackOff() time.Duration { 23 | if b.maxTries == 0 { 24 | return Stop 25 | } 26 | if b.maxTries > 0 { 27 | if b.maxTries <= b.numTries { 28 | return Stop 29 | } 30 | b.numTries++ 31 | } 32 | return b.delegate.NextBackOff() 33 | } 34 | 35 | func (b *backOffTries) Reset() { 36 | b.numTries = 0 37 | b.delegate.Reset() 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2012-2016 Dave Collins 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/bypasssafe.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2016 Dave Collins 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | // NOTE: Due to the following build constraints, this file will only be compiled 16 | // when the code is running on Google App Engine, compiled by GopherJS, or 17 | // "-tags safe" is added to the go build command line. The "disableunsafe" 18 | // tag is deprecated and thus should not be used. 19 | // +build js appengine safe disableunsafe !go1.4 20 | 21 | package spew 22 | 23 | import "reflect" 24 | 25 | const ( 26 | // UnsafeDisabled is a build-time constant which specifies whether or 27 | // not access to the unsafe package is available. 28 | UnsafeDisabled = true 29 | ) 30 | 31 | // unsafeReflectValue typically converts the passed reflect.Value into a one 32 | // that bypasses the typical safety restrictions preventing access to 33 | // unaddressable and unexported data. However, doing this relies on access to 34 | // the unsafe package. This is a stub version which simply returns the passed 35 | // reflect.Value when the unsafe package is not available. 36 | func unsafeReflectValue(v reflect.Value) reflect.Value { 37 | return v 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/emirpasic/gods/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Emir Pasic 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | ------------------------------------------------------------------------------- 26 | 27 | AVL Tree: 28 | 29 | Copyright (c) 2017 Benjamin Scher Purcell 30 | 31 | Permission to use, copy, modify, and distribute this software for any 32 | purpose with or without fee is hereby granted, provided that the above 33 | copyright notice and this permission notice appear in all copies. 34 | 35 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 36 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 37 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 38 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 39 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 40 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 41 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 42 | -------------------------------------------------------------------------------- /vendor/github.com/emirpasic/gods/containers/containers.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package containers provides core interfaces and functions for data structures. 6 | // 7 | // Container is the base interface for all data structures to implement. 8 | // 9 | // Iterators provide stateful iterators. 10 | // 11 | // Enumerable provides Ruby inspired (each, select, map, find, any?, etc.) container functions. 12 | // 13 | // Serialization provides serializers (marshalers) and deserializers (unmarshalers). 14 | package containers 15 | 16 | import "github.com/emirpasic/gods/utils" 17 | 18 | // Container is base interface that all data structures implement. 19 | type Container interface { 20 | Empty() bool 21 | Size() int 22 | Clear() 23 | Values() []interface{} 24 | } 25 | 26 | // GetSortedValues returns sorted container's elements with respect to the passed comparator. 27 | // Does not effect the ordering of elements within the container. 28 | func GetSortedValues(container Container, comparator utils.Comparator) []interface{} { 29 | values := container.Values() 30 | if len(values) < 2 { 31 | return values 32 | } 33 | utils.Sort(values, comparator) 34 | return values 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/emirpasic/gods/containers/enumerable.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package containers 6 | 7 | // EnumerableWithIndex provides functions for ordered containers whose values can be fetched by an index. 8 | type EnumerableWithIndex interface { 9 | // Each calls the given function once for each element, passing that element's index and value. 10 | Each(func(index int, value interface{})) 11 | 12 | // Map invokes the given function once for each element and returns a 13 | // container containing the values returned by the given function. 14 | // TODO would appreciate help on how to enforce this in containers (don't want to type assert when chaining) 15 | // Map(func(index int, value interface{}) interface{}) Container 16 | 17 | // Select returns a new container containing all elements for which the given function returns a true value. 18 | // TODO need help on how to enforce this in containers (don't want to type assert when chaining) 19 | // Select(func(index int, value interface{}) bool) Container 20 | 21 | // Any passes each element of the container to the given function and 22 | // returns true if the function ever returns true for any element. 23 | Any(func(index int, value interface{}) bool) bool 24 | 25 | // All passes each element of the container to the given function and 26 | // returns true if the function returns true for all elements. 27 | All(func(index int, value interface{}) bool) bool 28 | 29 | // Find passes each element of the container to the given function and returns 30 | // the first (index,value) for which the function is true or -1,nil otherwise 31 | // if no element matches the criteria. 32 | Find(func(index int, value interface{}) bool) (int, interface{}) 33 | } 34 | 35 | // EnumerableWithKey provides functions for ordered containers whose values whose elements are key/value pairs. 36 | type EnumerableWithKey interface { 37 | // Each calls the given function once for each element, passing that element's key and value. 38 | Each(func(key interface{}, value interface{})) 39 | 40 | // Map invokes the given function once for each element and returns a container 41 | // containing the values returned by the given function as key/value pairs. 42 | // TODO need help on how to enforce this in containers (don't want to type assert when chaining) 43 | // Map(func(key interface{}, value interface{}) (interface{}, interface{})) Container 44 | 45 | // Select returns a new container containing all elements for which the given function returns a true value. 46 | // TODO need help on how to enforce this in containers (don't want to type assert when chaining) 47 | // Select(func(key interface{}, value interface{}) bool) Container 48 | 49 | // Any passes each element of the container to the given function and 50 | // returns true if the function ever returns true for any element. 51 | Any(func(key interface{}, value interface{}) bool) bool 52 | 53 | // All passes each element of the container to the given function and 54 | // returns true if the function returns true for all elements. 55 | All(func(key interface{}, value interface{}) bool) bool 56 | 57 | // Find passes each element of the container to the given function and returns 58 | // the first (key,value) for which the function is true or nil,nil otherwise if no element 59 | // matches the criteria. 60 | Find(func(key interface{}, value interface{}) bool) (interface{}, interface{}) 61 | } 62 | -------------------------------------------------------------------------------- /vendor/github.com/emirpasic/gods/containers/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package containers 6 | 7 | // JSONSerializer provides JSON serialization 8 | type JSONSerializer interface { 9 | // ToJSON outputs the JSON representation of containers's elements. 10 | ToJSON() ([]byte, error) 11 | } 12 | 13 | // JSONDeserializer provides JSON deserialization 14 | type JSONDeserializer interface { 15 | // FromJSON populates containers's elements from the input JSON representation. 16 | FromJSON([]byte) error 17 | } 18 | -------------------------------------------------------------------------------- /vendor/github.com/emirpasic/gods/lists/arraylist/enumerable.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package arraylist 6 | 7 | import "github.com/emirpasic/gods/containers" 8 | 9 | func assertEnumerableImplementation() { 10 | var _ containers.EnumerableWithIndex = (*List)(nil) 11 | } 12 | 13 | // Each calls the given function once for each element, passing that element's index and value. 14 | func (list *List) Each(f func(index int, value interface{})) { 15 | iterator := list.Iterator() 16 | for iterator.Next() { 17 | f(iterator.Index(), iterator.Value()) 18 | } 19 | } 20 | 21 | // Map invokes the given function once for each element and returns a 22 | // container containing the values returned by the given function. 23 | func (list *List) Map(f func(index int, value interface{}) interface{}) *List { 24 | newList := &List{} 25 | iterator := list.Iterator() 26 | for iterator.Next() { 27 | newList.Add(f(iterator.Index(), iterator.Value())) 28 | } 29 | return newList 30 | } 31 | 32 | // Select returns a new container containing all elements for which the given function returns a true value. 33 | func (list *List) Select(f func(index int, value interface{}) bool) *List { 34 | newList := &List{} 35 | iterator := list.Iterator() 36 | for iterator.Next() { 37 | if f(iterator.Index(), iterator.Value()) { 38 | newList.Add(iterator.Value()) 39 | } 40 | } 41 | return newList 42 | } 43 | 44 | // Any passes each element of the collection to the given function and 45 | // returns true if the function ever returns true for any element. 46 | func (list *List) Any(f func(index int, value interface{}) bool) bool { 47 | iterator := list.Iterator() 48 | for iterator.Next() { 49 | if f(iterator.Index(), iterator.Value()) { 50 | return true 51 | } 52 | } 53 | return false 54 | } 55 | 56 | // All passes each element of the collection to the given function and 57 | // returns true if the function returns true for all elements. 58 | func (list *List) All(f func(index int, value interface{}) bool) bool { 59 | iterator := list.Iterator() 60 | for iterator.Next() { 61 | if !f(iterator.Index(), iterator.Value()) { 62 | return false 63 | } 64 | } 65 | return true 66 | } 67 | 68 | // Find passes each element of the container to the given function and returns 69 | // the first (index,value) for which the function is true or -1,nil otherwise 70 | // if no element matches the criteria. 71 | func (list *List) Find(f func(index int, value interface{}) bool) (int, interface{}) { 72 | iterator := list.Iterator() 73 | for iterator.Next() { 74 | if f(iterator.Index(), iterator.Value()) { 75 | return iterator.Index(), iterator.Value() 76 | } 77 | } 78 | return -1, nil 79 | } 80 | -------------------------------------------------------------------------------- /vendor/github.com/emirpasic/gods/lists/arraylist/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package arraylist 6 | 7 | import "github.com/emirpasic/gods/containers" 8 | 9 | func assertIteratorImplementation() { 10 | var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil) 11 | } 12 | 13 | // Iterator holding the iterator's state 14 | type Iterator struct { 15 | list *List 16 | index int 17 | } 18 | 19 | // Iterator returns a stateful iterator whose values can be fetched by an index. 20 | func (list *List) Iterator() Iterator { 21 | return Iterator{list: list, index: -1} 22 | } 23 | 24 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 25 | // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). 26 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 27 | // Modifies the state of the iterator. 28 | func (iterator *Iterator) Next() bool { 29 | if iterator.index < iterator.list.size { 30 | iterator.index++ 31 | } 32 | return iterator.list.withinRange(iterator.index) 33 | } 34 | 35 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 36 | // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). 37 | // Modifies the state of the iterator. 38 | func (iterator *Iterator) Prev() bool { 39 | if iterator.index >= 0 { 40 | iterator.index-- 41 | } 42 | return iterator.list.withinRange(iterator.index) 43 | } 44 | 45 | // Value returns the current element's value. 46 | // Does not modify the state of the iterator. 47 | func (iterator *Iterator) Value() interface{} { 48 | return iterator.list.elements[iterator.index] 49 | } 50 | 51 | // Index returns the current element's index. 52 | // Does not modify the state of the iterator. 53 | func (iterator *Iterator) Index() int { 54 | return iterator.index 55 | } 56 | 57 | // Begin resets the iterator to its initial state (one-before-first) 58 | // Call Next() to fetch the first element if any. 59 | func (iterator *Iterator) Begin() { 60 | iterator.index = -1 61 | } 62 | 63 | // End moves the iterator past the last element (one-past-the-end). 64 | // Call Prev() to fetch the last element if any. 65 | func (iterator *Iterator) End() { 66 | iterator.index = iterator.list.size 67 | } 68 | 69 | // First moves the iterator to the first element and returns true if there was a first element in the container. 70 | // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). 71 | // Modifies the state of the iterator. 72 | func (iterator *Iterator) First() bool { 73 | iterator.Begin() 74 | return iterator.Next() 75 | } 76 | 77 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 78 | // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). 79 | // Modifies the state of the iterator. 80 | func (iterator *Iterator) Last() bool { 81 | iterator.End() 82 | return iterator.Prev() 83 | } 84 | -------------------------------------------------------------------------------- /vendor/github.com/emirpasic/gods/lists/arraylist/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package arraylist 6 | 7 | import ( 8 | "encoding/json" 9 | "github.com/emirpasic/gods/containers" 10 | ) 11 | 12 | func assertSerializationImplementation() { 13 | var _ containers.JSONSerializer = (*List)(nil) 14 | var _ containers.JSONDeserializer = (*List)(nil) 15 | } 16 | 17 | // ToJSON outputs the JSON representation of list's elements. 18 | func (list *List) ToJSON() ([]byte, error) { 19 | return json.Marshal(list.elements[:list.size]) 20 | } 21 | 22 | // FromJSON populates list's elements from the input JSON representation. 23 | func (list *List) FromJSON(data []byte) error { 24 | err := json.Unmarshal(data, &list.elements) 25 | if err == nil { 26 | list.size = len(list.elements) 27 | } 28 | return err 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/emirpasic/gods/lists/lists.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package lists provides an abstract List interface. 6 | // 7 | // In computer science, a list or sequence is an abstract data type that represents an ordered sequence of values, where the same value may occur more than once. An instance of a list is a computer representation of the mathematical concept of a finite sequence; the (potentially) infinite analog of a list is a stream. Lists are a basic example of containers, as they contain other values. If the same value occurs multiple times, each occurrence is considered a distinct item. 8 | // 9 | // Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29 10 | package lists 11 | 12 | import ( 13 | "github.com/emirpasic/gods/containers" 14 | "github.com/emirpasic/gods/utils" 15 | ) 16 | 17 | // List interface that all lists implement 18 | type List interface { 19 | Get(index int) (interface{}, bool) 20 | Remove(index int) 21 | Add(values ...interface{}) 22 | Contains(values ...interface{}) bool 23 | Sort(comparator utils.Comparator) 24 | Swap(index1, index2 int) 25 | Insert(index int, values ...interface{}) 26 | Set(index int, value interface{}) 27 | 28 | containers.Container 29 | // Empty() bool 30 | // Size() int 31 | // Clear() 32 | // Values() []interface{} 33 | } 34 | -------------------------------------------------------------------------------- /vendor/github.com/emirpasic/gods/trees/binaryheap/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package binaryheap 6 | 7 | import "github.com/emirpasic/gods/containers" 8 | 9 | func assertIteratorImplementation() { 10 | var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil) 11 | } 12 | 13 | // Iterator returns a stateful iterator whose values can be fetched by an index. 14 | type Iterator struct { 15 | heap *Heap 16 | index int 17 | } 18 | 19 | // Iterator returns a stateful iterator whose values can be fetched by an index. 20 | func (heap *Heap) Iterator() Iterator { 21 | return Iterator{heap: heap, index: -1} 22 | } 23 | 24 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 25 | // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). 26 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 27 | // Modifies the state of the iterator. 28 | func (iterator *Iterator) Next() bool { 29 | if iterator.index < iterator.heap.Size() { 30 | iterator.index++ 31 | } 32 | return iterator.heap.withinRange(iterator.index) 33 | } 34 | 35 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 36 | // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). 37 | // Modifies the state of the iterator. 38 | func (iterator *Iterator) Prev() bool { 39 | if iterator.index >= 0 { 40 | iterator.index-- 41 | } 42 | return iterator.heap.withinRange(iterator.index) 43 | } 44 | 45 | // Value returns the current element's value. 46 | // Does not modify the state of the iterator. 47 | func (iterator *Iterator) Value() interface{} { 48 | value, _ := iterator.heap.list.Get(iterator.index) 49 | return value 50 | } 51 | 52 | // Index returns the current element's index. 53 | // Does not modify the state of the iterator. 54 | func (iterator *Iterator) Index() int { 55 | return iterator.index 56 | } 57 | 58 | // Begin resets the iterator to its initial state (one-before-first) 59 | // Call Next() to fetch the first element if any. 60 | func (iterator *Iterator) Begin() { 61 | iterator.index = -1 62 | } 63 | 64 | // End moves the iterator past the last element (one-past-the-end). 65 | // Call Prev() to fetch the last element if any. 66 | func (iterator *Iterator) End() { 67 | iterator.index = iterator.heap.Size() 68 | } 69 | 70 | // First moves the iterator to the first element and returns true if there was a first element in the container. 71 | // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). 72 | // Modifies the state of the iterator. 73 | func (iterator *Iterator) First() bool { 74 | iterator.Begin() 75 | return iterator.Next() 76 | } 77 | 78 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 79 | // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). 80 | // Modifies the state of the iterator. 81 | func (iterator *Iterator) Last() bool { 82 | iterator.End() 83 | return iterator.Prev() 84 | } 85 | -------------------------------------------------------------------------------- /vendor/github.com/emirpasic/gods/trees/binaryheap/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package binaryheap 6 | 7 | import "github.com/emirpasic/gods/containers" 8 | 9 | func assertSerializationImplementation() { 10 | var _ containers.JSONSerializer = (*Heap)(nil) 11 | var _ containers.JSONDeserializer = (*Heap)(nil) 12 | } 13 | 14 | // ToJSON outputs the JSON representation of the heap. 15 | func (heap *Heap) ToJSON() ([]byte, error) { 16 | return heap.list.ToJSON() 17 | } 18 | 19 | // FromJSON populates the heap from the input JSON representation. 20 | func (heap *Heap) FromJSON(data []byte) error { 21 | return heap.list.FromJSON(data) 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/emirpasic/gods/trees/trees.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package trees provides an abstract Tree interface. 6 | // 7 | // In computer science, a tree is a widely used abstract data type (ADT) or data structure implementing this ADT that simulates a hierarchical tree structure, with a root value and subtrees of children with a parent node, represented as a set of linked nodes. 8 | // 9 | // Reference: https://en.wikipedia.org/wiki/Tree_%28data_structure%29 10 | package trees 11 | 12 | import "github.com/emirpasic/gods/containers" 13 | 14 | // Tree interface that all trees implement 15 | type Tree interface { 16 | containers.Container 17 | // Empty() bool 18 | // Size() int 19 | // Clear() 20 | // Values() []interface{} 21 | } 22 | -------------------------------------------------------------------------------- /vendor/github.com/emirpasic/gods/utils/sort.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package utils 6 | 7 | import "sort" 8 | 9 | // Sort sorts values (in-place) with respect to the given comparator. 10 | // 11 | // Uses Go's sort (hybrid of quicksort for large and then insertion sort for smaller slices). 12 | func Sort(values []interface{}, comparator Comparator) { 13 | sort.Sort(sortable{values, comparator}) 14 | } 15 | 16 | type sortable struct { 17 | values []interface{} 18 | comparator Comparator 19 | } 20 | 21 | func (s sortable) Len() int { 22 | return len(s.values) 23 | } 24 | func (s sortable) Swap(i, j int) { 25 | s.values[i], s.values[j] = s.values[j], s.values[i] 26 | } 27 | func (s sortable) Less(i, j int) bool { 28 | return s.comparator(s.values[i], s.values[j]) < 0 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/emirpasic/gods/utils/utils.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package utils provides common utility functions. 6 | // 7 | // Provided functionalities: 8 | // - sorting 9 | // - comparators 10 | package utils 11 | 12 | import ( 13 | "fmt" 14 | "strconv" 15 | ) 16 | 17 | // ToString converts a value to string. 18 | func ToString(value interface{}) string { 19 | switch value.(type) { 20 | case string: 21 | return value.(string) 22 | case int8: 23 | return strconv.FormatInt(int64(value.(int8)), 10) 24 | case int16: 25 | return strconv.FormatInt(int64(value.(int16)), 10) 26 | case int32: 27 | return strconv.FormatInt(int64(value.(int32)), 10) 28 | case int64: 29 | return strconv.FormatInt(int64(value.(int64)), 10) 30 | case uint8: 31 | return strconv.FormatUint(uint64(value.(uint8)), 10) 32 | case uint16: 33 | return strconv.FormatUint(uint64(value.(uint16)), 10) 34 | case uint32: 35 | return strconv.FormatUint(uint64(value.(uint32)), 10) 36 | case uint64: 37 | return strconv.FormatUint(uint64(value.(uint64)), 10) 38 | case float32: 39 | return strconv.FormatFloat(float64(value.(float32)), 'g', -1, 64) 40 | case float64: 41 | return strconv.FormatFloat(float64(value.(float64)), 'g', -1, 64) 42 | case bool: 43 | return strconv.FormatBool(value.(bool)) 44 | default: 45 | return fmt.Sprintf("%+v", value) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /vendor/github.com/pmezard/go-difflib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Patrick Mezard 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | The names of its contributors may not be used to endorse or promote 14 | products derived from this software without specific prior written 15 | permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 18 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 20 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 23 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/objx/.codeclimate.yml: -------------------------------------------------------------------------------- 1 | engines: 2 | gofmt: 3 | enabled: true 4 | golint: 5 | enabled: true 6 | govet: 7 | enabled: true 8 | 9 | exclude_patterns: 10 | - ".github/" 11 | - "vendor/" 12 | - "codegen/" 13 | - "*.yml" 14 | - ".*.yml" 15 | - "*.md" 16 | - "Gopkg.*" 17 | - "doc.go" 18 | - "type_specific_codegen_test.go" 19 | - "type_specific_codegen.go" 20 | - ".gitignore" 21 | - "LICENSE" 22 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/objx/.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/objx/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014 Stretchr, Inc. 4 | Copyright (c) 2017-2018 objx contributors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/objx/README.md: -------------------------------------------------------------------------------- 1 | # Objx 2 | [![Build Status](https://travis-ci.org/stretchr/objx.svg?branch=master)](https://travis-ci.org/stretchr/objx) 3 | [![Go Report Card](https://goreportcard.com/badge/github.com/stretchr/objx)](https://goreportcard.com/report/github.com/stretchr/objx) 4 | [![Maintainability](https://api.codeclimate.com/v1/badges/1d64bc6c8474c2074f2b/maintainability)](https://codeclimate.com/github/stretchr/objx/maintainability) 5 | [![Test Coverage](https://api.codeclimate.com/v1/badges/1d64bc6c8474c2074f2b/test_coverage)](https://codeclimate.com/github/stretchr/objx/test_coverage) 6 | [![Sourcegraph](https://sourcegraph.com/github.com/stretchr/objx/-/badge.svg)](https://sourcegraph.com/github.com/stretchr/objx) 7 | [![GoDoc](https://godoc.org/github.com/stretchr/objx?status.svg)](https://godoc.org/github.com/stretchr/objx) 8 | 9 | Objx - Go package for dealing with maps, slices, JSON and other data. 10 | 11 | Get started: 12 | 13 | - Install Objx with [one line of code](#installation), or [update it with another](#staying-up-to-date) 14 | - Check out the API Documentation http://godoc.org/github.com/stretchr/objx 15 | 16 | ## Overview 17 | Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes a powerful `Get` method (among others) that allows you to easily and quickly get access to data within the map, without having to worry too much about type assertions, missing data, default values etc. 18 | 19 | ### Pattern 20 | Objx uses a preditable pattern to make access data from within `map[string]interface{}` easy. Call one of the `objx.` functions to create your `objx.Map` to get going: 21 | 22 | m, err := objx.FromJSON(json) 23 | 24 | NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong, the rest will be optimistic and try to figure things out without panicking. 25 | 26 | Use `Get` to access the value you're interested in. You can use dot and array 27 | notation too: 28 | 29 | m.Get("places[0].latlng") 30 | 31 | Once you have sought the `Value` you're interested in, you can use the `Is*` methods to determine its type. 32 | 33 | if m.Get("code").IsStr() { // Your code... } 34 | 35 | Or you can just assume the type, and use one of the strong type methods to extract the real value: 36 | 37 | m.Get("code").Int() 38 | 39 | If there's no value there (or if it's the wrong type) then a default value will be returned, or you can be explicit about the default value. 40 | 41 | Get("code").Int(-1) 42 | 43 | If you're dealing with a slice of data as a value, Objx provides many useful methods for iterating, manipulating and selecting that data. You can find out more by exploring the index below. 44 | 45 | ### Reading data 46 | A simple example of how to use Objx: 47 | 48 | // Use MustFromJSON to make an objx.Map from some JSON 49 | m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`) 50 | 51 | // Get the details 52 | name := m.Get("name").Str() 53 | age := m.Get("age").Int() 54 | 55 | // Get their nickname (or use their name if they don't have one) 56 | nickname := m.Get("nickname").Str(name) 57 | 58 | ### Ranging 59 | Since `objx.Map` is a `map[string]interface{}` you can treat it as such. For example, to `range` the data, do what you would expect: 60 | 61 | m := objx.MustFromJSON(json) 62 | for key, value := range m { 63 | // Your code... 64 | } 65 | 66 | ## Installation 67 | To install Objx, use go get: 68 | 69 | go get github.com/stretchr/objx 70 | 71 | ### Staying up to date 72 | To update Objx to the latest version, run: 73 | 74 | go get -u github.com/stretchr/objx 75 | 76 | ### Supported go versions 77 | We support the lastest three major Go versions, which are 1.10, 1.11 and 1.12 at the moment. 78 | 79 | ## Contributing 80 | Please feel free to submit issues, fork the repository and send pull requests! 81 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/objx/Taskfile.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | env: 4 | GOFLAGS: -mod=vendor 5 | 6 | tasks: 7 | default: 8 | deps: [test] 9 | 10 | lint: 11 | desc: Checks code style 12 | cmds: 13 | - gofmt -d -s *.go 14 | - go vet ./... 15 | silent: true 16 | 17 | lint-fix: 18 | desc: Fixes code style 19 | cmds: 20 | - gofmt -w -s *.go 21 | 22 | test: 23 | desc: Runs go tests 24 | cmds: 25 | - go test -race ./... 26 | 27 | test-coverage: 28 | desc: Runs go tests and calucates test coverage 29 | cmds: 30 | - go test -race -coverprofile=c.out ./... 31 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/objx/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Objx - Go package for dealing with maps, slices, JSON and other data. 3 | 4 | Overview 5 | 6 | Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes 7 | a powerful `Get` method (among others) that allows you to easily and quickly get 8 | access to data within the map, without having to worry too much about type assertions, 9 | missing data, default values etc. 10 | 11 | Pattern 12 | 13 | Objx uses a preditable pattern to make access data from within `map[string]interface{}` easy. 14 | Call one of the `objx.` functions to create your `objx.Map` to get going: 15 | 16 | m, err := objx.FromJSON(json) 17 | 18 | NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong, 19 | the rest will be optimistic and try to figure things out without panicking. 20 | 21 | Use `Get` to access the value you're interested in. You can use dot and array 22 | notation too: 23 | 24 | m.Get("places[0].latlng") 25 | 26 | Once you have sought the `Value` you're interested in, you can use the `Is*` methods to determine its type. 27 | 28 | if m.Get("code").IsStr() { // Your code... } 29 | 30 | Or you can just assume the type, and use one of the strong type methods to extract the real value: 31 | 32 | m.Get("code").Int() 33 | 34 | If there's no value there (or if it's the wrong type) then a default value will be returned, 35 | or you can be explicit about the default value. 36 | 37 | Get("code").Int(-1) 38 | 39 | If you're dealing with a slice of data as a value, Objx provides many useful methods for iterating, 40 | manipulating and selecting that data. You can find out more by exploring the index below. 41 | 42 | Reading data 43 | 44 | A simple example of how to use Objx: 45 | 46 | // Use MustFromJSON to make an objx.Map from some JSON 47 | m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`) 48 | 49 | // Get the details 50 | name := m.Get("name").Str() 51 | age := m.Get("age").Int() 52 | 53 | // Get their nickname (or use their name if they don't have one) 54 | nickname := m.Get("nickname").Str(name) 55 | 56 | Ranging 57 | 58 | Since `objx.Map` is a `map[string]interface{}` you can treat it as such. 59 | For example, to `range` the data, do what you would expect: 60 | 61 | m := objx.MustFromJSON(json) 62 | for key, value := range m { 63 | // Your code... 64 | } 65 | */ 66 | package objx 67 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/objx/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/stretchr/objx 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/davecgh/go-spew v1.1.1 // indirect 7 | github.com/stretchr/testify v1.7.1 8 | ) 9 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/objx/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 5 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 6 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 7 | github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= 8 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 9 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 10 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 11 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 12 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 13 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/objx/mutations.go: -------------------------------------------------------------------------------- 1 | package objx 2 | 3 | // Exclude returns a new Map with the keys in the specified []string 4 | // excluded. 5 | func (m Map) Exclude(exclude []string) Map { 6 | excluded := make(Map) 7 | for k, v := range m { 8 | if !contains(exclude, k) { 9 | excluded[k] = v 10 | } 11 | } 12 | return excluded 13 | } 14 | 15 | // Copy creates a shallow copy of the Obj. 16 | func (m Map) Copy() Map { 17 | copied := Map{} 18 | for k, v := range m { 19 | copied[k] = v 20 | } 21 | return copied 22 | } 23 | 24 | // Merge blends the specified map with a copy of this map and returns the result. 25 | // 26 | // Keys that appear in both will be selected from the specified map. 27 | // This method requires that the wrapped object be a map[string]interface{} 28 | func (m Map) Merge(merge Map) Map { 29 | return m.Copy().MergeHere(merge) 30 | } 31 | 32 | // MergeHere blends the specified map with this map and returns the current map. 33 | // 34 | // Keys that appear in both will be selected from the specified map. The original map 35 | // will be modified. This method requires that 36 | // the wrapped object be a map[string]interface{} 37 | func (m Map) MergeHere(merge Map) Map { 38 | for k, v := range merge { 39 | m[k] = v 40 | } 41 | return m 42 | } 43 | 44 | // Transform builds a new Obj giving the transformer a chance 45 | // to change the keys and values as it goes. This method requires that 46 | // the wrapped object be a map[string]interface{} 47 | func (m Map) Transform(transformer func(key string, value interface{}) (string, interface{})) Map { 48 | newMap := Map{} 49 | for k, v := range m { 50 | modifiedKey, modifiedVal := transformer(k, v) 51 | newMap[modifiedKey] = modifiedVal 52 | } 53 | return newMap 54 | } 55 | 56 | // TransformKeys builds a new map using the specified key mapping. 57 | // 58 | // Unspecified keys will be unaltered. 59 | // This method requires that the wrapped object be a map[string]interface{} 60 | func (m Map) TransformKeys(mapping map[string]string) Map { 61 | return m.Transform(func(key string, value interface{}) (string, interface{}) { 62 | if newKey, ok := mapping[key]; ok { 63 | return newKey, value 64 | } 65 | return key, value 66 | }) 67 | } 68 | 69 | // Checks if a string slice contains a string 70 | func contains(s []string, e string) bool { 71 | for _, a := range s { 72 | if a == e { 73 | return true 74 | } 75 | } 76 | return false 77 | } 78 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/objx/security.go: -------------------------------------------------------------------------------- 1 | package objx 2 | 3 | import ( 4 | "crypto/sha1" 5 | "encoding/hex" 6 | ) 7 | 8 | // HashWithKey hashes the specified string using the security key 9 | func HashWithKey(data, key string) string { 10 | d := sha1.Sum([]byte(data + ":" + key)) 11 | return hex.EncodeToString(d[:]) 12 | } 13 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/objx/tests.go: -------------------------------------------------------------------------------- 1 | package objx 2 | 3 | // Has gets whether there is something at the specified selector 4 | // or not. 5 | // 6 | // If m is nil, Has will always return false. 7 | func (m Map) Has(selector string) bool { 8 | if m == nil { 9 | return false 10 | } 11 | return !m.Get(selector).IsNil() 12 | } 13 | 14 | // IsNil gets whether the data is nil or not. 15 | func (v *Value) IsNil() bool { 16 | return v == nil || v.data == nil 17 | } 18 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go: -------------------------------------------------------------------------------- 1 | //go:build go1.17 2 | // +build go1.17 3 | 4 | // TODO: once support for Go 1.16 is dropped, this file can be 5 | // merged/removed with assertion_compare_go1.17_test.go and 6 | // assertion_compare_legacy.go 7 | 8 | package assert 9 | 10 | import "reflect" 11 | 12 | // Wrapper around reflect.Value.CanConvert, for compatibility 13 | // reasons. 14 | func canConvert(value reflect.Value, to reflect.Type) bool { 15 | return value.CanConvert(to) 16 | } 17 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go: -------------------------------------------------------------------------------- 1 | //go:build !go1.17 2 | // +build !go1.17 3 | 4 | // TODO: once support for Go 1.16 is dropped, this file can be 5 | // merged/removed with assertion_compare_go1.17_test.go and 6 | // assertion_compare_can_convert.go 7 | 8 | package assert 9 | 10 | import "reflect" 11 | 12 | // Older versions of Go does not have the reflect.Value.CanConvert 13 | // method. 14 | func canConvert(value reflect.Value, to reflect.Type) bool { 15 | return false 16 | } 17 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl: -------------------------------------------------------------------------------- 1 | {{.CommentFormat}} 2 | func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool { 3 | if h, ok := t.(tHelper); ok { h.Helper() } 4 | return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}}) 5 | } 6 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl: -------------------------------------------------------------------------------- 1 | {{.CommentWithoutT "a"}} 2 | func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { 3 | if h, ok := a.t.(tHelper); ok { h.Helper() } 4 | return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) 5 | } 6 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_order.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | // isOrdered checks that collection contains orderable elements. 9 | func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool { 10 | objKind := reflect.TypeOf(object).Kind() 11 | if objKind != reflect.Slice && objKind != reflect.Array { 12 | return false 13 | } 14 | 15 | objValue := reflect.ValueOf(object) 16 | objLen := objValue.Len() 17 | 18 | if objLen <= 1 { 19 | return true 20 | } 21 | 22 | value := objValue.Index(0) 23 | valueInterface := value.Interface() 24 | firstValueKind := value.Kind() 25 | 26 | for i := 1; i < objLen; i++ { 27 | prevValue := value 28 | prevValueInterface := valueInterface 29 | 30 | value = objValue.Index(i) 31 | valueInterface = value.Interface() 32 | 33 | compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind) 34 | 35 | if !isComparable { 36 | return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...) 37 | } 38 | 39 | if !containsValue(allowedComparesResults, compareResult) { 40 | return Fail(t, fmt.Sprintf(failMessage, prevValue, value), msgAndArgs...) 41 | } 42 | } 43 | 44 | return true 45 | } 46 | 47 | // IsIncreasing asserts that the collection is increasing 48 | // 49 | // assert.IsIncreasing(t, []int{1, 2, 3}) 50 | // assert.IsIncreasing(t, []float{1, 2}) 51 | // assert.IsIncreasing(t, []string{"a", "b"}) 52 | func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 53 | return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) 54 | } 55 | 56 | // IsNonIncreasing asserts that the collection is not increasing 57 | // 58 | // assert.IsNonIncreasing(t, []int{2, 1, 1}) 59 | // assert.IsNonIncreasing(t, []float{2, 1}) 60 | // assert.IsNonIncreasing(t, []string{"b", "a"}) 61 | func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 62 | return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) 63 | } 64 | 65 | // IsDecreasing asserts that the collection is decreasing 66 | // 67 | // assert.IsDecreasing(t, []int{2, 1, 0}) 68 | // assert.IsDecreasing(t, []float{2, 1}) 69 | // assert.IsDecreasing(t, []string{"b", "a"}) 70 | func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 71 | return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) 72 | } 73 | 74 | // IsNonDecreasing asserts that the collection is not decreasing 75 | // 76 | // assert.IsNonDecreasing(t, []int{1, 1, 2}) 77 | // assert.IsNonDecreasing(t, []float{1, 2}) 78 | // assert.IsNonDecreasing(t, []string{"a", "b"}) 79 | func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 80 | return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) 81 | } 82 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/doc.go: -------------------------------------------------------------------------------- 1 | // Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. 2 | // 3 | // Example Usage 4 | // 5 | // The following is a complete example using assert in a standard test function: 6 | // import ( 7 | // "testing" 8 | // "github.com/stretchr/testify/assert" 9 | // ) 10 | // 11 | // func TestSomething(t *testing.T) { 12 | // 13 | // var a string = "Hello" 14 | // var b string = "Hello" 15 | // 16 | // assert.Equal(t, a, b, "The two words should be the same.") 17 | // 18 | // } 19 | // 20 | // if you assert many times, use the format below: 21 | // 22 | // import ( 23 | // "testing" 24 | // "github.com/stretchr/testify/assert" 25 | // ) 26 | // 27 | // func TestSomething(t *testing.T) { 28 | // assert := assert.New(t) 29 | // 30 | // var a string = "Hello" 31 | // var b string = "Hello" 32 | // 33 | // assert.Equal(a, b, "The two words should be the same.") 34 | // } 35 | // 36 | // Assertions 37 | // 38 | // Assertions allow you to easily write test code, and are global funcs in the `assert` package. 39 | // All assertion functions take, as the first argument, the `*testing.T` object provided by the 40 | // testing framework. This allows the assertion funcs to write the failings and other details to 41 | // the correct place. 42 | // 43 | // Every assertion function also takes an optional string message as the final argument, 44 | // allowing custom error messages to be appended to the message the assertion method outputs. 45 | package assert 46 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/errors.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // AnError is an error instance useful for testing. If the code does not care 8 | // about error specifics, and only needs to return the error for example, this 9 | // error should be used to make the test code more readable. 10 | var AnError = errors.New("assert.AnError general error for testing") 11 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/forward_assertions.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | // Assertions provides assertion methods around the 4 | // TestingT interface. 5 | type Assertions struct { 6 | t TestingT 7 | } 8 | 9 | // New makes a new Assertions object for the specified TestingT. 10 | func New(t TestingT) *Assertions { 11 | return &Assertions{ 12 | t: t, 13 | } 14 | } 15 | 16 | //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs" 17 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/mock/doc.go: -------------------------------------------------------------------------------- 1 | // Package mock provides a system by which it is possible to mock your objects 2 | // and verify calls are happening as expected. 3 | // 4 | // Example Usage 5 | // 6 | // The mock package provides an object, Mock, that tracks activity on another object. It is usually 7 | // embedded into a test object as shown below: 8 | // 9 | // type MyTestObject struct { 10 | // // add a Mock object instance 11 | // mock.Mock 12 | // 13 | // // other fields go here as normal 14 | // } 15 | // 16 | // When implementing the methods of an interface, you wire your functions up 17 | // to call the Mock.Called(args...) method, and return the appropriate values. 18 | // 19 | // For example, to mock a method that saves the name and age of a person and returns 20 | // the year of their birth or an error, you might write this: 21 | // 22 | // func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) { 23 | // args := o.Called(firstname, lastname, age) 24 | // return args.Int(0), args.Error(1) 25 | // } 26 | // 27 | // The Int, Error and Bool methods are examples of strongly typed getters that take the argument 28 | // index position. Given this argument list: 29 | // 30 | // (12, true, "Something") 31 | // 32 | // You could read them out strongly typed like this: 33 | // 34 | // args.Int(0) 35 | // args.Bool(1) 36 | // args.String(2) 37 | // 38 | // For objects of your own type, use the generic Arguments.Get(index) method and make a type assertion: 39 | // 40 | // return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine) 41 | // 42 | // This may cause a panic if the object you are getting is nil (the type assertion will fail), in those 43 | // cases you should check for nil first. 44 | package mock 45 | -------------------------------------------------------------------------------- /vendor/github.com/teivah/onecontext/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | onecontext.iml 3 | *.out -------------------------------------------------------------------------------- /vendor/github.com/teivah/onecontext/README.md: -------------------------------------------------------------------------------- 1 | # teivah/onecontext 2 | 3 | [![Go Report Card](https://goreportcard.com/badge/github.com/teivah/onecontext)](https://goreportcard.com/report/github.com/teivah/onecontext) 4 | 5 | ## Overview 6 | 7 | Have you ever faced the situation where you have to merge multiple existing contexts? 8 | If not, then you might, eventually. 9 | 10 | For example, we can face the situation where we are building an application using a library that gives us a global context (for example `urfave/cli`). 11 | This context expires once the application is stopped. 12 | 13 | Meanwhile, we are exposing a gRPC service like this: 14 | 15 | ```go 16 | func (f *Foo) Get(ctx context.Context, bar *Bar) (*Baz, error) { 17 | 18 | } 19 | ``` 20 | 21 | Here, we receive another context provided by gRPC. 22 | 23 | Then, in the `Get` implementation, we want for example to query a database and we must provide a context for that. 24 | 25 | Ideally, we would like to provide a merged context that would expire either: 26 | - When the application is stopped 27 | - Or when the received gRPC context expires 28 | 29 | This is exactly the purpose of this library. 30 | 31 | In our case, we can now merge the two contexts in a single one like this: 32 | 33 | ```go 34 | ctx, cancel := onecontext.Merge(ctx1, ctx2) 35 | ``` 36 | 37 | This returns a merged context that we can now propagate. 38 | 39 | # Installation 40 | 41 | `go get github.com/teivah/onecontext` 42 | -------------------------------------------------------------------------------- /vendor/github.com/teivah/onecontext/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/teivah/onecontext 2 | 3 | go 1.12 4 | 5 | require github.com/stretchr/testify v1.3.0 6 | -------------------------------------------------------------------------------- /vendor/github.com/teivah/onecontext/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 4 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 5 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 6 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 7 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 8 | -------------------------------------------------------------------------------- /vendor/github.com/teivah/onecontext/onecontext.go: -------------------------------------------------------------------------------- 1 | // Package onecontext provides a mechanism to merge multiple existing contexts. 2 | package onecontext 3 | 4 | import ( 5 | "context" 6 | "sync" 7 | "time" 8 | ) 9 | 10 | // Canceled is the error returned when the CancelFunc returned by Merge is called 11 | type Canceled struct { 12 | } 13 | 14 | func (c *Canceled) Error() string { 15 | return "canceled context" 16 | } 17 | 18 | type onecontext struct { 19 | ctx context.Context 20 | ctxs []context.Context 21 | done chan struct{} 22 | err error 23 | errMutex sync.Mutex 24 | cancelFunc context.CancelFunc 25 | cancelCtx context.Context 26 | } 27 | 28 | // Merge allows to merge multiple contexts. 29 | // It returns the merged context and a CancelFunc to cancel it. 30 | func Merge(ctx context.Context, ctxs ...context.Context) (context.Context, context.CancelFunc) { 31 | cancelCtx, cancelFunc := context.WithCancel(context.Background()) 32 | o := &onecontext{ 33 | done: make(chan struct{}), 34 | ctx: ctx, 35 | ctxs: ctxs, 36 | cancelCtx: cancelCtx, 37 | cancelFunc: cancelFunc, 38 | } 39 | go o.run() 40 | return o, cancelFunc 41 | } 42 | 43 | func (o *onecontext) Deadline() (time.Time, bool) { 44 | min := time.Time{} 45 | 46 | if deadline, ok := o.ctx.Deadline(); ok { 47 | min = deadline 48 | } 49 | 50 | for _, ctx := range o.ctxs { 51 | if deadline, ok := ctx.Deadline(); ok { 52 | if min.IsZero() || deadline.Before(min) { 53 | min = deadline 54 | } 55 | } 56 | } 57 | 58 | return min, !min.IsZero() 59 | } 60 | 61 | func (o *onecontext) Done() <-chan struct{} { 62 | return o.done 63 | } 64 | 65 | func (o *onecontext) Err() error { 66 | o.errMutex.Lock() 67 | defer o.errMutex.Unlock() 68 | return o.err 69 | } 70 | 71 | func (o *onecontext) Value(key interface{}) interface{} { 72 | if value := o.ctx.Value(key); value != nil { 73 | return value 74 | } 75 | 76 | for _, ctx := range o.ctxs { 77 | if value := ctx.Value(key); value != nil { 78 | return value 79 | } 80 | } 81 | 82 | return nil 83 | } 84 | 85 | func (o *onecontext) run() { 86 | once := sync.Once{} 87 | 88 | if len(o.ctxs) == 1 { 89 | o.runTwoContexts(o.ctx, o.ctxs[0]) 90 | return 91 | } 92 | 93 | o.runMultipleContexts(o.ctx, &once) 94 | for _, ctx := range o.ctxs { 95 | o.runMultipleContexts(ctx, &once) 96 | } 97 | } 98 | 99 | func (o *onecontext) cancel(err error) { 100 | o.cancelFunc() 101 | o.errMutex.Lock() 102 | o.err = err 103 | o.errMutex.Unlock() 104 | close(o.done) 105 | } 106 | 107 | func (o *onecontext) runTwoContexts(ctx1, ctx2 context.Context) { 108 | go func() { 109 | select { 110 | case <-o.cancelCtx.Done(): 111 | o.cancel(&Canceled{}) 112 | case <-ctx1.Done(): 113 | o.cancel(ctx1.Err()) 114 | case <-ctx2.Done(): 115 | o.cancel(ctx2.Err()) 116 | } 117 | }() 118 | } 119 | 120 | func (o *onecontext) runMultipleContexts(ctx context.Context, once *sync.Once) { 121 | go func() { 122 | select { 123 | case <-o.cancelCtx.Done(): 124 | once.Do(func() { 125 | o.cancel(&Canceled{}) 126 | }) 127 | case <-ctx.Done(): 128 | once.Do(func() { 129 | o.cancel(ctx.Err()) 130 | }) 131 | } 132 | }() 133 | } 134 | -------------------------------------------------------------------------------- /vendor/go.uber.org/goleak/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | /bin 3 | /lint.log 4 | /cover.out 5 | /cover.html 6 | -------------------------------------------------------------------------------- /vendor/go.uber.org/goleak/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 6 | 7 | ## [1.1.12] 8 | ### Fixed 9 | - Fixed logic for ignoring trace related goroutines on Go versions 1.16 and above. 10 | 11 | ## [1.1.11] 12 | ### Fixed 13 | - Documentation fix on how to test. 14 | - Update dependency on stretchr/testify to v1.7.0. (#59) 15 | - Update dependency on golang.org/x/tools to address CVE-2020-14040. (#62) 16 | 17 | ## [1.1.10] 18 | ### Added 19 | - [#49]: Add option to ignore current goroutines, which checks for any additional leaks and allows for incremental adoption of goleak in larger projects. 20 | 21 | Thanks to @denis-tingajkin for their contributions to this release. 22 | 23 | ## [1.0.0] 24 | ### Changed 25 | - Migrate to Go modules. 26 | 27 | ### Fixed 28 | - Ignore trace related goroutines that cause false positives with -trace. 29 | 30 | ## 0.10.0 31 | - Initial release. 32 | 33 | [1.0.0]: https://github.com/uber-go/goleak/compare/v0.10.0...v1.0.0 34 | [#49]: https://github.com/uber-go/goleak/pull/49 35 | -------------------------------------------------------------------------------- /vendor/go.uber.org/goleak/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Uber Technologies, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/go.uber.org/goleak/Makefile: -------------------------------------------------------------------------------- 1 | export GOBIN ?= $(shell pwd)/bin 2 | 3 | GOLINT = $(GOBIN)/golint 4 | 5 | GO_FILES := $(shell \ 6 | find . '(' -path '*/.*' -o -path './vendor' ')' -prune \ 7 | -o -name '*.go' -print | cut -b3-) 8 | 9 | .PHONY: build 10 | build: 11 | go build ./... 12 | 13 | .PHONY: install 14 | install: 15 | go mod download 16 | 17 | .PHONY: test 18 | test: 19 | go test -v -race ./... 20 | go test -v -trace=/dev/null . 21 | 22 | .PHONY: cover 23 | cover: 24 | go test -race -coverprofile=cover.out -coverpkg=./... ./... 25 | go tool cover -html=cover.out -o cover.html 26 | 27 | $(GOLINT): 28 | go install golang.org/x/lint/golint 29 | 30 | .PHONY: lint 31 | lint: $(GOLINT) 32 | @rm -rf lint.log 33 | @echo "Checking formatting..." 34 | @gofmt -d -s $(GO_FILES) 2>&1 | tee lint.log 35 | @echo "Checking vet..." 36 | @go vet ./... 2>&1 | tee -a lint.log 37 | @echo "Checking lint..." 38 | @$(GOLINT) ./... 2>&1 | tee -a lint.log 39 | @echo "Checking for unresolved FIXMEs..." 40 | @git grep -i fixme | grep -v -e '^vendor/' -e '^Makefile' | tee -a lint.log 41 | @[ ! -s lint.log ] 42 | -------------------------------------------------------------------------------- /vendor/go.uber.org/goleak/README.md: -------------------------------------------------------------------------------- 1 | # goleak [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] 2 | 3 | Goroutine leak detector to help avoid Goroutine leaks. 4 | 5 | ## Installation 6 | 7 | You can use `go get` to get the latest version: 8 | 9 | `go get -u go.uber.org/goleak` 10 | 11 | `goleak` also supports semver releases. It is compatible with Go 1.5+. 12 | 13 | ## Quick Start 14 | 15 | To verify that there are no unexpected goroutines running at the end of a test: 16 | 17 | ```go 18 | func TestA(t *testing.T) { 19 | defer goleak.VerifyNone(t) 20 | 21 | // test logic here. 22 | } 23 | ``` 24 | 25 | Instead of checking for leaks at the end of every test, `goleak` can also be run 26 | at the end of every test package by creating a `TestMain` function for your 27 | package: 28 | 29 | ```go 30 | func TestMain(m *testing.M) { 31 | goleak.VerifyTestMain(m) 32 | } 33 | ``` 34 | 35 | ## Determine Source of Package Leaks 36 | 37 | When verifying leaks using `TestMain`, the leak test is only run once after all tests 38 | have been run. This is typically enough to ensure there's no goroutines leaked from 39 | tests, but when there are leaks, it's hard to determine which test is causing them. 40 | 41 | You can use the following bash script to determine the source of the failing test: 42 | 43 | ```sh 44 | # Create a test binary which will be used to run each test individually 45 | $ go test -c -o tests 46 | 47 | # Run each test individually, printing "." for successful tests, or the test name 48 | # for failing tests. 49 | $ for test in $(go test -list . | grep -E "^(Test|Example)"); do ./tests -test.run "^$test\$" &>/dev/null && echo -n "." || echo -e "\n$test failed"; done 50 | ``` 51 | 52 | This will only print names of failing tests which can be investigated individually. E.g., 53 | 54 | ``` 55 | ..... 56 | TestLeakyTest failed 57 | ....... 58 | ``` 59 | 60 | ## Stability 61 | 62 | goleak is v1 and follows [SemVer](http://semver.org/) strictly. 63 | 64 | No breaking changes will be made to exported APIs before 2.0. 65 | 66 | [doc-img]: https://godoc.org/go.uber.org/goleak?status.svg 67 | [doc]: https://godoc.org/go.uber.org/goleak 68 | [ci-img]: https://github.com/uber-go/goleak/actions/workflows/go.yml/badge.svg 69 | [ci]: https://github.com/uber-go/goleak/actions/workflows/go.yml 70 | [cov-img]: https://codecov.io/gh/uber-go/goleak/branch/master/graph/badge.svg 71 | [cov]: https://codecov.io/gh/uber-go/goleak 72 | -------------------------------------------------------------------------------- /vendor/go.uber.org/goleak/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Package goleak is a Goroutine leak detector. 22 | package goleak // import "go.uber.org/goleak" 23 | -------------------------------------------------------------------------------- /vendor/go.uber.org/goleak/glide.yaml: -------------------------------------------------------------------------------- 1 | package: go.uber.org/goleak 2 | import: [] 3 | testImport: 4 | - package: github.com/stretchr/testify 5 | version: ^1.1.4 6 | subpackages: 7 | - assert 8 | - require 9 | -------------------------------------------------------------------------------- /vendor/go.uber.org/goleak/go.mod: -------------------------------------------------------------------------------- 1 | module go.uber.org/goleak 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/kr/pretty v0.1.0 // indirect 7 | github.com/stretchr/testify v1.7.0 8 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de 9 | golang.org/x/tools v0.1.5 // indirect 10 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect 11 | ) 12 | -------------------------------------------------------------------------------- /vendor/go.uber.org/goleak/leaks.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Uber Technologies, Inc. 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package goleak 22 | 23 | import ( 24 | "fmt" 25 | 26 | "go.uber.org/goleak/internal/stack" 27 | ) 28 | 29 | // TestingT is the minimal subset of testing.TB that we use. 30 | type TestingT interface { 31 | Error(...interface{}) 32 | } 33 | 34 | // filterStacks will filter any stacks excluded by the given opts. 35 | // filterStacks modifies the passed in stacks slice. 36 | func filterStacks(stacks []stack.Stack, skipID int, opts *opts) []stack.Stack { 37 | filtered := stacks[:0] 38 | for _, stack := range stacks { 39 | // Always skip the running goroutine. 40 | if stack.ID() == skipID { 41 | continue 42 | } 43 | // Run any default or user-specified filters. 44 | if opts.filter(stack) { 45 | continue 46 | } 47 | filtered = append(filtered, stack) 48 | } 49 | return filtered 50 | } 51 | 52 | // Find looks for extra goroutines, and returns a descriptive error if 53 | // any are found. 54 | func Find(options ...Option) error { 55 | cur := stack.Current().ID() 56 | 57 | opts := buildOpts(options...) 58 | var stacks []stack.Stack 59 | retry := true 60 | for i := 0; retry; i++ { 61 | stacks = filterStacks(stack.All(), cur, opts) 62 | 63 | if len(stacks) == 0 { 64 | return nil 65 | } 66 | retry = opts.retry(i) 67 | } 68 | 69 | return fmt.Errorf("found unexpected goroutines:\n%s", stacks) 70 | } 71 | 72 | // VerifyNone marks the given TestingT as failed if any extra goroutines are 73 | // found by Find. This is a helper method to make it easier to integrate in 74 | // tests by doing: 75 | // defer VerifyNone(t) 76 | func VerifyNone(t TestingT, options ...Option) { 77 | if err := Find(options...); err != nil { 78 | t.Error(err) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /vendor/go.uber.org/goleak/testmain.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package goleak 22 | 23 | import ( 24 | "fmt" 25 | "io" 26 | "os" 27 | ) 28 | 29 | // Variables for stubbing in unit tests. 30 | var ( 31 | _osExit = os.Exit 32 | _osStderr io.Writer = os.Stderr 33 | ) 34 | 35 | // TestingM is the minimal subset of testing.M that we use. 36 | type TestingM interface { 37 | Run() int 38 | } 39 | 40 | // VerifyTestMain can be used in a TestMain function for package tests to 41 | // verify that there were no goroutine leaks. 42 | // To use it, your TestMain function should look like: 43 | // 44 | // func TestMain(m *testing.M) { 45 | // goleak.VerifyTestMain(m) 46 | // } 47 | // 48 | // See https://golang.org/pkg/testing/#hdr-Main for more details. 49 | // 50 | // This will run all tests as per normal, and if they were successful, look 51 | // for any goroutine leaks and fail the tests if any leaks were found. 52 | func VerifyTestMain(m TestingM, options ...Option) { 53 | exitCode := m.Run() 54 | 55 | if exitCode == 0 { 56 | if err := Find(options...); err != nil { 57 | fmt.Fprintf(_osStderr, "goleak: Errors on successful test run: %v\n", err) 58 | exitCode = 1 59 | } 60 | } 61 | 62 | _osExit(exitCode) 63 | } 64 | -------------------------------------------------------------------------------- /vendor/go.uber.org/goleak/tracestack_new.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //go:build go1.16 22 | // +build go1.16 23 | 24 | package goleak 25 | 26 | import ( 27 | "strings" 28 | 29 | "go.uber.org/goleak/internal/stack" 30 | ) 31 | 32 | func isTraceStack(s stack.Stack) bool { 33 | return strings.Contains(s.Full(), "runtime.ReadTrace") 34 | } 35 | -------------------------------------------------------------------------------- /vendor/go.uber.org/goleak/tracestack_old.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //go:build !go1.16 22 | // +build !go1.16 23 | 24 | package goleak 25 | 26 | import ( 27 | "strings" 28 | 29 | "go.uber.org/goleak/internal/stack" 30 | ) 31 | 32 | func isTraceStack(s stack.Stack) bool { 33 | if f := s.FirstFunction(); f != "runtime.goparkunlock" { 34 | return false 35 | } 36 | 37 | return strings.Contains(s.Full(), "runtime.ReadTrace") 38 | } 39 | -------------------------------------------------------------------------------- /vendor/golang.org/x/sync/AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at http://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/sync/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the Go contributors. 2 | # The master list of contributors is in the main Go distribution, 3 | # visible at http://tip.golang.org/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/sync/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/sync/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/sync/errgroup/errgroup.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package errgroup provides synchronization, error propagation, and Context 6 | // cancelation for groups of goroutines working on subtasks of a common task. 7 | package errgroup 8 | 9 | import ( 10 | "context" 11 | "sync" 12 | ) 13 | 14 | // A Group is a collection of goroutines working on subtasks that are part of 15 | // the same overall task. 16 | // 17 | // A zero Group is valid and does not cancel on error. 18 | type Group struct { 19 | cancel func() 20 | 21 | wg sync.WaitGroup 22 | 23 | errOnce sync.Once 24 | err error 25 | } 26 | 27 | // WithContext returns a new Group and an associated Context derived from ctx. 28 | // 29 | // The derived Context is canceled the first time a function passed to Go 30 | // returns a non-nil error or the first time Wait returns, whichever occurs 31 | // first. 32 | func WithContext(ctx context.Context) (*Group, context.Context) { 33 | ctx, cancel := context.WithCancel(ctx) 34 | return &Group{cancel: cancel}, ctx 35 | } 36 | 37 | // Wait blocks until all function calls from the Go method have returned, then 38 | // returns the first non-nil error (if any) from them. 39 | func (g *Group) Wait() error { 40 | g.wg.Wait() 41 | if g.cancel != nil { 42 | g.cancel() 43 | } 44 | return g.err 45 | } 46 | 47 | // Go calls the given function in a new goroutine. 48 | // 49 | // The first call to return a non-nil error cancels the group; its error will be 50 | // returned by Wait. 51 | func (g *Group) Go(f func() error) { 52 | g.wg.Add(1) 53 | 54 | go func() { 55 | defer g.wg.Done() 56 | 57 | if err := f(); err != nil { 58 | g.errOnce.Do(func() { 59 | g.err = err 60 | if g.cancel != nil { 61 | g.cancel() 62 | } 63 | }) 64 | } 65 | }() 66 | } 67 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v3/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | This project is covered by two different licenses: MIT and Apache. 3 | 4 | #### MIT License #### 5 | 6 | The following files were ported to Go from C files of libyaml, and thus 7 | are still covered by their original MIT license, with the additional 8 | copyright staring in 2011 when the project was ported over: 9 | 10 | apic.go emitterc.go parserc.go readerc.go scannerc.go 11 | writerc.go yamlh.go yamlprivateh.go 12 | 13 | Copyright (c) 2006-2010 Kirill Simonov 14 | Copyright (c) 2006-2011 Kirill Simonov 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy of 17 | this software and associated documentation files (the "Software"), to deal in 18 | the Software without restriction, including without limitation the rights to 19 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 20 | of the Software, and to permit persons to whom the Software is furnished to do 21 | so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. 33 | 34 | ### Apache License ### 35 | 36 | All the remaining project files are covered by the Apache license: 37 | 38 | Copyright (c) 2011-2019 Canonical Ltd 39 | 40 | Licensed under the Apache License, Version 2.0 (the "License"); 41 | you may not use this file except in compliance with the License. 42 | You may obtain a copy of the License at 43 | 44 | http://www.apache.org/licenses/LICENSE-2.0 45 | 46 | Unless required by applicable law or agreed to in writing, software 47 | distributed under the License is distributed on an "AS IS" BASIS, 48 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 49 | See the License for the specific language governing permissions and 50 | limitations under the License. 51 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v3/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2011-2016 Canonical Ltd. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v3/go.mod: -------------------------------------------------------------------------------- 1 | module "gopkg.in/yaml.v3" 2 | 3 | require ( 4 | "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405 5 | ) 6 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v3/writerc.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2011-2019 Canonical Ltd 3 | // Copyright (c) 2006-2010 Kirill Simonov 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | // of the Software, and to permit persons to whom the Software is furnished to do 10 | // so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | package yaml 24 | 25 | // Set the writer error and return false. 26 | func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { 27 | emitter.error = yaml_WRITER_ERROR 28 | emitter.problem = problem 29 | return false 30 | } 31 | 32 | // Flush the output buffer. 33 | func yaml_emitter_flush(emitter *yaml_emitter_t) bool { 34 | if emitter.write_handler == nil { 35 | panic("write handler not set") 36 | } 37 | 38 | // Check if the buffer is empty. 39 | if emitter.buffer_pos == 0 { 40 | return true 41 | } 42 | 43 | if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { 44 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 45 | } 46 | emitter.buffer_pos = 0 47 | return true 48 | } 49 | -------------------------------------------------------------------------------- /vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # github.com/cenkalti/backoff/v4 v4.1.1 2 | github.com/cenkalti/backoff/v4 3 | # github.com/davecgh/go-spew v1.1.1 4 | github.com/davecgh/go-spew/spew 5 | # github.com/emirpasic/gods v1.12.0 6 | github.com/emirpasic/gods/containers 7 | github.com/emirpasic/gods/lists 8 | github.com/emirpasic/gods/lists/arraylist 9 | github.com/emirpasic/gods/trees 10 | github.com/emirpasic/gods/trees/binaryheap 11 | github.com/emirpasic/gods/utils 12 | # github.com/pmezard/go-difflib v1.0.0 13 | github.com/pmezard/go-difflib/difflib 14 | # github.com/stretchr/objx v0.4.0 15 | github.com/stretchr/objx 16 | # github.com/stretchr/testify v1.8.0 17 | github.com/stretchr/testify/assert 18 | github.com/stretchr/testify/mock 19 | # github.com/teivah/onecontext v0.0.0-20200513185103-40f981bfd775 20 | github.com/teivah/onecontext 21 | # go.uber.org/goleak v1.1.12 22 | go.uber.org/goleak 23 | go.uber.org/goleak/internal/stack 24 | # golang.org/x/sync v0.0.0-20210220032951-036812b2e83c 25 | golang.org/x/sync/errgroup 26 | # gopkg.in/yaml.v3 v3.0.1 27 | gopkg.in/yaml.v3 28 | --------------------------------------------------------------------------------