Software / code / prosody
Annotate
util/iterators.lua @ 13801:a5d5fefb8b68 13.0
mod_tls: Enable Prosody's certificate checking for incoming s2s connections (fixes #1916) (thanks Damian, Zash)
Various options in Prosody allow control over the behaviour of the certificate
verification process For example, some deployments choose to allow falling
back to traditional "dialback" authentication (XEP-0220), while others verify
via DANE, hard-coded fingerprints, or other custom plugins.
Implementing this flexibility requires us to override OpenSSL's default
certificate verification, to allow Prosody to verify the certificate itself,
apply custom policies and make decisions based on the outcome.
To enable our custom logic, we have to suppress OpenSSL's default behaviour of
aborting the connection with a TLS alert message. With LuaSec, this can be
achieved by using the verifyext "lsec_continue" flag.
We also need to use the lsec_ignore_purpose flag, because XMPP s2s uses server
certificates as "client" certificates (for mutual TLS verification in outgoing
s2s connections).
Commit 99d2100d2918 moved these settings out of the defaults and into mod_s2s,
because we only really need these changes for s2s, and they should be opt-in,
rather than automatically applied to all TLS services we offer.
That commit was incomplete, because it only added the flags for incoming
direct TLS connections. StartTLS connections are handled by mod_tls, which was
not applying the lsec_* flags. It previously worked because they were already
in the defaults.
This resulted in incoming s2s connections with "invalid" certificates being
aborted early by OpenSSL, even if settings such as `s2s_secure_auth = false`
or DANE were present in the config.
Outgoing s2s connections inherit verify "none" from the defaults, which means
OpenSSL will receive the cert but will not terminate the connection when it is
deemed invalid. This means we don't need lsec_continue there, and we also
don't need lsec_ignore_purpose (because the remote peer is a "server").
Wondering why we can't just use verify "none" for incoming s2s? It's because
in that mode, OpenSSL won't request a certificate from the peer for incoming
connections. Setting verify "peer" is how you ask OpenSSL to request a
certificate from the client, but also what triggers its built-in verification.
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Tue, 01 Apr 2025 17:26:56 +0100 |
| parent | 12744:e894677359e5 |
| rev | line source |
|---|---|
|
1522
569d58d21612
Add copyright header to those files missing one
Matthew Wild <mwild1@gmail.com>
parents:
919
diff
changeset
|
1 -- Prosody IM |
|
2923
b7049746bd29
Update copyright headers for 2010
Matthew Wild <mwild1@gmail.com>
parents:
1660
diff
changeset
|
2 -- Copyright (C) 2008-2010 Matthew Wild |
|
b7049746bd29
Update copyright headers for 2010
Matthew Wild <mwild1@gmail.com>
parents:
1660
diff
changeset
|
3 -- Copyright (C) 2008-2010 Waqas Hussain |
|
5776
bd0ff8ae98a8
Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents:
5583
diff
changeset
|
4 -- |
|
1522
569d58d21612
Add copyright header to those files missing one
Matthew Wild <mwild1@gmail.com>
parents:
919
diff
changeset
|
5 -- This project is MIT/X11 licensed. Please see the |
|
569d58d21612
Add copyright header to those files missing one
Matthew Wild <mwild1@gmail.com>
parents:
919
diff
changeset
|
6 -- COPYING file in the source package for more information. |
|
569d58d21612
Add copyright header to those files missing one
Matthew Wild <mwild1@gmail.com>
parents:
919
diff
changeset
|
7 -- |
|
569d58d21612
Add copyright header to those files missing one
Matthew Wild <mwild1@gmail.com>
parents:
919
diff
changeset
|
8 |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
9 --[[ Iterators ]]-- |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
10 |
|
4545
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
11 local it = {}; |
|
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
12 |
|
5581
167c1da54606
util.iterators: Various fixes and improvements, primarily use pack() where it should be used.
Matthew Wild <mwild1@gmail.com>
parents:
5468
diff
changeset
|
13 local t_insert = table.insert; |
|
9688
eade1316728e
util.iterators: Use pack from table.pack
Kim Alvefur <zash@zash.se>
parents:
9327
diff
changeset
|
14 local next = next; |
|
12589
39ae08180c81
compat: Remove handling of Lua 5.1 location of 'unpack' function
Kim Alvefur <zash@zash.se>
parents:
9688
diff
changeset
|
15 local unpack = table.unpack; |
|
12590
5eaf77114fdb
compat: Use table.pack (there since Lua 5.2) over our util.table
Kim Alvefur <zash@zash.se>
parents:
12589
diff
changeset
|
16 local pack = table.pack; |
|
8797
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
17 local type = type; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
18 local table, setmetatable = table, setmetatable; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
19 |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
20 local _ENV = nil; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
21 --luacheck: std none |
|
5581
167c1da54606
util.iterators: Various fixes and improvements, primarily use pack() where it should be used.
Matthew Wild <mwild1@gmail.com>
parents:
5468
diff
changeset
|
22 |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
23 -- Reverse an iterator |
|
4545
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
24 function it.reverse(f, s, var) |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
25 local results = {}; |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
26 |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
27 -- First call the normal iterator |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
28 while true do |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
29 local ret = { f(s, var) }; |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
30 var = ret[1]; |
|
7351
11434c46b7b7
util.iterators: Normalize indentation
Kim Alvefur <zash@zash.se>
parents:
7309
diff
changeset
|
31 if var == nil then break; end |
|
5581
167c1da54606
util.iterators: Various fixes and improvements, primarily use pack() where it should be used.
Matthew Wild <mwild1@gmail.com>
parents:
5468
diff
changeset
|
32 t_insert(results, 1, ret); |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
33 end |
|
5776
bd0ff8ae98a8
Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents:
5583
diff
changeset
|
34 |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
35 -- Then return our reverse one |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
36 local i,max = 0, #results; |
|
7260
a9ef93bc81d9
util.iterators: Variable renaming to avoid shadowing [luacheck]
Matthew Wild <mwild1@gmail.com>
parents:
7258
diff
changeset
|
37 return function (_results) |
|
7351
11434c46b7b7
util.iterators: Normalize indentation
Kim Alvefur <zash@zash.se>
parents:
7309
diff
changeset
|
38 if i<max then |
|
11434c46b7b7
util.iterators: Normalize indentation
Kim Alvefur <zash@zash.se>
parents:
7309
diff
changeset
|
39 i = i + 1; |
|
11434c46b7b7
util.iterators: Normalize indentation
Kim Alvefur <zash@zash.se>
parents:
7309
diff
changeset
|
40 return unpack(_results[i]); |
|
11434c46b7b7
util.iterators: Normalize indentation
Kim Alvefur <zash@zash.se>
parents:
7309
diff
changeset
|
41 end |
|
11434c46b7b7
util.iterators: Normalize indentation
Kim Alvefur <zash@zash.se>
parents:
7309
diff
changeset
|
42 end, results; |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
43 end |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
44 |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
45 -- Iterate only over keys in a table |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
46 local function _keys_it(t, key) |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
47 return (next(t, key)); |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
48 end |
|
4545
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
49 function it.keys(t) |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
50 return _keys_it, t; |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
51 end |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
52 |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
53 -- Iterate only over values in a table |
|
4545
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
54 function it.values(t) |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
55 local key, val; |
|
7260
a9ef93bc81d9
util.iterators: Variable renaming to avoid shadowing [luacheck]
Matthew Wild <mwild1@gmail.com>
parents:
7258
diff
changeset
|
56 return function (_t) |
|
a9ef93bc81d9
util.iterators: Variable renaming to avoid shadowing [luacheck]
Matthew Wild <mwild1@gmail.com>
parents:
7258
diff
changeset
|
57 key, val = next(_t, key); |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
58 return val; |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
59 end, t; |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
60 end |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
61 |
|
7355
4b4cf0167391
util.iterators: Add iterator wrapper that works like select(n, ...) applied to original iterator
Kim Alvefur <zash@zash.se>
parents:
7351
diff
changeset
|
62 -- Iterate over the n:th return value |
|
4b4cf0167391
util.iterators: Add iterator wrapper that works like select(n, ...) applied to original iterator
Kim Alvefur <zash@zash.se>
parents:
7351
diff
changeset
|
63 function it.select(n, f, s, var) |
|
4b4cf0167391
util.iterators: Add iterator wrapper that works like select(n, ...) applied to original iterator
Kim Alvefur <zash@zash.se>
parents:
7351
diff
changeset
|
64 return function (_s) |
|
4b4cf0167391
util.iterators: Add iterator wrapper that works like select(n, ...) applied to original iterator
Kim Alvefur <zash@zash.se>
parents:
7351
diff
changeset
|
65 local ret = pack(f(_s, var)); |
|
4b4cf0167391
util.iterators: Add iterator wrapper that works like select(n, ...) applied to original iterator
Kim Alvefur <zash@zash.se>
parents:
7351
diff
changeset
|
66 var = ret[1]; |
|
4b4cf0167391
util.iterators: Add iterator wrapper that works like select(n, ...) applied to original iterator
Kim Alvefur <zash@zash.se>
parents:
7351
diff
changeset
|
67 return ret[n]; |
|
4b4cf0167391
util.iterators: Add iterator wrapper that works like select(n, ...) applied to original iterator
Kim Alvefur <zash@zash.se>
parents:
7351
diff
changeset
|
68 end, s, var; |
|
4b4cf0167391
util.iterators: Add iterator wrapper that works like select(n, ...) applied to original iterator
Kim Alvefur <zash@zash.se>
parents:
7351
diff
changeset
|
69 end |
|
4b4cf0167391
util.iterators: Add iterator wrapper that works like select(n, ...) applied to original iterator
Kim Alvefur <zash@zash.se>
parents:
7351
diff
changeset
|
70 |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
71 -- Given an iterator, iterate only over unique items |
|
4545
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
72 function it.unique(f, s, var) |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
73 local set = {}; |
|
5776
bd0ff8ae98a8
Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents:
5583
diff
changeset
|
74 |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
75 return function () |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
76 while true do |
|
5581
167c1da54606
util.iterators: Various fixes and improvements, primarily use pack() where it should be used.
Matthew Wild <mwild1@gmail.com>
parents:
5468
diff
changeset
|
77 local ret = pack(f(s, var)); |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
78 var = ret[1]; |
|
7351
11434c46b7b7
util.iterators: Normalize indentation
Kim Alvefur <zash@zash.se>
parents:
7309
diff
changeset
|
79 if var == nil then break; end |
|
11434c46b7b7
util.iterators: Normalize indentation
Kim Alvefur <zash@zash.se>
parents:
7309
diff
changeset
|
80 if not set[var] then |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
81 set[var] = true; |
|
5581
167c1da54606
util.iterators: Various fixes and improvements, primarily use pack() where it should be used.
Matthew Wild <mwild1@gmail.com>
parents:
5468
diff
changeset
|
82 return unpack(ret, 1, ret.n); |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
83 end |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
84 end |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
85 end; |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
86 end |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
87 |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
88 --[[ Return the number of items an iterator returns ]]-- |
|
4545
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
89 function it.count(f, s, var) |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
90 local x = 0; |
|
5776
bd0ff8ae98a8
Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents:
5583
diff
changeset
|
91 |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
92 while true do |
|
5583
78dbece77ce8
util.iterators: Small fix for variable scoping issue
Matthew Wild <mwild1@gmail.com>
parents:
5582
diff
changeset
|
93 var = f(s, var); |
|
7351
11434c46b7b7
util.iterators: Normalize indentation
Kim Alvefur <zash@zash.se>
parents:
7309
diff
changeset
|
94 if var == nil then break; end |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
95 x = x + 1; |
|
3540
bc139431830b
Monster whitespace commit (beware the whitespace monster).
Waqas Hussain <waqas20@gmail.com>
parents:
3392
diff
changeset
|
96 end |
|
5776
bd0ff8ae98a8
Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents:
5583
diff
changeset
|
97 |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
98 return x; |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
99 end |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
100 |
|
1659
6092fc9b078b
util.iterators: Add head() iterator, to return the first n items
Matthew Wild <mwild1@gmail.com>
parents:
1522
diff
changeset
|
101 -- Return the first n items an iterator returns |
|
4545
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
102 function it.head(n, f, s, var) |
|
1659
6092fc9b078b
util.iterators: Add head() iterator, to return the first n items
Matthew Wild <mwild1@gmail.com>
parents:
1522
diff
changeset
|
103 local c = 0; |
|
7260
a9ef93bc81d9
util.iterators: Variable renaming to avoid shadowing [luacheck]
Matthew Wild <mwild1@gmail.com>
parents:
7258
diff
changeset
|
104 return function (_s, _var) |
|
1659
6092fc9b078b
util.iterators: Add head() iterator, to return the first n items
Matthew Wild <mwild1@gmail.com>
parents:
1522
diff
changeset
|
105 if c >= n then |
|
6092fc9b078b
util.iterators: Add head() iterator, to return the first n items
Matthew Wild <mwild1@gmail.com>
parents:
1522
diff
changeset
|
106 return nil; |
|
6092fc9b078b
util.iterators: Add head() iterator, to return the first n items
Matthew Wild <mwild1@gmail.com>
parents:
1522
diff
changeset
|
107 end |
|
6092fc9b078b
util.iterators: Add head() iterator, to return the first n items
Matthew Wild <mwild1@gmail.com>
parents:
1522
diff
changeset
|
108 c = c + 1; |
|
7260
a9ef93bc81d9
util.iterators: Variable renaming to avoid shadowing [luacheck]
Matthew Wild <mwild1@gmail.com>
parents:
7258
diff
changeset
|
109 return f(_s, _var); |
|
7258
b8f60dd8e99a
util.iterators: Return initial var from upstream iterator [luacheck]
Matthew Wild <mwild1@gmail.com>
parents:
7257
diff
changeset
|
110 end, s, var; |
|
1659
6092fc9b078b
util.iterators: Add head() iterator, to return the first n items
Matthew Wild <mwild1@gmail.com>
parents:
1522
diff
changeset
|
111 end |
|
6092fc9b078b
util.iterators: Add head() iterator, to return the first n items
Matthew Wild <mwild1@gmail.com>
parents:
1522
diff
changeset
|
112 |
|
3392
6e31b49c4ab8
util.iterators: Add skip() to skip the first n items of an iterator
Matthew Wild <mwild1@gmail.com>
parents:
2923
diff
changeset
|
113 -- Skip the first n items an iterator returns |
|
4545
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
114 function it.skip(n, f, s, var) |
|
7260
a9ef93bc81d9
util.iterators: Variable renaming to avoid shadowing [luacheck]
Matthew Wild <mwild1@gmail.com>
parents:
7258
diff
changeset
|
115 for _ = 1, n do |
|
3392
6e31b49c4ab8
util.iterators: Add skip() to skip the first n items of an iterator
Matthew Wild <mwild1@gmail.com>
parents:
2923
diff
changeset
|
116 var = f(s, var); |
|
6e31b49c4ab8
util.iterators: Add skip() to skip the first n items of an iterator
Matthew Wild <mwild1@gmail.com>
parents:
2923
diff
changeset
|
117 end |
|
6e31b49c4ab8
util.iterators: Add skip() to skip the first n items of an iterator
Matthew Wild <mwild1@gmail.com>
parents:
2923
diff
changeset
|
118 return f, s, var; |
|
6e31b49c4ab8
util.iterators: Add skip() to skip the first n items of an iterator
Matthew Wild <mwild1@gmail.com>
parents:
2923
diff
changeset
|
119 end |
|
6e31b49c4ab8
util.iterators: Add skip() to skip the first n items of an iterator
Matthew Wild <mwild1@gmail.com>
parents:
2923
diff
changeset
|
120 |
|
6e31b49c4ab8
util.iterators: Add skip() to skip the first n items of an iterator
Matthew Wild <mwild1@gmail.com>
parents:
2923
diff
changeset
|
121 -- Return the last n items an iterator returns |
|
4545
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
122 function it.tail(n, f, s, var) |
|
1660
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
123 local results, count = {}, 0; |
|
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
124 while true do |
|
5581
167c1da54606
util.iterators: Various fixes and improvements, primarily use pack() where it should be used.
Matthew Wild <mwild1@gmail.com>
parents:
5468
diff
changeset
|
125 local ret = pack(f(s, var)); |
|
1660
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
126 var = ret[1]; |
|
7351
11434c46b7b7
util.iterators: Normalize indentation
Kim Alvefur <zash@zash.se>
parents:
7309
diff
changeset
|
127 if var == nil then break; end |
|
1660
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
128 results[(count%n)+1] = ret; |
|
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
129 count = count + 1; |
|
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
130 end |
|
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
131 |
|
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
132 if n > count then n = count; end |
|
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
133 |
|
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
134 local pos = 0; |
|
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
135 return function () |
|
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
136 pos = pos + 1; |
|
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
137 if pos > n then return nil; end |
|
5581
167c1da54606
util.iterators: Various fixes and improvements, primarily use pack() where it should be used.
Matthew Wild <mwild1@gmail.com>
parents:
5468
diff
changeset
|
138 local ret = results[((count-1+pos)%n)+1]; |
|
167c1da54606
util.iterators: Various fixes and improvements, primarily use pack() where it should be used.
Matthew Wild <mwild1@gmail.com>
parents:
5468
diff
changeset
|
139 return unpack(ret, 1, ret.n); |
|
1660
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
140 end |
|
5582
7bc2009fdd0c
util.iterators: Add filter() to run results through a filter function
Matthew Wild <mwild1@gmail.com>
parents:
5581
diff
changeset
|
141 --return reverse(head(n, reverse(f, s, var))); -- ! |
|
7bc2009fdd0c
util.iterators: Add filter() to run results through a filter function
Matthew Wild <mwild1@gmail.com>
parents:
5581
diff
changeset
|
142 end |
|
7bc2009fdd0c
util.iterators: Add filter() to run results through a filter function
Matthew Wild <mwild1@gmail.com>
parents:
5581
diff
changeset
|
143 |
|
7bc2009fdd0c
util.iterators: Add filter() to run results through a filter function
Matthew Wild <mwild1@gmail.com>
parents:
5581
diff
changeset
|
144 function it.filter(filter, f, s, var) |
|
7bc2009fdd0c
util.iterators: Add filter() to run results through a filter function
Matthew Wild <mwild1@gmail.com>
parents:
5581
diff
changeset
|
145 if type(filter) ~= "function" then |
|
7bc2009fdd0c
util.iterators: Add filter() to run results through a filter function
Matthew Wild <mwild1@gmail.com>
parents:
5581
diff
changeset
|
146 local filter_value = filter; |
|
7bc2009fdd0c
util.iterators: Add filter() to run results through a filter function
Matthew Wild <mwild1@gmail.com>
parents:
5581
diff
changeset
|
147 function filter(x) return x ~= filter_value; end |
|
7bc2009fdd0c
util.iterators: Add filter() to run results through a filter function
Matthew Wild <mwild1@gmail.com>
parents:
5581
diff
changeset
|
148 end |
|
7260
a9ef93bc81d9
util.iterators: Variable renaming to avoid shadowing [luacheck]
Matthew Wild <mwild1@gmail.com>
parents:
7258
diff
changeset
|
149 return function (_s, _var) |
|
5582
7bc2009fdd0c
util.iterators: Add filter() to run results through a filter function
Matthew Wild <mwild1@gmail.com>
parents:
5581
diff
changeset
|
150 local ret; |
|
7260
a9ef93bc81d9
util.iterators: Variable renaming to avoid shadowing [luacheck]
Matthew Wild <mwild1@gmail.com>
parents:
7258
diff
changeset
|
151 repeat ret = pack(f(_s, _var)); |
|
7309
471189342890
util.iterators: Fix use of incorrect variable accidentally introduced in a9ef93bc81d9
Matthew Wild <mwild1@gmail.com>
parents:
7260
diff
changeset
|
152 _var = ret[1]; |
|
471189342890
util.iterators: Fix use of incorrect variable accidentally introduced in a9ef93bc81d9
Matthew Wild <mwild1@gmail.com>
parents:
7260
diff
changeset
|
153 until _var == nil or filter(unpack(ret, 1, ret.n)); |
|
5582
7bc2009fdd0c
util.iterators: Add filter() to run results through a filter function
Matthew Wild <mwild1@gmail.com>
parents:
5581
diff
changeset
|
154 return unpack(ret, 1, ret.n); |
|
7bc2009fdd0c
util.iterators: Add filter() to run results through a filter function
Matthew Wild <mwild1@gmail.com>
parents:
5581
diff
changeset
|
155 end, s, var; |
|
1660
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
156 end |
|
ae2f60a20428
util.iterators: Add tail() iterator, to return the last n items
Matthew Wild <mwild1@gmail.com>
parents:
1659
diff
changeset
|
157 |
|
5468
2660407c3b73
util.iterators: Add ripairs() (ipairs() in reverse) (thanks Maranda)
Matthew Wild <mwild1@gmail.com>
parents:
4545
diff
changeset
|
158 local function _ripairs_iter(t, key) if key > 1 then return key-1, t[key-1]; end end |
|
2660407c3b73
util.iterators: Add ripairs() (ipairs() in reverse) (thanks Maranda)
Matthew Wild <mwild1@gmail.com>
parents:
4545
diff
changeset
|
159 function it.ripairs(t) |
|
2660407c3b73
util.iterators: Add ripairs() (ipairs() in reverse) (thanks Maranda)
Matthew Wild <mwild1@gmail.com>
parents:
4545
diff
changeset
|
160 return _ripairs_iter, t, #t+1; |
|
2660407c3b73
util.iterators: Add ripairs() (ipairs() in reverse) (thanks Maranda)
Matthew Wild <mwild1@gmail.com>
parents:
4545
diff
changeset
|
161 end |
|
2660407c3b73
util.iterators: Add ripairs() (ipairs() in reverse) (thanks Maranda)
Matthew Wild <mwild1@gmail.com>
parents:
4545
diff
changeset
|
162 |
|
4386
ce769240f8ec
util.iterators: Add range(from, to)
Matthew Wild <mwild1@gmail.com>
parents:
3540
diff
changeset
|
163 local function _range_iter(max, curr) if curr < max then return curr + 1; end end |
|
4545
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
164 function it.range(x, y) |
|
4386
ce769240f8ec
util.iterators: Add range(from, to)
Matthew Wild <mwild1@gmail.com>
parents:
3540
diff
changeset
|
165 if not y then x, y = 1, x; end -- Default to 1..x if y not given |
|
ce769240f8ec
util.iterators: Add range(from, to)
Matthew Wild <mwild1@gmail.com>
parents:
3540
diff
changeset
|
166 return _range_iter, y, x-1; |
|
ce769240f8ec
util.iterators: Add range(from, to)
Matthew Wild <mwild1@gmail.com>
parents:
3540
diff
changeset
|
167 end |
|
ce769240f8ec
util.iterators: Add range(from, to)
Matthew Wild <mwild1@gmail.com>
parents:
3540
diff
changeset
|
168 |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
169 -- Convert the values returned by an iterator to an array |
|
4545
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
170 function it.to_array(f, s, var) |
|
7257
425bc672d60b
util.iterators: Don't replace var, as we should preserve var from the original iterator [luacheck]
Matthew Wild <mwild1@gmail.com>
parents:
7186
diff
changeset
|
171 local t = {}; |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
172 while true do |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
173 var = f(s, var); |
|
7351
11434c46b7b7
util.iterators: Normalize indentation
Kim Alvefur <zash@zash.se>
parents:
7309
diff
changeset
|
174 if var == nil then break; end |
|
5581
167c1da54606
util.iterators: Various fixes and improvements, primarily use pack() where it should be used.
Matthew Wild <mwild1@gmail.com>
parents:
5468
diff
changeset
|
175 t_insert(t, var); |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
176 end |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
177 return t; |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
178 end |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
179 |
|
9327
f6f1dec164b5
util.iterators: Add sorted_pairs() method
Matthew Wild <mwild1@gmail.com>
parents:
8797
diff
changeset
|
180 function it.sorted_pairs(t, sort_func) |
|
f6f1dec164b5
util.iterators: Add sorted_pairs() method
Matthew Wild <mwild1@gmail.com>
parents:
8797
diff
changeset
|
181 local keys = it.to_array(it.keys(t)); |
|
f6f1dec164b5
util.iterators: Add sorted_pairs() method
Matthew Wild <mwild1@gmail.com>
parents:
8797
diff
changeset
|
182 table.sort(keys, sort_func); |
|
f6f1dec164b5
util.iterators: Add sorted_pairs() method
Matthew Wild <mwild1@gmail.com>
parents:
8797
diff
changeset
|
183 local i = 0; |
|
f6f1dec164b5
util.iterators: Add sorted_pairs() method
Matthew Wild <mwild1@gmail.com>
parents:
8797
diff
changeset
|
184 return function () |
|
f6f1dec164b5
util.iterators: Add sorted_pairs() method
Matthew Wild <mwild1@gmail.com>
parents:
8797
diff
changeset
|
185 i = i + 1; |
|
f6f1dec164b5
util.iterators: Add sorted_pairs() method
Matthew Wild <mwild1@gmail.com>
parents:
8797
diff
changeset
|
186 local key = keys[i]; |
|
f6f1dec164b5
util.iterators: Add sorted_pairs() method
Matthew Wild <mwild1@gmail.com>
parents:
8797
diff
changeset
|
187 if key ~= nil then |
|
f6f1dec164b5
util.iterators: Add sorted_pairs() method
Matthew Wild <mwild1@gmail.com>
parents:
8797
diff
changeset
|
188 return key, t[key]; |
|
f6f1dec164b5
util.iterators: Add sorted_pairs() method
Matthew Wild <mwild1@gmail.com>
parents:
8797
diff
changeset
|
189 end |
|
f6f1dec164b5
util.iterators: Add sorted_pairs() method
Matthew Wild <mwild1@gmail.com>
parents:
8797
diff
changeset
|
190 end; |
|
f6f1dec164b5
util.iterators: Add sorted_pairs() method
Matthew Wild <mwild1@gmail.com>
parents:
8797
diff
changeset
|
191 end |
|
f6f1dec164b5
util.iterators: Add sorted_pairs() method
Matthew Wild <mwild1@gmail.com>
parents:
8797
diff
changeset
|
192 |
|
3540
bc139431830b
Monster whitespace commit (beware the whitespace monster).
Waqas Hussain <waqas20@gmail.com>
parents:
3392
diff
changeset
|
193 -- Treat the return of an iterator as key,value pairs, |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
194 -- and build a table |
|
4545
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
195 function it.to_table(f, s, var) |
|
4441
a01b7207cb37
util.iterators: it2table: Fix variable name
Matthew Wild <mwild1@gmail.com>
parents:
4386
diff
changeset
|
196 local t, var2 = {}; |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
197 while true do |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
198 var, var2 = f(s, var); |
|
7351
11434c46b7b7
util.iterators: Normalize indentation
Kim Alvefur <zash@zash.se>
parents:
7309
diff
changeset
|
199 if var == nil then break; end |
|
919
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
200 t[var] = var2; |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
201 end |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
202 return t; |
|
75b8afb79143
util.iterators: New iterators library
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
203 end |
|
4386
ce769240f8ec
util.iterators: Add range(from, to)
Matthew Wild <mwild1@gmail.com>
parents:
3540
diff
changeset
|
204 |
|
8797
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
205 local function _join_iter(j_s, j_var) |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
206 local iterators, current_idx = j_s[1], j_s[2]; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
207 local f, s, var = unpack(iterators[current_idx], 1, 3); |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
208 if j_var ~= nil then |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
209 var = j_var; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
210 end |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
211 local ret = pack(f(s, var)); |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
212 local var1 = ret[1]; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
213 if var1 == nil then |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
214 -- End of this iterator, advance to next |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
215 if current_idx == #iterators then |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
216 -- No more iterators, return nil |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
217 return; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
218 end |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
219 j_s[2] = current_idx + 1; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
220 return _join_iter(j_s); |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
221 end |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
222 return unpack(ret, 1, ret.n); |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
223 end |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
224 local join_methods = {}; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
225 local join_mt = { |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
226 __index = join_methods; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
227 __call = function (t, s, var) --luacheck: ignore 212/t |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
228 return _join_iter(s, var); |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
229 end; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
230 }; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
231 |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
232 function join_methods:append(f, s, var) |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
233 table.insert(self, { f, s, var }); |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
234 return self, { self, 1 }; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
235 end |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
236 |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
237 function join_methods:prepend(f, s, var) |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
238 table.insert(self, { f, s, var }, 1); |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
239 return self, { self, 1 }; |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
240 end |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
241 |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
242 function it.join(f, s, var) |
|
12744
e894677359e5
util.iterators: join: Work even with only a single iterator in the chain
Matthew Wild <mwild1@gmail.com>
parents:
12590
diff
changeset
|
243 local t = setmetatable({ {f, s, var} }, join_mt); |
|
e894677359e5
util.iterators: join: Work even with only a single iterator in the chain
Matthew Wild <mwild1@gmail.com>
parents:
12590
diff
changeset
|
244 return t, { t, 1 }; |
|
8797
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
245 end |
|
7b621a4a2e8d
util.iterators: Add join() method and tests
Matthew Wild <mwild1@gmail.com>
parents:
8389
diff
changeset
|
246 |
|
4545
c9b91ddc9c11
util.iterators: Make a standard library (no longer injects into global namespace)
Matthew Wild <mwild1@gmail.com>
parents:
4441
diff
changeset
|
247 return it; |