summary refs log tree commit diff stats
path: root/worker/imap
Commit message (Expand)AuthorAgeFilesLines
* s/aerc2/aerc/gDrew DeVault2019-05-176-6/+6
* Copy sent emails to the Sent folderDrew DeVault2019-05-152-0/+31
* Implement :copy (aka :cp)Drew DeVault2019-05-142-0/+18
* Handle external message deletionsDrew DeVault2019-05-131-0/+7
* Handle incoming emails gracefullyDrew DeVault2019-05-132-3/+23
* worker/imap: use the IMAP connection from a single goroutineSimon Ser2019-04-293-86/+77
* Make message viewer real, part twoDrew DeVault2019-03-311-11/+14
* Rename FetchMessageBodies to FetchFullMessagesDrew DeVault2019-03-312-12/+12
* Make the message viewer real, part oneDrew DeVault2019-03-312-6/+28
* Don't parse mail in worker; send a reader insteadDrew DeVault2019-03-311-10/+2
* Pull BodyStructure up from IMAP workerDrew DeVault2019-03-311-4/+6
* Add body fetching support codeDrew DeVault2019-03-292-15/+48
* Implement :delete-messageDrew DeVault2019-03-204-1/+50
* Display message subjects in message listDrew DeVault2019-03-142-0/+48
* Implement message store side of message fetchingDrew DeVault2019-03-141-7/+2
* Fetch valid UIDs from server after opening dirDrew DeVault2019-03-102-3/+43
* Add name to DirectoryInfo messagesDrew DeVault2019-01-131-1/+2
* Issue IMAP SELECT commandDrew DeVault2019-01-132-1/+39
* Tidy up list.goDrew DeVault2018-02-021-22/+15
* Refactoring; consume listing responseDrew DeVault2018-02-012-25/+26
* Implement (most of) mailbox listingDrew DeVault2018-02-012-3/+40
* Reduce boilerplate in worker/UIDrew DeVault2018-02-011-34/+15
* Add certificate approval flowDrew DeVault2018-01-311-26/+55
* Improve loggingDrew DeVault2018-01-311-5/+23
* Connect to IMAP server, login and idleemersion2018-01-141-11/+111
* Move worker into account tabDrew DeVault2018-01-111-7/+2
* Renderer scaffoldingDrew DeVault2018-01-101-2/+0
* Misc idiomatic fixesemersion2018-01-101-5/+5
* Sleep main and worker loops on idleDrew DeVault2018-01-101-1/+2
* Parse account configurationDrew DeVault2018-01-091-3/+3
* Initial pass on worker/UI message passingDrew DeVault2018-01-091-0/+58
hawan/blame/src/io/promise.nim?id=34cffe0b658511ac18429c41453c24505c47c6d4'>^
80b45c0d ^



80b45c0d ^

58dee598 ^

80b45c0d ^

607545c8 ^











80b45c0d ^
80b45c0d ^


0edb5d32 ^
80b45c0d ^


80b45c0d ^

36390a56 ^
80b45c0d ^


36390a56 ^


80b45c0d ^


80b45c0d ^




36390a56 ^


80b45c0d ^

eff1e064 ^
eff1e064 ^





80b45c0d ^
80b45c0d ^





36390a56 ^


80b45c0d ^
58dee598 ^
17097052 ^

17097052 ^










58dee598 ^










1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
                 
 
                
 
    
                      

                                                        



                                       
                        










                                                       


                                   





                                                                                     
                                                        



                                                                   
                                                





                                      

                         
                    
                                     


                          
                      













                                                    




                                          



                                                                               

                               

                                        

                     











                                                                           
                                                                                    


                                              
                       


                                                                                            

                         
                 


                          


                       


                                                                                                  




                           


                       

             
                                                                                        





                           
                                                                                                 





                           


                       
             
 

                                                                         










                              










                                                      
import std/tables

import types/opt

type
  PromiseState* = enum
    PROMISE_PENDING, PROMISE_FULFILLED, PROMISE_REJECTED

  EmptyPromise* = ref object of RootObj
    cb: (proc())
    next: EmptyPromise
    opaque: pointer
    state*: PromiseState

  Promise*[T] = ref object of EmptyPromise
    res: T
    get: GetValueProc[T]

  GetValueProc[T] = (proc(opaque: pointer, res: var T))

  PromiseMap* = object
    tab: Table[int, EmptyPromise]
    opaque*: pointer

