| 1 | // This module defines the Context type, which carries deadlines, cancellation signals, |
| 2 | // and other request-scoped values across API boundaries and between processes. |
| 3 | // Based on: https://github.com/golang/go/tree/master/src/context |
| 4 | // Last commit: https://github.com/golang/go/commit/52bf14e0e8bdcd73f1ddfb0c4a1d0200097d3ba2 |
| 5 | module context |
| 6 | |
| 7 | import time |
| 8 | |
| 9 | const cancel_context_key = Key('context.CancelContext') |
| 10 | |
| 11 | // canceled is the error returned by Context.err when the context is canceled. |
| 12 | const canceled = error('context canceled') |
| 13 | |
| 14 | // deadline_exceeded is the error returned by Context.err when the context's |
| 15 | // deadline passes. |
| 16 | const deadline_exceeded = error('context deadline exceeded') |
| 17 | |
| 18 | // Key represents the type for the ValueContext key |
| 19 | pub type Key = bool | f32 | f64 | i16 | i64 | i8 | int | string | u16 | u32 | u64 | u8 | voidptr |
| 20 | |
| 21 | // Any represents a generic type for the ValueContext |
| 22 | pub interface Any {} |
| 23 | |
| 24 | // `Context` is an interface that defined the minimum required functionality |
| 25 | // for a Context. |
| 26 | // |
| 27 | // `deadline()` returns the time when work done on behalf of this context |
| 28 | // should be canceled. deadline returns none when no deadline is |
| 29 | // set. Successive calls to deadline return the same results. |
| 30 | // |
| 31 | // `value(key)` returns an Optional that wraps the value associated with this context for key. |
| 32 | // It returns none if no value is associated with key. Successive calls to Value with |
| 33 | // the same key returns the same result. |
| 34 | // |
| 35 | // Use context values only for request-scoped data that transits |
| 36 | // processes and API boundaries, not for passing optional parameters to |
| 37 | // functions. |
| 38 | // |
| 39 | // A key identifies a specific value in a Context. Functions that wish |
| 40 | // to store values in Context typically allocate a key in a global |
| 41 | // variable then use that key as the argument to context.with_value and |
| 42 | // Context.value. A key can be any type that supports equality; |
| 43 | // modules should define keys as an unexported type to avoid |
| 44 | // collisions. |
| 45 | // |
| 46 | // `done()` returns a channel that's closed when work done on behalf of this |
| 47 | // context should be canceled. done may return a closed channel if this context can |
| 48 | // never be canceled. Successive calls to done return the same value. |
| 49 | // The close of the done channel may happen asynchronously, |
| 50 | // after the cancel function returns. |
| 51 | // |
| 52 | // with_cancel arranges for done to be closed when cancel is called; |
| 53 | // with_deadline arranges for done to be closed when the deadline |
| 54 | // expires; with_timeout arranges for done to be closed when the timeout |
| 55 | // elapses. |
| 56 | // |
| 57 | // `err()` returns an IError based on some conditions |
| 58 | // If done is not yet closed, err returns none. |
| 59 | // If done is closed, err returns a non-none error explaining why: |
| 60 | // canceled if the context was canceled |
| 61 | // or deadline_exceeded if the context's deadline passed. |
| 62 | // After err returns a non-none error, successive calls to err return the same error. |
| 63 | pub interface Context { |
| 64 | deadline() ?time.Time |
| 65 | value(key Key) ?Any |
| 66 | mut: |
| 67 | done() chan int |
| 68 | err() IError |
| 69 | } |
| 70 | |
| 71 | // str returns the `str` method of the corresponding Context struct |
| 72 | pub fn (ctx &Context) str() string { |
| 73 | // since `Context` is an interface we have to manually match every possible |
| 74 | // type that implements `Context` if we want to use a `Context` as a field in a struct |
| 75 | // since the `Context` interface has to implement its own `str` method. |
| 76 | match ctx { |
| 77 | BackgroundContext { |
| 78 | return ctx.str() |
| 79 | } |
| 80 | EmptyContext { |
| 81 | return ctx.str() |
| 82 | } |
| 83 | TodoContext { |
| 84 | return ctx.str() |
| 85 | } |
| 86 | CancelContext { |
| 87 | return ctx.str() |
| 88 | } |
| 89 | CauseContext { |
| 90 | return ctx.str() |
| 91 | } |
| 92 | TimerContext { |
| 93 | return ctx.str() |
| 94 | } |
| 95 | ValueContext { |
| 96 | return ctx.str() |
| 97 | } |
| 98 | else { |
| 99 | return context_name(ctx) |
| 100 | } |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | fn context_name(ctx Context) string { |
| 105 | return typeof(ctx) |
| 106 | } |
| 107 | |