|
1 | | -{ lib, ... }: { |
2 | | - /* |
3 | | - Generates inclusive portrange given a lower and a higher number |
4 | | -
|
5 | | - Type: |
6 | | - utils.networking.portrange:: Int -> Int -> [ Int ] |
7 | | - */ |
8 | | - portrange = |
9 | | - from: |
10 | | - to: |
| 1 | +{ lib, utils, ... }: |
| 2 | +let |
| 3 | + inherit (builtins) length head; |
| 4 | + inherit (lib.trivial) throwIf; |
| 5 | + inherit (lib.strings) concatStrings; |
| 6 | + inherit (lib.lists) foldr last range; |
| 7 | + inherit (utils.networking) splitWhen; |
| 8 | +in |
| 9 | +{ |
| 10 | + |
| 11 | + /** |
| 12 | + # Description |
| 13 | +
|
| 14 | + Generates inclusive portrange given a lower and a higher number, |
| 15 | + additionally throws an error if the end of the range is not strictly |
| 16 | + greater. |
| 17 | +
|
| 18 | + # Type |
| 19 | +
|
| 20 | + ``` |
| 21 | + utils.networking.portrange :: Int -> Int -> [ Int ] |
| 22 | + ``` |
| 23 | + */ |
| 24 | + portrange = from: to: |
| 25 | + let ports = range from to; |
| 26 | + in throwIf (length ports == 0) |
| 27 | + (concatStrings [ |
| 28 | + "the second input has to be larger then the first one, " |
| 29 | + "otherwise you have a negative range which is impossible " |
| 30 | + "or not a range." |
| 31 | + ]) |
| 32 | + ports; |
| 33 | + |
| 34 | + /** |
| 35 | + # Example |
| 36 | +
|
| 37 | + ```nix |
| 38 | + let formatRange = { start, end }: "${toString start}-${toString end}" |
| 39 | + in map (x: if isAttrs x then formatRange x else x) |
| 40 | + (portsToRanges [ 1 2 3 ]) |
| 41 | + => [ "1-3" ] |
| 42 | + ``` |
| 43 | +
|
| 44 | + # Type |
| 45 | +
|
| 46 | + ``` |
| 47 | + utils.networking.portsToRanges :: [Int] -> [Int + { start end :: Int }] |
| 48 | + ``` |
| 49 | + */ |
| 50 | + portsToRanges = ports: |
11 | 51 | let |
12 | | - helper = input: |
13 | | - if input.counter >= 0 then |
14 | | - helper |
15 | | - { |
16 | | - list = [ (from + input.counter) ] ++ input.list; |
17 | | - counter = input.counter - 1; |
18 | | - } else input.list; |
| 52 | + partitioned = splitWhen (a: b: a + 1 == b) ports; |
| 53 | + format = range: |
| 54 | + if length range == 1 |
| 55 | + then head range |
| 56 | + else { start = head range; end = last range; }; |
19 | 57 | in |
20 | | - lib.throwIf (from > to) "the second input has to be larger then the first one, otherwise you have a negative range which is impossible or not a range." |
21 | | - helper |
22 | | - { list = [ ]; counter = to - from; } |
23 | | - ; |
| 58 | + map format partitioned; |
| 59 | + |
| 60 | + /** |
| 61 | + # Example |
| 62 | +
|
| 63 | + ```nix |
| 64 | + # split into strictly ordered sublists |
| 65 | + splitWhen (a: b: a < b) [ 7 8 9 4 5 6 1 2 3 ] |
| 66 | + => [ [ 7 8 9 ] [ 4 5 6 ] [ 1 2 3 ] ] |
| 67 | + ``` |
| 68 | +
|
| 69 | + # Type |
| 70 | +
|
| 71 | + ``` |
| 72 | + utils.networking.splitWhen :: (a -> a -> Bool) -> [a] -> [[a]] |
| 73 | + ``` |
| 74 | + */ |
| 75 | + splitWhen = p: xs: |
| 76 | + let |
| 77 | + unfold = { xs, xss }: |
| 78 | + if length xs == 0 then xss else [ xs ] ++ xss; |
| 79 | + |
| 80 | + addElement = x: { xs, xss }: |
| 81 | + if length xs == 0 |
| 82 | + then { xs = [ x ]; inherit xss; } |
| 83 | + else if p x (head xs) |
| 84 | + then { xs = [ x ] ++ xs; inherit xss; } |
| 85 | + else { xs = [ x ]; xss = [ xs ] ++ xss; }; |
| 86 | + in |
| 87 | + unfold (foldr addElement { xs = [ ]; xss = [ ]; } xs); |
| 88 | + |
24 | 89 | } |
0 commit comments