proc newPromise*[T](): Promise[T] =
  return Promise[T]()

proc newPromiseMap*(opaque: pointer): PromiseMap =
  return PromiseMap(
    opaque: opaque
  )

proc addPromise*[T](map: var PromiseMap, id: int, get: GetValueProc[T]): Promise[T] =
  let promise = Promise[T](get: get, opaque: map.opaque)
  map.tab[id] = promise
  return promise

proc addEmptyPromise*(map: var PromiseMap, id: int): EmptyPromise =
  let promise = EmptyPromise(opaque: map.opaque)
  map.tab[id] = promise
  return promise

proc resolve*(promise: EmptyPromise) =
  var promise = promise
  while true:
    if promise.cb != nil:
      promise.cb()
    promise.cb = nil
    promise.state = PROMISE_FULFILLED
    promise = promise.next
    if promise == nil:
      break
    promise.next = nil

proc resolve*[T](promise: Promise[T], res: T) =
  if promise.cb != nil:
    if promise.get != nil:
      promise.get(promise.opaque, promise.res)
      promise.get = nil
    promise.res = res
    promise.resolve()

proc resolve*(map: var PromiseMap, promiseid: int) =
  var promise: EmptyPromise
  if map.tab.pop(promiseid, promise):
    promise.resolve()

proc newResolvedPromise*(): EmptyPromise =
  let res = EmptyPromise()
  res.resolve()
  return res

func empty*(map: PromiseMap): bool =
  map.tab.len == 0

proc then*(promise: EmptyPromise, cb: (proc())): EmptyPromise {.discardable.} =
  promise.cb = cb
  promise.next = EmptyPromise()
  if promise.state == PROMISE_FULFILLED:
    promise.resolve()
  return promise.next

proc then*(promise: EmptyPromise, cb: (proc(): EmptyPromise)): EmptyPromise
    {.discardable.} =
  let next = EmptyPromise()
  promise.then(proc() =
    var p2 = cb()
    if p2 != nil:
      p2.then(proc() =
        next.resolve())
    else:
      next.resolve())
  return next

proc then*[T](promise: Promise[T], cb: (proc(x: T))): EmptyPromise {.discardable.} =
  return promise.then(proc() =
    if promise.get != nil:
      promise.get(promise.opaque, promise.res)
      promise.get = nil
    cb(promise.res))

proc then*[T](promise: EmptyPromise, cb: (proc(): Promise[T])): Promise[T] {.discardable.} =
  let next = Promise[T]()
  promise.then(proc() =
    var p2 = cb()
    if p2 != nil:
      p2.then(proc(x: T) =
        next.res = x
        next.resolve())
    else:
      next.resolve())
  return next

proc then*[T](promise: Promise[T], cb: (proc(x: T): EmptyPromise)): EmptyPromise {.discardable.} =
  let next = EmptyPromise()
  promise.then(proc(x: T) =
    let p2 = cb(x)
    if p2 != nil:
      p2.then(proc() =
        next.resolve())
    else:
      next.resolve())
  return next

proc then*[T, U](promise: Promise[T], cb: (proc(x: T): U)): Promise[U] {.discardable.} =
  let next = Promise[U]()
  promise.then(proc(x: T) =
    next.res = cb(x)
    next.resolve())
  return next

proc then*[T, U](promise: Promise[T], cb: (proc(x: T): Promise[U])): Promise[U] {.discardable.} =
  let next = Promise[U]()
  promise.then(proc(x: T) =
    let p2 = cb(x)
    if p2 != nil:
      p2.then(proc(y: U) =
        next.res = y
        next.resolve())
    else:
      next.resolve())
  return next

proc then*[T, U](promise: Promise[T], cb: (proc(x: T): Opt[Promise[U]])):
    Promise[Opt[U]] {.discardable.} =
  let next = Promise[Opt[U]]()
  promise.then(proc(x: T) =
    let p2 = cb(x)
    if p2.isOk:
      p2.get.then(proc(y: U) =
        next.res = opt(y)
        next.resolve())
    else:
      next.resolve())
  return next

proc all*(promises: seq[EmptyPromise]): EmptyPromise =
  let res = EmptyPromise()
  var i = 0
  for promise in promises:
    promise.then(proc() =
      inc i
      if i == promises.len:
        res.resolve())
  if promises.len == 0:
    res.resolve()
  return res