blob: 9c6ce2fb250b5aa195800aac9f21fc05c96e3c3a (
plain) (
blame)
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
|
{ depot, lib, pkgs, ... }:
let
inherit (depot.users.sterni.nix.flow)
cond
;
inherit (depot.nix)
yants
;
inherit (depot.users.sterni.nix)
string
;
# A char is the atomic element of a nix string
# which is essentially an array of arbitrary bytes
# as long as they are not a NUL byte.
#
# A char is neither a byte nor a unicode codepoint!
char = yants.restrict "char" (s: builtins.stringLength s == 1) yants.string;
# integer representation of char
charval = yants.restrict "charval" (i: i >= 1 && i < 256) yants.int;
allChars = builtins.readFile ./all-chars.bin;
# Originally I searched a list for this, but came to the
# conclusion that this can never be fast enough in Nix.
# We therefore use a solution similar to infinisil's.
ordMap = builtins.listToAttrs
(lib.imap1 (i: v: { name = v; value = i; })
(string.toChars allChars));
# Note on performance:
# chr and ord have been benchmarked using the following cases:
#
# builtins.map ord (lib.stringToCharacters allChars)
# builtins.map chr (builtins.genList (int.add 1) 255
#
# The findings are as follows:
# 1. Searching through either strings using recursion is
# unbearably slow in Nix, leading to evaluation times
# of up to 3s for the following very small test case.
# This is why we use the trusty attribute set for ord.
# 2. String indexing is much faster than list indexing which
# is why we use the former for chr.
ord = c: ordMap."${c}";
chr = i: string.charAt (i - 1) allChars;
asciiAlpha = c:
let
v = ord c;
in
(v >= 65 && v <= 90)
|| (v >= 97 && v <= 122);
asciiNum = c:
let
v = ord c;
in
v >= 48 && v <= 57;
asciiAlphaNum = c: asciiAlpha c || asciiNum c;
in
{
inherit
allChars
char
charval
ord
chr
asciiAlpha
asciiNum
asciiAlphaNum
;
# originally I generated a nix file containing a list of
# characters, but infinisil uses a better way which I adapt
# which is using builtins.readFile instead of import.
__generateAllChars = pkgs.runCommandCC "generate-all-chars"
{
source = ''
#include <stdio.h>
int main(void) {
for(int i = 1; i <= 0xff; i++) {
putchar(i);
}
}
'';
passAsFile = [ "source" ];
} ''
$CC -o "$out" -x c "$sourcePath"
'';
}
|